home *** CD-ROM | disk | FTP | other *** search
/ Media Share 9 / MEDIASHARE_09.ISO / hamradio / s920603.zip / PKTDRVR.C < prev    next >
C/C++ Source or Header  |  1992-05-01  |  11KB  |  441 lines

  1. /* Driver for FTP Software's packet driver interface. (PC specific code)
  2.  * Copyright 1991 Phil Karn, KA9Q
  3.  */
  4. #include <stdio.h>
  5. #include <dos.h>
  6. #include "global.h"
  7. #include "proc.h"
  8. #include "mbuf.h"
  9. #include "netuser.h"
  10. #include "enet.h"
  11. #include "arcnet.h"
  12. #include "ax25.h"
  13. #include "slip.h"
  14. #include "kiss.h"
  15. #include "iface.h"
  16. #include "arp.h"
  17. #include "trace.h"
  18. #include "pktdrvr.h"
  19. #include "config.h"
  20. #include "devparam.h"
  21.  
  22. static long access_type __ARGS((int intno,int if_class,int if_type,
  23.     int if_number, char *type,unsigned typelen,
  24.     INTERRUPT (*receiver) __ARGS((void)) ));
  25. static int driver_info __ARGS((int intno,int handle,int *version,
  26.     int *class,int *type,int *number,int *basic));
  27. static int release_type __ARGS((int intno,int handle));
  28. static int get_address __ARGS((int intno,int handle,char *buf,int len));
  29. static int pk_raw __ARGS((struct iface *iface,struct mbuf *bp));
  30. static int pk_stop __ARGS((struct iface *iface));
  31. static int send_pkt __ARGS((int intno,char *buffer,unsigned length));
  32.  
  33.  
  34. static INTERRUPT (*Pkvec[])() = { pkvec0,pkvec1,pkvec2 };
  35. static struct pktdrvr Pktdrvr[PK_MAX];
  36. static int Derr;
  37. static char Pkt_sig[] = "PKT DRVR";    /* Packet driver signature */
  38.  
  39. /*
  40.  * Send routine for packet driver
  41.  */
  42.  
  43. int
  44. pk_send(bp,iface,gateway,tos)
  45. struct mbuf *bp;    /* Buffer to send */
  46. struct iface *iface;    /* Pointer to interface control block */
  47. int32 gateway;        /* Ignored  */
  48. int tos;
  49. {
  50.     if(iface == NULLIF){
  51.         free_p(bp);
  52.         return -1;
  53.     }
  54.     return (*iface->raw)(iface,bp);
  55. }
  56.  
  57. /* Send raw packet (caller provides header) */
  58. static int
  59. pk_raw(iface,bp)
  60. struct iface *iface;    /* Pointer to interface control block */
  61. struct mbuf *bp;    /* Data field */
  62. {
  63.     register struct pktdrvr *pp;
  64.     int16 size;
  65.     struct mbuf *bp1;
  66.  
  67.     pp = &Pktdrvr[iface->dev];
  68.     size = len_p(bp);
  69.  
  70.     dump(iface,IF_TRACE_OUT,bp);
  71.     iface->rawsndcnt++;
  72.     iface->lastsent = secclock();
  73.  
  74.     /* Perform class-specific processing, if any */
  75.     switch(pp->class){
  76.     case CL_ETHERNET:
  77.         if(size < RUNT){
  78.             /* Pad the packet out to the minimum */
  79.             if((bp1 = alloc_mbuf(RUNT-size)) == NULLBUF){
  80.                 free_p(bp);
  81.                 return -1;
  82.             }
  83.             memset(bp1->data,0,RUNT-size);
  84.             bp1->cnt = RUNT-size;
  85.             append(&bp,bp1);
  86.             size = RUNT;
  87.         }
  88.         break;
  89.     case CL_KISS:
  90.         /* This *really* shouldn't be done here, but it was the
  91.          * easiest way. Put the type field for KISS TNC on front.
  92.          */
  93.         bp = pushdown(bp,1);
  94.         bp->data[0] = PARAM_DATA;
  95.         size++;
  96.         break;
  97.     }
  98.     if(bp->next != NULLBUF){
  99.         /* Copy to contiguous buffer, since driver can't handle mbufs */
  100.         bp1 = copy_p(bp,size);
  101.         free_p(bp);
  102.         bp = bp1;
  103.         if(bp == NULLBUF)
  104.             return -1;
  105.     }
  106.     send_pkt(pp->intno,bp->data,bp->cnt);
  107.     free_p(bp);
  108.     return 0;
  109. }
  110.  
  111. /* Packet driver receive routine. Called from an assembler hook that pushes
  112.  * the caller's registers on the stack so we can access and modify them.
  113.  * This is a rare example of call-by-location in C.
  114.  */
  115. INTERRUPT
  116. pkint(bp, di, si, ds, es, dx, cx, bx, ax, ip, cs, flags, dev)
  117. unsigned short  bp, di, si, ds, es, dx, cx, bx, ax, ip, cs, flags;
  118. int dev;
  119. {
  120.     register struct pktdrvr *pp;
  121.     
  122.     if(dev < 0 || dev >= PK_MAX)
  123.         return;    /* Unknown device */
  124.     pp = &Pktdrvr[dev];
  125.     if(pp->iface == NULLIF)
  126.         return;    /* Unknown device */
  127.     switch(ax){
  128.     case 0:    /* Space allocate call */
  129.         if((pp->buffer = alloc_mbuf(cx+sizeof(struct iface *))) != NULLBUF){
  130.             pp->buffer->data += sizeof(struct iface *);
  131.             es = FP_SEG(pp->buffer->data);
  132.             di = FP_OFF(pp->buffer->data);
  133.             pp->buffer->cnt = cx;
  134.         } else {
  135.             es = di = 0;
  136.         }
  137.         break;
  138.     case 1:    /* Packet complete call */
  139.         net_route(pp->iface,pp->buffer);
  140.         pp->buffer = NULLBUF;
  141.         break;
  142.     default:
  143.         break;
  144.     }
  145. }
  146.  
  147. /* Shut down the packet interface */
  148. static int
  149. pk_stop(iface)
  150. struct iface *iface;
  151. {
  152.     struct pktdrvr *pp;
  153.  
  154.     pp = &Pktdrvr[iface->dev];
  155.     /* Call driver's release_type() entry */
  156.     if(release_type(pp->intno,pp->handle1) == -1)
  157.         printf("%s: release_type error code %u\n",iface->name,Derr);
  158.  
  159.     if(pp->class == CL_ETHERNET || pp->class == CL_ARCNET){
  160.         release_type(pp->intno,pp->handle2);
  161.         release_type(pp->intno,pp->handle3);
  162.     }
  163.     pp->iface = NULLIF;
  164.     return 0;
  165. }
  166. /* Attach a packet driver to the system
  167.  * argv[0]: hardware type, must be "packet"
  168.  * argv[1]: software interrupt vector, e.g., x7e
  169.  * argv[2]: interface label, e.g., "trw0"
  170.  * argv[3]: maximum number of packets allowed on transmit queue, e.g., "5"
  171.  * argv[4]: maximum transmission unit, bytes, e.g., "1500"
  172.  */
  173. int
  174. pk_attach(argc,argv,p)
  175. int argc;
  176. char *argv[];
  177. void *p;
  178. {
  179.     register struct iface *if_pk;
  180.     int class,type;
  181.     unsigned int intno;
  182.     static char iptype[] = {IP_TYPE >> 8,IP_TYPE};
  183.     static char arptype[] = {ARP_TYPE >> 8,ARP_TYPE};
  184.     static char revarptype[] = {REVARP_TYPE >> 8, REVARP_TYPE};
  185.     long handle;
  186.     int i;
  187. #ifdef    ARCNET
  188.     static char arcip[] = {ARC_IP};
  189.     static char arcarp[] = {ARC_ARP};
  190. #endif
  191.  
  192.     long drvvec;
  193.     char sig[8];    /* Copy of driver signature "PKT DRVR" */
  194.     register struct pktdrvr *pp;
  195.     char tmp[25];
  196.     char *cp;
  197.  
  198.     for(i=0;i<PK_MAX;i++){
  199.         if(Pktdrvr[i].iface == NULLIF)
  200.             break;
  201.     }
  202.     if(i >= PK_MAX){
  203.         printf("Too many packet drivers\n");
  204.         return -1;
  205.     }
  206.     if(if_lookup(argv[2]) != NULLIF){
  207.         printf("Interface %s already exists\n",argv[2]);
  208.         return -1;
  209.     }
  210.  
  211.     intno = htoi(argv[1]);
  212.     /* Verify that there's really a packet driver there, so we don't
  213.      * go off into the ozone (if there's any left)
  214.      */
  215.     drvvec = (long)getvect(intno);
  216.     movblock(FP_OFF(drvvec)+3, FP_SEG(drvvec),
  217.         FP_OFF(sig),FP_SEG(sig),strlen(Pkt_sig));
  218.     if(strncmp(sig,Pkt_sig,strlen(Pkt_sig)) != 0){
  219.         printf("No packet driver loaded at int 0x%x\n",intno);
  220.         return -1;
  221.     }
  222.     if_pk = (struct iface *)callocw(1,sizeof(struct iface));
  223.     if_pk->name = strdup(argv[2]);
  224.     if_pk->addr = Ip_addr;
  225.     pp = &Pktdrvr[i];
  226.     if_pk->mtu = atoi(argv[4]);
  227.     if_pk->dev = i;
  228.     if_pk->raw = pk_raw;
  229.     if_pk->stop = pk_stop;
  230.     pp->intno = intno;
  231.     pp->iface = if_pk;
  232.  
  233.      /* Version 1.08 of the packet driver spec dropped the handle
  234.       * requirement from the driver_info call.  However, if we are using
  235.       * a version 1.05 packet driver, the following call will fail.
  236.        */
  237.      if(driver_info(intno,-1,NULL,&class,&type,NULL,NULL) < 0){
  238.         /* Find out by exhaustive search what class this driver is (ugh) */
  239.         for(class=1;class<=NCLASS;class++){
  240.             /* Store handle in temp long so we can tell an
  241.              * error return (-1) from a handle of 0xffff
  242.              */
  243.             handle = access_type(intno,class,ANYTYPE,0,iptype,2,
  244.                 Pkvec[if_pk->dev]);
  245.             if(handle != -1 || Derr == TYPE_INUSE){
  246.                 pp->handle1 = handle;
  247.                 break;
  248.             }
  249.         }
  250.         /* Now that we know, release it and do it all over again with the
  251.          * right type fields
  252.          */
  253.         release_type(intno,pp->handle1);
  254.     }
  255.     switch(class){
  256.     case CL_ETHERNET:
  257.         pp->handle1 = access_type(intno,class,ANYTYPE,0,iptype,2,
  258.             Pkvec[if_pk->dev]);
  259.         pp->handle2 = access_type(intno,class,ANYTYPE,0,arptype,2,
  260.             Pkvec[if_pk->dev]);
  261.         pp->handle3 = access_type(intno,class,ANYTYPE,0,revarptype,2,
  262.             Pkvec[if_pk->dev]);
  263.         setencap(if_pk,"Ethernet");
  264.         /* Get hardware Ethernet address from driver */
  265.         if_pk->hwaddr = mallocw(EADDR_LEN);
  266.         get_address(intno,pp->handle1,if_pk->hwaddr,EADDR_LEN);
  267.         if(if_pk->hwaddr[0] & 1){
  268.             printf("Warning! Interface '%s' has a multicast address:",
  269.              if_pk->name);
  270.             printf(" (%s)\n",
  271.              (*if_pk->iftype->format)(tmp,if_pk->hwaddr));
  272.         }
  273.         break;
  274. #ifdef    ARCNET
  275.     case CL_ARCNET:
  276.         pp->handle1 = access_type(intno,class,ANYTYPE,0,arcip,1,
  277.             Pkvec[if_pk->dev]);
  278.         pp->handle2 = access_type(intno,class,ANYTYPE,0,arcarp,1,
  279.             Pkvec[if_pk->dev]);
  280.         if_pk->output = anet_output;
  281.         /* Get hardware ARCnet address from driver */
  282.         if_pk->hwaddr = mallocw(AADDR_LEN);
  283.         get_address(intno,pp->handle1,if_pk->hwaddr,AADDR_LEN);
  284.         break;
  285. #endif
  286.     case CL_SERIAL_LINE:
  287.         pp->handle1 = access_type(intno,class,ANYTYPE,0,NULLCHAR,0,
  288.          Pkvec[if_pk->dev]);
  289.         setencap(if_pk,"SLIP");
  290.         break;
  291. #ifdef    AX25
  292.     case CL_KISS:    /* Note that the raw routine puts on the command */
  293.     case CL_AX25:
  294.         pp->handle1 = access_type(intno,class,ANYTYPE,0,NULLCHAR,0,
  295.          Pkvec[if_pk->dev]);
  296.         setencap(if_pk,"AX25");
  297.         if_pk->hwaddr = mallocw(AXALEN);
  298.         memcpy(if_pk->hwaddr,Mycall,AXALEN);
  299.         break;
  300. #endif
  301.     case CL_SLFP:
  302.         pp->handle1 = access_type(intno,class,ANYTYPE,0,NULLCHAR,0,
  303.          Pkvec[if_pk->dev]);
  304.         setencap(if_pk,"SLFP");
  305.         get_address(intno,pp->handle1,(char *)&if_pk->addr,4);
  306.         break;
  307.     default:
  308.         printf("Packet driver has unsupported class %u\n",class);
  309.         free(if_pk->name);
  310.         free((char *)if_pk);
  311.         return -1;
  312.     }
  313.     pp->class = class;
  314.     if_pk->next = Ifaces;
  315.     Ifaces = if_pk;
  316.     cp = if_name(if_pk," tx");
  317.     if_pk->txproc = newproc(cp,768,if_tx,if_pk->dev,if_pk,NULL,0);
  318.     free(cp);
  319.  
  320.     return 0;
  321. }
  322. static long
  323. access_type(intno,if_class,if_type,if_number,type,typelen,receiver)
  324. int intno;
  325. int if_class;
  326. int if_type;
  327. int if_number;
  328. char *type;
  329. unsigned typelen;
  330. INTERRUPT (*receiver)();
  331. {
  332.     union REGS regs;
  333.     struct SREGS sregs;
  334.  
  335.     segread(&sregs);
  336.     regs.h.dl = if_number;        /* Number */
  337.     sregs.ds = FP_SEG(type);    /* Packet type template */
  338.     regs.x.si = FP_OFF(type);
  339.     regs.x.cx = typelen;        /* Length of type */
  340.     sregs.es = FP_SEG(receiver);    /* Address of receive handler */
  341.     regs.x.di = FP_OFF(receiver);
  342.     regs.x.bx = if_type;        /* Type */
  343.     regs.h.ah = ACCESS_TYPE;    /* Access_type() function */
  344.     regs.h.al = if_class;        /* Class */
  345.     int86x(intno,®s,®s,&sregs);
  346.     if(regs.x.cflag){
  347.         Derr = regs.h.dh;
  348.         return -1;
  349.     } else
  350.         return regs.x.ax;
  351. }
  352. static int
  353. release_type(intno,handle)
  354. int intno;
  355. int handle;
  356. {
  357.     union REGS regs;
  358.  
  359.     regs.x.bx = handle;
  360.     regs.h.ah = RELEASE_TYPE;
  361.     int86(intno,®s,®s);
  362.     if(regs.x.cflag){
  363.         Derr = regs.h.dh;
  364.         return -1;
  365.     } else
  366.         return 0;
  367. }
  368. static int
  369. send_pkt(intno,buffer,length)
  370. int intno;
  371. char *buffer;
  372. unsigned length;
  373. {
  374.     union REGS regs;
  375.     struct SREGS sregs;
  376.  
  377.     segread(&sregs);
  378.     sregs.ds = FP_SEG(buffer);
  379.     sregs.es = FP_SEG(buffer); /* for buggy univation pkt driver - CDY */
  380.     regs.x.si = FP_OFF(buffer);
  381.     regs.x.cx = length;
  382.     regs.h.ah = SEND_PKT;
  383.     int86x(intno,®s,®s,&sregs);
  384.     if(regs.x.cflag){
  385.         Derr = regs.h.dh;
  386.         return -1;
  387.     } else
  388.         return 0;
  389. }
  390. static int
  391. driver_info(intno,handle,version,class,type,number,basic)
  392. int intno;
  393. int handle;
  394. int *version,*class,*type,*number,*basic;
  395. {
  396.     union REGS regs;
  397.  
  398.     regs.x.bx = handle;
  399.     regs.h.ah = DRIVER_INFO;
  400.     regs.h.al = 0xff;
  401.     int86(intno,®s,®s);
  402.     if(regs.x.cflag){
  403.         Derr = regs.h.dh;
  404.         return -1;
  405.     }
  406.     if(version != NULL)
  407.         *version = regs.x.bx;
  408.     if(class != NULL)
  409.         *class = regs.h.ch;
  410.     if(type != NULL)
  411.         *type = regs.x.dx;
  412.     if(number != NULL)
  413.         *number = regs.h.cl;
  414.     if(basic != NULL)
  415.         *basic = regs.h.al;
  416.     return 0;
  417. }
  418. static int
  419. get_address(intno,handle,buf,len)
  420. int intno;
  421. int handle;
  422. char *buf;
  423. int len;
  424. {
  425.     union REGS regs;
  426.     struct SREGS sregs;
  427.  
  428.     segread(&sregs);
  429.     sregs.es = FP_SEG(buf);
  430.     regs.x.di = FP_OFF(buf);
  431.     regs.x.cx = len;
  432.     regs.x.bx = handle;
  433.     regs.h.ah = GET_ADDRESS;
  434.     int86x(intno,®s,®s,&sregs);
  435.     if(regs.x.cflag){
  436.         Derr = regs.h.dh;
  437.         return -1;
  438.     }
  439.     return 0;
  440. }
  441.