121125Sdist /* 221127Sdist * Copyright (c) 1983 Regents of the University of California. 321125Sdist * All rights reserved. The Berkeley software License Agreement 421125Sdist * specifies the terms and conditions for redistribution. 521125Sdist */ 621125Sdist 78732Ssam #ifndef lint 8*23653Smckusick char copyright[] = 9*23653Smckusick "@(#) Copyright (c) 1983 Regents of the University of California.\n\ 10*23653Smckusick All rights reserved.\n"; 1121125Sdist #endif not lint 128732Ssam 13*23653Smckusick #ifndef lint 14*23653Smckusick static char sccsid[] = "@(#)htable.c 5.3 (Berkeley) 06/21/85"; 15*23653Smckusick #endif not lint 16*23653Smckusick 178732Ssam /* 188732Ssam * htable - convert NIC host table into a UNIX format. 198732Ssam * NIC format is described in RFC 810, 1 March 1982. 208732Ssam */ 218732Ssam #include <stdio.h> 228732Ssam #include <ctype.h> 239246Ssam #include <errno.h> 2412227Ssam #include <netdb.h> 2512227Ssam 269246Ssam #include "htable.h" /* includes <sys/types.h> */ 278732Ssam 2813193Ssam #include <sys/socket.h> 299246Ssam #include <netinet/in.h> 308732Ssam 3112610Smo #define DATELINES 3 /* these lines usually contain the date */ 3215377Skarels #define MAXNETS 30 /* array size for local, connected nets */ 3312610Smo 349246Ssam FILE *hf; /* hosts file */ 359246Ssam FILE *gf; /* gateways file */ 369246Ssam FILE *nf; /* networks file */ 3715377Skarels struct gateway *savegateway(), *gatewayto(); 389246Ssam 3915377Skarels int connected_nets[MAXNETS]; 4015377Skarels int nconnected; 4115377Skarels int local_nets[MAXNETS]; 4215377Skarels int nlocal; 4315377Skarels char *myname; 4415377Skarels 458732Ssam main(argc, argv) 468732Ssam int argc; 478732Ssam char *argv[]; 488732Ssam { 4915377Skarels int errs; 5015377Skarels 518732Ssam infile = "(stdin)"; 5215377Skarels myname = argv[0]; 5315377Skarels argc--; 5415377Skarels argv++; 5515377Skarels while (argc--) { 5615377Skarels if (*argv[0] == '-') { 5715377Skarels switch (argv[0][1]) { 5815377Skarels case 'c': 5915377Skarels nconnected = addlocal(argv[1], connected_nets); 6015377Skarels argv++; 6115377Skarels argc--; 6215377Skarels break; 6315377Skarels case 'l': 6415377Skarels nlocal = addlocal(argv[1], local_nets); 6515377Skarels argv++; 6615377Skarels argc--; 6715377Skarels break; 6815377Skarels default: 6915377Skarels usage(); 7015377Skarels /*NOTREACHED*/ 7115377Skarels } 7215377Skarels } else { 7315377Skarels infile = argv[0]; 7415377Skarels if (freopen(infile, "r", stdin) == NULL) { 7515377Skarels perror(infile); 7615377Skarels exit(1); 7715377Skarels } 788732Ssam } 7915377Skarels argv++; 808732Ssam } 818732Ssam hf = fopen("hosts", "w"); 828732Ssam if (hf == NULL) { 838732Ssam perror("hosts"); 848732Ssam exit(1); 858732Ssam } 869246Ssam copylocal(hf, "localhosts"); 879246Ssam gf = fopen("gateways", "w"); 889246Ssam if (gf == NULL) { 898732Ssam perror("gateways"); 908732Ssam exit(1); 918732Ssam } 9215377Skarels copygateways(gf, "localgateways"); 939246Ssam nf = fopen("networks", "w"); 949246Ssam if (nf == NULL) { 959246Ssam perror("networks"); 969246Ssam exit(1); 979246Ssam } 989246Ssam copylocal(nf, "localnetworks"); 9912610Smo copycomments(stdin, hf, DATELINES); 10015377Skarels errs = yyparse(); 10115377Skarels dogateways(); 10215377Skarels exit(errs); 1038732Ssam } 1048732Ssam 10515377Skarels usage() 10615377Skarels { 10715377Skarels fprintf(stderr, 10815377Skarels "usage: %s [ -c connected-nets ] [-l local-nets ] [ input-file ]\n", 10915377Skarels myname); 11015377Skarels exit(1); 11115377Skarels } 11215377Skarels 11315377Skarels /* 11415377Skarels * Turn a comma-separated list of network names or numbers in dot notation 11515377Skarels * (e.g. "arpanet, 128.32") into an array of net numbers. 11615377Skarels */ 11715377Skarels addlocal(arg, nets) 11815377Skarels char *arg; 11915377Skarels int *nets; 12015377Skarels { 12115377Skarels register char *p, c; 12215377Skarels register int nfound = 0; 12315377Skarels 12415377Skarels do { 12515377Skarels p = arg; 12615377Skarels while (*p && *p != ',' && !isspace(*p)) 12715377Skarels p++; 12815377Skarels c = *p; 12915377Skarels *p = 0; 13015377Skarels while (*arg && isspace(*arg)) 13115377Skarels arg++; 13215377Skarels if (*arg == 0) 13315377Skarels continue; 13415377Skarels if (nfound == MAXNETS) { 13515377Skarels fprintf(stderr, "%s: Too many networks in list\n", 13615377Skarels myname); 13715377Skarels return (nfound); 13815377Skarels } 13915377Skarels if (getnetaddr(arg, &nets[nfound])) 14015377Skarels nfound++; 14115377Skarels else { 14215377Skarels fprintf(stderr, "%s: %s: unknown network\n", 14315377Skarels myname, arg); 14415377Skarels exit(1); 14515377Skarels } 14615379Skarels arg = p + 1; 14715377Skarels } while (c); 14815377Skarels return (nfound); 14915377Skarels } 15015377Skarels 1518732Ssam struct name * 1528732Ssam newname(str) 1538732Ssam char *str; 1548732Ssam { 1558732Ssam char *p; 1568732Ssam struct name *nm; 1578732Ssam 1588732Ssam p = malloc(strlen(str) + 1); 1598732Ssam strcpy(p, str); 1609246Ssam nm = (struct name *)malloc(sizeof (struct name)); 1618732Ssam nm->name_val = p; 1628732Ssam nm->name_link = NONAME; 1638732Ssam return (nm); 1648732Ssam } 1658732Ssam 1668732Ssam char * 1678732Ssam lower(str) 1688732Ssam char *str; 1698732Ssam { 1708732Ssam register char *cp = str; 1718732Ssam 1728732Ssam while (*cp) { 1738732Ssam if (isupper(*cp)) 1748732Ssam *cp = tolower(*cp); 17516230Skarels if (*cp == '.') 17616230Skarels break; 1778732Ssam cp++; 1788732Ssam } 1798732Ssam return (str); 1808732Ssam } 1818732Ssam 1828732Ssam do_entry(keyword, addrlist, namelist, cputype, opsys, protos) 1838732Ssam int keyword; 1848732Ssam struct addr *addrlist; 1858732Ssam struct name *namelist, *cputype, *opsys, *protos; 1868732Ssam { 1878732Ssam register struct addr *al, *al2; 1889246Ssam register struct name *nl; 18915377Skarels struct addr *connect_addr; 19015377Skarels char *cp; 1918732Ssam 1928732Ssam switch (keyword) { 1938732Ssam 1948732Ssam case KW_NET: 1959246Ssam nl = namelist; 1969246Ssam if (nl == NONAME) { 1979246Ssam fprintf(stderr, "htable: net"); 19815789Skarels putnet(stderr, inet_netof(addrlist->addr_val)); 1999246Ssam fprintf(stderr, " missing names.\n"); 2009246Ssam break; 2019246Ssam } 2029246Ssam fprintf(nf, "%-16.16s", lower(nl->name_val)); 2039246Ssam al2 = addrlist; 2049246Ssam while (al = al2) { 2059246Ssam char *cp; 2068732Ssam 20715789Skarels putnet(nf, inet_netof(al->addr_val)); 2089246Ssam cp = "\t%s"; 2099246Ssam while (nl = nl->name_link) { 2109246Ssam fprintf(nf, cp, lower(nl->name_val)); 2119246Ssam cp = " %s"; 2129246Ssam } 2139246Ssam putc('\n', nf); 2149246Ssam al2 = al->addr_link; 2159246Ssam free((char *)al); 2169246Ssam } 21715377Skarels break; 2189246Ssam 2198732Ssam case KW_GATEWAY: 22015377Skarels /* locate locally connected address, if one */ 22115377Skarels for (al = addrlist; al; al = al->addr_link) 22215377Skarels if (connectedto(inet_netof(al->addr_val))) 22315377Skarels break; 22415377Skarels if (al == NULL) { 22515377Skarels /* 22615377Skarels * Not connected to known networks. Save for later. 22715377Skarels */ 22815377Skarels struct gateway *gw, *firstgw = (struct gateway *) NULL; 22915377Skarels 23015377Skarels for (al = addrlist; al; al = al->addr_link) { 23115377Skarels register int net; 23215377Skarels 23315377Skarels net = inet_netof(al->addr_val); 23415377Skarels gw = savegateway(namelist, net, 23515377Skarels al->addr_val, 0); 23615377Skarels if (firstgw == (struct gateway *) NULL) 23715377Skarels firstgw = gw; 23815377Skarels gw->g_firstent = firstgw; 23915377Skarels } 24015377Skarels freeaddrs(addrlist); 24115377Skarels goto dontfree; 24215377Skarels } 24312227Ssam /* 24415377Skarels * Connected to a known network. 24515377Skarels * Mark this as the gateway to all other networks 24615377Skarels * that are on the addrlist (unless we already have 24715377Skarels * gateways to them). 24812227Ssam */ 24915377Skarels connect_addr = al; 25015377Skarels for (al = addrlist; al; al = al->addr_link) { 25112227Ssam register int net; 2529246Ssam 2539246Ssam /* suppress duplicates -- not optimal */ 25412227Ssam net = inet_netof(al->addr_val); 25516024Skarels if (connectedto(net) || gatewayto(net)) 25615377Skarels continue; 25715377Skarels printgateway(net, namelist->name_val, 1); 25815377Skarels (void) savegateway(namelist, net, al->addr_val, 1); 25912227Ssam } 26015377Skarels /* 26115377Skarels * Put the gateway in the hosts file. 26215377Skarels */ 26315377Skarels putaddr(hf, connect_addr->addr_val); 26415377Skarels cp = "%s"; 26515377Skarels for (nl = namelist; nl; nl = nl->name_link) { 26615377Skarels fprintf(hf, cp, lower(nl->name_val)); 26715377Skarels cp = " %s"; 2689246Ssam } 26915377Skarels fprintf(hf, "\t# gateway\n"); 27015377Skarels freeaddrs(addrlist); 27115377Skarels goto dontfree; 2728732Ssam 2738732Ssam case KW_HOST: 2749246Ssam al2 = addrlist; 2759246Ssam while (al = al2) { 27615377Skarels if (!local(inet_netof(al->addr_val))) { 2779246Ssam char *cp; 2789246Ssam 2799246Ssam putaddr(hf, al->addr_val); 2809246Ssam cp = "%s"; 2819246Ssam for (nl = namelist; nl; nl = nl->name_link) { 2829246Ssam fprintf(hf, cp, lower(nl->name_val)); 2839246Ssam cp = " %s"; 2849246Ssam } 2858732Ssam putc('\n', hf); 2868732Ssam } 2878732Ssam al2 = al->addr_link; 2889246Ssam free((char *)al); 2898732Ssam } 29015377Skarels break; 2918732Ssam 2928732Ssam default: 2938732Ssam fprintf(stderr, "Unknown keyword: %d.\n", keyword); 2948732Ssam } 2959246Ssam freenames(namelist); 29615377Skarels dontfree: 2979246Ssam freenames(protos); 2988732Ssam } 2998732Ssam 30015377Skarels printgateway(net, name, metric) 30115377Skarels int net; 30215377Skarels char *name; 30315377Skarels int metric; 30415377Skarels { 30515377Skarels struct netent *np; 30615377Skarels 30715377Skarels fprintf(gf, "net "); 30815377Skarels np = getnetbyaddr(net, AF_INET); 30915377Skarels if (np) 31015377Skarels fprintf(gf, "%s", np->n_name); 31115377Skarels else 31215377Skarels putnet(gf, net); 31315377Skarels fprintf(gf, " gateway %s metric %d passive\n", 31415377Skarels lower(name), metric); 31515377Skarels } 31615377Skarels 3179246Ssam copylocal(f, filename) 3189246Ssam FILE *f; 3199246Ssam char *filename; 3208732Ssam { 3218732Ssam register FILE *lhf; 3228732Ssam register cc; 3238732Ssam char buf[BUFSIZ]; 3249246Ssam extern int errno; 3258732Ssam 3269246Ssam lhf = fopen(filename, "r"); 3278732Ssam if (lhf == NULL) { 3289246Ssam if (errno != ENOENT) { 3299246Ssam perror(filename); 3309246Ssam exit(1); 3319246Ssam } 3329246Ssam fprintf(stderr, "Warning, no %s file.\n", filename); 3338732Ssam return; 3348732Ssam } 3358732Ssam while (cc = fread(buf, 1, sizeof(buf), lhf)) 3369246Ssam fwrite(buf, 1, cc, f); 3378732Ssam fclose(lhf); 3388732Ssam } 3399246Ssam 34015377Skarels copygateways(f, filename) 34115377Skarels FILE *f; 34215377Skarels char *filename; 34315377Skarels { 34415377Skarels register FILE *lhf; 34515377Skarels struct name *nl; 34615377Skarels char type[80]; 34715377Skarels char dname[80]; 34815377Skarels char gname[80]; 34915377Skarels char junk[80]; 35016066Skarels char buf[500]; 35115377Skarels u_long addr; 35215377Skarels int net, metric; 35315377Skarels extern int errno; 35415377Skarels 35515377Skarels lhf = fopen(filename, "r"); 35615377Skarels if (lhf == NULL) { 35715377Skarels if (errno != ENOENT) { 35815377Skarels perror(filename); 35915377Skarels exit(1); 36015377Skarels } 36115377Skarels fprintf(stderr, "Warning, no %s file.\n", filename); 36215377Skarels return; 36315377Skarels } 36415377Skarels /* format: {net | host} XX gateway XX metric DD [passive]\n */ 36515789Skarels for (;;) { 36615789Skarels junk[0] = 0; 36716066Skarels if (fgets(buf, sizeof(buf), lhf) == (char *)NULL) 36815789Skarels break; 36916066Skarels fputs(buf, gf); 37016066Skarels if (buf[0] == '#' || 37116066Skarels sscanf(buf, "%s %s gateway %s metric %d %s", 37216066Skarels type, dname, gname, &metric, junk) < 5) 37316066Skarels continue; 37415377Skarels if (strcmp(type, "net")) 37516066Skarels continue; 37615377Skarels if (!getnetaddr(dname, &net)) 37716066Skarels continue; 37815377Skarels if (!gethostaddr(gname, &addr)) 37916066Skarels continue; 38015377Skarels nl = newname(gname); 38115377Skarels (void) savegateway(nl, net, addr, metric); 38215377Skarels } 38315377Skarels fclose(lhf); 38415377Skarels } 38515377Skarels 38615377Skarels getnetaddr(name, addr) 38715377Skarels char *name; 38815377Skarels int *addr; 38915377Skarels { 39015377Skarels struct netent *np = getnetbyname(name); 39115377Skarels int n; 39215377Skarels 39315377Skarels if (np == 0) { 39415377Skarels *addr = inet_network(name); 39515377Skarels return (*addr != -1); 39615377Skarels } else { 39715377Skarels if (np->n_addrtype != AF_INET) 39815377Skarels return (0); 39915377Skarels *addr = np->n_net; 40015377Skarels return (1); 40115377Skarels } 40215377Skarels } 40315377Skarels 40415377Skarels gethostaddr(name, addr) 40515377Skarels char *name; 40615377Skarels u_long *addr; 40715377Skarels { 40815377Skarels struct hostent *hp; 40915377Skarels 41015377Skarels hp = gethostbyname(name); 41115377Skarels if (hp) { 41215377Skarels *addr = *(u_long *)(hp->h_addr); 41315377Skarels return (1); 41415377Skarels } 41515377Skarels *addr = inet_addr(name); 41615377Skarels return (*addr != -1); 41715377Skarels } 41815377Skarels 41912610Smo copycomments(in, out, ccount) 42012610Smo FILE *in, *out; 42112610Smo int ccount; 42212610Smo { 42312610Smo char buf[BUFSIZ]; 42412610Smo int length; 42512610Smo int count; 42612610Smo char *fgets(); 42712610Smo 42812610Smo for (count=0; count < ccount; count++) { 42912610Smo if ((fgets(buf, sizeof(buf), in) == NULL) || (buf[0] != ';')) 43012610Smo return; 43112610Smo buf[0] = '#'; 43212610Smo fputs(buf, out); 43312610Smo } 43412610Smo return; 43512610Smo } 4369246Ssam #define UC(b) (((int)(b))&0xff) 4379246Ssam 43815785Skarels /* 43915785Skarels * Print network number in internet-standard dot notation; 44015785Skarels * v is in host byte order. 44115785Skarels */ 4429246Ssam putnet(f, v) 4439246Ssam FILE *f; 44415789Skarels register int v; 4459246Ssam { 44615785Skarels if (v < 128) 44715785Skarels fprintf(f, "%d", v); 44815785Skarels else if (v < 65536) 44915789Skarels fprintf(f, "%d.%d", UC(v >> 8), UC(v)); 4509246Ssam else 45115789Skarels fprintf(f, "%d.%d.%d", UC(v >> 16), UC(v >> 8), UC(v)); 4529246Ssam } 4539246Ssam 4549246Ssam putaddr(f, v) 4559246Ssam FILE *f; 4569246Ssam u_long v; 4579246Ssam { 4589246Ssam register char *a = (char *)&v; 4599246Ssam char buf[32]; 4609246Ssam 4619246Ssam sprintf(buf,"%d.%d.%d.%d", UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3])); 4629246Ssam fprintf(f, "%-16.16s", buf); 4639246Ssam } 4649246Ssam 4659246Ssam freenames(list) 4669246Ssam struct name *list; 4679246Ssam { 4689246Ssam register struct name *nl, *nl2; 4699246Ssam 4709246Ssam nl2 = list; 4719246Ssam while (nl = nl2) { 4729246Ssam nl2 = nl->name_link; 4739246Ssam free(nl->name_val); 4749246Ssam free((char *)nl); 4759246Ssam } 4769246Ssam } 4779246Ssam 47815377Skarels freeaddrs(list) 47915377Skarels struct addr *list; 48015377Skarels { 48115377Skarels register struct addr *al, *al2; 48215377Skarels 48315377Skarels al2 = list; 48415377Skarels while (al = al2) 48515377Skarels al2 = al->addr_link, free((char *)al); 48615377Skarels } 48715377Skarels 4889246Ssam struct gateway *gateways = 0; 48915377Skarels struct gateway *lastgateway = 0; 4909246Ssam 49115377Skarels struct gateway * 49215377Skarels gatewayto(net) 4939246Ssam register int net; 4949246Ssam { 4959246Ssam register struct gateway *gp; 4969246Ssam 4979246Ssam for (gp = gateways; gp; gp = gp->g_link) 49815377Skarels if ((gp->g_net == net) && (gp->g_metric > 0)) 49915377Skarels return (gp); 50015377Skarels return ((struct gateway *) NULL); 5019246Ssam } 5029246Ssam 50315377Skarels struct gateway * 50415377Skarels savegateway(namelist, net, addr, metric) 50515377Skarels struct name *namelist; 50615377Skarels u_long addr; 50715377Skarels int net, metric; 5089246Ssam { 5099246Ssam register struct gateway *gp; 5109246Ssam 5119246Ssam gp = (struct gateway *)malloc(sizeof (struct gateway)); 5129246Ssam if (gp == 0) { 5139246Ssam fprintf(stderr, "htable: out of memory\n"); 5149246Ssam exit(1); 5159246Ssam } 51615377Skarels gp->g_link = (struct gateway *) NULL; 51715377Skarels if (lastgateway) 51815377Skarels lastgateway->g_link = gp; 51915377Skarels else 52015377Skarels gateways = gp; 52115377Skarels lastgateway = gp; 52215377Skarels gp->g_name = namelist; 5239246Ssam gp->g_net = net; 52415377Skarels gp->g_addr = addr; 52515377Skarels gp->g_metric = metric; 52615377Skarels if (metric == 1) 52715377Skarels gp->g_dst = gp; 5289246Ssam } 52915377Skarels 53015377Skarels connectedto(net) 53115377Skarels u_long net; 53215377Skarels { 53315377Skarels register i; 53415377Skarels 53515377Skarels for (i = 0; i < nconnected; i++) 53615377Skarels if (connected_nets[i] == net) 53715377Skarels return(1); 53815377Skarels return(0); 53915377Skarels } 54015377Skarels 54115377Skarels local(net) 54215377Skarels u_long net; 54315377Skarels { 54415377Skarels register i; 54515377Skarels 54615377Skarels for (i = 0; i < nlocal; i++) 54715377Skarels if (local_nets[i] == net) 54815377Skarels return(1); 54915377Skarels return(0); 55015377Skarels } 55115377Skarels 55215377Skarels #define MAXHOPS 10 55315377Skarels 55415377Skarels /* 55515377Skarels * Go through list of gateways, finding connections for gateways 55615377Skarels * that are not yet connected. 55715377Skarels */ 55815377Skarels dogateways() 55915377Skarels { 56015377Skarels register struct gateway *gp, *gw, *ggp; 56115377Skarels register int hops, changed = 1; 56215377Skarels struct name *nl; 56315377Skarels char *cp; 56415377Skarels 56515377Skarels for (hops = 0; hops < MAXHOPS && changed; hops++, changed = 0) { 56615377Skarels for (gp = gateways; gp; gp = gp->g_link) 56715377Skarels if ((gp->g_metric == 0) && (gw = gatewayto(gp->g_net))) { 56815377Skarels /* 56915377Skarels * Found a new connection. 57015377Skarels * For each other network that this gateway is on, 57115377Skarels * add a new gateway to that network. 57215377Skarels */ 57315377Skarels changed = 1; 57415377Skarels gp->g_dst = gw->g_dst; 57515377Skarels gp->g_metric = gw->g_metric + 1; 57615377Skarels for (ggp = gp->g_firstent; ggp->g_name == gp->g_name; 57715377Skarels ggp = ggp->g_link) { 57815377Skarels if (ggp == gp) 57915377Skarels continue; 58015377Skarels if (gatewayto(ggp->g_net)) 58115377Skarels continue; 58215377Skarels ggp->g_dst = gp->g_dst; 58315377Skarels ggp->g_metric = gp->g_metric; 58415377Skarels printgateway(ggp->g_net, 58515377Skarels gw->g_dst->g_name->name_val, gp->g_metric); 58615377Skarels } 58715377Skarels /* 58815377Skarels * Put the gateway in the hosts file, 58915377Skarels * using the address for the connected net. 59015377Skarels */ 59115377Skarels putaddr(hf, gp->g_addr); 59215377Skarels cp = "%s"; 59315377Skarels for (nl = gp->g_name; nl; nl = nl->name_link) { 59415377Skarels fprintf(hf, cp, lower(nl->name_val)); 59515377Skarels cp = " %s"; 59615377Skarels } 59715377Skarels fprintf(hf, "\t# gateway\n"); 59815377Skarels } 59915377Skarels } 60015377Skarels } 601