home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / usr.sbin / htable / htable.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-19  |  12.9 KB  |  620 lines

  1. /*
  2.  * Copyright (c) 1983 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33.  
  34. #ifndef lint
  35. char copyright[] =
  36. "@(#) Copyright (c) 1983 Regents of the University of California.\n\
  37.  All rights reserved.\n";
  38. #endif /* not lint */
  39.  
  40. #ifndef lint
  41. static char sccsid[] = "@(#)htable.c    5.10 (Berkeley) 2/6/91";
  42. #endif /* not lint */
  43.  
  44. /*
  45.  * htable - convert NIC host table into a UNIX format.
  46.  * NIC format is described in RFC 810, 1 March 1982.
  47.  */
  48. #include <stdio.h>
  49. #include <ctype.h>
  50. #include <errno.h>
  51. #include <netdb.h>
  52.  
  53. #include "htable.h"        /* includes <sys/types.h> */
  54.  
  55. #include <sys/socket.h>
  56. #include <arpa/inet.h>
  57. #include <stdlib.h>
  58.  
  59. #define    DATELINES    3    /* these lines usually contain the date */
  60. #define    MAXNETS        30    /* array size for local, connected nets */
  61.  
  62. FILE    *hf;            /* hosts file */
  63. FILE    *gf;            /* gateways file */
  64. FILE    *nf;            /* networks file */
  65. struct gateway *savegateway(), *gatewayto();
  66.  
  67. int connected_nets[MAXNETS];
  68. int nconnected;
  69. int local_nets[MAXNETS];
  70. int nlocal;
  71. char *myname;
  72.  
  73. main(argc, argv)
  74.     int argc;
  75.     char *argv[];
  76. {
  77.     int errs;
  78.  
  79.     infile = "(stdin)";
  80.     myname = argv[0];
  81.     argc--;
  82.     argv++;
  83.     while (argc--) {
  84.         if (*argv[0] == '-') {
  85.             switch (argv[0][1]) {
  86.             case 'c':
  87.                 nconnected = addlocal(argv[1], connected_nets);
  88.                 argv++;
  89.                 argc--;
  90.                 break;
  91.             case 'l':
  92.                 nlocal = addlocal(argv[1], local_nets);
  93.                 argv++;
  94.                 argc--;
  95.                 break;
  96.             default:
  97.                 usage();
  98.                 /*NOTREACHED*/
  99.             }
  100.         } else {
  101.             infile = argv[0];
  102.             if (freopen(infile, "r", stdin) == NULL) {
  103.                 perror(infile);
  104.                 exit(1);
  105.             }
  106.         }
  107.         argv++;
  108.     }
  109.     hf = fopen("hosts", "w");
  110.     if (hf == NULL) {
  111.         perror("hosts");
  112.         exit(1);
  113.     }
  114.     copylocal(hf, "localhosts");
  115.     gf = fopen("gateways", "w");
  116.     if (gf == NULL) {
  117.         perror("gateways");
  118.         exit(1);
  119.     }
  120.     copygateways("localgateways");
  121.     nf = fopen("networks", "w");
  122.     if (nf == NULL) {
  123.         perror("networks");
  124.         exit(1);
  125.     }
  126.     copylocal(nf, "localnetworks");
  127.     copycomments(stdin, hf, DATELINES);
  128.     errs = yyparse();
  129.     dogateways();
  130.     exit(errs);
  131. }
  132.  
  133. usage()
  134. {
  135.     fprintf(stderr,
  136.     "usage: %s [ -c connected-nets ] [-l local-nets ] [ input-file ]\n",
  137.         myname);
  138.     exit(1);
  139. }
  140.  
  141. /*
  142.  *  Turn a comma-separated list of network names or numbers in dot notation
  143.  *  (e.g.  "arpanet, 128.32") into an array of net numbers.
  144.  */
  145. addlocal(arg, nets)
  146.     char *arg;
  147.     int *nets;
  148. {
  149.     register char *p, c;
  150.     register int nfound = 0;
  151.  
  152.     do {
  153.         p = arg;
  154.         while (*p && *p != ',' && !isspace(*p))
  155.             p++;
  156.         c = *p;
  157.         *p = 0;
  158.         while (*arg && isspace(*arg))
  159.             arg++;
  160.         if (*arg == 0)
  161.             continue;
  162.         if (nfound == MAXNETS) {
  163.             fprintf(stderr, "%s: Too many networks in list\n",
  164.                 myname);
  165.             return (nfound);
  166.         }
  167.         if (getnetaddr(arg, &nets[nfound]))
  168.             nfound++;
  169.         else {
  170.             fprintf(stderr, "%s: %s: unknown network\n",
  171.                 myname, arg);
  172.             exit(1);
  173.         }
  174.         arg = p + 1;
  175.     } while (c);
  176.     return (nfound);
  177. }
  178.  
  179. struct name *
  180. newname(str)
  181.     char *str;
  182. {
  183.     char *p;
  184.     struct name *nm;
  185.  
  186.     p = malloc(strlen(str) + 1);
  187.     strcpy(p, str);
  188.     nm = (struct name *)malloc(sizeof (struct name));
  189.     nm->name_val = p;
  190.     nm->name_link = NONAME;
  191.     return (nm);
  192. }
  193.  
  194. char *
  195. lower(str)
  196.     char *str;
  197. {
  198.     register char *cp = str;
  199.  
  200.     while (*cp) {
  201.         if (isupper(*cp))
  202.             *cp = tolower(*cp);
  203.         cp++;
  204.     }
  205.     return (str);
  206. }
  207.  
  208. do_entry(keyword, addrlist, namelist, cputype, opsys, protos)
  209.     int keyword;
  210.     struct addr *addrlist;
  211.     struct name *namelist, *cputype, *opsys, *protos;
  212. {
  213.     register struct addr *al, *al2;
  214.     register struct name *nl;
  215.     struct addr *connect_addr;
  216.     char *cp;
  217.  
  218.     switch (keyword) {
  219.  
  220.     case KW_NET:
  221.         nl = namelist;
  222.         if (nl == NONAME) {
  223.             fprintf(stderr, "htable: net");
  224.             putnet(stderr, inet_netof(addrlist->addr_val));
  225.             fprintf(stderr, " missing names.\n");
  226.             break;
  227.         }
  228.         fprintf(nf, "%-16.16s", lower(nl->name_val));
  229.         al2 = addrlist;
  230.         while (al = al2) {
  231.             char *cp;
  232.  
  233.             putnet(nf, inet_netof(al->addr_val));
  234.             cp = "\t%s";
  235.             while (nl = nl->name_link) {
  236.                 fprintf(nf, cp, lower(nl->name_val));
  237.                 cp = " %s";
  238.             }
  239.             putc('\n', nf);
  240.             al2 = al->addr_link;
  241.             free((char *)al);
  242.         }
  243.         break;
  244.  
  245.     case KW_GATEWAY:
  246.         /* locate locally connected address, if one */
  247.         for (al = addrlist; al; al = al->addr_link)
  248.             if (connectedto(inet_netof(al->addr_val)))
  249.                 break;
  250.         if (al == NULL) {
  251.             /*
  252.              * Not connected to known networks.  Save for later.
  253.              */
  254.             struct gateway *gw, *firstgw = (struct gateway *) NULL;
  255.  
  256.             for (al = addrlist; al; al = al->addr_link) {
  257.                 register int net;
  258.  
  259.                 net = inet_netof(al->addr_val);
  260.                 gw = savegateway(namelist, net,
  261.                     al->addr_val, 0);
  262.                 if (firstgw == (struct gateway *) NULL)
  263.                     firstgw = gw;
  264.                 gw->g_firstent = firstgw;
  265.             }
  266.             freeaddrs(addrlist);
  267.             goto dontfree;
  268.         }
  269.         /*
  270.          * Connected to a known network.
  271.          * Mark this as the gateway to all other networks
  272.          * that are on the addrlist (unless we already have
  273.          * gateways to them).
  274.          */
  275.         connect_addr = al;
  276.         for (al = addrlist; al; al = al->addr_link) {
  277.             register int net;
  278.  
  279.             /* suppress duplicates -- not optimal */
  280.             net = inet_netof(al->addr_val);
  281.             if (connectedto(net) || gatewayto(net))
  282.                 continue;
  283.             printgateway(net, namelist->name_val, 1);
  284.             (void) savegateway(namelist, net, al->addr_val, 1);
  285.         }
  286.         /*
  287.          * Put the gateway in the hosts file.
  288.          */
  289.         putaddr(hf, connect_addr->addr_val);
  290.         cp = "%s";
  291.         for (nl = namelist; nl; nl = nl->name_link) {
  292.             fprintf(hf, cp, lower(nl->name_val));
  293.             cp = " %s";
  294.         }
  295.         fprintf(hf, "\t# gateway\n");
  296.         freeaddrs(addrlist);
  297.         goto dontfree;
  298.  
  299.     case KW_HOST:
  300.         al2 = addrlist;
  301.         while (al = al2) {
  302.             if (!local(inet_netof(al->addr_val))) {
  303.                 char *cp;
  304.  
  305.                 putaddr(hf, al->addr_val);
  306.                 cp = "%s";
  307.                 for (nl = namelist; nl; nl = nl->name_link) {
  308.                     fprintf(hf, cp, lower(nl->name_val));
  309.                     cp = " %s";
  310.                 }
  311.                 putc('\n', hf);
  312.             }
  313.             al2 = al->addr_link;
  314.             free((char *)al);
  315.         }
  316.         break;
  317.  
  318.     default:
  319.         fprintf(stderr, "Unknown keyword: %d.\n", keyword);
  320.     }
  321.     freenames(namelist);
  322. dontfree:
  323.     freenames(protos);
  324. }
  325.  
  326. printgateway(net, name, metric)
  327.     int net;
  328.     char *name;
  329.     int metric;
  330. {
  331.     struct netent *np;
  332.  
  333.     fprintf(gf, "net ");
  334.     np = getnetbyaddr(net, AF_INET);
  335.     if (np)
  336.         fprintf(gf, "%s", np->n_name);
  337.     else
  338.         putnet(gf, net);
  339.     fprintf(gf, " gateway %s metric %d passive\n",
  340.         lower(name), metric);
  341. }
  342.  
  343. copylocal(f, filename)
  344.     FILE *f;
  345.     char *filename;
  346. {
  347.     register FILE *lhf;
  348.     register cc;
  349.     char buf[BUFSIZ];
  350.     extern int errno;
  351.  
  352.     lhf = fopen(filename, "r");
  353.     if (lhf == NULL) {
  354.         if (errno != ENOENT) {
  355.             perror(filename);
  356.             exit(1);
  357.         }
  358.         fprintf(stderr, "Warning, no %s file.\n", filename);
  359.         return;
  360.     }
  361.     while (cc = fread(buf, 1, sizeof(buf), lhf))
  362.         fwrite(buf, 1, cc, f);
  363.     fclose(lhf);
  364. }
  365.  
  366. copygateways(filename)
  367.     char *filename;
  368. {
  369.     register FILE *lhf;
  370.     struct name *nl;
  371.     char type[80];
  372.     char dname[80];
  373.     char gname[80];
  374.     char junk[80];
  375.     char buf[500];
  376.     struct in_addr addr;
  377.     int net, metric;
  378.     extern int errno;
  379.  
  380.     lhf = fopen(filename, "r");
  381.     if (lhf == NULL) {
  382.         if (errno != ENOENT) {
  383.             perror(filename);
  384.             exit(1);
  385.         }
  386.         fprintf(stderr, "Warning, no %s file.\n", filename);
  387.         return;
  388.     }
  389.     /* format: {net | host} XX gateway XX metric DD [passive]\n */
  390.     for (;;) {
  391.         junk[0] = 0;
  392.         if (fgets(buf, sizeof(buf), lhf) == (char *)NULL)
  393.             break;
  394.         fputs(buf, gf);
  395.         if (buf[0] == '#' ||
  396.             sscanf(buf, "%s %s gateway %s metric %d %s",
  397.             type, dname, gname, &metric, junk) < 5)
  398.             continue;
  399.         if (strcmp(type, "net"))
  400.             continue;
  401.         if (!getnetaddr(dname, &net))
  402.             continue;
  403.         if (!gethostaddr(gname, &addr.s_addr))
  404.             continue;
  405.         nl = newname(gname);
  406.         (void) savegateway(nl, net, addr, metric);
  407.     }
  408.     fclose(lhf);
  409. }
  410.  
  411. getnetaddr(name, addr)
  412.     char *name;
  413.     int *addr;
  414. {
  415.     struct netent *np = getnetbyname(name);
  416.  
  417.     if (np == 0) {
  418.         *addr = inet_network(name);
  419.         return (*addr != -1);
  420.     } else {
  421.         if (np->n_addrtype != AF_INET)
  422.             return (0);
  423.         *addr = np->n_net;
  424.         return (1);
  425.     }
  426. }
  427.  
  428. gethostaddr(name, addr)
  429.     char *name;
  430.     u_long *addr;
  431. {
  432.     struct hostent *hp;
  433.  
  434.     hp = gethostbyname(name);
  435.     if (hp) {
  436.         *addr = *(u_long *)(hp->h_addr);
  437.         return (1);
  438.     }
  439.     *addr = inet_addr(name);
  440.     return (*addr != -1);
  441. }
  442.  
  443. copycomments(in, out, ccount)
  444.     FILE *in, *out;
  445.     int ccount;
  446. {
  447.     int count;
  448.     char buf[BUFSIZ], *fgets();
  449.  
  450.     for (count=0; count < ccount; count++) {
  451.         if ((fgets(buf, sizeof(buf), in) == NULL) || (buf[0] != ';'))
  452.             return;
  453.         buf[0] = '#';
  454.         fputs(buf, out);
  455.     }
  456.     return;
  457. }
  458. #define    UC(b)    (((int)(b))&0xff)
  459.  
  460. /*
  461.  * Print network number in internet-standard dot notation;
  462.  * v is in host byte order.
  463.  */
  464. putnet(f, v)
  465.     FILE *f;
  466.     register int v;
  467. {
  468.     if (v < 128)
  469.         fprintf(f, "%d", v);
  470.     else if (v < 65536)
  471.         fprintf(f, "%d.%d", UC(v >> 8), UC(v));
  472.     else
  473.         fprintf(f, "%d.%d.%d", UC(v >> 16), UC(v >> 8), UC(v));
  474. }
  475.  
  476. putaddr(f, v)
  477.     FILE *f;
  478.     struct in_addr v;
  479. {
  480.     fprintf(f, "%-16.16s", inet_ntoa(v));
  481. }
  482.  
  483. freenames(list)
  484.     struct name *list;
  485. {
  486.     register struct name *nl, *nl2;
  487.  
  488.     nl2 = list;
  489.     while (nl = nl2) {
  490.         nl2 = nl->name_link;
  491.         free(nl->name_val);
  492.         free((char *)nl);
  493.     }
  494. }
  495.  
  496. freeaddrs(list)
  497.     struct addr *list;
  498. {
  499.     register struct addr *al, *al2;
  500.  
  501.     al2 = list;
  502.     while (al = al2)
  503.         al2 = al->addr_link, free((char *)al);
  504. }
  505.  
  506. struct gateway *gateways = 0;
  507. struct gateway *lastgateway = 0;
  508.  
  509. struct gateway *
  510. gatewayto(net)
  511.     register int net;
  512. {
  513.     register struct gateway *gp;
  514.  
  515.     for (gp = gateways; gp; gp = gp->g_link)
  516.         if ((gp->g_net == net) && (gp->g_metric > 0))
  517.             return (gp);
  518.     return ((struct gateway *) NULL);
  519. }
  520.  
  521. struct gateway *
  522. savegateway(namelist, net, addr, metric)
  523.     struct name *namelist;
  524.     struct in_addr addr;
  525.     int net, metric;
  526. {
  527.     register struct gateway *gp;
  528.  
  529.     gp = (struct gateway *)malloc(sizeof (struct gateway));
  530.     if (gp == 0) {
  531.         fprintf(stderr, "htable: out of memory\n");
  532.         exit(1);
  533.     }
  534.     gp->g_link = (struct gateway *) NULL;
  535.     if (lastgateway)
  536.         lastgateway->g_link = gp;
  537.     else
  538.         gateways = gp;
  539.     lastgateway = gp;
  540.     gp->g_name = namelist;
  541.     gp->g_net = net;
  542.     gp->g_addr = addr;
  543.     gp->g_metric = metric;
  544.     if (metric == 1)
  545.         gp->g_dst = gp;
  546.     return (gp);
  547. }
  548.  
  549. connectedto(net)
  550.     u_long net;
  551. {
  552.     register i;
  553.  
  554.     for (i = 0; i < nconnected; i++)
  555.         if (connected_nets[i] == net)
  556.             return(1);
  557.     return(0);
  558. }
  559.  
  560. local(net)
  561.     u_long net;
  562. {
  563.     register i;
  564.  
  565.     for (i = 0; i < nlocal; i++)
  566.         if (local_nets[i] == net)
  567.             return(1);
  568.     return(0);
  569. }
  570.  
  571. #define    MAXHOPS    10
  572.  
  573. /*
  574.  * Go through list of gateways, finding connections for gateways
  575.  * that are not yet connected.
  576.  */
  577. dogateways()
  578. {
  579.     register struct gateway *gp, *gw, *ggp;
  580.     register int hops, changed = 1;
  581.     struct name *nl;
  582.     char *cp;
  583.  
  584.     for (hops = 0; hops < MAXHOPS && changed; hops++, changed = 0) {
  585.         for (gp = gateways; gp; gp = gp->g_link)
  586.         if ((gp->g_metric == 0) && (gw = gatewayto(gp->g_net))) {
  587.             /*
  588.              * Found a new connection.
  589.              * For each other network that this gateway is on,
  590.              * add a new gateway to that network.
  591.              */
  592.             changed = 1;
  593.             gp->g_dst = gw->g_dst;
  594.             gp->g_metric = gw->g_metric + 1;
  595.             for (ggp = gp->g_firstent; ggp->g_name == gp->g_name;
  596.             ggp = ggp->g_link) {
  597.                 if (ggp == gp)
  598.                 continue;
  599.                 if (gatewayto(ggp->g_net))
  600.                 continue;
  601.                 ggp->g_dst = gp->g_dst;
  602.                 ggp->g_metric = gp->g_metric;
  603.                 printgateway(ggp->g_net,
  604.                     gw->g_dst->g_name->name_val, gp->g_metric);
  605.             }
  606.             /*
  607.              * Put the gateway in the hosts file,
  608.              * using the address for the connected net.
  609.              */
  610.             putaddr(hf, gp->g_addr);
  611.             cp = "%s";
  612.             for (nl = gp->g_name; nl; nl = nl->name_link) {
  613.                 fprintf(hf, cp, lower(nl->name_val));
  614.                 cp = " %s";
  615.             }
  616.             fprintf(hf, "\t# gateway\n");
  617.         }
  618.     }
  619. }
  620.