18732Ssam #ifndef lint 2*15377Skarels static char sccsid[] = "@(#)htable.c 4.6 (Berkeley) 11/03/83"; 38732Ssam #endif 48732Ssam 58732Ssam /* 68732Ssam * htable - convert NIC host table into a UNIX format. 78732Ssam * NIC format is described in RFC 810, 1 March 1982. 88732Ssam */ 98732Ssam #include <stdio.h> 108732Ssam #include <ctype.h> 119246Ssam #include <errno.h> 1212227Ssam #include <netdb.h> 1312227Ssam 149246Ssam #include "htable.h" /* includes <sys/types.h> */ 158732Ssam 1613193Ssam #include <sys/socket.h> 179246Ssam #include <netinet/in.h> 188732Ssam 1912610Smo #define DATELINES 3 /* these lines usually contain the date */ 20*15377Skarels #define MAXNETS 30 /* array size for local, connected nets */ 2112610Smo 229246Ssam FILE *hf; /* hosts file */ 239246Ssam FILE *gf; /* gateways file */ 249246Ssam FILE *nf; /* networks file */ 25*15377Skarels struct gateway *savegateway(), *gatewayto(); 269246Ssam 27*15377Skarels int connected_nets[MAXNETS]; 28*15377Skarels int nconnected; 29*15377Skarels int local_nets[MAXNETS]; 30*15377Skarels int nlocal; 31*15377Skarels char *myname; 32*15377Skarels 338732Ssam main(argc, argv) 348732Ssam int argc; 358732Ssam char *argv[]; 368732Ssam { 37*15377Skarels int errs; 38*15377Skarels 398732Ssam infile = "(stdin)"; 40*15377Skarels myname = argv[0]; 41*15377Skarels argc--; 42*15377Skarels argv++; 43*15377Skarels while (argc--) { 44*15377Skarels if (*argv[0] == '-') { 45*15377Skarels switch (argv[0][1]) { 46*15377Skarels case 'c': 47*15377Skarels nconnected = addlocal(argv[1], connected_nets); 48*15377Skarels argv++; 49*15377Skarels argc--; 50*15377Skarels break; 51*15377Skarels case 'l': 52*15377Skarels nlocal = addlocal(argv[1], local_nets); 53*15377Skarels argv++; 54*15377Skarels argc--; 55*15377Skarels break; 56*15377Skarels default: 57*15377Skarels usage(); 58*15377Skarels /*NOTREACHED*/ 59*15377Skarels } 60*15377Skarels } else { 61*15377Skarels infile = argv[0]; 62*15377Skarels if (freopen(infile, "r", stdin) == NULL) { 63*15377Skarels perror(infile); 64*15377Skarels exit(1); 65*15377Skarels } 668732Ssam } 67*15377Skarels argv++; 688732Ssam } 698732Ssam hf = fopen("hosts", "w"); 708732Ssam if (hf == NULL) { 718732Ssam perror("hosts"); 728732Ssam exit(1); 738732Ssam } 749246Ssam copylocal(hf, "localhosts"); 759246Ssam gf = fopen("gateways", "w"); 769246Ssam if (gf == NULL) { 778732Ssam perror("gateways"); 788732Ssam exit(1); 798732Ssam } 80*15377Skarels copygateways(gf, "localgateways"); 819246Ssam nf = fopen("networks", "w"); 829246Ssam if (nf == NULL) { 839246Ssam perror("networks"); 849246Ssam exit(1); 859246Ssam } 869246Ssam copylocal(nf, "localnetworks"); 8712610Smo copycomments(stdin, hf, DATELINES); 88*15377Skarels errs = yyparse(); 89*15377Skarels dogateways(); 90*15377Skarels exit(errs); 918732Ssam } 928732Ssam 93*15377Skarels usage() 94*15377Skarels { 95*15377Skarels fprintf(stderr, 96*15377Skarels "usage: %s [ -c connected-nets ] [-l local-nets ] [ input-file ]\n", 97*15377Skarels myname); 98*15377Skarels exit(1); 99*15377Skarels } 100*15377Skarels 101*15377Skarels /* 102*15377Skarels * Turn a comma-separated list of network names or numbers in dot notation 103*15377Skarels * (e.g. "arpanet, 128.32") into an array of net numbers. 104*15377Skarels */ 105*15377Skarels addlocal(arg, nets) 106*15377Skarels char *arg; 107*15377Skarels int *nets; 108*15377Skarels { 109*15377Skarels register char *p, c; 110*15377Skarels register int nfound = 0; 111*15377Skarels 112*15377Skarels do { 113*15377Skarels p = arg; 114*15377Skarels while (*p && *p != ',' && !isspace(*p)) 115*15377Skarels p++; 116*15377Skarels c = *p; 117*15377Skarels *p = 0; 118*15377Skarels while (*arg && isspace(*arg)) 119*15377Skarels arg++; 120*15377Skarels if (*arg == 0) 121*15377Skarels continue; 122*15377Skarels if (nfound == MAXNETS) { 123*15377Skarels fprintf(stderr, "%s: Too many networks in list\n", 124*15377Skarels myname); 125*15377Skarels return (nfound); 126*15377Skarels } 127*15377Skarels if (getnetaddr(arg, &nets[nfound])) 128*15377Skarels nfound++; 129*15377Skarels else { 130*15377Skarels fprintf(stderr, "%s: %s: unknown network\n", 131*15377Skarels myname, arg); 132*15377Skarels exit(1); 133*15377Skarels } 134*15377Skarels } while (c); 135*15377Skarels return (nfound); 136*15377Skarels } 137*15377Skarels 1388732Ssam struct name * 1398732Ssam newname(str) 1408732Ssam char *str; 1418732Ssam { 1428732Ssam char *p; 1438732Ssam struct name *nm; 1448732Ssam 1458732Ssam p = malloc(strlen(str) + 1); 1468732Ssam strcpy(p, str); 1479246Ssam nm = (struct name *)malloc(sizeof (struct name)); 1488732Ssam nm->name_val = p; 1498732Ssam nm->name_link = NONAME; 1508732Ssam return (nm); 1518732Ssam } 1528732Ssam 1538732Ssam char * 1548732Ssam lower(str) 1558732Ssam char *str; 1568732Ssam { 1578732Ssam register char *cp = str; 1588732Ssam 1598732Ssam while (*cp) { 1608732Ssam if (isupper(*cp)) 1618732Ssam *cp = tolower(*cp); 1628732Ssam cp++; 1638732Ssam } 1648732Ssam return (str); 1658732Ssam } 1668732Ssam 1678732Ssam do_entry(keyword, addrlist, namelist, cputype, opsys, protos) 1688732Ssam int keyword; 1698732Ssam struct addr *addrlist; 1708732Ssam struct name *namelist, *cputype, *opsys, *protos; 1718732Ssam { 1728732Ssam register struct addr *al, *al2; 1739246Ssam register struct name *nl; 174*15377Skarels struct addr *connect_addr; 175*15377Skarels char *cp; 1768732Ssam 1778732Ssam switch (keyword) { 1788732Ssam 1798732Ssam case KW_NET: 1809246Ssam nl = namelist; 1819246Ssam if (nl == NONAME) { 1829246Ssam fprintf(stderr, "htable: net"); 1839246Ssam putnet(stderr, addrlist->addr_val); 1849246Ssam fprintf(stderr, " missing names.\n"); 1859246Ssam break; 1869246Ssam } 1879246Ssam fprintf(nf, "%-16.16s", lower(nl->name_val)); 1889246Ssam al2 = addrlist; 1899246Ssam while (al = al2) { 1909246Ssam char *cp; 1918732Ssam 1929246Ssam putnet(nf, al->addr_val); 1939246Ssam cp = "\t%s"; 1949246Ssam while (nl = nl->name_link) { 1959246Ssam fprintf(nf, cp, lower(nl->name_val)); 1969246Ssam cp = " %s"; 1979246Ssam } 1989246Ssam putc('\n', nf); 1999246Ssam al2 = al->addr_link; 2009246Ssam free((char *)al); 2019246Ssam } 202*15377Skarels break; 2039246Ssam 2048732Ssam case KW_GATEWAY: 205*15377Skarels /* locate locally connected address, if one */ 206*15377Skarels for (al = addrlist; al; al = al->addr_link) 207*15377Skarels if (connectedto(inet_netof(al->addr_val))) 208*15377Skarels break; 209*15377Skarels if (al == NULL) { 210*15377Skarels /* 211*15377Skarels * Not connected to known networks. Save for later. 212*15377Skarels */ 213*15377Skarels struct gateway *gw, *firstgw = (struct gateway *) NULL; 214*15377Skarels 215*15377Skarels for (al = addrlist; al; al = al->addr_link) { 216*15377Skarels register int net; 217*15377Skarels 218*15377Skarels net = inet_netof(al->addr_val); 219*15377Skarels gw = savegateway(namelist, net, 220*15377Skarels al->addr_val, 0); 221*15377Skarels if (firstgw == (struct gateway *) NULL) 222*15377Skarels firstgw = gw; 223*15377Skarels gw->g_firstent = firstgw; 224*15377Skarels } 225*15377Skarels freeaddrs(addrlist); 226*15377Skarels goto dontfree; 227*15377Skarels } 22812227Ssam /* 229*15377Skarels * Connected to a known network. 230*15377Skarels * Mark this as the gateway to all other networks 231*15377Skarels * that are on the addrlist (unless we already have 232*15377Skarels * gateways to them). 23312227Ssam */ 234*15377Skarels connect_addr = al; 235*15377Skarels for (al = addrlist; al; al = al->addr_link) { 23612227Ssam register int net; 2379246Ssam 238*15377Skarels if (al == connect_addr) 23912227Ssam continue; 2409246Ssam /* suppress duplicates -- not optimal */ 24112227Ssam net = inet_netof(al->addr_val); 242*15377Skarels if (gatewayto(net)) 243*15377Skarels continue; 244*15377Skarels printgateway(net, namelist->name_val, 1); 245*15377Skarels (void) savegateway(namelist, net, al->addr_val, 1); 24612227Ssam } 247*15377Skarels /* 248*15377Skarels * Put the gateway in the hosts file. 249*15377Skarels */ 250*15377Skarels putaddr(hf, connect_addr->addr_val); 251*15377Skarels cp = "%s"; 252*15377Skarels for (nl = namelist; nl; nl = nl->name_link) { 253*15377Skarels fprintf(hf, cp, lower(nl->name_val)); 254*15377Skarels cp = " %s"; 2559246Ssam } 256*15377Skarels fprintf(hf, "\t# gateway\n"); 257*15377Skarels freeaddrs(addrlist); 258*15377Skarels goto dontfree; 2598732Ssam 2608732Ssam case KW_HOST: 2619246Ssam al2 = addrlist; 2629246Ssam while (al = al2) { 263*15377Skarels if (!local(inet_netof(al->addr_val))) { 2649246Ssam char *cp; 2659246Ssam 2669246Ssam putaddr(hf, al->addr_val); 2679246Ssam cp = "%s"; 2689246Ssam for (nl = namelist; nl; nl = nl->name_link) { 2699246Ssam fprintf(hf, cp, lower(nl->name_val)); 2709246Ssam cp = " %s"; 2719246Ssam } 2728732Ssam putc('\n', hf); 2738732Ssam } 2748732Ssam al2 = al->addr_link; 2759246Ssam free((char *)al); 2768732Ssam } 277*15377Skarels break; 2788732Ssam 2798732Ssam default: 2808732Ssam fprintf(stderr, "Unknown keyword: %d.\n", keyword); 2818732Ssam } 2829246Ssam freenames(namelist); 283*15377Skarels dontfree: 2849246Ssam freenames(protos); 2858732Ssam } 2868732Ssam 287*15377Skarels printgateway(net, name, metric) 288*15377Skarels int net; 289*15377Skarels char *name; 290*15377Skarels int metric; 291*15377Skarels { 292*15377Skarels struct netent *np; 293*15377Skarels 294*15377Skarels fprintf(gf, "net "); 295*15377Skarels np = getnetbyaddr(net, AF_INET); 296*15377Skarels if (np) 297*15377Skarels fprintf(gf, "%s", np->n_name); 298*15377Skarels else 299*15377Skarels putnet(gf, net); 300*15377Skarels fprintf(gf, " gateway %s metric %d passive\n", 301*15377Skarels lower(name), metric); 302*15377Skarels } 303*15377Skarels 3049246Ssam copylocal(f, filename) 3059246Ssam FILE *f; 3069246Ssam char *filename; 3078732Ssam { 3088732Ssam register FILE *lhf; 3098732Ssam register cc; 3108732Ssam char buf[BUFSIZ]; 3119246Ssam extern int errno; 3128732Ssam 3139246Ssam lhf = fopen(filename, "r"); 3148732Ssam if (lhf == NULL) { 3159246Ssam if (errno != ENOENT) { 3169246Ssam perror(filename); 3179246Ssam exit(1); 3189246Ssam } 3199246Ssam fprintf(stderr, "Warning, no %s file.\n", filename); 3208732Ssam return; 3218732Ssam } 3228732Ssam while (cc = fread(buf, 1, sizeof(buf), lhf)) 3239246Ssam fwrite(buf, 1, cc, f); 3248732Ssam fclose(lhf); 3258732Ssam } 3269246Ssam 327*15377Skarels copygateways(f, filename) 328*15377Skarels FILE *f; 329*15377Skarels char *filename; 330*15377Skarels { 331*15377Skarels register FILE *lhf; 332*15377Skarels register cc; 333*15377Skarels struct name *nl; 334*15377Skarels char type[80]; 335*15377Skarels char dname[80]; 336*15377Skarels char gname[80]; 337*15377Skarels char junk[80]; 338*15377Skarels u_long addr; 339*15377Skarels int net, metric; 340*15377Skarels extern int errno; 341*15377Skarels 342*15377Skarels lhf = fopen(filename, "r"); 343*15377Skarels if (lhf == NULL) { 344*15377Skarels if (errno != ENOENT) { 345*15377Skarels perror(filename); 346*15377Skarels exit(1); 347*15377Skarels } 348*15377Skarels fprintf(stderr, "Warning, no %s file.\n", filename); 349*15377Skarels return; 350*15377Skarels } 351*15377Skarels /* format: {net | host} XX gateway XX metric DD [passive]\n */ 352*15377Skarels #define readentry(fp) \ 353*15377Skarels fscanf((fp), "%s %s gateway %s metric %d %s\n", \ 354*15377Skarels type, dname, gname, &metric, junk) 355*15377Skarels while (readentry(lhf) != EOF) { 356*15377Skarels if (strcmp(type, "net")) 357*15377Skarels goto dumpit; 358*15377Skarels if (!getnetaddr(dname, &net)) 359*15377Skarels goto dumpit; 360*15377Skarels if (!gethostaddr(gname, &addr)) 361*15377Skarels goto dumpit; 362*15377Skarels nl = newname(gname); 363*15377Skarels (void) savegateway(nl, net, addr, metric); 364*15377Skarels dumpit: 365*15377Skarels fprintf(gf, "%s %s gateway %s metric %d %s\n", 366*15377Skarels type, dname, gname, metric, junk); 367*15377Skarels } 368*15377Skarels fclose(lhf); 369*15377Skarels } 370*15377Skarels 371*15377Skarels getnetaddr(name, addr) 372*15377Skarels char *name; 373*15377Skarels int *addr; 374*15377Skarels { 375*15377Skarels struct netent *np = getnetbyname(name); 376*15377Skarels int n; 377*15377Skarels 378*15377Skarels if (np == 0) { 379*15377Skarels *addr = inet_network(name); 380*15377Skarels return (*addr != -1); 381*15377Skarels } else { 382*15377Skarels if (np->n_addrtype != AF_INET) 383*15377Skarels return (0); 384*15377Skarels *addr = np->n_net; 385*15377Skarels return (1); 386*15377Skarels } 387*15377Skarels } 388*15377Skarels 389*15377Skarels gethostaddr(name, addr) 390*15377Skarels char *name; 391*15377Skarels u_long *addr; 392*15377Skarels { 393*15377Skarels struct hostent *hp; 394*15377Skarels 395*15377Skarels hp = gethostbyname(name); 396*15377Skarels if (hp) { 397*15377Skarels *addr = *(u_long *)(hp->h_addr); 398*15377Skarels return (1); 399*15377Skarels } 400*15377Skarels *addr = inet_addr(name); 401*15377Skarels return (*addr != -1); 402*15377Skarels } 403*15377Skarels 40412610Smo copycomments(in, out, ccount) 40512610Smo FILE *in, *out; 40612610Smo int ccount; 40712610Smo { 40812610Smo char buf[BUFSIZ]; 40912610Smo int length; 41012610Smo int count; 41112610Smo char *fgets(); 41212610Smo 41312610Smo for (count=0; count < ccount; count++) { 41412610Smo if ((fgets(buf, sizeof(buf), in) == NULL) || (buf[0] != ';')) 41512610Smo return; 41612610Smo buf[0] = '#'; 41712610Smo fputs(buf, out); 41812610Smo } 41912610Smo return; 42012610Smo } 4219246Ssam #define UC(b) (((int)(b))&0xff) 4229246Ssam 4239246Ssam putnet(f, v) 4249246Ssam FILE *f; 4259246Ssam u_long v; 4269246Ssam { 4279246Ssam register char *a = (char *)&v; 4289246Ssam 4299246Ssam if (UC(a[0]&0x80) == 0) 4309246Ssam fprintf(f, "%d", UC(a[0])); 4319246Ssam else if ((UC(a[0])&0x40) == 0) 4329246Ssam fprintf(f, "%d.%d", UC(a[0]), UC(a[1])); 4339246Ssam else 4349246Ssam fprintf(f, "%d.%d.%d", UC(a[0]), UC(a[1]), UC(a[2])); 4359246Ssam } 4369246Ssam 4379246Ssam putaddr(f, v) 4389246Ssam FILE *f; 4399246Ssam u_long v; 4409246Ssam { 4419246Ssam register char *a = (char *)&v; 4429246Ssam char buf[32]; 4439246Ssam 4449246Ssam sprintf(buf,"%d.%d.%d.%d", UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3])); 4459246Ssam fprintf(f, "%-16.16s", buf); 4469246Ssam } 4479246Ssam 4489246Ssam freenames(list) 4499246Ssam struct name *list; 4509246Ssam { 4519246Ssam register struct name *nl, *nl2; 4529246Ssam 4539246Ssam nl2 = list; 4549246Ssam while (nl = nl2) { 4559246Ssam nl2 = nl->name_link; 4569246Ssam free(nl->name_val); 4579246Ssam free((char *)nl); 4589246Ssam } 4599246Ssam } 4609246Ssam 461*15377Skarels freeaddrs(list) 462*15377Skarels struct addr *list; 463*15377Skarels { 464*15377Skarels register struct addr *al, *al2; 465*15377Skarels 466*15377Skarels al2 = list; 467*15377Skarels while (al = al2) 468*15377Skarels al2 = al->addr_link, free((char *)al); 469*15377Skarels } 470*15377Skarels 4719246Ssam struct gateway *gateways = 0; 472*15377Skarels struct gateway *lastgateway = 0; 4739246Ssam 474*15377Skarels struct gateway * 475*15377Skarels gatewayto(net) 4769246Ssam register int net; 4779246Ssam { 4789246Ssam register struct gateway *gp; 4799246Ssam 4809246Ssam for (gp = gateways; gp; gp = gp->g_link) 481*15377Skarels if ((gp->g_net == net) && (gp->g_metric > 0)) 482*15377Skarels return (gp); 483*15377Skarels return ((struct gateway *) NULL); 4849246Ssam } 4859246Ssam 486*15377Skarels struct gateway * 487*15377Skarels savegateway(namelist, net, addr, metric) 488*15377Skarels struct name *namelist; 489*15377Skarels u_long addr; 490*15377Skarels int net, metric; 4919246Ssam { 4929246Ssam register struct gateway *gp; 4939246Ssam 4949246Ssam gp = (struct gateway *)malloc(sizeof (struct gateway)); 4959246Ssam if (gp == 0) { 4969246Ssam fprintf(stderr, "htable: out of memory\n"); 4979246Ssam exit(1); 4989246Ssam } 499*15377Skarels gp->g_link = (struct gateway *) NULL; 500*15377Skarels if (lastgateway) 501*15377Skarels lastgateway->g_link = gp; 502*15377Skarels else 503*15377Skarels gateways = gp; 504*15377Skarels lastgateway = gp; 505*15377Skarels gp->g_name = namelist; 5069246Ssam gp->g_net = net; 507*15377Skarels gp->g_addr = addr; 508*15377Skarels gp->g_metric = metric; 509*15377Skarels if (metric == 1) 510*15377Skarels gp->g_dst = gp; 5119246Ssam } 512*15377Skarels 513*15377Skarels connectedto(net) 514*15377Skarels u_long net; 515*15377Skarels { 516*15377Skarels register i; 517*15377Skarels 518*15377Skarels for (i = 0; i < nconnected; i++) 519*15377Skarels if (connected_nets[i] == net) 520*15377Skarels return(1); 521*15377Skarels return(0); 522*15377Skarels } 523*15377Skarels 524*15377Skarels local(net) 525*15377Skarels u_long net; 526*15377Skarels { 527*15377Skarels register i; 528*15377Skarels 529*15377Skarels for (i = 0; i < nlocal; i++) 530*15377Skarels if (local_nets[i] == net) 531*15377Skarels return(1); 532*15377Skarels return(0); 533*15377Skarels } 534*15377Skarels 535*15377Skarels #define MAXHOPS 10 536*15377Skarels 537*15377Skarels /* 538*15377Skarels * Go through list of gateways, finding connections for gateways 539*15377Skarels * that are not yet connected. 540*15377Skarels */ 541*15377Skarels dogateways() 542*15377Skarels { 543*15377Skarels register struct gateway *gp, *gw, *ggp; 544*15377Skarels register int hops, changed = 1; 545*15377Skarels struct name *nl; 546*15377Skarels char *cp; 547*15377Skarels 548*15377Skarels for (hops = 0; hops < MAXHOPS && changed; hops++, changed = 0) { 549*15377Skarels for (gp = gateways; gp; gp = gp->g_link) 550*15377Skarels if ((gp->g_metric == 0) && (gw = gatewayto(gp->g_net))) { 551*15377Skarels /* 552*15377Skarels * Found a new connection. 553*15377Skarels * For each other network that this gateway is on, 554*15377Skarels * add a new gateway to that network. 555*15377Skarels */ 556*15377Skarels changed = 1; 557*15377Skarels gp->g_dst = gw->g_dst; 558*15377Skarels gp->g_metric = gw->g_metric + 1; 559*15377Skarels for (ggp = gp->g_firstent; ggp->g_name == gp->g_name; 560*15377Skarels ggp = ggp->g_link) { 561*15377Skarels if (ggp == gp) 562*15377Skarels continue; 563*15377Skarels if (gatewayto(ggp->g_net)) 564*15377Skarels continue; 565*15377Skarels ggp->g_dst = gp->g_dst; 566*15377Skarels ggp->g_metric = gp->g_metric; 567*15377Skarels printgateway(ggp->g_net, 568*15377Skarels gw->g_dst->g_name->name_val, gp->g_metric); 569*15377Skarels } 570*15377Skarels /* 571*15377Skarels * Put the gateway in the hosts file, 572*15377Skarels * using the address for the connected net. 573*15377Skarels */ 574*15377Skarels putaddr(hf, gp->g_addr); 575*15377Skarels cp = "%s"; 576*15377Skarels for (nl = gp->g_name; nl; nl = nl->name_link) { 577*15377Skarels fprintf(hf, cp, lower(nl->name_val)); 578*15377Skarels cp = " %s"; 579*15377Skarels } 580*15377Skarels fprintf(hf, "\t# gateway\n"); 581*15377Skarels } 582*15377Skarels } 583*15377Skarels } 584