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