121125Sdist /* 221127Sdist * Copyright (c) 1983 Regents of the University of California. 333539Sbostic * All rights reserved. 433539Sbostic * 5*42798Sbostic * %sccs.include.redist.c% 621125Sdist */ 721125Sdist 88732Ssam #ifndef lint 923653Smckusick char copyright[] = 1023653Smckusick "@(#) Copyright (c) 1983 Regents of the University of California.\n\ 1123653Smckusick All rights reserved.\n"; 1233539Sbostic #endif /* not lint */ 138732Ssam 1423653Smckusick #ifndef lint 15*42798Sbostic static char sccsid[] = "@(#)htable.c 5.9 (Berkeley) 06/01/90"; 1633539Sbostic #endif /* not lint */ 1723653Smckusick 188732Ssam /* 198732Ssam * htable - convert NIC host table into a UNIX format. 208732Ssam * NIC format is described in RFC 810, 1 March 1982. 218732Ssam */ 228732Ssam #include <stdio.h> 238732Ssam #include <ctype.h> 249246Ssam #include <errno.h> 2512227Ssam #include <netdb.h> 2612227Ssam 279246Ssam #include "htable.h" /* includes <sys/types.h> */ 288732Ssam 2913193Ssam #include <sys/socket.h> 3033539Sbostic #include <arpa/inet.h> 318732Ssam 3212610Smo #define DATELINES 3 /* these lines usually contain the date */ 3315377Skarels #define MAXNETS 30 /* array size for local, connected nets */ 3412610Smo 359246Ssam FILE *hf; /* hosts file */ 369246Ssam FILE *gf; /* gateways file */ 379246Ssam FILE *nf; /* networks file */ 3815377Skarels struct gateway *savegateway(), *gatewayto(); 399246Ssam 4015377Skarels int connected_nets[MAXNETS]; 4115377Skarels int nconnected; 4215377Skarels int local_nets[MAXNETS]; 4315377Skarels int nlocal; 4415377Skarels char *myname; 4515377Skarels 468732Ssam main(argc, argv) 478732Ssam int argc; 488732Ssam char *argv[]; 498732Ssam { 5015377Skarels int errs; 5115377Skarels 528732Ssam infile = "(stdin)"; 5315377Skarels myname = argv[0]; 5415377Skarels argc--; 5515377Skarels argv++; 5615377Skarels while (argc--) { 5715377Skarels if (*argv[0] == '-') { 5815377Skarels switch (argv[0][1]) { 5915377Skarels case 'c': 6015377Skarels nconnected = addlocal(argv[1], connected_nets); 6115377Skarels argv++; 6215377Skarels argc--; 6315377Skarels break; 6415377Skarels case 'l': 6515377Skarels nlocal = addlocal(argv[1], local_nets); 6615377Skarels argv++; 6715377Skarels argc--; 6815377Skarels break; 6915377Skarels default: 7015377Skarels usage(); 7115377Skarels /*NOTREACHED*/ 7215377Skarels } 7315377Skarels } else { 7415377Skarels infile = argv[0]; 7515377Skarels if (freopen(infile, "r", stdin) == NULL) { 7615377Skarels perror(infile); 7715377Skarels exit(1); 7815377Skarels } 798732Ssam } 8015377Skarels argv++; 818732Ssam } 828732Ssam hf = fopen("hosts", "w"); 838732Ssam if (hf == NULL) { 848732Ssam perror("hosts"); 858732Ssam exit(1); 868732Ssam } 879246Ssam copylocal(hf, "localhosts"); 889246Ssam gf = fopen("gateways", "w"); 899246Ssam if (gf == NULL) { 908732Ssam perror("gateways"); 918732Ssam exit(1); 928732Ssam } 9333539Sbostic copygateways("localgateways"); 949246Ssam nf = fopen("networks", "w"); 959246Ssam if (nf == NULL) { 969246Ssam perror("networks"); 979246Ssam exit(1); 989246Ssam } 999246Ssam copylocal(nf, "localnetworks"); 10012610Smo copycomments(stdin, hf, DATELINES); 10115377Skarels errs = yyparse(); 10215377Skarels dogateways(); 10315377Skarels exit(errs); 1048732Ssam } 1058732Ssam 10615377Skarels usage() 10715377Skarels { 10815377Skarels fprintf(stderr, 10915377Skarels "usage: %s [ -c connected-nets ] [-l local-nets ] [ input-file ]\n", 11015377Skarels myname); 11115377Skarels exit(1); 11215377Skarels } 11315377Skarels 11415377Skarels /* 11515377Skarels * Turn a comma-separated list of network names or numbers in dot notation 11615377Skarels * (e.g. "arpanet, 128.32") into an array of net numbers. 11715377Skarels */ 11815377Skarels addlocal(arg, nets) 11915377Skarels char *arg; 12015377Skarels int *nets; 12115377Skarels { 12215377Skarels register char *p, c; 12315377Skarels register int nfound = 0; 12415377Skarels 12515377Skarels do { 12615377Skarels p = arg; 12715377Skarels while (*p && *p != ',' && !isspace(*p)) 12815377Skarels p++; 12915377Skarels c = *p; 13015377Skarels *p = 0; 13115377Skarels while (*arg && isspace(*arg)) 13215377Skarels arg++; 13315377Skarels if (*arg == 0) 13415377Skarels continue; 13515377Skarels if (nfound == MAXNETS) { 13615377Skarels fprintf(stderr, "%s: Too many networks in list\n", 13715377Skarels myname); 13815377Skarels return (nfound); 13915377Skarels } 14015377Skarels if (getnetaddr(arg, &nets[nfound])) 14115377Skarels nfound++; 14215377Skarels else { 14315377Skarels fprintf(stderr, "%s: %s: unknown network\n", 14415377Skarels myname, arg); 14515377Skarels exit(1); 14615377Skarels } 14715379Skarels arg = p + 1; 14815377Skarels } while (c); 14915377Skarels return (nfound); 15015377Skarels } 15115377Skarels 1528732Ssam struct name * 1538732Ssam newname(str) 1548732Ssam char *str; 1558732Ssam { 1568732Ssam char *p; 1578732Ssam struct name *nm; 1588732Ssam 1598732Ssam p = malloc(strlen(str) + 1); 1608732Ssam strcpy(p, str); 1619246Ssam nm = (struct name *)malloc(sizeof (struct name)); 1628732Ssam nm->name_val = p; 1638732Ssam nm->name_link = NONAME; 1648732Ssam return (nm); 1658732Ssam } 1668732Ssam 1678732Ssam char * 1688732Ssam lower(str) 1698732Ssam char *str; 1708732Ssam { 1718732Ssam register char *cp = str; 1728732Ssam 1738732Ssam while (*cp) { 1748732Ssam if (isupper(*cp)) 1758732Ssam *cp = tolower(*cp); 1768732Ssam cp++; 1778732Ssam } 1788732Ssam return (str); 1798732Ssam } 1808732Ssam 1818732Ssam do_entry(keyword, addrlist, namelist, cputype, opsys, protos) 1828732Ssam int keyword; 1838732Ssam struct addr *addrlist; 1848732Ssam struct name *namelist, *cputype, *opsys, *protos; 1858732Ssam { 1868732Ssam register struct addr *al, *al2; 1879246Ssam register struct name *nl; 18815377Skarels struct addr *connect_addr; 18915377Skarels char *cp; 1908732Ssam 1918732Ssam switch (keyword) { 1928732Ssam 1938732Ssam case KW_NET: 1949246Ssam nl = namelist; 1959246Ssam if (nl == NONAME) { 1969246Ssam fprintf(stderr, "htable: net"); 19715789Skarels putnet(stderr, inet_netof(addrlist->addr_val)); 1989246Ssam fprintf(stderr, " missing names.\n"); 1999246Ssam break; 2009246Ssam } 2019246Ssam fprintf(nf, "%-16.16s", lower(nl->name_val)); 2029246Ssam al2 = addrlist; 2039246Ssam while (al = al2) { 2049246Ssam char *cp; 2058732Ssam 20615789Skarels putnet(nf, inet_netof(al->addr_val)); 2079246Ssam cp = "\t%s"; 2089246Ssam while (nl = nl->name_link) { 2099246Ssam fprintf(nf, cp, lower(nl->name_val)); 2109246Ssam cp = " %s"; 2119246Ssam } 2129246Ssam putc('\n', nf); 2139246Ssam al2 = al->addr_link; 2149246Ssam free((char *)al); 2159246Ssam } 21615377Skarels break; 2179246Ssam 2188732Ssam case KW_GATEWAY: 21915377Skarels /* locate locally connected address, if one */ 22015377Skarels for (al = addrlist; al; al = al->addr_link) 22115377Skarels if (connectedto(inet_netof(al->addr_val))) 22215377Skarels break; 22315377Skarels if (al == NULL) { 22415377Skarels /* 22515377Skarels * Not connected to known networks. Save for later. 22615377Skarels */ 22715377Skarels struct gateway *gw, *firstgw = (struct gateway *) NULL; 22815377Skarels 22915377Skarels for (al = addrlist; al; al = al->addr_link) { 23015377Skarels register int net; 23115377Skarels 23215377Skarels net = inet_netof(al->addr_val); 23315377Skarels gw = savegateway(namelist, net, 23415377Skarels al->addr_val, 0); 23515377Skarels if (firstgw == (struct gateway *) NULL) 23615377Skarels firstgw = gw; 23715377Skarels gw->g_firstent = firstgw; 23815377Skarels } 23915377Skarels freeaddrs(addrlist); 24015377Skarels goto dontfree; 24115377Skarels } 24212227Ssam /* 24315377Skarels * Connected to a known network. 24415377Skarels * Mark this as the gateway to all other networks 24515377Skarels * that are on the addrlist (unless we already have 24615377Skarels * gateways to them). 24712227Ssam */ 24815377Skarels connect_addr = al; 24915377Skarels for (al = addrlist; al; al = al->addr_link) { 25012227Ssam register int net; 2519246Ssam 2529246Ssam /* suppress duplicates -- not optimal */ 25312227Ssam net = inet_netof(al->addr_val); 25416024Skarels if (connectedto(net) || gatewayto(net)) 25515377Skarels continue; 25615377Skarels printgateway(net, namelist->name_val, 1); 25715377Skarels (void) savegateway(namelist, net, al->addr_val, 1); 25812227Ssam } 25915377Skarels /* 26015377Skarels * Put the gateway in the hosts file. 26115377Skarels */ 26215377Skarels putaddr(hf, connect_addr->addr_val); 26315377Skarels cp = "%s"; 26415377Skarels for (nl = namelist; nl; nl = nl->name_link) { 26515377Skarels fprintf(hf, cp, lower(nl->name_val)); 26615377Skarels cp = " %s"; 2679246Ssam } 26815377Skarels fprintf(hf, "\t# gateway\n"); 26915377Skarels freeaddrs(addrlist); 27015377Skarels goto dontfree; 2718732Ssam 2728732Ssam case KW_HOST: 2739246Ssam al2 = addrlist; 2749246Ssam while (al = al2) { 27515377Skarels if (!local(inet_netof(al->addr_val))) { 2769246Ssam char *cp; 2779246Ssam 2789246Ssam putaddr(hf, al->addr_val); 2799246Ssam cp = "%s"; 2809246Ssam for (nl = namelist; nl; nl = nl->name_link) { 2819246Ssam fprintf(hf, cp, lower(nl->name_val)); 2829246Ssam cp = " %s"; 2839246Ssam } 2848732Ssam putc('\n', hf); 2858732Ssam } 2868732Ssam al2 = al->addr_link; 2879246Ssam free((char *)al); 2888732Ssam } 28915377Skarels break; 2908732Ssam 2918732Ssam default: 2928732Ssam fprintf(stderr, "Unknown keyword: %d.\n", keyword); 2938732Ssam } 2949246Ssam freenames(namelist); 29515377Skarels dontfree: 2969246Ssam freenames(protos); 2978732Ssam } 2988732Ssam 29915377Skarels printgateway(net, name, metric) 30015377Skarels int net; 30115377Skarels char *name; 30215377Skarels int metric; 30315377Skarels { 30415377Skarels struct netent *np; 30515377Skarels 30615377Skarels fprintf(gf, "net "); 30715377Skarels np = getnetbyaddr(net, AF_INET); 30815377Skarels if (np) 30915377Skarels fprintf(gf, "%s", np->n_name); 31015377Skarels else 31115377Skarels putnet(gf, net); 31215377Skarels fprintf(gf, " gateway %s metric %d passive\n", 31315377Skarels lower(name), metric); 31415377Skarels } 31515377Skarels 3169246Ssam copylocal(f, filename) 3179246Ssam FILE *f; 3189246Ssam char *filename; 3198732Ssam { 3208732Ssam register FILE *lhf; 3218732Ssam register cc; 3228732Ssam char buf[BUFSIZ]; 3239246Ssam extern int errno; 3248732Ssam 3259246Ssam lhf = fopen(filename, "r"); 3268732Ssam if (lhf == NULL) { 3279246Ssam if (errno != ENOENT) { 3289246Ssam perror(filename); 3299246Ssam exit(1); 3309246Ssam } 3319246Ssam fprintf(stderr, "Warning, no %s file.\n", filename); 3328732Ssam return; 3338732Ssam } 3348732Ssam while (cc = fread(buf, 1, sizeof(buf), lhf)) 3359246Ssam fwrite(buf, 1, cc, f); 3368732Ssam fclose(lhf); 3378732Ssam } 3389246Ssam 33933539Sbostic copygateways(filename) 34015377Skarels char *filename; 34115377Skarels { 34215377Skarels register FILE *lhf; 34315377Skarels struct name *nl; 34415377Skarels char type[80]; 34515377Skarels char dname[80]; 34615377Skarels char gname[80]; 34715377Skarels char junk[80]; 34816066Skarels char buf[500]; 34933539Sbostic struct in_addr addr; 35015377Skarels int net, metric; 35115377Skarels extern int errno; 35215377Skarels 35315377Skarels lhf = fopen(filename, "r"); 35415377Skarels if (lhf == NULL) { 35515377Skarels if (errno != ENOENT) { 35615377Skarels perror(filename); 35715377Skarels exit(1); 35815377Skarels } 35915377Skarels fprintf(stderr, "Warning, no %s file.\n", filename); 36015377Skarels return; 36115377Skarels } 36215377Skarels /* format: {net | host} XX gateway XX metric DD [passive]\n */ 36315789Skarels for (;;) { 36415789Skarels junk[0] = 0; 36516066Skarels if (fgets(buf, sizeof(buf), lhf) == (char *)NULL) 36615789Skarels break; 36716066Skarels fputs(buf, gf); 36816066Skarels if (buf[0] == '#' || 36916066Skarels sscanf(buf, "%s %s gateway %s metric %d %s", 37016066Skarels type, dname, gname, &metric, junk) < 5) 37116066Skarels continue; 37215377Skarels if (strcmp(type, "net")) 37316066Skarels continue; 37415377Skarels if (!getnetaddr(dname, &net)) 37516066Skarels continue; 37633539Sbostic if (!gethostaddr(gname, &addr.s_addr)) 37716066Skarels continue; 37815377Skarels nl = newname(gname); 37915377Skarels (void) savegateway(nl, net, addr, metric); 38015377Skarels } 38115377Skarels fclose(lhf); 38215377Skarels } 38315377Skarels 38415377Skarels getnetaddr(name, addr) 38515377Skarels char *name; 38615377Skarels int *addr; 38715377Skarels { 38815377Skarels struct netent *np = getnetbyname(name); 38915377Skarels 39015377Skarels if (np == 0) { 39115377Skarels *addr = inet_network(name); 39215377Skarels return (*addr != -1); 39315377Skarels } else { 39415377Skarels if (np->n_addrtype != AF_INET) 39515377Skarels return (0); 39615377Skarels *addr = np->n_net; 39715377Skarels return (1); 39815377Skarels } 39915377Skarels } 40015377Skarels 40115377Skarels gethostaddr(name, addr) 40215377Skarels char *name; 40315377Skarels u_long *addr; 40415377Skarels { 40515377Skarels struct hostent *hp; 40615377Skarels 40715377Skarels hp = gethostbyname(name); 40815377Skarels if (hp) { 40915377Skarels *addr = *(u_long *)(hp->h_addr); 41015377Skarels return (1); 41115377Skarels } 41215377Skarels *addr = inet_addr(name); 41315377Skarels return (*addr != -1); 41415377Skarels } 41515377Skarels 41612610Smo copycomments(in, out, ccount) 41712610Smo FILE *in, *out; 41812610Smo int ccount; 41912610Smo { 42012610Smo int count; 42133539Sbostic char buf[BUFSIZ], *fgets(); 42212610Smo 42312610Smo for (count=0; count < ccount; count++) { 42412610Smo if ((fgets(buf, sizeof(buf), in) == NULL) || (buf[0] != ';')) 42512610Smo return; 42612610Smo buf[0] = '#'; 42712610Smo fputs(buf, out); 42812610Smo } 42912610Smo return; 43012610Smo } 4319246Ssam #define UC(b) (((int)(b))&0xff) 4329246Ssam 43315785Skarels /* 43415785Skarels * Print network number in internet-standard dot notation; 43515785Skarels * v is in host byte order. 43615785Skarels */ 4379246Ssam putnet(f, v) 4389246Ssam FILE *f; 43915789Skarels register int v; 4409246Ssam { 44115785Skarels if (v < 128) 44215785Skarels fprintf(f, "%d", v); 44315785Skarels else if (v < 65536) 44415789Skarels fprintf(f, "%d.%d", UC(v >> 8), UC(v)); 4459246Ssam else 44615789Skarels fprintf(f, "%d.%d.%d", UC(v >> 16), UC(v >> 8), UC(v)); 4479246Ssam } 4489246Ssam 4499246Ssam putaddr(f, v) 4509246Ssam FILE *f; 45133539Sbostic struct in_addr v; 4529246Ssam { 45333539Sbostic fprintf(f, "%-16.16s", inet_ntoa(v)); 4549246Ssam } 4559246Ssam 4569246Ssam freenames(list) 4579246Ssam struct name *list; 4589246Ssam { 4599246Ssam register struct name *nl, *nl2; 4609246Ssam 4619246Ssam nl2 = list; 4629246Ssam while (nl = nl2) { 4639246Ssam nl2 = nl->name_link; 4649246Ssam free(nl->name_val); 4659246Ssam free((char *)nl); 4669246Ssam } 4679246Ssam } 4689246Ssam 46915377Skarels freeaddrs(list) 47015377Skarels struct addr *list; 47115377Skarels { 47215377Skarels register struct addr *al, *al2; 47315377Skarels 47415377Skarels al2 = list; 47515377Skarels while (al = al2) 47615377Skarels al2 = al->addr_link, free((char *)al); 47715377Skarels } 47815377Skarels 4799246Ssam struct gateway *gateways = 0; 48015377Skarels struct gateway *lastgateway = 0; 4819246Ssam 48215377Skarels struct gateway * 48315377Skarels gatewayto(net) 4849246Ssam register int net; 4859246Ssam { 4869246Ssam register struct gateway *gp; 4879246Ssam 4889246Ssam for (gp = gateways; gp; gp = gp->g_link) 48915377Skarels if ((gp->g_net == net) && (gp->g_metric > 0)) 49015377Skarels return (gp); 49115377Skarels return ((struct gateway *) NULL); 4929246Ssam } 4939246Ssam 49415377Skarels struct gateway * 49515377Skarels savegateway(namelist, net, addr, metric) 49615377Skarels struct name *namelist; 49733539Sbostic struct in_addr addr; 49815377Skarels int net, metric; 4999246Ssam { 5009246Ssam register struct gateway *gp; 5019246Ssam 5029246Ssam gp = (struct gateway *)malloc(sizeof (struct gateway)); 5039246Ssam if (gp == 0) { 5049246Ssam fprintf(stderr, "htable: out of memory\n"); 5059246Ssam exit(1); 5069246Ssam } 50715377Skarels gp->g_link = (struct gateway *) NULL; 50815377Skarels if (lastgateway) 50915377Skarels lastgateway->g_link = gp; 51015377Skarels else 51115377Skarels gateways = gp; 51215377Skarels lastgateway = gp; 51315377Skarels gp->g_name = namelist; 5149246Ssam gp->g_net = net; 51515377Skarels gp->g_addr = addr; 51615377Skarels gp->g_metric = metric; 51715377Skarels if (metric == 1) 51815377Skarels gp->g_dst = gp; 51927079Sbloom return (gp); 5209246Ssam } 52115377Skarels 52215377Skarels connectedto(net) 52315377Skarels u_long net; 52415377Skarels { 52515377Skarels register i; 52615377Skarels 52715377Skarels for (i = 0; i < nconnected; i++) 52815377Skarels if (connected_nets[i] == net) 52915377Skarels return(1); 53015377Skarels return(0); 53115377Skarels } 53215377Skarels 53315377Skarels local(net) 53415377Skarels u_long net; 53515377Skarels { 53615377Skarels register i; 53715377Skarels 53815377Skarels for (i = 0; i < nlocal; i++) 53915377Skarels if (local_nets[i] == net) 54015377Skarels return(1); 54115377Skarels return(0); 54215377Skarels } 54315377Skarels 54415377Skarels #define MAXHOPS 10 54515377Skarels 54615377Skarels /* 54715377Skarels * Go through list of gateways, finding connections for gateways 54815377Skarels * that are not yet connected. 54915377Skarels */ 55015377Skarels dogateways() 55115377Skarels { 55215377Skarels register struct gateway *gp, *gw, *ggp; 55315377Skarels register int hops, changed = 1; 55415377Skarels struct name *nl; 55515377Skarels char *cp; 55615377Skarels 55715377Skarels for (hops = 0; hops < MAXHOPS && changed; hops++, changed = 0) { 55815377Skarels for (gp = gateways; gp; gp = gp->g_link) 55915377Skarels if ((gp->g_metric == 0) && (gw = gatewayto(gp->g_net))) { 56015377Skarels /* 56115377Skarels * Found a new connection. 56215377Skarels * For each other network that this gateway is on, 56315377Skarels * add a new gateway to that network. 56415377Skarels */ 56515377Skarels changed = 1; 56615377Skarels gp->g_dst = gw->g_dst; 56715377Skarels gp->g_metric = gw->g_metric + 1; 56815377Skarels for (ggp = gp->g_firstent; ggp->g_name == gp->g_name; 56915377Skarels ggp = ggp->g_link) { 57015377Skarels if (ggp == gp) 57115377Skarels continue; 57215377Skarels if (gatewayto(ggp->g_net)) 57315377Skarels continue; 57415377Skarels ggp->g_dst = gp->g_dst; 57515377Skarels ggp->g_metric = gp->g_metric; 57615377Skarels printgateway(ggp->g_net, 57715377Skarels gw->g_dst->g_name->name_val, gp->g_metric); 57815377Skarels } 57915377Skarels /* 58015377Skarels * Put the gateway in the hosts file, 58115377Skarels * using the address for the connected net. 58215377Skarels */ 58315377Skarels putaddr(hf, gp->g_addr); 58415377Skarels cp = "%s"; 58515377Skarels for (nl = gp->g_name; nl; nl = nl->name_link) { 58615377Skarels fprintf(hf, cp, lower(nl->name_val)); 58715377Skarels cp = " %s"; 58815377Skarels } 58915377Skarels fprintf(hf, "\t# gateway\n"); 59015377Skarels } 59115377Skarels } 59215377Skarels } 593