home *** CD-ROM | disk | FTP | other *** search
/ High Voltage Shareware / high1.zip / high1 / DIR3 / KA9Q212.ZIP / IFACE.C < prev    next >
C/C++ Source or Header  |  1993-07-16  |  11KB  |  501 lines

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