home *** CD-ROM | disk | FTP | other *** search
/ HAM Radio 3 / hamradioversion3.0examsandprograms1992.iso / misc / 9q920411 / iface.c < prev    next >
C/C++ Source or Header  |  1992-04-08  |  13KB  |  578 lines

  1. /* IP interface control and configuration routines
  2.  * Copyright 1991 Phil Karn, KA9Q
  3.  */
  4. #include <stdio.h>
  5. #include "global.h"
  6. #include "mbuf.h"
  7. #include "proc.h"
  8. #include "iface.h"
  9. #include "ip.h"
  10. #include "netuser.h"
  11. #include "ax25.h"
  12. #include "enet.h"
  13. #include "pktdrvr.h"
  14. #include "cmdparse.h"
  15. #include "commands.h"
  16. #include "trace.h"
  17.  
  18. static void showiface __ARGS((struct iface *ifp));
  19. static int mask2width __ARGS((int32 mask));
  20. static int ifipaddr __ARGS((int argc,char *argv[],void *p));
  21. static int iflinkadr __ARGS((int argc,char *argv[],void *p));
  22. static int ifbroad __ARGS((int argc,char *argv[],void *p));
  23. static int ifnetmsk __ARGS((int argc,char *argv[],void *p));
  24. static int ifrxbuf __ARGS((int argc,char *argv[],void *p));
  25. static int ifmtu __ARGS((int argc,char *argv[],void *p));
  26. static int ifforw __ARGS((int argc,char *argv[],void *p));
  27. static int ifencap __ARGS((int argc,char *argv[],void *p));
  28.  
  29. /* Interface list header */
  30. struct iface *Ifaces = &Loopback;
  31.  
  32. /* Loopback pseudo-interface */
  33. struct iface Loopback = {
  34.     &Encap,        /* Link to next entry */
  35.     "loopback",    /* name        */
  36.     0x7f000001L,    /* addr        127.0.0.1 */
  37.     0xffffffffL,    /* broadcast    255.255.255.255 */
  38.     0xffffffffL,    /* netmask    255.255.255.255 */
  39.     MAXINT16,    /* mtu        No limit */
  40.     0,        /* flags    */
  41.     0,        /* trace    */
  42.     NULLCHAR,    /* trfile    */
  43.     NULLFILE,    /* trfp        */
  44.     NULLIF,        /* forw        */
  45.     NULLPROC,    /* rxproc    */
  46.     NULLPROC,    /* txproc    */
  47.     NULLPROC,    /* supv        */
  48.     NULLBUF,    /* outq        */
  49.     0,        /* dev        */
  50.     NULL,        /* (*ioctl)    */
  51.     NULLFP,        /* (*iostatus)    */
  52.     NULLFP,        /* (*stop)    */
  53.     NULLCHAR,    /* hwaddr    */
  54.     NULL,        /* extension    */
  55.     CL_NONE,    /* type        */
  56.     0,        /* xdev        */
  57.     &Iftypes[0],    /* iftype    */
  58.     NULLFP,        /* (*send)    */
  59.     NULLFP,        /* (*output)    */
  60.     NULLFP,        /* (*raw)    */
  61.     NULLFP,        /* (*status)    */
  62.     NULLFP,        /* (*discard)    */
  63.     NULLFP,        /* (*echo)    */
  64.     0,        /* ipsndcnt    */
  65.     0,        /* rawsndcnt    */
  66.     0,        /* iprecvcnt    */
  67.     0,        /* rawrcvcnt    */
  68.     0,        /* lastsent    */
  69.     0,        /* lastrecv    */
  70. };
  71. /* Encapsulation pseudo-interface */
  72. struct iface Encap = {
  73.     NULLIF,
  74.     "encap",    /* name        */
  75.     INADDR_ANY,    /* addr        0.0.0.0 */
  76.     0xffffffffL,    /* broadcast    255.255.255.255 */
  77.     0xffffffffL,    /* netmask    255.255.255.255 */
  78.     MAXINT16,    /* mtu        No limit */
  79.     0,        /* flags    */
  80.     0,        /* trace    */
  81.     NULLCHAR,    /* trfile    */
  82.     NULLFILE,    /* trfp        */
  83.     NULLIF,        /* forw        */
  84.     NULLPROC,    /* rxproc    */
  85.     NULLPROC,    /* txproc    */
  86.     NULLPROC,    /* supv        */
  87.     NULLBUF,    /* outq        */
  88.     0,        /* dev        */
  89.     NULL,        /* (*ioctl)    */
  90.     NULLFP,        /* (*iostatus)    */
  91.     NULLFP,        /* (*stop)    */
  92.     NULLCHAR,    /* hwaddr    */
  93.     NULL,        /* extension    */
  94.     CL_NONE,    /* type        */
  95.     0,        /* xdev        */
  96.     &Iftypes[0],    /* iftype    */
  97.     ip_encap,    /* (*send)    */
  98.     NULLFP,        /* (*output)    */
  99.     NULLFP,        /* (*raw)    */
  100.     NULLFP,        /* (*status)    */
  101.     NULLFP,        /* (*discard)    */
  102.     NULLFP,        /* (*echo)    */
  103.     0,        /* ipsndcnt    */
  104.     0,        /* rawsndcnt    */
  105.     0,        /* iprecvcnt    */
  106.     0,        /* rawrcvcnt    */
  107.     0,        /* lastsent    */
  108.     0,        /* lastrecv    */
  109. };
  110.  
  111. char Noipaddr[] = "IP address field missing, and ip address not set\n";
  112.  
  113. struct cmds Ifcmds[] = {
  114.     "broadcast",        ifbroad,    0,    2,    NULLCHAR,
  115.     "encapsulation",    ifencap,    0,    2,    NULLCHAR,
  116.     "forward",        ifforw,        0,    2,    NULLCHAR,
  117.     "ipaddress",        ifipaddr,    0,    2,    NULLCHAR,
  118.     "linkaddress",        iflinkadr,    0,    2,    NULLCHAR,
  119.     "mtu",            ifmtu,        0,    2,    NULLCHAR,
  120.     "netmask",        ifnetmsk,    0,    2,    NULLCHAR,
  121.     "rxbuf",        ifrxbuf,    0,    2,    NULLCHAR,
  122.     NULLCHAR,
  123. };
  124. /*
  125.  * General purpose interface transmit task, one for each device that can
  126.  * send IP datagrams. It waits on the interface's IP output queue (outq),
  127.  * extracts IP datagrams placed there in priority order by ip_route(),
  128.  * and sends them to the device's send routine.
  129.  */
  130. void
  131. if_tx(dev,arg1,unused)
  132. int dev;
  133. void *arg1;
  134. void *unused;
  135. {
  136.     struct mbuf *bp;    /* Buffer to send */
  137.     struct iface *iface;    /* Pointer to interface control block */
  138.     struct qhdr qhdr;
  139.  
  140.     iface = arg1;
  141.     for(;;){
  142.         while(iface->outq == NULLBUF)
  143.             pwait(&iface->outq);
  144.  
  145.         bp = dequeue(&iface->outq);
  146.         pullup(&bp,(char *)&qhdr,sizeof(qhdr));
  147.         (*iface->send)(bp,iface,qhdr.gateway,qhdr.tos);
  148.  
  149.         /* Let other tasks run, just in case send didn't block */
  150.         pwait(NULL);
  151.     }
  152. }
  153. /* Process packets in the Hopper */
  154. void
  155. network(i,v1,v2)
  156. int i;
  157. void *v1;
  158. void *v2;
  159. {
  160.     struct mbuf *bp;
  161.     struct phdr phdr;
  162.     char i_state;
  163.     struct rfunc *rp;
  164.  
  165. loop:
  166.     refiq();    /* Replenish interrupt buffer pool */
  167.  
  168.     i_state = dirps();
  169.     while(Hopper == NULLBUF)
  170.         pwait(&Hopper);
  171.     restore(i_state);
  172.  
  173.     /* Process the input packet */
  174.     bp = dequeue(&Hopper);
  175.     pullup(&bp,(char *)&phdr,sizeof(phdr));
  176.     if(phdr.iface != NULLIF){
  177.         phdr.iface->rawrecvcnt++;
  178.         phdr.iface->lastrecv = secclock();
  179.     }
  180.     dump(phdr.iface,IF_TRACE_IN,phdr.type,bp);
  181.     for(rp = &Rfunc[0];rp->class != -1;rp++){
  182.         if(phdr.type == rp->class){
  183.             (*rp->rcvf)(phdr.iface,bp);
  184.                 break;
  185.         }
  186.     }                    
  187.     if(rp->class == -1)
  188.         free_p(bp);
  189.     /* Let everything else run - this keeps the system from wedging
  190.      * when we're hit by a big burst of packets
  191.      */
  192.     pwait(NULL);
  193.     goto loop;
  194. }
  195.  
  196. /* put mbuf into Hopper for network task
  197.  * returns 0 if OK
  198.  */
  199. int
  200. net_route(ifp, type, bp)
  201. struct iface *ifp;
  202. int type;
  203. struct mbuf *bp;
  204. {
  205.     struct phdr phdr;
  206.  
  207.     phdr.iface = ifp;
  208.     phdr.type = type;
  209.  
  210.     bp = pushdown(bp,sizeof(phdr));
  211.     memcpy(&bp->data[0],(char *)&phdr,sizeof(phdr));
  212.     enqueue(&Hopper,bp);
  213.     return 0;
  214. }
  215.  
  216. /* Set interface parameters */
  217. int
  218. doifconfig(argc,argv,p)
  219. int argc;
  220. char *argv[];
  221. void *p;
  222. {
  223.     struct iface *ifp;
  224.     int i;
  225.  
  226.     if(argc < 2){
  227.         for(ifp = Ifaces;ifp != NULLIF;ifp = ifp->next)
  228.             showiface(ifp);
  229.         return 0;
  230.     }
  231.     if((ifp = if_lookup(argv[1])) == NULLIF){
  232.         tprintf("Interface %s unknown\n",argv[1]);
  233.         return 1;
  234.     }
  235.     if(argc == 2){
  236.         showiface(ifp);
  237.         if(ifp->show != NULLVFP){
  238.             (*ifp->show)(ifp);
  239.         }
  240.         return 0;
  241.     }
  242.     if(argc == 3){
  243.         tprintf("Argument missing\n");
  244.         return 1;
  245.     }
  246.     for(i=2;i<argc-1;i+=2)
  247.         subcmd(Ifcmds,3,&argv[i-1],ifp);
  248.  
  249.     return 0;
  250. }
  251.  
  252. /* Set interface IP address */
  253. static int
  254. ifipaddr(argc,argv,p)
  255. int argc;
  256. char *argv[];
  257. void *p;
  258. {
  259.     struct iface *ifp = p;
  260.  
  261.     ifp->addr = resolve(argv[1]);
  262.     return 0;
  263. }
  264.  
  265.  
  266. /* Set link (hardware) address */
  267. static int
  268. iflinkadr(argc,argv,p)
  269. int argc;
  270. char *argv[];
  271. void *p;
  272. {
  273.     struct iface *ifp = p;
  274.  
  275.     if(ifp->iftype == NULLIFT || ifp->iftype->scan == NULL){
  276.         tprintf("Can't set link address\n");
  277.         return 1;
  278.     }
  279.     if(ifp->hwaddr != NULLCHAR)
  280.         free(ifp->hwaddr);
  281.     ifp->hwaddr = mallocw(ifp->iftype->hwalen);
  282.     (*ifp->iftype->scan)(ifp->hwaddr,argv[1]);
  283.     return 0;
  284. }
  285.  
  286. /* Set interface broadcast address. This is actually done
  287.  * by installing a private entry in the routing table.
  288.  */
  289. static int
  290. ifbroad(argc,argv,p)
  291. int argc;
  292. char *argv[];
  293. void *p;
  294. {
  295.     struct iface *ifp = p;
  296.     struct route *rp;
  297.  
  298.     rp = rt_blookup(ifp->broadcast,32);
  299.     if(rp != NULLROUTE && rp->iface == ifp)
  300.         rt_drop(ifp->broadcast,32);
  301.     ifp->broadcast = resolve(argv[1]);
  302.     rt_add(ifp->broadcast,32,0L,ifp,1L,0L,1);
  303.     return 0;
  304. }
  305.  
  306. /* Set the network mask. This is actually done by installing
  307.  * a routing entry.
  308.  */
  309. static int
  310. ifnetmsk(argc,argv,p)
  311. int argc;
  312. char *argv[];
  313. void *p;
  314. {
  315.     struct iface *ifp = p;
  316.     struct route *rp;
  317.  
  318.     /* Remove old entry if it exists */
  319.     rp = rt_blookup(ifp->addr & ifp->netmask,mask2width(ifp->netmask));
  320.     if(rp != NULLROUTE)
  321.         rt_drop(rp->target,rp->bits);
  322.  
  323.     ifp->netmask = htol(argv[1]);
  324.     rt_add(ifp->addr,mask2width(ifp->netmask),0L,ifp,0L,0L,0);
  325.     return 0;
  326. }
  327.  
  328. /* Command to set interface encapsulation mode */
  329. static int
  330. ifencap(argc,argv,p)
  331. int argc;
  332. char *argv[];
  333. void *p;
  334. {
  335.     struct iface *ifp = p;
  336.  
  337.     if(setencap(ifp,argv[1]) != 0){
  338.         tprintf("Encapsulation mode '%s' unknown\n",argv[1]);
  339.         return 1;
  340.     }
  341.     return 0;
  342. }
  343. /* Function to set encapsulation mode */
  344. int
  345. setencap(ifp,mode)
  346. struct iface *ifp;
  347. char *mode;
  348. {
  349.     struct iftype *ift;
  350.  
  351.     for(ift = &Iftypes[0];ift->name != NULLCHAR;ift++)
  352.         if(strnicmp(ift->name,mode,strlen(mode)) == 0)
  353.             break;
  354.     if(ift->name == NULLCHAR){
  355.         return -1;
  356.     }
  357.     ifp->iftype = ift;
  358.     ifp->send = ift->send;
  359.     ifp->output = ift->output;
  360.     ifp->type = ift->type;
  361.     return 0;
  362. }
  363. /* Set interface receive buffer size */
  364. static int
  365. ifrxbuf(argc,argv,p)
  366. int argc;
  367. char *argv[];
  368. void *p;
  369. {
  370.     return 0;    /* To be written */
  371. }
  372.  
  373. /* Set interface Maximum Transmission Unit */
  374. static int
  375. ifmtu(argc,argv,p)
  376. int argc;
  377. char *argv[];
  378. void *p;
  379. {
  380.     struct iface *ifp = p;
  381.  
  382.     ifp->mtu = atoi(argv[1]);
  383.     return 0;
  384. }
  385.  
  386. /* Set interface forwarding */
  387. static int
  388. ifforw(argc,argv,p)
  389. int argc;
  390. char *argv[];
  391. void *p;
  392. {
  393.     struct iface *ifp = p;
  394.  
  395.     ifp->forw = if_lookup(argv[1]);
  396.     if(ifp->forw == ifp)
  397.         ifp->forw = NULLIF;
  398.     return 0;
  399. }
  400.  
  401. /* Display the parameters for a specified interface */
  402. static void
  403. showiface(ifp)
  404. register struct iface *ifp;
  405. {
  406.     char tmp[25];
  407.  
  408.     tprintf("%-10s IP addr %s MTU %u Link encap ",ifp->name,
  409.      inet_ntoa(ifp->addr),(int)ifp->mtu);
  410.     if(ifp->iftype == NULLIFT){
  411.         tprintf("not set\n");
  412.     } else {
  413.         tprintf("%s\n",ifp->iftype->name);
  414.         if(ifp->iftype->format != NULL && ifp->hwaddr != NULLCHAR)
  415.             tprintf("           Link addr %s\n",
  416.              (*ifp->iftype->format)(tmp,ifp->hwaddr));
  417.     }
  418.     tprintf("           flags %u trace 0x%x netmask 0x%08lx broadcast %s\n",
  419.         ifp->flags,ifp->trace,ifp->netmask,inet_ntoa(ifp->broadcast));
  420.     if(ifp->forw != NULLIF)
  421.         tprintf("           output forward to %s\n",ifp->forw->name);
  422.     tprintf("           sent: ip %lu tot %lu idle %s qlen %d\n",
  423.      ifp->ipsndcnt,ifp->rawsndcnt,tformat(secclock() - ifp->lastsent),
  424.         len_q(ifp->outq));
  425.     tprintf("           recv: ip %lu tot %lu idle %s\n",
  426.      ifp->iprecvcnt,ifp->rawrecvcnt,tformat(secclock() - ifp->lastrecv));
  427. }
  428.  
  429. /* Command to detach an interface */
  430. int
  431. dodetach(argc,argv,p)
  432. int argc;
  433. char *argv[];
  434. void *p;
  435. {
  436.     register struct iface *ifp;
  437.  
  438.     if((ifp = if_lookup(argv[1])) == NULLIF){
  439.         tprintf("Interface %s unknown\n",argv[1]);
  440.         return 1;
  441.     }
  442.     if(if_detach(ifp) == -1)
  443.         tprintf("Can't detach loopback or encap interface\n");
  444.     return 0;
  445. }
  446. /* Detach a specified interface */
  447. int
  448. if_detach(ifp)
  449. register struct iface *ifp;
  450. {
  451.     struct iface *iftmp;
  452.     struct route *rp,*rptmp;
  453.     int i,j;
  454.  
  455.     if(ifp == &Loopback || ifp == &Encap)
  456.         return -1;
  457.  
  458.     /* Drop all routes that point to this interface */
  459.     if(R_default.iface == ifp)
  460.         rt_drop(0L,0);    /* Drop default route */
  461.  
  462.     for(i=0;i<HASHMOD;i++){
  463.         for(j=0;j<32;j++){
  464.             for(rp = Routes[j][i];rp != NULLROUTE;rp = rptmp){
  465.                 /* Save next pointer in case we delete this entry */
  466.                 rptmp = rp->next;
  467.                 if(rp->iface == ifp)
  468.                     rt_drop(rp->target,rp->bits);
  469.             }
  470.         }
  471.     }
  472.     /* Unforward any other interfaces forwarding to this one */
  473.     for(iftmp = Ifaces;iftmp != NULLIF;iftmp = iftmp->next){
  474.         if(iftmp->forw == ifp)
  475.             iftmp->forw = NULLIF;
  476.     }
  477.     /* Call device shutdown routine, if any */
  478.     if(ifp->stop != NULLFP)
  479.         (*ifp->stop)(ifp);
  480.  
  481.     killproc(ifp->rxproc);
  482.     killproc(ifp->txproc);
  483.     killproc(ifp->supv);
  484.  
  485.     /* Free allocated memory associated with this interface */
  486.     if(ifp->name != NULLCHAR)
  487.         free(ifp->name);
  488.     if(ifp->hwaddr != NULLCHAR)
  489.         free(ifp->hwaddr);
  490.     /* Remove from interface list */
  491.     if(ifp == Ifaces){
  492.         Ifaces = ifp->next;
  493.     } else {
  494.         /* Search for entry just before this one
  495.          * (necessary because list is only singly-linked.)
  496.          */
  497.         for(iftmp = Ifaces;iftmp != NULLIF ;iftmp = iftmp->next)
  498.             if(iftmp->next == ifp)
  499.                 break;
  500.         if(iftmp != NULLIF && iftmp->next == ifp)
  501.             iftmp->next = ifp->next;
  502.     }
  503.     /* Finally free the structure itself */
  504.     free((char *)ifp);
  505.     return 0;
  506. }
  507.  
  508. /* Given the ascii name of an interface, return a pointer to the structure,
  509.  * or NULLIF if it doesn't exist
  510.  */
  511. struct iface *
  512. if_lookup(name)
  513. char *name;
  514. {
  515.     register struct iface *ifp;
  516.  
  517.     for(ifp = Ifaces; ifp != NULLIF; ifp = ifp->next)
  518.         if(strcmp(ifp->name,name) == 0)
  519.             break;
  520.     return ifp;
  521. }
  522.  
  523. /* Return iface pointer if 'addr' belongs to one of our interfaces,
  524.  * NULLIF otherwise.
  525.  * This is used to tell if an incoming IP datagram is for us, or if it
  526.  * has to be routed.
  527.  */
  528. struct iface *
  529. ismyaddr(addr)
  530. int32 addr;
  531. {
  532.     register struct iface *ifp;
  533.  
  534.     for(ifp = Ifaces; ifp != NULLIF; ifp = ifp->next)
  535.         if(addr == ifp->addr)
  536.             break;
  537.     return ifp;
  538. }
  539.  
  540. /* Given a network mask, return the number of contiguous 1-bits starting
  541.  * from the most significant bit.
  542.  */
  543. static int
  544. mask2width(mask)
  545. int32 mask;
  546. {
  547.     int width,i;
  548.  
  549.     width = 0;
  550.     for(i = 31;i >= 0;i--){
  551.         if(!(mask & (1L << i)))
  552.             break;
  553.         width++;
  554.     }
  555.     return width;
  556. }
  557.  
  558. /* return buffer with name + comment */
  559. char *
  560. if_name(ifp,comment)
  561. struct iface *ifp;
  562. char *comment;
  563. {
  564.     char *result = mallocw( strlen(ifp->name) + strlen(comment) + 1 );
  565.     strcpy( result, ifp->name );
  566.     return strcat( result, comment );
  567. }
  568.  
  569. /* Raw output routine that tosses all packets. Used by dialer, tip, etc */
  570. int
  571. bitbucket(ifp,bp)
  572. struct iface *ifp;
  573. struct mbuf *bp;
  574. {
  575.     free_p(bp);
  576.     return 0;
  577. }
  578.