18732Ssam #ifndef lint 2*15785Skarels static char sccsid[] = "@(#)htable.c 4.8 (Berkeley) 12/30/83"; 38732Ssam #endif 48732Ssam 58732Ssam /* 68732Ssam * htable - convert NIC host table into a UNIX format. 78732Ssam * NIC format is described in RFC 810, 1 March 1982. 88732Ssam */ 98732Ssam #include <stdio.h> 108732Ssam #include <ctype.h> 119246Ssam #include <errno.h> 1212227Ssam #include <netdb.h> 1312227Ssam 149246Ssam #include "htable.h" /* includes <sys/types.h> */ 158732Ssam 1613193Ssam #include <sys/socket.h> 179246Ssam #include <netinet/in.h> 188732Ssam 1912610Smo #define DATELINES 3 /* these lines usually contain the date */ 2015377Skarels #define MAXNETS 30 /* array size for local, connected nets */ 2112610Smo 229246Ssam FILE *hf; /* hosts file */ 239246Ssam FILE *gf; /* gateways file */ 249246Ssam FILE *nf; /* networks file */ 2515377Skarels struct gateway *savegateway(), *gatewayto(); 269246Ssam 2715377Skarels int connected_nets[MAXNETS]; 2815377Skarels int nconnected; 2915377Skarels int local_nets[MAXNETS]; 3015377Skarels int nlocal; 3115377Skarels char *myname; 3215377Skarels 338732Ssam main(argc, argv) 348732Ssam int argc; 358732Ssam char *argv[]; 368732Ssam { 3715377Skarels int errs; 3815377Skarels 398732Ssam infile = "(stdin)"; 4015377Skarels myname = argv[0]; 4115377Skarels argc--; 4215377Skarels argv++; 4315377Skarels while (argc--) { 4415377Skarels if (*argv[0] == '-') { 4515377Skarels switch (argv[0][1]) { 4615377Skarels case 'c': 4715377Skarels nconnected = addlocal(argv[1], connected_nets); 4815377Skarels argv++; 4915377Skarels argc--; 5015377Skarels break; 5115377Skarels case 'l': 5215377Skarels nlocal = addlocal(argv[1], local_nets); 5315377Skarels argv++; 5415377Skarels argc--; 5515377Skarels break; 5615377Skarels default: 5715377Skarels usage(); 5815377Skarels /*NOTREACHED*/ 5915377Skarels } 6015377Skarels } else { 6115377Skarels infile = argv[0]; 6215377Skarels if (freopen(infile, "r", stdin) == NULL) { 6315377Skarels perror(infile); 6415377Skarels exit(1); 6515377Skarels } 668732Ssam } 6715377Skarels argv++; 688732Ssam } 698732Ssam hf = fopen("hosts", "w"); 708732Ssam if (hf == NULL) { 718732Ssam perror("hosts"); 728732Ssam exit(1); 738732Ssam } 749246Ssam copylocal(hf, "localhosts"); 759246Ssam gf = fopen("gateways", "w"); 769246Ssam if (gf == NULL) { 778732Ssam perror("gateways"); 788732Ssam exit(1); 798732Ssam } 8015377Skarels copygateways(gf, "localgateways"); 819246Ssam nf = fopen("networks", "w"); 829246Ssam if (nf == NULL) { 839246Ssam perror("networks"); 849246Ssam exit(1); 859246Ssam } 869246Ssam copylocal(nf, "localnetworks"); 8712610Smo copycomments(stdin, hf, DATELINES); 8815377Skarels errs = yyparse(); 8915377Skarels dogateways(); 9015377Skarels exit(errs); 918732Ssam } 928732Ssam 9315377Skarels usage() 9415377Skarels { 9515377Skarels fprintf(stderr, 9615377Skarels "usage: %s [ -c connected-nets ] [-l local-nets ] [ input-file ]\n", 9715377Skarels myname); 9815377Skarels exit(1); 9915377Skarels } 10015377Skarels 10115377Skarels /* 10215377Skarels * Turn a comma-separated list of network names or numbers in dot notation 10315377Skarels * (e.g. "arpanet, 128.32") into an array of net numbers. 10415377Skarels */ 10515377Skarels addlocal(arg, nets) 10615377Skarels char *arg; 10715377Skarels int *nets; 10815377Skarels { 10915377Skarels register char *p, c; 11015377Skarels register int nfound = 0; 11115377Skarels 11215377Skarels do { 11315377Skarels p = arg; 11415377Skarels while (*p && *p != ',' && !isspace(*p)) 11515377Skarels p++; 11615377Skarels c = *p; 11715377Skarels *p = 0; 11815377Skarels while (*arg && isspace(*arg)) 11915377Skarels arg++; 12015377Skarels if (*arg == 0) 12115377Skarels continue; 12215377Skarels if (nfound == MAXNETS) { 12315377Skarels fprintf(stderr, "%s: Too many networks in list\n", 12415377Skarels myname); 12515377Skarels return (nfound); 12615377Skarels } 12715377Skarels if (getnetaddr(arg, &nets[nfound])) 12815377Skarels nfound++; 12915377Skarels else { 13015377Skarels fprintf(stderr, "%s: %s: unknown network\n", 13115377Skarels myname, arg); 13215377Skarels exit(1); 13315377Skarels } 13415379Skarels arg = p + 1; 13515377Skarels } while (c); 13615377Skarels return (nfound); 13715377Skarels } 13815377Skarels 1398732Ssam struct name * 1408732Ssam newname(str) 1418732Ssam char *str; 1428732Ssam { 1438732Ssam char *p; 1448732Ssam struct name *nm; 1458732Ssam 1468732Ssam p = malloc(strlen(str) + 1); 1478732Ssam strcpy(p, str); 1489246Ssam nm = (struct name *)malloc(sizeof (struct name)); 1498732Ssam nm->name_val = p; 1508732Ssam nm->name_link = NONAME; 1518732Ssam return (nm); 1528732Ssam } 1538732Ssam 1548732Ssam char * 1558732Ssam lower(str) 1568732Ssam char *str; 1578732Ssam { 1588732Ssam register char *cp = str; 1598732Ssam 1608732Ssam while (*cp) { 1618732Ssam if (isupper(*cp)) 1628732Ssam *cp = tolower(*cp); 1638732Ssam cp++; 1648732Ssam } 1658732Ssam return (str); 1668732Ssam } 1678732Ssam 1688732Ssam do_entry(keyword, addrlist, namelist, cputype, opsys, protos) 1698732Ssam int keyword; 1708732Ssam struct addr *addrlist; 1718732Ssam struct name *namelist, *cputype, *opsys, *protos; 1728732Ssam { 1738732Ssam register struct addr *al, *al2; 1749246Ssam register struct name *nl; 17515377Skarels struct addr *connect_addr; 17615377Skarels char *cp; 1778732Ssam 1788732Ssam switch (keyword) { 1798732Ssam 1808732Ssam case KW_NET: 1819246Ssam nl = namelist; 1829246Ssam if (nl == NONAME) { 1839246Ssam fprintf(stderr, "htable: net"); 1849246Ssam putnet(stderr, addrlist->addr_val); 1859246Ssam fprintf(stderr, " missing names.\n"); 1869246Ssam break; 1879246Ssam } 1889246Ssam fprintf(nf, "%-16.16s", lower(nl->name_val)); 1899246Ssam al2 = addrlist; 1909246Ssam while (al = al2) { 1919246Ssam char *cp; 1928732Ssam 1939246Ssam putnet(nf, al->addr_val); 1949246Ssam cp = "\t%s"; 1959246Ssam while (nl = nl->name_link) { 1969246Ssam fprintf(nf, cp, lower(nl->name_val)); 1979246Ssam cp = " %s"; 1989246Ssam } 1999246Ssam putc('\n', nf); 2009246Ssam al2 = al->addr_link; 2019246Ssam free((char *)al); 2029246Ssam } 20315377Skarels break; 2049246Ssam 2058732Ssam case KW_GATEWAY: 20615377Skarels /* locate locally connected address, if one */ 20715377Skarels for (al = addrlist; al; al = al->addr_link) 20815377Skarels if (connectedto(inet_netof(al->addr_val))) 20915377Skarels break; 21015377Skarels if (al == NULL) { 21115377Skarels /* 21215377Skarels * Not connected to known networks. Save for later. 21315377Skarels */ 21415377Skarels struct gateway *gw, *firstgw = (struct gateway *) NULL; 21515377Skarels 21615377Skarels for (al = addrlist; al; al = al->addr_link) { 21715377Skarels register int net; 21815377Skarels 21915377Skarels net = inet_netof(al->addr_val); 22015377Skarels gw = savegateway(namelist, net, 22115377Skarels al->addr_val, 0); 22215377Skarels if (firstgw == (struct gateway *) NULL) 22315377Skarels firstgw = gw; 22415377Skarels gw->g_firstent = firstgw; 22515377Skarels } 22615377Skarels freeaddrs(addrlist); 22715377Skarels goto dontfree; 22815377Skarels } 22912227Ssam /* 23015377Skarels * Connected to a known network. 23115377Skarels * Mark this as the gateway to all other networks 23215377Skarels * that are on the addrlist (unless we already have 23315377Skarels * gateways to them). 23412227Ssam */ 23515377Skarels connect_addr = al; 23615377Skarels for (al = addrlist; al; al = al->addr_link) { 23712227Ssam register int net; 2389246Ssam 23915377Skarels if (al == connect_addr) 24012227Ssam continue; 2419246Ssam /* suppress duplicates -- not optimal */ 24212227Ssam net = inet_netof(al->addr_val); 24315377Skarels if (gatewayto(net)) 24415377Skarels continue; 24515377Skarels printgateway(net, namelist->name_val, 1); 24615377Skarels (void) savegateway(namelist, net, al->addr_val, 1); 24712227Ssam } 24815377Skarels /* 24915377Skarels * Put the gateway in the hosts file. 25015377Skarels */ 25115377Skarels putaddr(hf, connect_addr->addr_val); 25215377Skarels cp = "%s"; 25315377Skarels for (nl = namelist; nl; nl = nl->name_link) { 25415377Skarels fprintf(hf, cp, lower(nl->name_val)); 25515377Skarels cp = " %s"; 2569246Ssam } 25715377Skarels fprintf(hf, "\t# gateway\n"); 25815377Skarels freeaddrs(addrlist); 25915377Skarels goto dontfree; 2608732Ssam 2618732Ssam case KW_HOST: 2629246Ssam al2 = addrlist; 2639246Ssam while (al = al2) { 26415377Skarels if (!local(inet_netof(al->addr_val))) { 2659246Ssam char *cp; 2669246Ssam 2679246Ssam putaddr(hf, al->addr_val); 2689246Ssam cp = "%s"; 2699246Ssam for (nl = namelist; nl; nl = nl->name_link) { 2709246Ssam fprintf(hf, cp, lower(nl->name_val)); 2719246Ssam cp = " %s"; 2729246Ssam } 2738732Ssam putc('\n', hf); 2748732Ssam } 2758732Ssam al2 = al->addr_link; 2769246Ssam free((char *)al); 2778732Ssam } 27815377Skarels break; 2798732Ssam 2808732Ssam default: 2818732Ssam fprintf(stderr, "Unknown keyword: %d.\n", keyword); 2828732Ssam } 2839246Ssam freenames(namelist); 28415377Skarels dontfree: 2859246Ssam freenames(protos); 2868732Ssam } 2878732Ssam 28815377Skarels printgateway(net, name, metric) 28915377Skarels int net; 29015377Skarels char *name; 29115377Skarels int metric; 29215377Skarels { 29315377Skarels struct netent *np; 29415377Skarels 29515377Skarels fprintf(gf, "net "); 29615377Skarels np = getnetbyaddr(net, AF_INET); 29715377Skarels if (np) 29815377Skarels fprintf(gf, "%s", np->n_name); 29915377Skarels else 30015377Skarels putnet(gf, net); 30115377Skarels fprintf(gf, " gateway %s metric %d passive\n", 30215377Skarels lower(name), metric); 30315377Skarels } 30415377Skarels 3059246Ssam copylocal(f, filename) 3069246Ssam FILE *f; 3079246Ssam char *filename; 3088732Ssam { 3098732Ssam register FILE *lhf; 3108732Ssam register cc; 3118732Ssam char buf[BUFSIZ]; 3129246Ssam extern int errno; 3138732Ssam 3149246Ssam lhf = fopen(filename, "r"); 3158732Ssam if (lhf == NULL) { 3169246Ssam if (errno != ENOENT) { 3179246Ssam perror(filename); 3189246Ssam exit(1); 3199246Ssam } 3209246Ssam fprintf(stderr, "Warning, no %s file.\n", filename); 3218732Ssam return; 3228732Ssam } 3238732Ssam while (cc = fread(buf, 1, sizeof(buf), lhf)) 3249246Ssam fwrite(buf, 1, cc, f); 3258732Ssam fclose(lhf); 3268732Ssam } 3279246Ssam 32815377Skarels copygateways(f, filename) 32915377Skarels FILE *f; 33015377Skarels char *filename; 33115377Skarels { 33215377Skarels register FILE *lhf; 33315377Skarels register cc; 33415377Skarels struct name *nl; 33515377Skarels char type[80]; 33615377Skarels char dname[80]; 33715377Skarels char gname[80]; 33815377Skarels char junk[80]; 33915377Skarels u_long addr; 34015377Skarels int net, metric; 34115377Skarels extern int errno; 34215377Skarels 34315377Skarels lhf = fopen(filename, "r"); 34415377Skarels if (lhf == NULL) { 34515377Skarels if (errno != ENOENT) { 34615377Skarels perror(filename); 34715377Skarels exit(1); 34815377Skarels } 34915377Skarels fprintf(stderr, "Warning, no %s file.\n", filename); 35015377Skarels return; 35115377Skarels } 35215377Skarels /* format: {net | host} XX gateway XX metric DD [passive]\n */ 35315377Skarels #define readentry(fp) \ 35415377Skarels fscanf((fp), "%s %s gateway %s metric %d %s\n", \ 35515377Skarels type, dname, gname, &metric, junk) 35615377Skarels while (readentry(lhf) != EOF) { 35715377Skarels if (strcmp(type, "net")) 35815377Skarels goto dumpit; 35915377Skarels if (!getnetaddr(dname, &net)) 36015377Skarels goto dumpit; 36115377Skarels if (!gethostaddr(gname, &addr)) 36215377Skarels goto dumpit; 36315377Skarels nl = newname(gname); 36415377Skarels (void) savegateway(nl, net, addr, metric); 36515377Skarels dumpit: 36615377Skarels fprintf(gf, "%s %s gateway %s metric %d %s\n", 36715377Skarels type, dname, gname, metric, junk); 36815377Skarels } 36915377Skarels fclose(lhf); 37015377Skarels } 37115377Skarels 37215377Skarels getnetaddr(name, addr) 37315377Skarels char *name; 37415377Skarels int *addr; 37515377Skarels { 37615377Skarels struct netent *np = getnetbyname(name); 37715377Skarels int n; 37815377Skarels 37915377Skarels if (np == 0) { 38015377Skarels *addr = inet_network(name); 38115377Skarels return (*addr != -1); 38215377Skarels } else { 38315377Skarels if (np->n_addrtype != AF_INET) 38415377Skarels return (0); 38515377Skarels *addr = np->n_net; 38615377Skarels return (1); 38715377Skarels } 38815377Skarels } 38915377Skarels 39015377Skarels gethostaddr(name, addr) 39115377Skarels char *name; 39215377Skarels u_long *addr; 39315377Skarels { 39415377Skarels struct hostent *hp; 39515377Skarels 39615377Skarels hp = gethostbyname(name); 39715377Skarels if (hp) { 39815377Skarels *addr = *(u_long *)(hp->h_addr); 39915377Skarels return (1); 40015377Skarels } 40115377Skarels *addr = inet_addr(name); 40215377Skarels return (*addr != -1); 40315377Skarels } 40415377Skarels 40512610Smo copycomments(in, out, ccount) 40612610Smo FILE *in, *out; 40712610Smo int ccount; 40812610Smo { 40912610Smo char buf[BUFSIZ]; 41012610Smo int length; 41112610Smo int count; 41212610Smo char *fgets(); 41312610Smo 41412610Smo for (count=0; count < ccount; count++) { 41512610Smo if ((fgets(buf, sizeof(buf), in) == NULL) || (buf[0] != ';')) 41612610Smo return; 41712610Smo buf[0] = '#'; 41812610Smo fputs(buf, out); 41912610Smo } 42012610Smo return; 42112610Smo } 4229246Ssam #define UC(b) (((int)(b))&0xff) 4239246Ssam 424*15785Skarels /* 425*15785Skarels * Print network number in internet-standard dot notation; 426*15785Skarels * v is in host byte order. 427*15785Skarels */ 4289246Ssam putnet(f, v) 4299246Ssam FILE *f; 4309246Ssam u_long v; 4319246Ssam { 432*15785Skarels if (v < 128) 433*15785Skarels fprintf(f, "%d", v); 434*15785Skarels else if (v < 65536) 435*15785Skarels fprintf(f, "%d.%d", (v >> 8) & 0xff, v & 0xff); 4369246Ssam else 437*15785Skarels fprintf(f, "%d.%d.%d", (v >> 16) & 0xff, 438*15785Skarels (v >> 8) & 0xff, v & 0xff); 4399246Ssam } 4409246Ssam 4419246Ssam putaddr(f, v) 4429246Ssam FILE *f; 4439246Ssam u_long v; 4449246Ssam { 4459246Ssam register char *a = (char *)&v; 4469246Ssam char buf[32]; 4479246Ssam 4489246Ssam sprintf(buf,"%d.%d.%d.%d", UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3])); 4499246Ssam fprintf(f, "%-16.16s", buf); 4509246Ssam } 4519246Ssam 4529246Ssam freenames(list) 4539246Ssam struct name *list; 4549246Ssam { 4559246Ssam register struct name *nl, *nl2; 4569246Ssam 4579246Ssam nl2 = list; 4589246Ssam while (nl = nl2) { 4599246Ssam nl2 = nl->name_link; 4609246Ssam free(nl->name_val); 4619246Ssam free((char *)nl); 4629246Ssam } 4639246Ssam } 4649246Ssam 46515377Skarels freeaddrs(list) 46615377Skarels struct addr *list; 46715377Skarels { 46815377Skarels register struct addr *al, *al2; 46915377Skarels 47015377Skarels al2 = list; 47115377Skarels while (al = al2) 47215377Skarels al2 = al->addr_link, free((char *)al); 47315377Skarels } 47415377Skarels 4759246Ssam struct gateway *gateways = 0; 47615377Skarels struct gateway *lastgateway = 0; 4779246Ssam 47815377Skarels struct gateway * 47915377Skarels gatewayto(net) 4809246Ssam register int net; 4819246Ssam { 4829246Ssam register struct gateway *gp; 4839246Ssam 4849246Ssam for (gp = gateways; gp; gp = gp->g_link) 48515377Skarels if ((gp->g_net == net) && (gp->g_metric > 0)) 48615377Skarels return (gp); 48715377Skarels return ((struct gateway *) NULL); 4889246Ssam } 4899246Ssam 49015377Skarels struct gateway * 49115377Skarels savegateway(namelist, net, addr, metric) 49215377Skarels struct name *namelist; 49315377Skarels u_long addr; 49415377Skarels int net, metric; 4959246Ssam { 4969246Ssam register struct gateway *gp; 4979246Ssam 4989246Ssam gp = (struct gateway *)malloc(sizeof (struct gateway)); 4999246Ssam if (gp == 0) { 5009246Ssam fprintf(stderr, "htable: out of memory\n"); 5019246Ssam exit(1); 5029246Ssam } 50315377Skarels gp->g_link = (struct gateway *) NULL; 50415377Skarels if (lastgateway) 50515377Skarels lastgateway->g_link = gp; 50615377Skarels else 50715377Skarels gateways = gp; 50815377Skarels lastgateway = gp; 50915377Skarels gp->g_name = namelist; 5109246Ssam gp->g_net = net; 51115377Skarels gp->g_addr = addr; 51215377Skarels gp->g_metric = metric; 51315377Skarels if (metric == 1) 51415377Skarels gp->g_dst = gp; 5159246Ssam } 51615377Skarels 51715377Skarels connectedto(net) 51815377Skarels u_long net; 51915377Skarels { 52015377Skarels register i; 52115377Skarels 52215377Skarels for (i = 0; i < nconnected; i++) 52315377Skarels if (connected_nets[i] == net) 52415377Skarels return(1); 52515377Skarels return(0); 52615377Skarels } 52715377Skarels 52815377Skarels local(net) 52915377Skarels u_long net; 53015377Skarels { 53115377Skarels register i; 53215377Skarels 53315377Skarels for (i = 0; i < nlocal; i++) 53415377Skarels if (local_nets[i] == net) 53515377Skarels return(1); 53615377Skarels return(0); 53715377Skarels } 53815377Skarels 53915377Skarels #define MAXHOPS 10 54015377Skarels 54115377Skarels /* 54215377Skarels * Go through list of gateways, finding connections for gateways 54315377Skarels * that are not yet connected. 54415377Skarels */ 54515377Skarels dogateways() 54615377Skarels { 54715377Skarels register struct gateway *gp, *gw, *ggp; 54815377Skarels register int hops, changed = 1; 54915377Skarels struct name *nl; 55015377Skarels char *cp; 55115377Skarels 55215377Skarels for (hops = 0; hops < MAXHOPS && changed; hops++, changed = 0) { 55315377Skarels for (gp = gateways; gp; gp = gp->g_link) 55415377Skarels if ((gp->g_metric == 0) && (gw = gatewayto(gp->g_net))) { 55515377Skarels /* 55615377Skarels * Found a new connection. 55715377Skarels * For each other network that this gateway is on, 55815377Skarels * add a new gateway to that network. 55915377Skarels */ 56015377Skarels changed = 1; 56115377Skarels gp->g_dst = gw->g_dst; 56215377Skarels gp->g_metric = gw->g_metric + 1; 56315377Skarels for (ggp = gp->g_firstent; ggp->g_name == gp->g_name; 56415377Skarels ggp = ggp->g_link) { 56515377Skarels if (ggp == gp) 56615377Skarels continue; 56715377Skarels if (gatewayto(ggp->g_net)) 56815377Skarels continue; 56915377Skarels ggp->g_dst = gp->g_dst; 57015377Skarels ggp->g_metric = gp->g_metric; 57115377Skarels printgateway(ggp->g_net, 57215377Skarels gw->g_dst->g_name->name_val, gp->g_metric); 57315377Skarels } 57415377Skarels /* 57515377Skarels * Put the gateway in the hosts file, 57615377Skarels * using the address for the connected net. 57715377Skarels */ 57815377Skarels putaddr(hf, gp->g_addr); 57915377Skarels cp = "%s"; 58015377Skarels for (nl = gp->g_name; nl; nl = nl->name_link) { 58115377Skarels fprintf(hf, cp, lower(nl->name_val)); 58215377Skarels cp = " %s"; 58315377Skarels } 58415377Skarels fprintf(hf, "\t# gateway\n"); 58515377Skarels } 58615377Skarels } 58715377Skarels } 588