home *** CD-ROM | disk | FTP | other *** search
/ HAM Radio 3 / hamradioversion3.0examsandprograms1992.iso / packet / n17jsrc / iface.c < prev    next >
C/C++ Source or Header  |  1991-06-24  |  11KB  |  487 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.  
  17. static void showiface __ARGS((struct iface *ifp));
  18. static int mask2width __ARGS((int32 mask));
  19. static int ifipaddr __ARGS((int argc,char *argv[],void *p));
  20. static int iflinkadr __ARGS((int argc,char *argv[],void *p));
  21. static int ifbroad __ARGS((int argc,char *argv[],void *p));
  22. static int ifnetmsk __ARGS((int argc,char *argv[],void *p));
  23. static int ifrxbuf __ARGS((int argc,char *argv[],void *p));
  24. static int ifmtu __ARGS((int argc,char *argv[],void *p));
  25. static int ifforw __ARGS((int argc,char *argv[],void *p));
  26. static int ifencap __ARGS((int argc,char *argv[],void *p));
  27.  
  28. /* Interface list header */
  29. struct iface *Ifaces = &Loopback;
  30.  
  31. /* Loopback pseudo-interface */
  32. struct iface Loopback = {
  33.     &Encap,        /* Link to next entry */
  34.     "loopback",    /* name        */
  35.     CL_NONE,    /* type        */
  36.     &Iftypes[0],    /* iftype    */
  37.     0x7f000001L,    /* addr        127.0.0.1 */
  38.     0xffffffffL,    /* broadcast    255.255.255.255 */
  39.     0xffffffffL,    /* netmask    255.255.255.255 */
  40.     NULL,        /* (*ioctl)    */
  41.     NULLFP,        /* (*iostatus)    */
  42.     NULLFP,        /* (*send)    */
  43.     NULLFP,        /* (*output)    */
  44.     NULLFP,        /* (*raw)    */
  45.     NULLFP,        /* (*stop)    */
  46.     NULLFP,        /* (*status)    */
  47.     MAXINT16,    /* mtu        No limit */
  48.     0,        /* dev        */
  49.     0,        /* xdev        */
  50.     0,        /* port        */
  51.     0,        /* flags    */
  52.     0,        /* trace    */
  53.     NULLCHAR,    /* trfile    */
  54.     NULLFILE,    /* trfp        */
  55.     NULLCHAR,    /* hwaddr    */
  56.     NULLIF,        /* forw        */
  57.     0,        /* ipsndcnt    */
  58.     0,        /* rawsndcnt    */
  59.     0,        /* iprcvcnt    */
  60.     0,        /* rawrcvcnt    */
  61.     0,        /* lastsent    */
  62.     0,        /* lastrecv    */
  63.     NULLPROC,    /* rxproc    */
  64.     NULLPROC,    /* txproc    */
  65.     NULLPROC,    /* supv        */
  66.     NULL,        /* extension    */
  67.     NULLFP,        /* (*discard)    */
  68.     NULLFP,        /* (*echo)      */
  69. };
  70. /* Encapsulation pseudo-interface */
  71. struct iface Encap = {
  72.     NULLIF,
  73.     "encap",    /* name        */
  74.     CL_NONE,    /* type        */
  75.     &Iftypes[0],    /* iftype    */
  76.     INADDR_ANY,    /* addr        0.0.0.0 */
  77.     0xffffffffL,    /* broadcast    255.255.255.255 */
  78.     0xffffffffL,    /* netmask    255.255.255.255 */
  79.     NULL,        /* (*ioctl)    */
  80.     NULLFP,        /* (*iostatus)    */
  81.     ip_encap,    /* (*send)    */
  82.     NULLFP,        /* (*output)    */
  83.     NULLFP,        /* (*raw)    */
  84.     NULLFP,        /* (*stop)    */
  85.     NULLFP,        /* (*status)    */
  86.     MAXINT16,    /* mtu        No limit */
  87.     0,        /* dev        */
  88.     0,        /* xdev        */
  89.     0,        /* port        */
  90.     0,        /* flags    */
  91.     0,        /* trace    */
  92.     NULLCHAR,    /* trfile    */
  93.     NULLFILE,    /* trfp        */
  94.     NULLCHAR,    /* hwaddr    */
  95.     NULLIF,        /* forw        */
  96.     0,        /* ipsndcnt    */
  97.     0,        /* rawsndcnt    */
  98.     0,        /* iprcvcnt    */
  99.     0,        /* rawrcvcnt    */
  100.     0,        /* lastsent    */
  101.     0,        /* lastrecv    */
  102.     NULLPROC,    /* rxproc    */
  103.     NULLPROC,    /* txproc    */
  104.     NULLPROC,    /* supv        */
  105.     NULL,        /* extension    */
  106.     NULLFP,        /* (*discard)    */
  107.     NULLFP,        /* (*echo)      */
  108. };
  109.  
  110. char Noipaddr[] = "IP address field missing, and ip address not set\n";
  111.  
  112. struct cmds Ifcmds[] = {
  113.     "broadcast",        ifbroad,    0,    2,    NULLCHAR,
  114.     "encapsulation",    ifencap,    0,    2,    NULLCHAR,
  115.     "forward",        ifforw,        0,    2,    NULLCHAR,
  116.     "ipaddress",        ifipaddr,    0,    2,    NULLCHAR,
  117.     "linkaddress",        iflinkadr,    0,    2,    NULLCHAR,
  118.     "mtu",            ifmtu,        0,    2,    NULLCHAR,
  119.     "netmask",        ifnetmsk,    0,    2,    NULLCHAR,
  120.     "rxbuf",        ifrxbuf,    0,    2,    NULLCHAR,
  121.     NULLCHAR,
  122. };
  123.  
  124. /* Set interface parameters */
  125. int
  126. doifconfig(argc,argv,p)
  127. int argc;
  128. char *argv[];
  129. void *p;
  130. {
  131.     struct iface *ifp;
  132.     int i;
  133.  
  134.     if(argc < 2){
  135.         for(ifp = Ifaces;ifp != NULLIF;ifp = ifp->next)
  136.             showiface(ifp);
  137.         return 0;
  138.     }
  139.     if((ifp = if_lookup(argv[1])) == NULLIF){
  140.         tprintf("Interface %s unknown\n",argv[1]);
  141.         return 1;
  142.     }
  143.     if(argc == 2){
  144.         showiface(ifp);
  145.         if ( ifp->status != NULLFP ) {
  146.             (*ifp->status)(ifp);
  147.         }
  148.         return 0;
  149.     }
  150.     if(argc == 3){
  151.         tprintf("Argument missing\n");
  152.         return 1;
  153.     }
  154.     for(i=2;i<argc-1;i+=2)
  155.         subcmd(Ifcmds,3,&argv[i-1],ifp);
  156.  
  157.     return 0;
  158. }
  159.  
  160. /* Set interface IP address */
  161. static int
  162. ifipaddr(argc,argv,p)
  163. int argc;
  164. char *argv[];
  165. void *p;
  166. {
  167.     struct iface *ifp = p;
  168.  
  169.     ifp->addr = resolve(argv[1]);
  170.     return 0;
  171. }
  172.  
  173.  
  174. /* Set link (hardware) address */
  175. static int
  176. iflinkadr(argc,argv,p)
  177. int argc;
  178. char *argv[];
  179. void *p;
  180. {
  181.     struct iface *ifp = p;
  182.  
  183.     if(ifp->iftype == NULLIFT || ifp->iftype->scan == NULL){
  184.         tprintf("Can't set link address\n");
  185.         return 1;
  186.     }
  187.     if(ifp->hwaddr != NULLCHAR)
  188.         free(ifp->hwaddr);
  189.     ifp->hwaddr = mallocw(ifp->iftype->hwalen);
  190.     (*ifp->iftype->scan)(ifp->hwaddr,argv[1]);
  191.     return 0;
  192. }
  193.  
  194. /* Set interface broadcast address. This is actually done
  195.  * by installing a private entry in the routing table.
  196.  */
  197. static int
  198. ifbroad(argc,argv,p)
  199. int argc;
  200. char *argv[];
  201. void *p;
  202. {
  203.     struct iface *ifp = p;
  204.     struct route *rp;
  205.  
  206.     rp = rt_blookup(ifp->broadcast,32);
  207.     if(rp != NULLROUTE && rp->iface == ifp)
  208.         rt_drop(ifp->broadcast,32);
  209.     ifp->broadcast = resolve(argv[1]);
  210.     rt_add(ifp->broadcast,32,0L,ifp,1L,0L,1);
  211.     return 0;
  212. }
  213.  
  214. /* Set the network mask. This is actually done by installing
  215.  * a routing entry.
  216.  */
  217. static int
  218. ifnetmsk(argc,argv,p)
  219. int argc;
  220. char *argv[];
  221. void *p;
  222. {
  223.     struct iface *ifp = p;
  224.     struct route *rp;
  225.  
  226.     /* Remove old entry if it exists */
  227.     rp = rt_blookup(ifp->addr & ifp->netmask,mask2width(ifp->netmask));
  228.     if(rp != NULLROUTE)
  229.         rt_drop(rp->target,rp->bits);
  230.  
  231.     ifp->netmask = htol(argv[1]);
  232.     rt_add(ifp->addr,mask2width(ifp->netmask),0L,ifp,0L,0L,0);
  233.     return 0;
  234. }
  235.  
  236. /* Command to set interface encapsulation mode */
  237. static int
  238. ifencap(argc,argv,p)
  239. int argc;
  240. char *argv[];
  241. void *p;
  242. {
  243.     struct iface *ifp = p;
  244.  
  245.     if(setencap(ifp,argv[1]) != 0){
  246.         tprintf("Encapsulation mode '%s' unknown\n",argv[1]);
  247.         return 1;
  248.     }
  249.     return 0;
  250. }
  251. /* Function to set encapsulation mode */
  252. int
  253. setencap(ifp,mode)
  254. struct iface *ifp;
  255. char *mode;
  256. {
  257.     struct iftype *ift;
  258.  
  259.     for(ift = &Iftypes[0];ift->name != NULLCHAR;ift++)
  260.         if(strnicmp(ift->name,mode,strlen(mode)) == 0)
  261.             break;
  262.     if(ift->name == NULLCHAR){
  263.         return -1;
  264.     }
  265.     ifp->iftype = ift;
  266.     ifp->send = ift->send;
  267.     ifp->output = ift->output;
  268.     ifp->type = ift->type;
  269.     return 0;
  270. }
  271. /* Set interface receive buffer size */
  272. static int
  273. ifrxbuf(argc,argv,p)
  274. int argc;
  275. char *argv[];
  276. void *p;
  277. {
  278.     return 0;    /* To be written */
  279. }
  280.  
  281. /* Set interface Maximum Transmission Unit */
  282. static int
  283. ifmtu(argc,argv,p)
  284. int argc;
  285. char *argv[];
  286. void *p;
  287. {
  288.     struct iface *ifp = p;
  289.  
  290.     ifp->mtu = atoi(argv[1]);
  291.     return 0;
  292. }
  293.  
  294. /* Set interface forwarding */
  295. static int
  296. ifforw(argc,argv,p)
  297. int argc;
  298. char *argv[];
  299. void *p;
  300. {
  301.     struct iface *ifp = p;
  302.  
  303.     ifp->forw = if_lookup(argv[1]);
  304.     if(ifp->forw == ifp)
  305.         ifp->forw = NULLIF;
  306.     return 0;
  307. }
  308.  
  309. /* Display the parameters for a specified interface */
  310. static void
  311. showiface(ifp)
  312. register struct iface *ifp;
  313. {
  314.     char tmp[25];
  315.  
  316.     tprintf("%-10s IP addr %s MTU %u Link encap ",ifp->name,
  317.      inet_ntoa(ifp->addr),(int)ifp->mtu);
  318.     if(ifp->iftype == NULLIFT){
  319.         tprintf("not set\n");
  320.     } else {
  321.         tprintf("%s\n",ifp->iftype->name);
  322.         if(ifp->iftype->format != NULL && ifp->hwaddr != NULLCHAR)
  323.             tprintf("           Link addr %s\n",
  324.              (*ifp->iftype->format)(tmp,ifp->hwaddr));
  325.     }
  326.     tprintf("           flags %u trace 0x%x netmask 0x%08lx broadcast %s\n",
  327.         ifp->flags,ifp->trace,ifp->netmask,inet_ntoa(ifp->broadcast));
  328.     if(ifp->forw != NULLIF)
  329.         tprintf("           output forward to %s\n",ifp->forw->name);
  330.     tprintf("           sent: ip %lu tot %lu idle %s\n",
  331.      ifp->ipsndcnt,ifp->rawsndcnt,tformat(secclock() - ifp->lastsent));
  332.     tprintf("           recv: ip %lu tot %lu idle %s\n",
  333.      ifp->iprecvcnt,ifp->rawrecvcnt,tformat(secclock() - ifp->lastrecv));
  334. }
  335.  
  336. /* Command to detach an interface */
  337. int
  338. dodetach(argc,argv,p)
  339. int argc;
  340. char *argv[];
  341. void *p;
  342. {
  343.     register struct iface *ifp;
  344.  
  345.     if((ifp = if_lookup(argv[1])) == NULLIF){
  346.         tprintf("Interface %s unknown\n",argv[1]);
  347.         return 1;
  348.     }
  349.     if(if_detach(ifp) == -1)
  350.         tprintf("Can't detach loopback or encap interface\n");
  351.     return 0;
  352. }
  353. /* Detach a specified interface */
  354. int
  355. if_detach(ifp)
  356. register struct iface *ifp;
  357. {
  358.     struct iface *iftmp;
  359.     struct route *rp,*rptmp;
  360.     int i,j;
  361.  
  362.     if(ifp == &Loopback || ifp == &Encap)
  363.         return -1;
  364.  
  365.     /* Drop all routes that point to this interface */
  366.     if(R_default.iface == ifp)
  367.         rt_drop(0L,0);    /* Drop default route */
  368.  
  369.     for(i=0;i<HASHMOD;i++){
  370.         for(j=0;j<32;j++){
  371.             for(rp = Routes[j][i];rp != NULLROUTE;rp = rptmp){
  372.                 /* Save next pointer in case we delete this entry */
  373.                 rptmp = rp->next;
  374.                 if(rp->iface == ifp)
  375.                     rt_drop(rp->target,rp->bits);
  376.             }
  377.         }
  378.     }
  379.     /* Unforward any other interfaces forwarding to this one */
  380.     for(iftmp = Ifaces;iftmp != NULLIF;iftmp = iftmp->next){
  381.         if(iftmp->forw == ifp)
  382.             iftmp->forw = NULLIF;
  383.     }
  384.  
  385.     /* Call device shutdown routine, if any */
  386.     if(ifp->stop != NULLFP)
  387.         (*ifp->stop)(ifp);
  388.  
  389.     killproc(ifp->rxproc);
  390.     killproc(ifp->txproc);
  391.     killproc(ifp->supv);
  392.  
  393.     /* Free allocated memory associated with this interface */
  394.     if(ifp->name != NULLCHAR)
  395.         free(ifp->name);
  396.     if(ifp->hwaddr != NULLCHAR)
  397.         free(ifp->hwaddr);
  398.  
  399.     /* Remove from interface list */
  400.     if(ifp == Ifaces){
  401.         Ifaces = ifp->next;
  402.     } else {
  403.         /* Search for entry just before this one
  404.          * (necessary because list is only singly-linked.)
  405.          */
  406.         for(iftmp = Ifaces;iftmp != NULLIF ;iftmp = iftmp->next)
  407.             if(iftmp->next == ifp)
  408.                 break;
  409.         if(iftmp != NULLIF && iftmp->next == ifp)
  410.             iftmp->next = ifp->next;
  411.     }
  412.     /* Finally free the structure itself */
  413.     free((char *)ifp);
  414.     return 0;
  415. }
  416.  
  417. /* Given the ascii name of an interface, return a pointer to the structure,
  418.  * or NULLIF if it doesn't exist
  419.  */
  420. struct iface *
  421. if_lookup(name)
  422. char *name;
  423. {
  424.     register struct iface *ifp;
  425.  
  426.     for(ifp = Ifaces; ifp != NULLIF; ifp = ifp->next)
  427.         if(strcmp(ifp->name,name) == 0)
  428.             break;
  429.     return ifp;
  430. }
  431.  
  432. /* Return iface pointer if 'addr' belongs to one of our interfaces,
  433.  * NULLIF otherwise.
  434.  * This is used to tell if an incoming IP datagram is for us, or if it
  435.  * has to be routed.
  436.  */
  437. struct iface *
  438. ismyaddr(addr)
  439. int32 addr;
  440. {
  441.     register struct iface *ifp;
  442.  
  443.     for(ifp = Ifaces; ifp != NULLIF; ifp = ifp->next)
  444.         if(addr == ifp->addr)
  445.             break;
  446.     return ifp;
  447. }
  448.  
  449. /* Given a network mask, return the number of contiguous 1-bits starting
  450.  * from the most significant bit.
  451.  */
  452. static int
  453. mask2width(mask)
  454. int32 mask;
  455. {
  456.     int width,i;
  457.  
  458.     width = 0;
  459.     for(i = 31;i >= 0;i--){
  460.         if(!(mask & (1L << i)))
  461.             break;
  462.         width++;
  463.     }
  464.     return width;
  465. }
  466.  
  467. /* return buffer with name + comment */
  468. char *
  469. if_name(ifp,comment)
  470. struct iface *ifp;
  471. char *comment;
  472. {
  473.     char *result = mallocw( strlen(ifp->name) + strlen(comment) + 1 );
  474.     strcpy( result, ifp->name );
  475.     return strcat( result, comment );
  476. }
  477.  
  478. /* Raw output routine that tosses all packets. Used by dialer, tip, etc */
  479. int
  480. bitbucket(ifp,bp)
  481. struct iface *ifp;
  482. struct mbuf *bp;
  483. {
  484.     free_p(bp);
  485.     return 0;
  486. }
  487.