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