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