1*21125Sdist /* 2*21125Sdist * Copyright (c) 1980 Regents of the University of California. 3*21125Sdist * All rights reserved. The Berkeley software License Agreement 4*21125Sdist * specifies the terms and conditions for redistribution. 5*21125Sdist */ 6*21125Sdist 78732Ssam #ifndef lint 8*21125Sdist static char sccsid[] = "@(#)htable.c 5.1 (Berkeley) 05/28/85"; 9*21125Sdist #endif not lint 108732Ssam 118732Ssam /* 128732Ssam * htable - convert NIC host table into a UNIX format. 138732Ssam * NIC format is described in RFC 810, 1 March 1982. 148732Ssam */ 158732Ssam #include <stdio.h> 168732Ssam #include <ctype.h> 179246Ssam #include <errno.h> 1812227Ssam #include <netdb.h> 1912227Ssam 209246Ssam #include "htable.h" /* includes <sys/types.h> */ 218732Ssam 2213193Ssam #include <sys/socket.h> 239246Ssam #include <netinet/in.h> 248732Ssam 2512610Smo #define DATELINES 3 /* these lines usually contain the date */ 2615377Skarels #define MAXNETS 30 /* array size for local, connected nets */ 2712610Smo 289246Ssam FILE *hf; /* hosts file */ 299246Ssam FILE *gf; /* gateways file */ 309246Ssam FILE *nf; /* networks file */ 3115377Skarels struct gateway *savegateway(), *gatewayto(); 329246Ssam 3315377Skarels int connected_nets[MAXNETS]; 3415377Skarels int nconnected; 3515377Skarels int local_nets[MAXNETS]; 3615377Skarels int nlocal; 3715377Skarels char *myname; 3815377Skarels 398732Ssam main(argc, argv) 408732Ssam int argc; 418732Ssam char *argv[]; 428732Ssam { 4315377Skarels int errs; 4415377Skarels 458732Ssam infile = "(stdin)"; 4615377Skarels myname = argv[0]; 4715377Skarels argc--; 4815377Skarels argv++; 4915377Skarels while (argc--) { 5015377Skarels if (*argv[0] == '-') { 5115377Skarels switch (argv[0][1]) { 5215377Skarels case 'c': 5315377Skarels nconnected = addlocal(argv[1], connected_nets); 5415377Skarels argv++; 5515377Skarels argc--; 5615377Skarels break; 5715377Skarels case 'l': 5815377Skarels nlocal = addlocal(argv[1], local_nets); 5915377Skarels argv++; 6015377Skarels argc--; 6115377Skarels break; 6215377Skarels default: 6315377Skarels usage(); 6415377Skarels /*NOTREACHED*/ 6515377Skarels } 6615377Skarels } else { 6715377Skarels infile = argv[0]; 6815377Skarels if (freopen(infile, "r", stdin) == NULL) { 6915377Skarels perror(infile); 7015377Skarels exit(1); 7115377Skarels } 728732Ssam } 7315377Skarels argv++; 748732Ssam } 758732Ssam hf = fopen("hosts", "w"); 768732Ssam if (hf == NULL) { 778732Ssam perror("hosts"); 788732Ssam exit(1); 798732Ssam } 809246Ssam copylocal(hf, "localhosts"); 819246Ssam gf = fopen("gateways", "w"); 829246Ssam if (gf == NULL) { 838732Ssam perror("gateways"); 848732Ssam exit(1); 858732Ssam } 8615377Skarels copygateways(gf, "localgateways"); 879246Ssam nf = fopen("networks", "w"); 889246Ssam if (nf == NULL) { 899246Ssam perror("networks"); 909246Ssam exit(1); 919246Ssam } 929246Ssam copylocal(nf, "localnetworks"); 9312610Smo copycomments(stdin, hf, DATELINES); 9415377Skarels errs = yyparse(); 9515377Skarels dogateways(); 9615377Skarels exit(errs); 978732Ssam } 988732Ssam 9915377Skarels usage() 10015377Skarels { 10115377Skarels fprintf(stderr, 10215377Skarels "usage: %s [ -c connected-nets ] [-l local-nets ] [ input-file ]\n", 10315377Skarels myname); 10415377Skarels exit(1); 10515377Skarels } 10615377Skarels 10715377Skarels /* 10815377Skarels * Turn a comma-separated list of network names or numbers in dot notation 10915377Skarels * (e.g. "arpanet, 128.32") into an array of net numbers. 11015377Skarels */ 11115377Skarels addlocal(arg, nets) 11215377Skarels char *arg; 11315377Skarels int *nets; 11415377Skarels { 11515377Skarels register char *p, c; 11615377Skarels register int nfound = 0; 11715377Skarels 11815377Skarels do { 11915377Skarels p = arg; 12015377Skarels while (*p && *p != ',' && !isspace(*p)) 12115377Skarels p++; 12215377Skarels c = *p; 12315377Skarels *p = 0; 12415377Skarels while (*arg && isspace(*arg)) 12515377Skarels arg++; 12615377Skarels if (*arg == 0) 12715377Skarels continue; 12815377Skarels if (nfound == MAXNETS) { 12915377Skarels fprintf(stderr, "%s: Too many networks in list\n", 13015377Skarels myname); 13115377Skarels return (nfound); 13215377Skarels } 13315377Skarels if (getnetaddr(arg, &nets[nfound])) 13415377Skarels nfound++; 13515377Skarels else { 13615377Skarels fprintf(stderr, "%s: %s: unknown network\n", 13715377Skarels myname, arg); 13815377Skarels exit(1); 13915377Skarels } 14015379Skarels arg = p + 1; 14115377Skarels } while (c); 14215377Skarels return (nfound); 14315377Skarels } 14415377Skarels 1458732Ssam struct name * 1468732Ssam newname(str) 1478732Ssam char *str; 1488732Ssam { 1498732Ssam char *p; 1508732Ssam struct name *nm; 1518732Ssam 1528732Ssam p = malloc(strlen(str) + 1); 1538732Ssam strcpy(p, str); 1549246Ssam nm = (struct name *)malloc(sizeof (struct name)); 1558732Ssam nm->name_val = p; 1568732Ssam nm->name_link = NONAME; 1578732Ssam return (nm); 1588732Ssam } 1598732Ssam 1608732Ssam char * 1618732Ssam lower(str) 1628732Ssam char *str; 1638732Ssam { 1648732Ssam register char *cp = str; 1658732Ssam 1668732Ssam while (*cp) { 1678732Ssam if (isupper(*cp)) 1688732Ssam *cp = tolower(*cp); 16916230Skarels if (*cp == '.') 17016230Skarels break; 1718732Ssam cp++; 1728732Ssam } 1738732Ssam return (str); 1748732Ssam } 1758732Ssam 1768732Ssam do_entry(keyword, addrlist, namelist, cputype, opsys, protos) 1778732Ssam int keyword; 1788732Ssam struct addr *addrlist; 1798732Ssam struct name *namelist, *cputype, *opsys, *protos; 1808732Ssam { 1818732Ssam register struct addr *al, *al2; 1829246Ssam register struct name *nl; 18315377Skarels struct addr *connect_addr; 18415377Skarels char *cp; 1858732Ssam 1868732Ssam switch (keyword) { 1878732Ssam 1888732Ssam case KW_NET: 1899246Ssam nl = namelist; 1909246Ssam if (nl == NONAME) { 1919246Ssam fprintf(stderr, "htable: net"); 19215789Skarels putnet(stderr, inet_netof(addrlist->addr_val)); 1939246Ssam fprintf(stderr, " missing names.\n"); 1949246Ssam break; 1959246Ssam } 1969246Ssam fprintf(nf, "%-16.16s", lower(nl->name_val)); 1979246Ssam al2 = addrlist; 1989246Ssam while (al = al2) { 1999246Ssam char *cp; 2008732Ssam 20115789Skarels putnet(nf, inet_netof(al->addr_val)); 2029246Ssam cp = "\t%s"; 2039246Ssam while (nl = nl->name_link) { 2049246Ssam fprintf(nf, cp, lower(nl->name_val)); 2059246Ssam cp = " %s"; 2069246Ssam } 2079246Ssam putc('\n', nf); 2089246Ssam al2 = al->addr_link; 2099246Ssam free((char *)al); 2109246Ssam } 21115377Skarels break; 2129246Ssam 2138732Ssam case KW_GATEWAY: 21415377Skarels /* locate locally connected address, if one */ 21515377Skarels for (al = addrlist; al; al = al->addr_link) 21615377Skarels if (connectedto(inet_netof(al->addr_val))) 21715377Skarels break; 21815377Skarels if (al == NULL) { 21915377Skarels /* 22015377Skarels * Not connected to known networks. Save for later. 22115377Skarels */ 22215377Skarels struct gateway *gw, *firstgw = (struct gateway *) NULL; 22315377Skarels 22415377Skarels for (al = addrlist; al; al = al->addr_link) { 22515377Skarels register int net; 22615377Skarels 22715377Skarels net = inet_netof(al->addr_val); 22815377Skarels gw = savegateway(namelist, net, 22915377Skarels al->addr_val, 0); 23015377Skarels if (firstgw == (struct gateway *) NULL) 23115377Skarels firstgw = gw; 23215377Skarels gw->g_firstent = firstgw; 23315377Skarels } 23415377Skarels freeaddrs(addrlist); 23515377Skarels goto dontfree; 23615377Skarels } 23712227Ssam /* 23815377Skarels * Connected to a known network. 23915377Skarels * Mark this as the gateway to all other networks 24015377Skarels * that are on the addrlist (unless we already have 24115377Skarels * gateways to them). 24212227Ssam */ 24315377Skarels connect_addr = al; 24415377Skarels for (al = addrlist; al; al = al->addr_link) { 24512227Ssam register int net; 2469246Ssam 2479246Ssam /* suppress duplicates -- not optimal */ 24812227Ssam net = inet_netof(al->addr_val); 24916024Skarels if (connectedto(net) || gatewayto(net)) 25015377Skarels continue; 25115377Skarels printgateway(net, namelist->name_val, 1); 25215377Skarels (void) savegateway(namelist, net, al->addr_val, 1); 25312227Ssam } 25415377Skarels /* 25515377Skarels * Put the gateway in the hosts file. 25615377Skarels */ 25715377Skarels putaddr(hf, connect_addr->addr_val); 25815377Skarels cp = "%s"; 25915377Skarels for (nl = namelist; nl; nl = nl->name_link) { 26015377Skarels fprintf(hf, cp, lower(nl->name_val)); 26115377Skarels cp = " %s"; 2629246Ssam } 26315377Skarels fprintf(hf, "\t# gateway\n"); 26415377Skarels freeaddrs(addrlist); 26515377Skarels goto dontfree; 2668732Ssam 2678732Ssam case KW_HOST: 2689246Ssam al2 = addrlist; 2699246Ssam while (al = al2) { 27015377Skarels if (!local(inet_netof(al->addr_val))) { 2719246Ssam char *cp; 2729246Ssam 2739246Ssam putaddr(hf, al->addr_val); 2749246Ssam cp = "%s"; 2759246Ssam for (nl = namelist; nl; nl = nl->name_link) { 2769246Ssam fprintf(hf, cp, lower(nl->name_val)); 2779246Ssam cp = " %s"; 2789246Ssam } 2798732Ssam putc('\n', hf); 2808732Ssam } 2818732Ssam al2 = al->addr_link; 2829246Ssam free((char *)al); 2838732Ssam } 28415377Skarels break; 2858732Ssam 2868732Ssam default: 2878732Ssam fprintf(stderr, "Unknown keyword: %d.\n", keyword); 2888732Ssam } 2899246Ssam freenames(namelist); 29015377Skarels dontfree: 2919246Ssam freenames(protos); 2928732Ssam } 2938732Ssam 29415377Skarels printgateway(net, name, metric) 29515377Skarels int net; 29615377Skarels char *name; 29715377Skarels int metric; 29815377Skarels { 29915377Skarels struct netent *np; 30015377Skarels 30115377Skarels fprintf(gf, "net "); 30215377Skarels np = getnetbyaddr(net, AF_INET); 30315377Skarels if (np) 30415377Skarels fprintf(gf, "%s", np->n_name); 30515377Skarels else 30615377Skarels putnet(gf, net); 30715377Skarels fprintf(gf, " gateway %s metric %d passive\n", 30815377Skarels lower(name), metric); 30915377Skarels } 31015377Skarels 3119246Ssam copylocal(f, filename) 3129246Ssam FILE *f; 3139246Ssam char *filename; 3148732Ssam { 3158732Ssam register FILE *lhf; 3168732Ssam register cc; 3178732Ssam char buf[BUFSIZ]; 3189246Ssam extern int errno; 3198732Ssam 3209246Ssam lhf = fopen(filename, "r"); 3218732Ssam if (lhf == NULL) { 3229246Ssam if (errno != ENOENT) { 3239246Ssam perror(filename); 3249246Ssam exit(1); 3259246Ssam } 3269246Ssam fprintf(stderr, "Warning, no %s file.\n", filename); 3278732Ssam return; 3288732Ssam } 3298732Ssam while (cc = fread(buf, 1, sizeof(buf), lhf)) 3309246Ssam fwrite(buf, 1, cc, f); 3318732Ssam fclose(lhf); 3328732Ssam } 3339246Ssam 33415377Skarels copygateways(f, filename) 33515377Skarels FILE *f; 33615377Skarels char *filename; 33715377Skarels { 33815377Skarels register FILE *lhf; 33915377Skarels struct name *nl; 34015377Skarels char type[80]; 34115377Skarels char dname[80]; 34215377Skarels char gname[80]; 34315377Skarels char junk[80]; 34416066Skarels char buf[500]; 34515377Skarels u_long addr; 34615377Skarels int net, metric; 34715377Skarels extern int errno; 34815377Skarels 34915377Skarels lhf = fopen(filename, "r"); 35015377Skarels if (lhf == NULL) { 35115377Skarels if (errno != ENOENT) { 35215377Skarels perror(filename); 35315377Skarels exit(1); 35415377Skarels } 35515377Skarels fprintf(stderr, "Warning, no %s file.\n", filename); 35615377Skarels return; 35715377Skarels } 35815377Skarels /* format: {net | host} XX gateway XX metric DD [passive]\n */ 35915789Skarels for (;;) { 36015789Skarels junk[0] = 0; 36116066Skarels if (fgets(buf, sizeof(buf), lhf) == (char *)NULL) 36215789Skarels break; 36316066Skarels fputs(buf, gf); 36416066Skarels if (buf[0] == '#' || 36516066Skarels sscanf(buf, "%s %s gateway %s metric %d %s", 36616066Skarels type, dname, gname, &metric, junk) < 5) 36716066Skarels continue; 36815377Skarels if (strcmp(type, "net")) 36916066Skarels continue; 37015377Skarels if (!getnetaddr(dname, &net)) 37116066Skarels continue; 37215377Skarels if (!gethostaddr(gname, &addr)) 37316066Skarels continue; 37415377Skarels nl = newname(gname); 37515377Skarels (void) savegateway(nl, net, addr, metric); 37615377Skarels } 37715377Skarels fclose(lhf); 37815377Skarels } 37915377Skarels 38015377Skarels getnetaddr(name, addr) 38115377Skarels char *name; 38215377Skarels int *addr; 38315377Skarels { 38415377Skarels struct netent *np = getnetbyname(name); 38515377Skarels int n; 38615377Skarels 38715377Skarels if (np == 0) { 38815377Skarels *addr = inet_network(name); 38915377Skarels return (*addr != -1); 39015377Skarels } else { 39115377Skarels if (np->n_addrtype != AF_INET) 39215377Skarels return (0); 39315377Skarels *addr = np->n_net; 39415377Skarels return (1); 39515377Skarels } 39615377Skarels } 39715377Skarels 39815377Skarels gethostaddr(name, addr) 39915377Skarels char *name; 40015377Skarels u_long *addr; 40115377Skarels { 40215377Skarels struct hostent *hp; 40315377Skarels 40415377Skarels hp = gethostbyname(name); 40515377Skarels if (hp) { 40615377Skarels *addr = *(u_long *)(hp->h_addr); 40715377Skarels return (1); 40815377Skarels } 40915377Skarels *addr = inet_addr(name); 41015377Skarels return (*addr != -1); 41115377Skarels } 41215377Skarels 41312610Smo copycomments(in, out, ccount) 41412610Smo FILE *in, *out; 41512610Smo int ccount; 41612610Smo { 41712610Smo char buf[BUFSIZ]; 41812610Smo int length; 41912610Smo int count; 42012610Smo char *fgets(); 42112610Smo 42212610Smo for (count=0; count < ccount; count++) { 42312610Smo if ((fgets(buf, sizeof(buf), in) == NULL) || (buf[0] != ';')) 42412610Smo return; 42512610Smo buf[0] = '#'; 42612610Smo fputs(buf, out); 42712610Smo } 42812610Smo return; 42912610Smo } 4309246Ssam #define UC(b) (((int)(b))&0xff) 4319246Ssam 43215785Skarels /* 43315785Skarels * Print network number in internet-standard dot notation; 43415785Skarels * v is in host byte order. 43515785Skarels */ 4369246Ssam putnet(f, v) 4379246Ssam FILE *f; 43815789Skarels register int v; 4399246Ssam { 44015785Skarels if (v < 128) 44115785Skarels fprintf(f, "%d", v); 44215785Skarels else if (v < 65536) 44315789Skarels fprintf(f, "%d.%d", UC(v >> 8), UC(v)); 4449246Ssam else 44515789Skarels fprintf(f, "%d.%d.%d", UC(v >> 16), UC(v >> 8), UC(v)); 4469246Ssam } 4479246Ssam 4489246Ssam putaddr(f, v) 4499246Ssam FILE *f; 4509246Ssam u_long v; 4519246Ssam { 4529246Ssam register char *a = (char *)&v; 4539246Ssam char buf[32]; 4549246Ssam 4559246Ssam sprintf(buf,"%d.%d.%d.%d", UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3])); 4569246Ssam fprintf(f, "%-16.16s", buf); 4579246Ssam } 4589246Ssam 4599246Ssam freenames(list) 4609246Ssam struct name *list; 4619246Ssam { 4629246Ssam register struct name *nl, *nl2; 4639246Ssam 4649246Ssam nl2 = list; 4659246Ssam while (nl = nl2) { 4669246Ssam nl2 = nl->name_link; 4679246Ssam free(nl->name_val); 4689246Ssam free((char *)nl); 4699246Ssam } 4709246Ssam } 4719246Ssam 47215377Skarels freeaddrs(list) 47315377Skarels struct addr *list; 47415377Skarels { 47515377Skarels register struct addr *al, *al2; 47615377Skarels 47715377Skarels al2 = list; 47815377Skarels while (al = al2) 47915377Skarels al2 = al->addr_link, free((char *)al); 48015377Skarels } 48115377Skarels 4829246Ssam struct gateway *gateways = 0; 48315377Skarels struct gateway *lastgateway = 0; 4849246Ssam 48515377Skarels struct gateway * 48615377Skarels gatewayto(net) 4879246Ssam register int net; 4889246Ssam { 4899246Ssam register struct gateway *gp; 4909246Ssam 4919246Ssam for (gp = gateways; gp; gp = gp->g_link) 49215377Skarels if ((gp->g_net == net) && (gp->g_metric > 0)) 49315377Skarels return (gp); 49415377Skarels return ((struct gateway *) NULL); 4959246Ssam } 4969246Ssam 49715377Skarels struct gateway * 49815377Skarels savegateway(namelist, net, addr, metric) 49915377Skarels struct name *namelist; 50015377Skarels u_long addr; 50115377Skarels int net, metric; 5029246Ssam { 5039246Ssam register struct gateway *gp; 5049246Ssam 5059246Ssam gp = (struct gateway *)malloc(sizeof (struct gateway)); 5069246Ssam if (gp == 0) { 5079246Ssam fprintf(stderr, "htable: out of memory\n"); 5089246Ssam exit(1); 5099246Ssam } 51015377Skarels gp->g_link = (struct gateway *) NULL; 51115377Skarels if (lastgateway) 51215377Skarels lastgateway->g_link = gp; 51315377Skarels else 51415377Skarels gateways = gp; 51515377Skarels lastgateway = gp; 51615377Skarels gp->g_name = namelist; 5179246Ssam gp->g_net = net; 51815377Skarels gp->g_addr = addr; 51915377Skarels gp->g_metric = metric; 52015377Skarels if (metric == 1) 52115377Skarels gp->g_dst = gp; 5229246Ssam } 52315377Skarels 52415377Skarels connectedto(net) 52515377Skarels u_long net; 52615377Skarels { 52715377Skarels register i; 52815377Skarels 52915377Skarels for (i = 0; i < nconnected; i++) 53015377Skarels if (connected_nets[i] == net) 53115377Skarels return(1); 53215377Skarels return(0); 53315377Skarels } 53415377Skarels 53515377Skarels local(net) 53615377Skarels u_long net; 53715377Skarels { 53815377Skarels register i; 53915377Skarels 54015377Skarels for (i = 0; i < nlocal; i++) 54115377Skarels if (local_nets[i] == net) 54215377Skarels return(1); 54315377Skarels return(0); 54415377Skarels } 54515377Skarels 54615377Skarels #define MAXHOPS 10 54715377Skarels 54815377Skarels /* 54915377Skarels * Go through list of gateways, finding connections for gateways 55015377Skarels * that are not yet connected. 55115377Skarels */ 55215377Skarels dogateways() 55315377Skarels { 55415377Skarels register struct gateway *gp, *gw, *ggp; 55515377Skarels register int hops, changed = 1; 55615377Skarels struct name *nl; 55715377Skarels char *cp; 55815377Skarels 55915377Skarels for (hops = 0; hops < MAXHOPS && changed; hops++, changed = 0) { 56015377Skarels for (gp = gateways; gp; gp = gp->g_link) 56115377Skarels if ((gp->g_metric == 0) && (gw = gatewayto(gp->g_net))) { 56215377Skarels /* 56315377Skarels * Found a new connection. 56415377Skarels * For each other network that this gateway is on, 56515377Skarels * add a new gateway to that network. 56615377Skarels */ 56715377Skarels changed = 1; 56815377Skarels gp->g_dst = gw->g_dst; 56915377Skarels gp->g_metric = gw->g_metric + 1; 57015377Skarels for (ggp = gp->g_firstent; ggp->g_name == gp->g_name; 57115377Skarels ggp = ggp->g_link) { 57215377Skarels if (ggp == gp) 57315377Skarels continue; 57415377Skarels if (gatewayto(ggp->g_net)) 57515377Skarels continue; 57615377Skarels ggp->g_dst = gp->g_dst; 57715377Skarels ggp->g_metric = gp->g_metric; 57815377Skarels printgateway(ggp->g_net, 57915377Skarels gw->g_dst->g_name->name_val, gp->g_metric); 58015377Skarels } 58115377Skarels /* 58215377Skarels * Put the gateway in the hosts file, 58315377Skarels * using the address for the connected net. 58415377Skarels */ 58515377Skarels putaddr(hf, gp->g_addr); 58615377Skarels cp = "%s"; 58715377Skarels for (nl = gp->g_name; nl; nl = nl->name_link) { 58815377Skarels fprintf(hf, cp, lower(nl->name_val)); 58915377Skarels cp = " %s"; 59015377Skarels } 59115377Skarels fprintf(hf, "\t# gateway\n"); 59215377Skarels } 59315377Skarels } 59415377Skarels } 595