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 823653Smckusick char copyright[] = 923653Smckusick "@(#) Copyright (c) 1983 Regents of the University of California.\n\ 1023653Smckusick All rights reserved.\n"; 1121125Sdist #endif not lint 128732Ssam 1323653Smckusick #ifndef lint 14*27079Sbloom static char sccsid[] = "@(#)htable.c 5.5 (Berkeley) 04/15/86"; 1523653Smckusick #endif not lint 1623653Smckusick 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); 1758732Ssam cp++; 1768732Ssam } 1778732Ssam return (str); 1788732Ssam } 1798732Ssam 1808732Ssam do_entry(keyword, addrlist, namelist, cputype, opsys, protos) 1818732Ssam int keyword; 1828732Ssam struct addr *addrlist; 1838732Ssam struct name *namelist, *cputype, *opsys, *protos; 1848732Ssam { 1858732Ssam register struct addr *al, *al2; 1869246Ssam register struct name *nl; 18715377Skarels struct addr *connect_addr; 18815377Skarels char *cp; 1898732Ssam 1908732Ssam switch (keyword) { 1918732Ssam 1928732Ssam case KW_NET: 1939246Ssam nl = namelist; 1949246Ssam if (nl == NONAME) { 1959246Ssam fprintf(stderr, "htable: net"); 19615789Skarels putnet(stderr, inet_netof(addrlist->addr_val)); 1979246Ssam fprintf(stderr, " missing names.\n"); 1989246Ssam break; 1999246Ssam } 2009246Ssam fprintf(nf, "%-16.16s", lower(nl->name_val)); 2019246Ssam al2 = addrlist; 2029246Ssam while (al = al2) { 2039246Ssam char *cp; 2048732Ssam 20515789Skarels putnet(nf, inet_netof(al->addr_val)); 2069246Ssam cp = "\t%s"; 2079246Ssam while (nl = nl->name_link) { 2089246Ssam fprintf(nf, cp, lower(nl->name_val)); 2099246Ssam cp = " %s"; 2109246Ssam } 2119246Ssam putc('\n', nf); 2129246Ssam al2 = al->addr_link; 2139246Ssam free((char *)al); 2149246Ssam } 21515377Skarels break; 2169246Ssam 2178732Ssam case KW_GATEWAY: 21815377Skarels /* locate locally connected address, if one */ 21915377Skarels for (al = addrlist; al; al = al->addr_link) 22015377Skarels if (connectedto(inet_netof(al->addr_val))) 22115377Skarels break; 22215377Skarels if (al == NULL) { 22315377Skarels /* 22415377Skarels * Not connected to known networks. Save for later. 22515377Skarels */ 22615377Skarels struct gateway *gw, *firstgw = (struct gateway *) NULL; 22715377Skarels 22815377Skarels for (al = addrlist; al; al = al->addr_link) { 22915377Skarels register int net; 23015377Skarels 23115377Skarels net = inet_netof(al->addr_val); 23215377Skarels gw = savegateway(namelist, net, 23315377Skarels al->addr_val, 0); 23415377Skarels if (firstgw == (struct gateway *) NULL) 23515377Skarels firstgw = gw; 23615377Skarels gw->g_firstent = firstgw; 23715377Skarels } 23815377Skarels freeaddrs(addrlist); 23915377Skarels goto dontfree; 24015377Skarels } 24112227Ssam /* 24215377Skarels * Connected to a known network. 24315377Skarels * Mark this as the gateway to all other networks 24415377Skarels * that are on the addrlist (unless we already have 24515377Skarels * gateways to them). 24612227Ssam */ 24715377Skarels connect_addr = al; 24815377Skarels for (al = addrlist; al; al = al->addr_link) { 24912227Ssam register int net; 2509246Ssam 2519246Ssam /* suppress duplicates -- not optimal */ 25212227Ssam net = inet_netof(al->addr_val); 25316024Skarels if (connectedto(net) || gatewayto(net)) 25415377Skarels continue; 25515377Skarels printgateway(net, namelist->name_val, 1); 25615377Skarels (void) savegateway(namelist, net, al->addr_val, 1); 25712227Ssam } 25815377Skarels /* 25915377Skarels * Put the gateway in the hosts file. 26015377Skarels */ 26115377Skarels putaddr(hf, connect_addr->addr_val); 26215377Skarels cp = "%s"; 26315377Skarels for (nl = namelist; nl; nl = nl->name_link) { 26415377Skarels fprintf(hf, cp, lower(nl->name_val)); 26515377Skarels cp = " %s"; 2669246Ssam } 26715377Skarels fprintf(hf, "\t# gateway\n"); 26815377Skarels freeaddrs(addrlist); 26915377Skarels goto dontfree; 2708732Ssam 2718732Ssam case KW_HOST: 2729246Ssam al2 = addrlist; 2739246Ssam while (al = al2) { 27415377Skarels if (!local(inet_netof(al->addr_val))) { 2759246Ssam char *cp; 2769246Ssam 2779246Ssam putaddr(hf, al->addr_val); 2789246Ssam cp = "%s"; 2799246Ssam for (nl = namelist; nl; nl = nl->name_link) { 2809246Ssam fprintf(hf, cp, lower(nl->name_val)); 2819246Ssam cp = " %s"; 2829246Ssam } 2838732Ssam putc('\n', hf); 2848732Ssam } 2858732Ssam al2 = al->addr_link; 2869246Ssam free((char *)al); 2878732Ssam } 28815377Skarels break; 2898732Ssam 2908732Ssam default: 2918732Ssam fprintf(stderr, "Unknown keyword: %d.\n", keyword); 2928732Ssam } 2939246Ssam freenames(namelist); 29415377Skarels dontfree: 2959246Ssam freenames(protos); 2968732Ssam } 2978732Ssam 29815377Skarels printgateway(net, name, metric) 29915377Skarels int net; 30015377Skarels char *name; 30115377Skarels int metric; 30215377Skarels { 30315377Skarels struct netent *np; 30415377Skarels 30515377Skarels fprintf(gf, "net "); 30615377Skarels np = getnetbyaddr(net, AF_INET); 30715377Skarels if (np) 30815377Skarels fprintf(gf, "%s", np->n_name); 30915377Skarels else 31015377Skarels putnet(gf, net); 31115377Skarels fprintf(gf, " gateway %s metric %d passive\n", 31215377Skarels lower(name), metric); 31315377Skarels } 31415377Skarels 3159246Ssam copylocal(f, filename) 3169246Ssam FILE *f; 3179246Ssam char *filename; 3188732Ssam { 3198732Ssam register FILE *lhf; 3208732Ssam register cc; 3218732Ssam char buf[BUFSIZ]; 3229246Ssam extern int errno; 3238732Ssam 3249246Ssam lhf = fopen(filename, "r"); 3258732Ssam if (lhf == NULL) { 3269246Ssam if (errno != ENOENT) { 3279246Ssam perror(filename); 3289246Ssam exit(1); 3299246Ssam } 3309246Ssam fprintf(stderr, "Warning, no %s file.\n", filename); 3318732Ssam return; 3328732Ssam } 3338732Ssam while (cc = fread(buf, 1, sizeof(buf), lhf)) 3349246Ssam fwrite(buf, 1, cc, f); 3358732Ssam fclose(lhf); 3368732Ssam } 3379246Ssam 33815377Skarels copygateways(f, filename) 33915377Skarels FILE *f; 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]; 34915377Skarels u_long 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; 37615377Skarels if (!gethostaddr(gname, &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 int n; 39015377Skarels 39115377Skarels if (np == 0) { 39215377Skarels *addr = inet_network(name); 39315377Skarels return (*addr != -1); 39415377Skarels } else { 39515377Skarels if (np->n_addrtype != AF_INET) 39615377Skarels return (0); 39715377Skarels *addr = np->n_net; 39815377Skarels return (1); 39915377Skarels } 40015377Skarels } 40115377Skarels 40215377Skarels gethostaddr(name, addr) 40315377Skarels char *name; 40415377Skarels u_long *addr; 40515377Skarels { 40615377Skarels struct hostent *hp; 40715377Skarels 40815377Skarels hp = gethostbyname(name); 40915377Skarels if (hp) { 41015377Skarels *addr = *(u_long *)(hp->h_addr); 41115377Skarels return (1); 41215377Skarels } 41315377Skarels *addr = inet_addr(name); 41415377Skarels return (*addr != -1); 41515377Skarels } 41615377Skarels 41712610Smo copycomments(in, out, ccount) 41812610Smo FILE *in, *out; 41912610Smo int ccount; 42012610Smo { 42112610Smo char buf[BUFSIZ]; 42212610Smo int length; 42312610Smo int count; 42412610Smo char *fgets(); 42512610Smo 42612610Smo for (count=0; count < ccount; count++) { 42712610Smo if ((fgets(buf, sizeof(buf), in) == NULL) || (buf[0] != ';')) 42812610Smo return; 42912610Smo buf[0] = '#'; 43012610Smo fputs(buf, out); 43112610Smo } 43212610Smo return; 43312610Smo } 4349246Ssam #define UC(b) (((int)(b))&0xff) 4359246Ssam 43615785Skarels /* 43715785Skarels * Print network number in internet-standard dot notation; 43815785Skarels * v is in host byte order. 43915785Skarels */ 4409246Ssam putnet(f, v) 4419246Ssam FILE *f; 44215789Skarels register int v; 4439246Ssam { 44415785Skarels if (v < 128) 44515785Skarels fprintf(f, "%d", v); 44615785Skarels else if (v < 65536) 44715789Skarels fprintf(f, "%d.%d", UC(v >> 8), UC(v)); 4489246Ssam else 44915789Skarels fprintf(f, "%d.%d.%d", UC(v >> 16), UC(v >> 8), UC(v)); 4509246Ssam } 4519246Ssam 4529246Ssam putaddr(f, v) 4539246Ssam FILE *f; 4549246Ssam u_long v; 4559246Ssam { 4569246Ssam register char *a = (char *)&v; 4579246Ssam char buf[32]; 4589246Ssam 4599246Ssam sprintf(buf,"%d.%d.%d.%d", UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3])); 4609246Ssam fprintf(f, "%-16.16s", buf); 4619246Ssam } 4629246Ssam 4639246Ssam freenames(list) 4649246Ssam struct name *list; 4659246Ssam { 4669246Ssam register struct name *nl, *nl2; 4679246Ssam 4689246Ssam nl2 = list; 4699246Ssam while (nl = nl2) { 4709246Ssam nl2 = nl->name_link; 4719246Ssam free(nl->name_val); 4729246Ssam free((char *)nl); 4739246Ssam } 4749246Ssam } 4759246Ssam 47615377Skarels freeaddrs(list) 47715377Skarels struct addr *list; 47815377Skarels { 47915377Skarels register struct addr *al, *al2; 48015377Skarels 48115377Skarels al2 = list; 48215377Skarels while (al = al2) 48315377Skarels al2 = al->addr_link, free((char *)al); 48415377Skarels } 48515377Skarels 4869246Ssam struct gateway *gateways = 0; 48715377Skarels struct gateway *lastgateway = 0; 4889246Ssam 48915377Skarels struct gateway * 49015377Skarels gatewayto(net) 4919246Ssam register int net; 4929246Ssam { 4939246Ssam register struct gateway *gp; 4949246Ssam 4959246Ssam for (gp = gateways; gp; gp = gp->g_link) 49615377Skarels if ((gp->g_net == net) && (gp->g_metric > 0)) 49715377Skarels return (gp); 49815377Skarels return ((struct gateway *) NULL); 4999246Ssam } 5009246Ssam 50115377Skarels struct gateway * 50215377Skarels savegateway(namelist, net, addr, metric) 50315377Skarels struct name *namelist; 50415377Skarels u_long addr; 50515377Skarels int net, metric; 5069246Ssam { 5079246Ssam register struct gateway *gp; 5089246Ssam 5099246Ssam gp = (struct gateway *)malloc(sizeof (struct gateway)); 5109246Ssam if (gp == 0) { 5119246Ssam fprintf(stderr, "htable: out of memory\n"); 5129246Ssam exit(1); 5139246Ssam } 51415377Skarels gp->g_link = (struct gateway *) NULL; 51515377Skarels if (lastgateway) 51615377Skarels lastgateway->g_link = gp; 51715377Skarels else 51815377Skarels gateways = gp; 51915377Skarels lastgateway = gp; 52015377Skarels gp->g_name = namelist; 5219246Ssam gp->g_net = net; 52215377Skarels gp->g_addr = addr; 52315377Skarels gp->g_metric = metric; 52415377Skarels if (metric == 1) 52515377Skarels gp->g_dst = gp; 526*27079Sbloom return (gp); 5279246Ssam } 52815377Skarels 52915377Skarels connectedto(net) 53015377Skarels u_long net; 53115377Skarels { 53215377Skarels register i; 53315377Skarels 53415377Skarels for (i = 0; i < nconnected; i++) 53515377Skarels if (connected_nets[i] == net) 53615377Skarels return(1); 53715377Skarels return(0); 53815377Skarels } 53915377Skarels 54015377Skarels local(net) 54115377Skarels u_long net; 54215377Skarels { 54315377Skarels register i; 54415377Skarels 54515377Skarels for (i = 0; i < nlocal; i++) 54615377Skarels if (local_nets[i] == net) 54715377Skarels return(1); 54815377Skarels return(0); 54915377Skarels } 55015377Skarels 55115377Skarels #define MAXHOPS 10 55215377Skarels 55315377Skarels /* 55415377Skarels * Go through list of gateways, finding connections for gateways 55515377Skarels * that are not yet connected. 55615377Skarels */ 55715377Skarels dogateways() 55815377Skarels { 55915377Skarels register struct gateway *gp, *gw, *ggp; 56015377Skarels register int hops, changed = 1; 56115377Skarels struct name *nl; 56215377Skarels char *cp; 56315377Skarels 56415377Skarels for (hops = 0; hops < MAXHOPS && changed; hops++, changed = 0) { 56515377Skarels for (gp = gateways; gp; gp = gp->g_link) 56615377Skarels if ((gp->g_metric == 0) && (gw = gatewayto(gp->g_net))) { 56715377Skarels /* 56815377Skarels * Found a new connection. 56915377Skarels * For each other network that this gateway is on, 57015377Skarels * add a new gateway to that network. 57115377Skarels */ 57215377Skarels changed = 1; 57315377Skarels gp->g_dst = gw->g_dst; 57415377Skarels gp->g_metric = gw->g_metric + 1; 57515377Skarels for (ggp = gp->g_firstent; ggp->g_name == gp->g_name; 57615377Skarels ggp = ggp->g_link) { 57715377Skarels if (ggp == gp) 57815377Skarels continue; 57915377Skarels if (gatewayto(ggp->g_net)) 58015377Skarels continue; 58115377Skarels ggp->g_dst = gp->g_dst; 58215377Skarels ggp->g_metric = gp->g_metric; 58315377Skarels printgateway(ggp->g_net, 58415377Skarels gw->g_dst->g_name->name_val, gp->g_metric); 58515377Skarels } 58615377Skarels /* 58715377Skarels * Put the gateway in the hosts file, 58815377Skarels * using the address for the connected net. 58915377Skarels */ 59015377Skarels putaddr(hf, gp->g_addr); 59115377Skarels cp = "%s"; 59215377Skarels for (nl = gp->g_name; nl; nl = nl->name_link) { 59315377Skarels fprintf(hf, cp, lower(nl->name_val)); 59415377Skarels cp = " %s"; 59515377Skarels } 59615377Skarels fprintf(hf, "\t# gateway\n"); 59715377Skarels } 59815377Skarels } 59915377Skarels } 600