121125Sdist /* 221127Sdist * Copyright (c) 1983 Regents of the University of California. 3*33539Sbostic * All rights reserved. 4*33539Sbostic * 5*33539Sbostic * Redistribution and use in source and binary forms are permitted 6*33539Sbostic * provided that this notice is preserved and that due credit is given 7*33539Sbostic * to the University of California at Berkeley. The name of the University 8*33539Sbostic * may not be used to endorse or promote products derived from this 9*33539Sbostic * software without specific prior written permission. This software 10*33539Sbostic * is provided ``as is'' without express or implied warranty. 1121125Sdist */ 1221125Sdist 138732Ssam #ifndef lint 1423653Smckusick char copyright[] = 1523653Smckusick "@(#) Copyright (c) 1983 Regents of the University of California.\n\ 1623653Smckusick All rights reserved.\n"; 17*33539Sbostic #endif /* not lint */ 188732Ssam 1923653Smckusick #ifndef lint 20*33539Sbostic static char sccsid[] = "@(#)htable.c 5.7 (Berkeley) 02/23/88"; 21*33539Sbostic #endif /* not lint */ 2223653Smckusick 238732Ssam /* 248732Ssam * htable - convert NIC host table into a UNIX format. 258732Ssam * NIC format is described in RFC 810, 1 March 1982. 268732Ssam */ 278732Ssam #include <stdio.h> 288732Ssam #include <ctype.h> 299246Ssam #include <errno.h> 3012227Ssam #include <netdb.h> 3112227Ssam 329246Ssam #include "htable.h" /* includes <sys/types.h> */ 338732Ssam 3413193Ssam #include <sys/socket.h> 35*33539Sbostic #include <arpa/inet.h> 368732Ssam 3712610Smo #define DATELINES 3 /* these lines usually contain the date */ 3815377Skarels #define MAXNETS 30 /* array size for local, connected nets */ 3912610Smo 409246Ssam FILE *hf; /* hosts file */ 419246Ssam FILE *gf; /* gateways file */ 429246Ssam FILE *nf; /* networks file */ 4315377Skarels struct gateway *savegateway(), *gatewayto(); 449246Ssam 4515377Skarels int connected_nets[MAXNETS]; 4615377Skarels int nconnected; 4715377Skarels int local_nets[MAXNETS]; 4815377Skarels int nlocal; 4915377Skarels char *myname; 5015377Skarels 518732Ssam main(argc, argv) 528732Ssam int argc; 538732Ssam char *argv[]; 548732Ssam { 5515377Skarels int errs; 5615377Skarels 578732Ssam infile = "(stdin)"; 5815377Skarels myname = argv[0]; 5915377Skarels argc--; 6015377Skarels argv++; 6115377Skarels while (argc--) { 6215377Skarels if (*argv[0] == '-') { 6315377Skarels switch (argv[0][1]) { 6415377Skarels case 'c': 6515377Skarels nconnected = addlocal(argv[1], connected_nets); 6615377Skarels argv++; 6715377Skarels argc--; 6815377Skarels break; 6915377Skarels case 'l': 7015377Skarels nlocal = addlocal(argv[1], local_nets); 7115377Skarels argv++; 7215377Skarels argc--; 7315377Skarels break; 7415377Skarels default: 7515377Skarels usage(); 7615377Skarels /*NOTREACHED*/ 7715377Skarels } 7815377Skarels } else { 7915377Skarels infile = argv[0]; 8015377Skarels if (freopen(infile, "r", stdin) == NULL) { 8115377Skarels perror(infile); 8215377Skarels exit(1); 8315377Skarels } 848732Ssam } 8515377Skarels argv++; 868732Ssam } 878732Ssam hf = fopen("hosts", "w"); 888732Ssam if (hf == NULL) { 898732Ssam perror("hosts"); 908732Ssam exit(1); 918732Ssam } 929246Ssam copylocal(hf, "localhosts"); 939246Ssam gf = fopen("gateways", "w"); 949246Ssam if (gf == NULL) { 958732Ssam perror("gateways"); 968732Ssam exit(1); 978732Ssam } 98*33539Sbostic copygateways("localgateways"); 999246Ssam nf = fopen("networks", "w"); 1009246Ssam if (nf == NULL) { 1019246Ssam perror("networks"); 1029246Ssam exit(1); 1039246Ssam } 1049246Ssam copylocal(nf, "localnetworks"); 10512610Smo copycomments(stdin, hf, DATELINES); 10615377Skarels errs = yyparse(); 10715377Skarels dogateways(); 10815377Skarels exit(errs); 1098732Ssam } 1108732Ssam 11115377Skarels usage() 11215377Skarels { 11315377Skarels fprintf(stderr, 11415377Skarels "usage: %s [ -c connected-nets ] [-l local-nets ] [ input-file ]\n", 11515377Skarels myname); 11615377Skarels exit(1); 11715377Skarels } 11815377Skarels 11915377Skarels /* 12015377Skarels * Turn a comma-separated list of network names or numbers in dot notation 12115377Skarels * (e.g. "arpanet, 128.32") into an array of net numbers. 12215377Skarels */ 12315377Skarels addlocal(arg, nets) 12415377Skarels char *arg; 12515377Skarels int *nets; 12615377Skarels { 12715377Skarels register char *p, c; 12815377Skarels register int nfound = 0; 12915377Skarels 13015377Skarels do { 13115377Skarels p = arg; 13215377Skarels while (*p && *p != ',' && !isspace(*p)) 13315377Skarels p++; 13415377Skarels c = *p; 13515377Skarels *p = 0; 13615377Skarels while (*arg && isspace(*arg)) 13715377Skarels arg++; 13815377Skarels if (*arg == 0) 13915377Skarels continue; 14015377Skarels if (nfound == MAXNETS) { 14115377Skarels fprintf(stderr, "%s: Too many networks in list\n", 14215377Skarels myname); 14315377Skarels return (nfound); 14415377Skarels } 14515377Skarels if (getnetaddr(arg, &nets[nfound])) 14615377Skarels nfound++; 14715377Skarels else { 14815377Skarels fprintf(stderr, "%s: %s: unknown network\n", 14915377Skarels myname, arg); 15015377Skarels exit(1); 15115377Skarels } 15215379Skarels arg = p + 1; 15315377Skarels } while (c); 15415377Skarels return (nfound); 15515377Skarels } 15615377Skarels 1578732Ssam struct name * 1588732Ssam newname(str) 1598732Ssam char *str; 1608732Ssam { 1618732Ssam char *p; 1628732Ssam struct name *nm; 1638732Ssam 1648732Ssam p = malloc(strlen(str) + 1); 1658732Ssam strcpy(p, str); 1669246Ssam nm = (struct name *)malloc(sizeof (struct name)); 1678732Ssam nm->name_val = p; 1688732Ssam nm->name_link = NONAME; 1698732Ssam return (nm); 1708732Ssam } 1718732Ssam 1728732Ssam char * 1738732Ssam lower(str) 1748732Ssam char *str; 1758732Ssam { 1768732Ssam register char *cp = str; 1778732Ssam 1788732Ssam while (*cp) { 1798732Ssam if (isupper(*cp)) 1808732Ssam *cp = tolower(*cp); 1818732Ssam cp++; 1828732Ssam } 1838732Ssam return (str); 1848732Ssam } 1858732Ssam 1868732Ssam do_entry(keyword, addrlist, namelist, cputype, opsys, protos) 1878732Ssam int keyword; 1888732Ssam struct addr *addrlist; 1898732Ssam struct name *namelist, *cputype, *opsys, *protos; 1908732Ssam { 1918732Ssam register struct addr *al, *al2; 1929246Ssam register struct name *nl; 19315377Skarels struct addr *connect_addr; 19415377Skarels char *cp; 1958732Ssam 1968732Ssam switch (keyword) { 1978732Ssam 1988732Ssam case KW_NET: 1999246Ssam nl = namelist; 2009246Ssam if (nl == NONAME) { 2019246Ssam fprintf(stderr, "htable: net"); 20215789Skarels putnet(stderr, inet_netof(addrlist->addr_val)); 2039246Ssam fprintf(stderr, " missing names.\n"); 2049246Ssam break; 2059246Ssam } 2069246Ssam fprintf(nf, "%-16.16s", lower(nl->name_val)); 2079246Ssam al2 = addrlist; 2089246Ssam while (al = al2) { 2099246Ssam char *cp; 2108732Ssam 21115789Skarels putnet(nf, inet_netof(al->addr_val)); 2129246Ssam cp = "\t%s"; 2139246Ssam while (nl = nl->name_link) { 2149246Ssam fprintf(nf, cp, lower(nl->name_val)); 2159246Ssam cp = " %s"; 2169246Ssam } 2179246Ssam putc('\n', nf); 2189246Ssam al2 = al->addr_link; 2199246Ssam free((char *)al); 2209246Ssam } 22115377Skarels break; 2229246Ssam 2238732Ssam case KW_GATEWAY: 22415377Skarels /* locate locally connected address, if one */ 22515377Skarels for (al = addrlist; al; al = al->addr_link) 22615377Skarels if (connectedto(inet_netof(al->addr_val))) 22715377Skarels break; 22815377Skarels if (al == NULL) { 22915377Skarels /* 23015377Skarels * Not connected to known networks. Save for later. 23115377Skarels */ 23215377Skarels struct gateway *gw, *firstgw = (struct gateway *) NULL; 23315377Skarels 23415377Skarels for (al = addrlist; al; al = al->addr_link) { 23515377Skarels register int net; 23615377Skarels 23715377Skarels net = inet_netof(al->addr_val); 23815377Skarels gw = savegateway(namelist, net, 23915377Skarels al->addr_val, 0); 24015377Skarels if (firstgw == (struct gateway *) NULL) 24115377Skarels firstgw = gw; 24215377Skarels gw->g_firstent = firstgw; 24315377Skarels } 24415377Skarels freeaddrs(addrlist); 24515377Skarels goto dontfree; 24615377Skarels } 24712227Ssam /* 24815377Skarels * Connected to a known network. 24915377Skarels * Mark this as the gateway to all other networks 25015377Skarels * that are on the addrlist (unless we already have 25115377Skarels * gateways to them). 25212227Ssam */ 25315377Skarels connect_addr = al; 25415377Skarels for (al = addrlist; al; al = al->addr_link) { 25512227Ssam register int net; 2569246Ssam 2579246Ssam /* suppress duplicates -- not optimal */ 25812227Ssam net = inet_netof(al->addr_val); 25916024Skarels if (connectedto(net) || gatewayto(net)) 26015377Skarels continue; 26115377Skarels printgateway(net, namelist->name_val, 1); 26215377Skarels (void) savegateway(namelist, net, al->addr_val, 1); 26312227Ssam } 26415377Skarels /* 26515377Skarels * Put the gateway in the hosts file. 26615377Skarels */ 26715377Skarels putaddr(hf, connect_addr->addr_val); 26815377Skarels cp = "%s"; 26915377Skarels for (nl = namelist; nl; nl = nl->name_link) { 27015377Skarels fprintf(hf, cp, lower(nl->name_val)); 27115377Skarels cp = " %s"; 2729246Ssam } 27315377Skarels fprintf(hf, "\t# gateway\n"); 27415377Skarels freeaddrs(addrlist); 27515377Skarels goto dontfree; 2768732Ssam 2778732Ssam case KW_HOST: 2789246Ssam al2 = addrlist; 2799246Ssam while (al = al2) { 28015377Skarels if (!local(inet_netof(al->addr_val))) { 2819246Ssam char *cp; 2829246Ssam 2839246Ssam putaddr(hf, al->addr_val); 2849246Ssam cp = "%s"; 2859246Ssam for (nl = namelist; nl; nl = nl->name_link) { 2869246Ssam fprintf(hf, cp, lower(nl->name_val)); 2879246Ssam cp = " %s"; 2889246Ssam } 2898732Ssam putc('\n', hf); 2908732Ssam } 2918732Ssam al2 = al->addr_link; 2929246Ssam free((char *)al); 2938732Ssam } 29415377Skarels break; 2958732Ssam 2968732Ssam default: 2978732Ssam fprintf(stderr, "Unknown keyword: %d.\n", keyword); 2988732Ssam } 2999246Ssam freenames(namelist); 30015377Skarels dontfree: 3019246Ssam freenames(protos); 3028732Ssam } 3038732Ssam 30415377Skarels printgateway(net, name, metric) 30515377Skarels int net; 30615377Skarels char *name; 30715377Skarels int metric; 30815377Skarels { 30915377Skarels struct netent *np; 31015377Skarels 31115377Skarels fprintf(gf, "net "); 31215377Skarels np = getnetbyaddr(net, AF_INET); 31315377Skarels if (np) 31415377Skarels fprintf(gf, "%s", np->n_name); 31515377Skarels else 31615377Skarels putnet(gf, net); 31715377Skarels fprintf(gf, " gateway %s metric %d passive\n", 31815377Skarels lower(name), metric); 31915377Skarels } 32015377Skarels 3219246Ssam copylocal(f, filename) 3229246Ssam FILE *f; 3239246Ssam char *filename; 3248732Ssam { 3258732Ssam register FILE *lhf; 3268732Ssam register cc; 3278732Ssam char buf[BUFSIZ]; 3289246Ssam extern int errno; 3298732Ssam 3309246Ssam lhf = fopen(filename, "r"); 3318732Ssam if (lhf == NULL) { 3329246Ssam if (errno != ENOENT) { 3339246Ssam perror(filename); 3349246Ssam exit(1); 3359246Ssam } 3369246Ssam fprintf(stderr, "Warning, no %s file.\n", filename); 3378732Ssam return; 3388732Ssam } 3398732Ssam while (cc = fread(buf, 1, sizeof(buf), lhf)) 3409246Ssam fwrite(buf, 1, cc, f); 3418732Ssam fclose(lhf); 3428732Ssam } 3439246Ssam 344*33539Sbostic copygateways(filename) 34515377Skarels char *filename; 34615377Skarels { 34715377Skarels register FILE *lhf; 34815377Skarels struct name *nl; 34915377Skarels char type[80]; 35015377Skarels char dname[80]; 35115377Skarels char gname[80]; 35215377Skarels char junk[80]; 35316066Skarels char buf[500]; 354*33539Sbostic struct in_addr addr; 35515377Skarels int net, metric; 35615377Skarels extern int errno; 35715377Skarels 35815377Skarels lhf = fopen(filename, "r"); 35915377Skarels if (lhf == NULL) { 36015377Skarels if (errno != ENOENT) { 36115377Skarels perror(filename); 36215377Skarels exit(1); 36315377Skarels } 36415377Skarels fprintf(stderr, "Warning, no %s file.\n", filename); 36515377Skarels return; 36615377Skarels } 36715377Skarels /* format: {net | host} XX gateway XX metric DD [passive]\n */ 36815789Skarels for (;;) { 36915789Skarels junk[0] = 0; 37016066Skarels if (fgets(buf, sizeof(buf), lhf) == (char *)NULL) 37115789Skarels break; 37216066Skarels fputs(buf, gf); 37316066Skarels if (buf[0] == '#' || 37416066Skarels sscanf(buf, "%s %s gateway %s metric %d %s", 37516066Skarels type, dname, gname, &metric, junk) < 5) 37616066Skarels continue; 37715377Skarels if (strcmp(type, "net")) 37816066Skarels continue; 37915377Skarels if (!getnetaddr(dname, &net)) 38016066Skarels continue; 381*33539Sbostic if (!gethostaddr(gname, &addr.s_addr)) 38216066Skarels continue; 38315377Skarels nl = newname(gname); 38415377Skarels (void) savegateway(nl, net, addr, metric); 38515377Skarels } 38615377Skarels fclose(lhf); 38715377Skarels } 38815377Skarels 38915377Skarels getnetaddr(name, addr) 39015377Skarels char *name; 39115377Skarels int *addr; 39215377Skarels { 39315377Skarels struct netent *np = getnetbyname(name); 39415377Skarels 39515377Skarels if (np == 0) { 39615377Skarels *addr = inet_network(name); 39715377Skarels return (*addr != -1); 39815377Skarels } else { 39915377Skarels if (np->n_addrtype != AF_INET) 40015377Skarels return (0); 40115377Skarels *addr = np->n_net; 40215377Skarels return (1); 40315377Skarels } 40415377Skarels } 40515377Skarels 40615377Skarels gethostaddr(name, addr) 40715377Skarels char *name; 40815377Skarels u_long *addr; 40915377Skarels { 41015377Skarels struct hostent *hp; 41115377Skarels 41215377Skarels hp = gethostbyname(name); 41315377Skarels if (hp) { 41415377Skarels *addr = *(u_long *)(hp->h_addr); 41515377Skarels return (1); 41615377Skarels } 41715377Skarels *addr = inet_addr(name); 41815377Skarels return (*addr != -1); 41915377Skarels } 42015377Skarels 42112610Smo copycomments(in, out, ccount) 42212610Smo FILE *in, *out; 42312610Smo int ccount; 42412610Smo { 42512610Smo int count; 426*33539Sbostic char buf[BUFSIZ], *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; 456*33539Sbostic struct in_addr v; 4579246Ssam { 458*33539Sbostic fprintf(f, "%-16.16s", inet_ntoa(v)); 4599246Ssam } 4609246Ssam 4619246Ssam freenames(list) 4629246Ssam struct name *list; 4639246Ssam { 4649246Ssam register struct name *nl, *nl2; 4659246Ssam 4669246Ssam nl2 = list; 4679246Ssam while (nl = nl2) { 4689246Ssam nl2 = nl->name_link; 4699246Ssam free(nl->name_val); 4709246Ssam free((char *)nl); 4719246Ssam } 4729246Ssam } 4739246Ssam 47415377Skarels freeaddrs(list) 47515377Skarels struct addr *list; 47615377Skarels { 47715377Skarels register struct addr *al, *al2; 47815377Skarels 47915377Skarels al2 = list; 48015377Skarels while (al = al2) 48115377Skarels al2 = al->addr_link, free((char *)al); 48215377Skarels } 48315377Skarels 4849246Ssam struct gateway *gateways = 0; 48515377Skarels struct gateway *lastgateway = 0; 4869246Ssam 48715377Skarels struct gateway * 48815377Skarels gatewayto(net) 4899246Ssam register int net; 4909246Ssam { 4919246Ssam register struct gateway *gp; 4929246Ssam 4939246Ssam for (gp = gateways; gp; gp = gp->g_link) 49415377Skarels if ((gp->g_net == net) && (gp->g_metric > 0)) 49515377Skarels return (gp); 49615377Skarels return ((struct gateway *) NULL); 4979246Ssam } 4989246Ssam 49915377Skarels struct gateway * 50015377Skarels savegateway(namelist, net, addr, metric) 50115377Skarels struct name *namelist; 502*33539Sbostic struct in_addr addr; 50315377Skarels int net, metric; 5049246Ssam { 5059246Ssam register struct gateway *gp; 5069246Ssam 5079246Ssam gp = (struct gateway *)malloc(sizeof (struct gateway)); 5089246Ssam if (gp == 0) { 5099246Ssam fprintf(stderr, "htable: out of memory\n"); 5109246Ssam exit(1); 5119246Ssam } 51215377Skarels gp->g_link = (struct gateway *) NULL; 51315377Skarels if (lastgateway) 51415377Skarels lastgateway->g_link = gp; 51515377Skarels else 51615377Skarels gateways = gp; 51715377Skarels lastgateway = gp; 51815377Skarels gp->g_name = namelist; 5199246Ssam gp->g_net = net; 52015377Skarels gp->g_addr = addr; 52115377Skarels gp->g_metric = metric; 52215377Skarels if (metric == 1) 52315377Skarels gp->g_dst = gp; 52427079Sbloom return (gp); 5259246Ssam } 52615377Skarels 52715377Skarels connectedto(net) 52815377Skarels u_long net; 52915377Skarels { 53015377Skarels register i; 53115377Skarels 53215377Skarels for (i = 0; i < nconnected; i++) 53315377Skarels if (connected_nets[i] == net) 53415377Skarels return(1); 53515377Skarels return(0); 53615377Skarels } 53715377Skarels 53815377Skarels local(net) 53915377Skarels u_long net; 54015377Skarels { 54115377Skarels register i; 54215377Skarels 54315377Skarels for (i = 0; i < nlocal; i++) 54415377Skarels if (local_nets[i] == net) 54515377Skarels return(1); 54615377Skarels return(0); 54715377Skarels } 54815377Skarels 54915377Skarels #define MAXHOPS 10 55015377Skarels 55115377Skarels /* 55215377Skarels * Go through list of gateways, finding connections for gateways 55315377Skarels * that are not yet connected. 55415377Skarels */ 55515377Skarels dogateways() 55615377Skarels { 55715377Skarels register struct gateway *gp, *gw, *ggp; 55815377Skarels register int hops, changed = 1; 55915377Skarels struct name *nl; 56015377Skarels char *cp; 56115377Skarels 56215377Skarels for (hops = 0; hops < MAXHOPS && changed; hops++, changed = 0) { 56315377Skarels for (gp = gateways; gp; gp = gp->g_link) 56415377Skarels if ((gp->g_metric == 0) && (gw = gatewayto(gp->g_net))) { 56515377Skarels /* 56615377Skarels * Found a new connection. 56715377Skarels * For each other network that this gateway is on, 56815377Skarels * add a new gateway to that network. 56915377Skarels */ 57015377Skarels changed = 1; 57115377Skarels gp->g_dst = gw->g_dst; 57215377Skarels gp->g_metric = gw->g_metric + 1; 57315377Skarels for (ggp = gp->g_firstent; ggp->g_name == gp->g_name; 57415377Skarels ggp = ggp->g_link) { 57515377Skarels if (ggp == gp) 57615377Skarels continue; 57715377Skarels if (gatewayto(ggp->g_net)) 57815377Skarels continue; 57915377Skarels ggp->g_dst = gp->g_dst; 58015377Skarels ggp->g_metric = gp->g_metric; 58115377Skarels printgateway(ggp->g_net, 58215377Skarels gw->g_dst->g_name->name_val, gp->g_metric); 58315377Skarels } 58415377Skarels /* 58515377Skarels * Put the gateway in the hosts file, 58615377Skarels * using the address for the connected net. 58715377Skarels */ 58815377Skarels putaddr(hf, gp->g_addr); 58915377Skarels cp = "%s"; 59015377Skarels for (nl = gp->g_name; nl; nl = nl->name_link) { 59115377Skarels fprintf(hf, cp, lower(nl->name_val)); 59215377Skarels cp = " %s"; 59315377Skarels } 59415377Skarels fprintf(hf, "\t# gateway\n"); 59515377Skarels } 59615377Skarels } 59715377Skarels } 598