18732Ssam #ifndef lint 2*16024Skarels static char sccsid[] = "@(#)htable.c 4.10 (Berkeley) 02/09/84"; 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"); 18415789Skarels putnet(stderr, inet_netof(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 19315789Skarels putnet(nf, inet_netof(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 2399246Ssam /* suppress duplicates -- not optimal */ 24012227Ssam net = inet_netof(al->addr_val); 241*16024Skarels if (connectedto(net) || gatewayto(net)) 24215377Skarels continue; 24315377Skarels printgateway(net, namelist->name_val, 1); 24415377Skarels (void) savegateway(namelist, net, al->addr_val, 1); 24512227Ssam } 24615377Skarels /* 24715377Skarels * Put the gateway in the hosts file. 24815377Skarels */ 24915377Skarels putaddr(hf, connect_addr->addr_val); 25015377Skarels cp = "%s"; 25115377Skarels for (nl = namelist; nl; nl = nl->name_link) { 25215377Skarels fprintf(hf, cp, lower(nl->name_val)); 25315377Skarels cp = " %s"; 2549246Ssam } 25515377Skarels fprintf(hf, "\t# gateway\n"); 25615377Skarels freeaddrs(addrlist); 25715377Skarels goto dontfree; 2588732Ssam 2598732Ssam case KW_HOST: 2609246Ssam al2 = addrlist; 2619246Ssam while (al = al2) { 26215377Skarels if (!local(inet_netof(al->addr_val))) { 2639246Ssam char *cp; 2649246Ssam 2659246Ssam putaddr(hf, al->addr_val); 2669246Ssam cp = "%s"; 2679246Ssam for (nl = namelist; nl; nl = nl->name_link) { 2689246Ssam fprintf(hf, cp, lower(nl->name_val)); 2699246Ssam cp = " %s"; 2709246Ssam } 2718732Ssam putc('\n', hf); 2728732Ssam } 2738732Ssam al2 = al->addr_link; 2749246Ssam free((char *)al); 2758732Ssam } 27615377Skarels break; 2778732Ssam 2788732Ssam default: 2798732Ssam fprintf(stderr, "Unknown keyword: %d.\n", keyword); 2808732Ssam } 2819246Ssam freenames(namelist); 28215377Skarels dontfree: 2839246Ssam freenames(protos); 2848732Ssam } 2858732Ssam 28615377Skarels printgateway(net, name, metric) 28715377Skarels int net; 28815377Skarels char *name; 28915377Skarels int metric; 29015377Skarels { 29115377Skarels struct netent *np; 29215377Skarels 29315377Skarels fprintf(gf, "net "); 29415377Skarels np = getnetbyaddr(net, AF_INET); 29515377Skarels if (np) 29615377Skarels fprintf(gf, "%s", np->n_name); 29715377Skarels else 29815377Skarels putnet(gf, net); 29915377Skarels fprintf(gf, " gateway %s metric %d passive\n", 30015377Skarels lower(name), metric); 30115377Skarels } 30215377Skarels 3039246Ssam copylocal(f, filename) 3049246Ssam FILE *f; 3059246Ssam char *filename; 3068732Ssam { 3078732Ssam register FILE *lhf; 3088732Ssam register cc; 3098732Ssam char buf[BUFSIZ]; 3109246Ssam extern int errno; 3118732Ssam 3129246Ssam lhf = fopen(filename, "r"); 3138732Ssam if (lhf == NULL) { 3149246Ssam if (errno != ENOENT) { 3159246Ssam perror(filename); 3169246Ssam exit(1); 3179246Ssam } 3189246Ssam fprintf(stderr, "Warning, no %s file.\n", filename); 3198732Ssam return; 3208732Ssam } 3218732Ssam while (cc = fread(buf, 1, sizeof(buf), lhf)) 3229246Ssam fwrite(buf, 1, cc, f); 3238732Ssam fclose(lhf); 3248732Ssam } 3259246Ssam 32615377Skarels copygateways(f, filename) 32715377Skarels FILE *f; 32815377Skarels char *filename; 32915377Skarels { 33015377Skarels register FILE *lhf; 33115377Skarels struct name *nl; 33215377Skarels char type[80]; 33315377Skarels char dname[80]; 33415377Skarels char gname[80]; 33515377Skarels char junk[80]; 33615377Skarels u_long addr; 33715377Skarels int net, metric; 33815377Skarels extern int errno; 33915377Skarels 34015377Skarels lhf = fopen(filename, "r"); 34115377Skarels if (lhf == NULL) { 34215377Skarels if (errno != ENOENT) { 34315377Skarels perror(filename); 34415377Skarels exit(1); 34515377Skarels } 34615377Skarels fprintf(stderr, "Warning, no %s file.\n", filename); 34715377Skarels return; 34815377Skarels } 34915377Skarels /* format: {net | host} XX gateway XX metric DD [passive]\n */ 35015377Skarels #define readentry(fp) \ 35115377Skarels fscanf((fp), "%s %s gateway %s metric %d %s\n", \ 35215377Skarels type, dname, gname, &metric, junk) 35315789Skarels for (;;) { 35415789Skarels junk[0] = 0; 35515789Skarels if (readentry(lhf) == EOF) 35615789Skarels break; 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 42415785Skarels /* 42515785Skarels * Print network number in internet-standard dot notation; 42615785Skarels * v is in host byte order. 42715785Skarels */ 4289246Ssam putnet(f, v) 4299246Ssam FILE *f; 43015789Skarels register int v; 4319246Ssam { 43215785Skarels if (v < 128) 43315785Skarels fprintf(f, "%d", v); 43415785Skarels else if (v < 65536) 43515789Skarels fprintf(f, "%d.%d", UC(v >> 8), UC(v)); 4369246Ssam else 43715789Skarels fprintf(f, "%d.%d.%d", UC(v >> 16), UC(v >> 8), UC(v)); 4389246Ssam } 4399246Ssam 4409246Ssam putaddr(f, v) 4419246Ssam FILE *f; 4429246Ssam u_long v; 4439246Ssam { 4449246Ssam register char *a = (char *)&v; 4459246Ssam char buf[32]; 4469246Ssam 4479246Ssam sprintf(buf,"%d.%d.%d.%d", UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3])); 4489246Ssam fprintf(f, "%-16.16s", buf); 4499246Ssam } 4509246Ssam 4519246Ssam freenames(list) 4529246Ssam struct name *list; 4539246Ssam { 4549246Ssam register struct name *nl, *nl2; 4559246Ssam 4569246Ssam nl2 = list; 4579246Ssam while (nl = nl2) { 4589246Ssam nl2 = nl->name_link; 4599246Ssam free(nl->name_val); 4609246Ssam free((char *)nl); 4619246Ssam } 4629246Ssam } 4639246Ssam 46415377Skarels freeaddrs(list) 46515377Skarels struct addr *list; 46615377Skarels { 46715377Skarels register struct addr *al, *al2; 46815377Skarels 46915377Skarels al2 = list; 47015377Skarels while (al = al2) 47115377Skarels al2 = al->addr_link, free((char *)al); 47215377Skarels } 47315377Skarels 4749246Ssam struct gateway *gateways = 0; 47515377Skarels struct gateway *lastgateway = 0; 4769246Ssam 47715377Skarels struct gateway * 47815377Skarels gatewayto(net) 4799246Ssam register int net; 4809246Ssam { 4819246Ssam register struct gateway *gp; 4829246Ssam 4839246Ssam for (gp = gateways; gp; gp = gp->g_link) 48415377Skarels if ((gp->g_net == net) && (gp->g_metric > 0)) 48515377Skarels return (gp); 48615377Skarels return ((struct gateway *) NULL); 4879246Ssam } 4889246Ssam 48915377Skarels struct gateway * 49015377Skarels savegateway(namelist, net, addr, metric) 49115377Skarels struct name *namelist; 49215377Skarels u_long addr; 49315377Skarels int net, metric; 4949246Ssam { 4959246Ssam register struct gateway *gp; 4969246Ssam 4979246Ssam gp = (struct gateway *)malloc(sizeof (struct gateway)); 4989246Ssam if (gp == 0) { 4999246Ssam fprintf(stderr, "htable: out of memory\n"); 5009246Ssam exit(1); 5019246Ssam } 50215377Skarels gp->g_link = (struct gateway *) NULL; 50315377Skarels if (lastgateway) 50415377Skarels lastgateway->g_link = gp; 50515377Skarels else 50615377Skarels gateways = gp; 50715377Skarels lastgateway = gp; 50815377Skarels gp->g_name = namelist; 5099246Ssam gp->g_net = net; 51015377Skarels gp->g_addr = addr; 51115377Skarels gp->g_metric = metric; 51215377Skarels if (metric == 1) 51315377Skarels gp->g_dst = gp; 5149246Ssam } 51515377Skarels 51615377Skarels connectedto(net) 51715377Skarels u_long net; 51815377Skarels { 51915377Skarels register i; 52015377Skarels 52115377Skarels for (i = 0; i < nconnected; i++) 52215377Skarels if (connected_nets[i] == net) 52315377Skarels return(1); 52415377Skarels return(0); 52515377Skarels } 52615377Skarels 52715377Skarels local(net) 52815377Skarels u_long net; 52915377Skarels { 53015377Skarels register i; 53115377Skarels 53215377Skarels for (i = 0; i < nlocal; i++) 53315377Skarels if (local_nets[i] == net) 53415377Skarels return(1); 53515377Skarels return(0); 53615377Skarels } 53715377Skarels 53815377Skarels #define MAXHOPS 10 53915377Skarels 54015377Skarels /* 54115377Skarels * Go through list of gateways, finding connections for gateways 54215377Skarels * that are not yet connected. 54315377Skarels */ 54415377Skarels dogateways() 54515377Skarels { 54615377Skarels register struct gateway *gp, *gw, *ggp; 54715377Skarels register int hops, changed = 1; 54815377Skarels struct name *nl; 54915377Skarels char *cp; 55015377Skarels 55115377Skarels for (hops = 0; hops < MAXHOPS && changed; hops++, changed = 0) { 55215377Skarels for (gp = gateways; gp; gp = gp->g_link) 55315377Skarels if ((gp->g_metric == 0) && (gw = gatewayto(gp->g_net))) { 55415377Skarels /* 55515377Skarels * Found a new connection. 55615377Skarels * For each other network that this gateway is on, 55715377Skarels * add a new gateway to that network. 55815377Skarels */ 55915377Skarels changed = 1; 56015377Skarels gp->g_dst = gw->g_dst; 56115377Skarels gp->g_metric = gw->g_metric + 1; 56215377Skarels for (ggp = gp->g_firstent; ggp->g_name == gp->g_name; 56315377Skarels ggp = ggp->g_link) { 56415377Skarels if (ggp == gp) 56515377Skarels continue; 56615377Skarels if (gatewayto(ggp->g_net)) 56715377Skarels continue; 56815377Skarels ggp->g_dst = gp->g_dst; 56915377Skarels ggp->g_metric = gp->g_metric; 57015377Skarels printgateway(ggp->g_net, 57115377Skarels gw->g_dst->g_name->name_val, gp->g_metric); 57215377Skarels } 57315377Skarels /* 57415377Skarels * Put the gateway in the hosts file, 57515377Skarels * using the address for the connected net. 57615377Skarels */ 57715377Skarels putaddr(hf, gp->g_addr); 57815377Skarels cp = "%s"; 57915377Skarels for (nl = gp->g_name; nl; nl = nl->name_link) { 58015377Skarels fprintf(hf, cp, lower(nl->name_val)); 58115377Skarels cp = " %s"; 58215377Skarels } 58315377Skarels fprintf(hf, "\t# gateway\n"); 58415377Skarels } 58515377Skarels } 58615377Skarels } 587