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