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