121125Sdist /*
221127Sdist * Copyright (c) 1983 Regents of the University of California.
333539Sbostic * All rights reserved.
433539Sbostic *
542798Sbostic * %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*46299Sbostic static char sccsid[] = "@(#)htable.c 5.10 (Berkeley) 02/06/91";
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>
31*46299Sbostic #include <stdlib.h>
328732Ssam
3312610Smo #define DATELINES 3 /* these lines usually contain the date */
3415377Skarels #define MAXNETS 30 /* array size for local, connected nets */
3512610Smo
369246Ssam FILE *hf; /* hosts file */
379246Ssam FILE *gf; /* gateways file */
389246Ssam FILE *nf; /* networks file */
3915377Skarels struct gateway *savegateway(), *gatewayto();
409246Ssam
4115377Skarels int connected_nets[MAXNETS];
4215377Skarels int nconnected;
4315377Skarels int local_nets[MAXNETS];
4415377Skarels int nlocal;
4515377Skarels char *myname;
4615377Skarels
main(argc,argv)478732Ssam main(argc, argv)
488732Ssam int argc;
498732Ssam char *argv[];
508732Ssam {
5115377Skarels int errs;
5215377Skarels
538732Ssam infile = "(stdin)";
5415377Skarels myname = argv[0];
5515377Skarels argc--;
5615377Skarels argv++;
5715377Skarels while (argc--) {
5815377Skarels if (*argv[0] == '-') {
5915377Skarels switch (argv[0][1]) {
6015377Skarels case 'c':
6115377Skarels nconnected = addlocal(argv[1], connected_nets);
6215377Skarels argv++;
6315377Skarels argc--;
6415377Skarels break;
6515377Skarels case 'l':
6615377Skarels nlocal = addlocal(argv[1], local_nets);
6715377Skarels argv++;
6815377Skarels argc--;
6915377Skarels break;
7015377Skarels default:
7115377Skarels usage();
7215377Skarels /*NOTREACHED*/
7315377Skarels }
7415377Skarels } else {
7515377Skarels infile = argv[0];
7615377Skarels if (freopen(infile, "r", stdin) == NULL) {
7715377Skarels perror(infile);
7815377Skarels exit(1);
7915377Skarels }
808732Ssam }
8115377Skarels argv++;
828732Ssam }
838732Ssam hf = fopen("hosts", "w");
848732Ssam if (hf == NULL) {
858732Ssam perror("hosts");
868732Ssam exit(1);
878732Ssam }
889246Ssam copylocal(hf, "localhosts");
899246Ssam gf = fopen("gateways", "w");
909246Ssam if (gf == NULL) {
918732Ssam perror("gateways");
928732Ssam exit(1);
938732Ssam }
9433539Sbostic copygateways("localgateways");
959246Ssam nf = fopen("networks", "w");
969246Ssam if (nf == NULL) {
979246Ssam perror("networks");
989246Ssam exit(1);
999246Ssam }
1009246Ssam copylocal(nf, "localnetworks");
10112610Smo copycomments(stdin, hf, DATELINES);
10215377Skarels errs = yyparse();
10315377Skarels dogateways();
10415377Skarels exit(errs);
1058732Ssam }
1068732Ssam
usage()10715377Skarels usage()
10815377Skarels {
10915377Skarels fprintf(stderr,
11015377Skarels "usage: %s [ -c connected-nets ] [-l local-nets ] [ input-file ]\n",
11115377Skarels myname);
11215377Skarels exit(1);
11315377Skarels }
11415377Skarels
11515377Skarels /*
11615377Skarels * Turn a comma-separated list of network names or numbers in dot notation
11715377Skarels * (e.g. "arpanet, 128.32") into an array of net numbers.
11815377Skarels */
addlocal(arg,nets)11915377Skarels addlocal(arg, nets)
12015377Skarels char *arg;
12115377Skarels int *nets;
12215377Skarels {
12315377Skarels register char *p, c;
12415377Skarels register int nfound = 0;
12515377Skarels
12615377Skarels do {
12715377Skarels p = arg;
12815377Skarels while (*p && *p != ',' && !isspace(*p))
12915377Skarels p++;
13015377Skarels c = *p;
13115377Skarels *p = 0;
13215377Skarels while (*arg && isspace(*arg))
13315377Skarels arg++;
13415377Skarels if (*arg == 0)
13515377Skarels continue;
13615377Skarels if (nfound == MAXNETS) {
13715377Skarels fprintf(stderr, "%s: Too many networks in list\n",
13815377Skarels myname);
13915377Skarels return (nfound);
14015377Skarels }
14115377Skarels if (getnetaddr(arg, &nets[nfound]))
14215377Skarels nfound++;
14315377Skarels else {
14415377Skarels fprintf(stderr, "%s: %s: unknown network\n",
14515377Skarels myname, arg);
14615377Skarels exit(1);
14715377Skarels }
14815379Skarels arg = p + 1;
14915377Skarels } while (c);
15015377Skarels return (nfound);
15115377Skarels }
15215377Skarels
1538732Ssam struct name *
newname(str)1548732Ssam newname(str)
1558732Ssam char *str;
1568732Ssam {
1578732Ssam char *p;
1588732Ssam struct name *nm;
1598732Ssam
1608732Ssam p = malloc(strlen(str) + 1);
1618732Ssam strcpy(p, str);
1629246Ssam nm = (struct name *)malloc(sizeof (struct name));
1638732Ssam nm->name_val = p;
1648732Ssam nm->name_link = NONAME;
1658732Ssam return (nm);
1668732Ssam }
1678732Ssam
1688732Ssam char *
lower(str)1698732Ssam lower(str)
1708732Ssam char *str;
1718732Ssam {
1728732Ssam register char *cp = str;
1738732Ssam
1748732Ssam while (*cp) {
1758732Ssam if (isupper(*cp))
1768732Ssam *cp = tolower(*cp);
1778732Ssam cp++;
1788732Ssam }
1798732Ssam return (str);
1808732Ssam }
1818732Ssam
do_entry(keyword,addrlist,namelist,cputype,opsys,protos)1828732Ssam do_entry(keyword, addrlist, namelist, cputype, opsys, protos)
1838732Ssam int keyword;
1848732Ssam struct addr *addrlist;
1858732Ssam struct name *namelist, *cputype, *opsys, *protos;
1868732Ssam {
1878732Ssam register struct addr *al, *al2;
1889246Ssam register struct name *nl;
18915377Skarels struct addr *connect_addr;
19015377Skarels char *cp;
1918732Ssam
1928732Ssam switch (keyword) {
1938732Ssam
1948732Ssam case KW_NET:
1959246Ssam nl = namelist;
1969246Ssam if (nl == NONAME) {
1979246Ssam fprintf(stderr, "htable: net");
19815789Skarels putnet(stderr, inet_netof(addrlist->addr_val));
1999246Ssam fprintf(stderr, " missing names.\n");
2009246Ssam break;
2019246Ssam }
2029246Ssam fprintf(nf, "%-16.16s", lower(nl->name_val));
2039246Ssam al2 = addrlist;
2049246Ssam while (al = al2) {
2059246Ssam char *cp;
2068732Ssam
20715789Skarels putnet(nf, inet_netof(al->addr_val));
2089246Ssam cp = "\t%s";
2099246Ssam while (nl = nl->name_link) {
2109246Ssam fprintf(nf, cp, lower(nl->name_val));
2119246Ssam cp = " %s";
2129246Ssam }
2139246Ssam putc('\n', nf);
2149246Ssam al2 = al->addr_link;
2159246Ssam free((char *)al);
2169246Ssam }
21715377Skarels break;
2189246Ssam
2198732Ssam case KW_GATEWAY:
22015377Skarels /* locate locally connected address, if one */
22115377Skarels for (al = addrlist; al; al = al->addr_link)
22215377Skarels if (connectedto(inet_netof(al->addr_val)))
22315377Skarels break;
22415377Skarels if (al == NULL) {
22515377Skarels /*
22615377Skarels * Not connected to known networks. Save for later.
22715377Skarels */
22815377Skarels struct gateway *gw, *firstgw = (struct gateway *) NULL;
22915377Skarels
23015377Skarels for (al = addrlist; al; al = al->addr_link) {
23115377Skarels register int net;
23215377Skarels
23315377Skarels net = inet_netof(al->addr_val);
23415377Skarels gw = savegateway(namelist, net,
23515377Skarels al->addr_val, 0);
23615377Skarels if (firstgw == (struct gateway *) NULL)
23715377Skarels firstgw = gw;
23815377Skarels gw->g_firstent = firstgw;
23915377Skarels }
24015377Skarels freeaddrs(addrlist);
24115377Skarels goto dontfree;
24215377Skarels }
24312227Ssam /*
24415377Skarels * Connected to a known network.
24515377Skarels * Mark this as the gateway to all other networks
24615377Skarels * that are on the addrlist (unless we already have
24715377Skarels * gateways to them).
24812227Ssam */
24915377Skarels connect_addr = al;
25015377Skarels for (al = addrlist; al; al = al->addr_link) {
25112227Ssam register int net;
2529246Ssam
2539246Ssam /* suppress duplicates -- not optimal */
25412227Ssam net = inet_netof(al->addr_val);
25516024Skarels if (connectedto(net) || gatewayto(net))
25615377Skarels continue;
25715377Skarels printgateway(net, namelist->name_val, 1);
25815377Skarels (void) savegateway(namelist, net, al->addr_val, 1);
25912227Ssam }
26015377Skarels /*
26115377Skarels * Put the gateway in the hosts file.
26215377Skarels */
26315377Skarels putaddr(hf, connect_addr->addr_val);
26415377Skarels cp = "%s";
26515377Skarels for (nl = namelist; nl; nl = nl->name_link) {
26615377Skarels fprintf(hf, cp, lower(nl->name_val));
26715377Skarels cp = " %s";
2689246Ssam }
26915377Skarels fprintf(hf, "\t# gateway\n");
27015377Skarels freeaddrs(addrlist);
27115377Skarels goto dontfree;
2728732Ssam
2738732Ssam case KW_HOST:
2749246Ssam al2 = addrlist;
2759246Ssam while (al = al2) {
27615377Skarels if (!local(inet_netof(al->addr_val))) {
2779246Ssam char *cp;
2789246Ssam
2799246Ssam putaddr(hf, al->addr_val);
2809246Ssam cp = "%s";
2819246Ssam for (nl = namelist; nl; nl = nl->name_link) {
2829246Ssam fprintf(hf, cp, lower(nl->name_val));
2839246Ssam cp = " %s";
2849246Ssam }
2858732Ssam putc('\n', hf);
2868732Ssam }
2878732Ssam al2 = al->addr_link;
2889246Ssam free((char *)al);
2898732Ssam }
29015377Skarels break;
2918732Ssam
2928732Ssam default:
2938732Ssam fprintf(stderr, "Unknown keyword: %d.\n", keyword);
2948732Ssam }
2959246Ssam freenames(namelist);
29615377Skarels dontfree:
2979246Ssam freenames(protos);
2988732Ssam }
2998732Ssam
printgateway(net,name,metric)30015377Skarels printgateway(net, name, metric)
30115377Skarels int net;
30215377Skarels char *name;
30315377Skarels int metric;
30415377Skarels {
30515377Skarels struct netent *np;
30615377Skarels
30715377Skarels fprintf(gf, "net ");
30815377Skarels np = getnetbyaddr(net, AF_INET);
30915377Skarels if (np)
31015377Skarels fprintf(gf, "%s", np->n_name);
31115377Skarels else
31215377Skarels putnet(gf, net);
31315377Skarels fprintf(gf, " gateway %s metric %d passive\n",
31415377Skarels lower(name), metric);
31515377Skarels }
31615377Skarels
copylocal(f,filename)3179246Ssam copylocal(f, filename)
3189246Ssam FILE *f;
3199246Ssam char *filename;
3208732Ssam {
3218732Ssam register FILE *lhf;
3228732Ssam register cc;
3238732Ssam char buf[BUFSIZ];
3249246Ssam extern int errno;
3258732Ssam
3269246Ssam lhf = fopen(filename, "r");
3278732Ssam if (lhf == NULL) {
3289246Ssam if (errno != ENOENT) {
3299246Ssam perror(filename);
3309246Ssam exit(1);
3319246Ssam }
3329246Ssam fprintf(stderr, "Warning, no %s file.\n", filename);
3338732Ssam return;
3348732Ssam }
3358732Ssam while (cc = fread(buf, 1, sizeof(buf), lhf))
3369246Ssam fwrite(buf, 1, cc, f);
3378732Ssam fclose(lhf);
3388732Ssam }
3399246Ssam
copygateways(filename)34033539Sbostic copygateways(filename)
34115377Skarels char *filename;
34215377Skarels {
34315377Skarels register FILE *lhf;
34415377Skarels struct name *nl;
34515377Skarels char type[80];
34615377Skarels char dname[80];
34715377Skarels char gname[80];
34815377Skarels char junk[80];
34916066Skarels char buf[500];
35033539Sbostic struct in_addr addr;
35115377Skarels int net, metric;
35215377Skarels extern int errno;
35315377Skarels
35415377Skarels lhf = fopen(filename, "r");
35515377Skarels if (lhf == NULL) {
35615377Skarels if (errno != ENOENT) {
35715377Skarels perror(filename);
35815377Skarels exit(1);
35915377Skarels }
36015377Skarels fprintf(stderr, "Warning, no %s file.\n", filename);
36115377Skarels return;
36215377Skarels }
36315377Skarels /* format: {net | host} XX gateway XX metric DD [passive]\n */
36415789Skarels for (;;) {
36515789Skarels junk[0] = 0;
36616066Skarels if (fgets(buf, sizeof(buf), lhf) == (char *)NULL)
36715789Skarels break;
36816066Skarels fputs(buf, gf);
36916066Skarels if (buf[0] == '#' ||
37016066Skarels sscanf(buf, "%s %s gateway %s metric %d %s",
37116066Skarels type, dname, gname, &metric, junk) < 5)
37216066Skarels continue;
37315377Skarels if (strcmp(type, "net"))
37416066Skarels continue;
37515377Skarels if (!getnetaddr(dname, &net))
37616066Skarels continue;
37733539Sbostic if (!gethostaddr(gname, &addr.s_addr))
37816066Skarels continue;
37915377Skarels nl = newname(gname);
38015377Skarels (void) savegateway(nl, net, addr, metric);
38115377Skarels }
38215377Skarels fclose(lhf);
38315377Skarels }
38415377Skarels
getnetaddr(name,addr)38515377Skarels getnetaddr(name, addr)
38615377Skarels char *name;
38715377Skarels int *addr;
38815377Skarels {
38915377Skarels struct netent *np = getnetbyname(name);
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
gethostaddr(name,addr)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
copycomments(in,out,ccount)41712610Smo copycomments(in, out, ccount)
41812610Smo FILE *in, *out;
41912610Smo int ccount;
42012610Smo {
42112610Smo int count;
42233539Sbostic char buf[BUFSIZ], *fgets();
42312610Smo
42412610Smo for (count=0; count < ccount; count++) {
42512610Smo if ((fgets(buf, sizeof(buf), in) == NULL) || (buf[0] != ';'))
42612610Smo return;
42712610Smo buf[0] = '#';
42812610Smo fputs(buf, out);
42912610Smo }
43012610Smo return;
43112610Smo }
4329246Ssam #define UC(b) (((int)(b))&0xff)
4339246Ssam
43415785Skarels /*
43515785Skarels * Print network number in internet-standard dot notation;
43615785Skarels * v is in host byte order.
43715785Skarels */
putnet(f,v)4389246Ssam putnet(f, v)
4399246Ssam FILE *f;
44015789Skarels register int v;
4419246Ssam {
44215785Skarels if (v < 128)
44315785Skarels fprintf(f, "%d", v);
44415785Skarels else if (v < 65536)
44515789Skarels fprintf(f, "%d.%d", UC(v >> 8), UC(v));
4469246Ssam else
44715789Skarels fprintf(f, "%d.%d.%d", UC(v >> 16), UC(v >> 8), UC(v));
4489246Ssam }
4499246Ssam
putaddr(f,v)4509246Ssam putaddr(f, v)
4519246Ssam FILE *f;
45233539Sbostic struct in_addr v;
4539246Ssam {
45433539Sbostic fprintf(f, "%-16.16s", inet_ntoa(v));
4559246Ssam }
4569246Ssam
4579246Ssam freenames(list)
4589246Ssam struct name *list;
4599246Ssam {
4609246Ssam register struct name *nl, *nl2;
4619246Ssam
4629246Ssam nl2 = list;
4639246Ssam while (nl = nl2) {
4649246Ssam nl2 = nl->name_link;
4659246Ssam free(nl->name_val);
4669246Ssam free((char *)nl);
4679246Ssam }
4689246Ssam }
4699246Ssam
47015377Skarels freeaddrs(list)
47115377Skarels struct addr *list;
47215377Skarels {
47315377Skarels register struct addr *al, *al2;
47415377Skarels
47515377Skarels al2 = list;
47615377Skarels while (al = al2)
47715377Skarels al2 = al->addr_link, free((char *)al);
47815377Skarels }
47915377Skarels
4809246Ssam struct gateway *gateways = 0;
48115377Skarels struct gateway *lastgateway = 0;
4829246Ssam
48315377Skarels struct gateway *
gatewayto(net)48415377Skarels gatewayto(net)
4859246Ssam register int net;
4869246Ssam {
4879246Ssam register struct gateway *gp;
4889246Ssam
4899246Ssam for (gp = gateways; gp; gp = gp->g_link)
49015377Skarels if ((gp->g_net == net) && (gp->g_metric > 0))
49115377Skarels return (gp);
49215377Skarels return ((struct gateway *) NULL);
4939246Ssam }
4949246Ssam
49515377Skarels struct gateway *
savegateway(namelist,net,addr,metric)49615377Skarels savegateway(namelist, net, addr, metric)
49715377Skarels struct name *namelist;
49833539Sbostic struct in_addr addr;
49915377Skarels int net, metric;
5009246Ssam {
5019246Ssam register struct gateway *gp;
5029246Ssam
5039246Ssam gp = (struct gateway *)malloc(sizeof (struct gateway));
5049246Ssam if (gp == 0) {
5059246Ssam fprintf(stderr, "htable: out of memory\n");
5069246Ssam exit(1);
5079246Ssam }
50815377Skarels gp->g_link = (struct gateway *) NULL;
50915377Skarels if (lastgateway)
51015377Skarels lastgateway->g_link = gp;
51115377Skarels else
51215377Skarels gateways = gp;
51315377Skarels lastgateway = gp;
51415377Skarels gp->g_name = namelist;
5159246Ssam gp->g_net = net;
51615377Skarels gp->g_addr = addr;
51715377Skarels gp->g_metric = metric;
51815377Skarels if (metric == 1)
51915377Skarels gp->g_dst = gp;
52027079Sbloom return (gp);
5219246Ssam }
52215377Skarels
connectedto(net)52315377Skarels connectedto(net)
52415377Skarels u_long net;
52515377Skarels {
52615377Skarels register i;
52715377Skarels
52815377Skarels for (i = 0; i < nconnected; i++)
52915377Skarels if (connected_nets[i] == net)
53015377Skarels return(1);
53115377Skarels return(0);
53215377Skarels }
53315377Skarels
local(net)53415377Skarels local(net)
53515377Skarels u_long net;
53615377Skarels {
53715377Skarels register i;
53815377Skarels
53915377Skarels for (i = 0; i < nlocal; i++)
54015377Skarels if (local_nets[i] == net)
54115377Skarels return(1);
54215377Skarels return(0);
54315377Skarels }
54415377Skarels
54515377Skarels #define MAXHOPS 10
54615377Skarels
54715377Skarels /*
54815377Skarels * Go through list of gateways, finding connections for gateways
54915377Skarels * that are not yet connected.
55015377Skarels */
dogateways()55115377Skarels dogateways()
55215377Skarels {
55315377Skarels register struct gateway *gp, *gw, *ggp;
55415377Skarels register int hops, changed = 1;
55515377Skarels struct name *nl;
55615377Skarels char *cp;
55715377Skarels
55815377Skarels for (hops = 0; hops < MAXHOPS && changed; hops++, changed = 0) {
55915377Skarels for (gp = gateways; gp; gp = gp->g_link)
56015377Skarels if ((gp->g_metric == 0) && (gw = gatewayto(gp->g_net))) {
56115377Skarels /*
56215377Skarels * Found a new connection.
56315377Skarels * For each other network that this gateway is on,
56415377Skarels * add a new gateway to that network.
56515377Skarels */
56615377Skarels changed = 1;
56715377Skarels gp->g_dst = gw->g_dst;
56815377Skarels gp->g_metric = gw->g_metric + 1;
56915377Skarels for (ggp = gp->g_firstent; ggp->g_name == gp->g_name;
57015377Skarels ggp = ggp->g_link) {
57115377Skarels if (ggp == gp)
57215377Skarels continue;
57315377Skarels if (gatewayto(ggp->g_net))
57415377Skarels continue;
57515377Skarels ggp->g_dst = gp->g_dst;
57615377Skarels ggp->g_metric = gp->g_metric;
57715377Skarels printgateway(ggp->g_net,
57815377Skarels gw->g_dst->g_name->name_val, gp->g_metric);
57915377Skarels }
58015377Skarels /*
58115377Skarels * Put the gateway in the hosts file,
58215377Skarels * using the address for the connected net.
58315377Skarels */
58415377Skarels putaddr(hf, gp->g_addr);
58515377Skarels cp = "%s";
58615377Skarels for (nl = gp->g_name; nl; nl = nl->name_link) {
58715377Skarels fprintf(hf, cp, lower(nl->name_val));
58815377Skarels cp = " %s";
58915377Skarels }
59015377Skarels fprintf(hf, "\t# gateway\n");
59115377Skarels }
59215377Skarels }
59315377Skarels }
594