1: /*
2: * Copyright (c) 1983 Regents of the University of California.
3: * All rights reserved. The Berkeley software License Agreement
4: * specifies the terms and conditions for redistribution.
5: */
6:
7: #if defined(DOSCCS) && !defined(lint)
8: char copyright[] =
9: "@(#) Copyright (c) 1983 Regents of the University of California.\n\
10: All rights reserved.\n";
11:
12: static char sccsid[] = "@(#)htable.c 5.5.1 (2.11BSD GTE) 1/1/94";
13: #endif
14:
15: /*
16: * htable - convert NIC host table into a UNIX format.
17: * NIC format is described in RFC 810, 1 March 1982.
18: */
19:
20: #include <stdio.h>
21: #include <ctype.h>
22: #include <errno.h>
23: #include <netdb.h>
24:
25: #include "htable.h" /* includes <sys/types.h> */
26:
27: #include <sys/socket.h>
28: #include <netinet/in.h>
29: #include <arpa/inet.h>
30:
31: #define DATELINES 3 /* these lines usually contain the date */
32: #define MAXNETS 30 /* array size for local, connected nets */
33:
34: FILE *hf; /* hosts file */
35: FILE *gf; /* gateways file */
36: FILE *nf; /* networks file */
37: struct gateway *savegateway(), *gatewayto();
38:
39: u_long connected_nets[MAXNETS];
40: int nconnected;
41: u_long local_nets[MAXNETS];
42: int nlocal;
43: char *myname;
44:
45: main(argc, argv)
46: int argc;
47: char *argv[];
48: {
49: int errs;
50:
51: infile = "(stdin)";
52: myname = argv[0];
53: argc--;
54: argv++;
55: while (argc--) {
56: if (*argv[0] == '-') {
57: switch (argv[0][1]) {
58: case 'c':
59: nconnected = addlocal(argv[1], connected_nets);
60: argv++;
61: argc--;
62: break;
63: case 'l':
64: nlocal = addlocal(argv[1], local_nets);
65: argv++;
66: argc--;
67: break;
68: default:
69: usage();
70: /*NOTREACHED*/
71: }
72: } else {
73: infile = argv[0];
74: if (freopen(infile, "r", stdin) == NULL) {
75: perror(infile);
76: exit(1);
77: }
78: }
79: argv++;
80: }
81: hf = fopen("hosts", "w");
82: if (hf == NULL) {
83: perror("hosts");
84: exit(1);
85: }
86: copylocal(hf, "localhosts");
87: gf = fopen("gateways", "w");
88: if (gf == NULL) {
89: perror("gateways");
90: exit(1);
91: }
92: copygateways(gf, "localgateways");
93: nf = fopen("networks", "w");
94: if (nf == NULL) {
95: perror("networks");
96: exit(1);
97: }
98: copylocal(nf, "localnetworks");
99: copycomments(stdin, hf, DATELINES);
100: errs = yyparse();
101: dogateways();
102: exit(errs);
103: }
104:
105: usage()
106: {
107: fprintf(stderr,
108: "usage: %s [ -c connected-nets ] [-l local-nets ] [ input-file ]\n",
109: myname);
110: exit(1);
111: }
112:
113: /*
114: * Turn a comma-separated list of network names or numbers in dot notation
115: * (e.g. "arpanet, 128.32") into an array of net numbers.
116: */
117: addlocal(arg, nets)
118: char *arg;
119: int *nets;
120: {
121: register char *p, c;
122: register int nfound = 0;
123:
124: do {
125: p = arg;
126: while (*p && *p != ',' && !isspace(*p))
127: p++;
128: c = *p;
129: *p = 0;
130: while (*arg && isspace(*arg))
131: arg++;
132: if (*arg == 0)
133: continue;
134: if (nfound == MAXNETS) {
135: fprintf(stderr, "%s: Too many networks in list\n",
136: myname);
137: return (nfound);
138: }
139: if (getnetaddr(arg, &nets[nfound]))
140: nfound++;
141: else {
142: fprintf(stderr, "%s: %s: unknown network\n",
143: myname, arg);
144: exit(1);
145: }
146: arg = p + 1;
147: } while (c);
148: return (nfound);
149: }
150:
151: struct name *
152: newname(str)
153: char *str;
154: {
155: char *p;
156: struct name *nm;
157:
158: p = malloc(strlen(str) + 1);
159: strcpy(p, str);
160: nm = (struct name *)malloc(sizeof (struct name));
161: nm->name_val = p;
162: nm->name_link = NONAME;
163: return (nm);
164: }
165:
166: char *
167: lower(str)
168: char *str;
169: {
170: register char *cp = str;
171:
172: while (*cp) {
173: if (isupper(*cp))
174: *cp = tolower(*cp);
175: cp++;
176: }
177: return (str);
178: }
179:
180: do_entry(keyword, addrlist, namelist, cputype, opsys, protos)
181: int keyword;
182: struct addr *addrlist;
183: struct name *namelist, *cputype, *opsys, *protos;
184: {
185: register struct addr *al, *al2;
186: register struct name *nl;
187: struct addr *connect_addr;
188: char *cp;
189:
190: switch (keyword) {
191:
192: case KW_NET:
193: nl = namelist;
194: if (nl == NONAME) {
195: fprintf(stderr, "htable: net");
196: putnet(stderr, inet_netof(addrlist->addr_val));
197: fprintf(stderr, " missing names.\n");
198: break;
199: }
200: fprintf(nf, "%-16.16s", lower(nl->name_val));
201: al2 = addrlist;
202: while (al = al2) {
203: char *cp;
204:
205: putnet(nf, inet_netof(al->addr_val));
206: cp = "\t%s";
207: while (nl = nl->name_link) {
208: fprintf(nf, cp, lower(nl->name_val));
209: cp = " %s";
210: }
211: putc('\n', nf);
212: al2 = al->addr_link;
213: free((char *)al);
214: }
215: break;
216:
217: case KW_GATEWAY:
218: /* locate locally connected address, if one */
219: for (al = addrlist; al; al = al->addr_link)
220: if (connectedto(inet_netof(al->addr_val)))
221: break;
222: if (al == NULL) {
223: /*
224: * Not connected to known networks. Save for later.
225: */
226: struct gateway *gw, *firstgw = (struct gateway *) NULL;
227:
228: for (al = addrlist; al; al = al->addr_link) {
229: register u_long net;
230:
231: net = inet_netof(al->addr_val);
232: gw = savegateway(namelist, net,
233: al->addr_val, 0);
234: if (firstgw == (struct gateway *) NULL)
235: firstgw = gw;
236: gw->g_firstent = firstgw;
237: }
238: freeaddrs(addrlist);
239: goto dontfree;
240: }
241: /*
242: * Connected to a known network.
243: * Mark this as the gateway to all other networks
244: * that are on the addrlist (unless we already have
245: * gateways to them).
246: */
247: connect_addr = al;
248: for (al = addrlist; al; al = al->addr_link) {
249: register u_long net;
250:
251: /* suppress duplicates -- not optimal */
252: net = inet_netof(al->addr_val);
253: if (connectedto(net) || gatewayto(net))
254: continue;
255: printgateway(net, namelist->name_val, 1);
256: (void) savegateway(namelist, net, al->addr_val, 1);
257: }
258: /*
259: * Put the gateway in the hosts file.
260: */
261: putaddr(hf, connect_addr->addr_val);
262: cp = "%s";
263: for (nl = namelist; nl; nl = nl->name_link) {
264: fprintf(hf, cp, lower(nl->name_val));
265: cp = " %s";
266: }
267: fprintf(hf, "\t# gateway\n");
268: freeaddrs(addrlist);
269: goto dontfree;
270:
271: case KW_HOST:
272: al2 = addrlist;
273: while (al = al2) {
274: if (!local(inet_netof(al->addr_val))) {
275: char *cp;
276:
277: putaddr(hf, al->addr_val);
278: cp = "%s";
279: for (nl = namelist; nl; nl = nl->name_link) {
280: fprintf(hf, cp, lower(nl->name_val));
281: cp = " %s";
282: }
283: putc('\n', hf);
284: }
285: al2 = al->addr_link;
286: free((char *)al);
287: }
288: break;
289:
290: default:
291: fprintf(stderr, "Unknown keyword: %d.\n", keyword);
292: }
293: freenames(namelist);
294: dontfree:
295: freenames(cputype);
296: freenames(opsys);
297: freenames(protos);
298: }
299:
300: printgateway(net, name, metric)
301: u_long net;
302: char *name;
303: int metric;
304: {
305: struct netent *np;
306:
307: fprintf(gf, "net ");
308: np = getnetbyaddr(net, AF_INET);
309: if (np)
310: fprintf(gf, "%s", np->n_name);
311: else
312: putnet(gf, net);
313: fprintf(gf, " gateway %s metric %d passive\n",
314: lower(name), metric);
315: }
316:
317: copylocal(f, filename)
318: FILE *f;
319: char *filename;
320: {
321: register FILE *lhf;
322: register cc;
323: char buf[BUFSIZ];
324: extern int errno;
325:
326: lhf = fopen(filename, "r");
327: if (lhf == NULL) {
328: if (errno != ENOENT) {
329: perror(filename);
330: exit(1);
331: }
332: fprintf(stderr, "Warning, no %s file.\n", filename);
333: return;
334: }
335: while (cc = fread(buf, 1, sizeof(buf), lhf))
336: fwrite(buf, 1, cc, f);
337: fclose(lhf);
338: }
339:
340: copygateways(f, filename)
341: FILE *f;
342: char *filename;
343: {
344: register FILE *lhf;
345: struct name *nl;
346: char type[80];
347: char dname[80];
348: char gname[80];
349: char junk[80];
350: char buf[500];
351: u_long addr, net;
352: int metric;
353: extern int errno;
354:
355: lhf = fopen(filename, "r");
356: if (lhf == NULL) {
357: if (errno != ENOENT) {
358: perror(filename);
359: exit(1);
360: }
361: fprintf(stderr, "Warning, no %s file.\n", filename);
362: return;
363: }
364: /* format: {net | host} XX gateway XX metric DD [passive]\n */
365: for (;;) {
366: junk[0] = 0;
367: if (fgets(buf, sizeof(buf), lhf) == (char *)NULL)
368: break;
369: fputs(buf, gf);
370: if (buf[0] == '#' ||
371: sscanf(buf, "%s %s gateway %s metric %d %s",
372: type, dname, gname, &metric, junk) < 5)
373: continue;
374: if (strcmp(type, "net"))
375: continue;
376: if (!getnetaddr(dname, &net))
377: continue;
378: if (!gethostaddr(gname, &addr))
379: continue;
380: nl = newname(gname);
381: (void) savegateway(nl, net, addr, metric);
382: }
383: fclose(lhf);
384: }
385:
386: getnetaddr(name, addr)
387: char *name;
388: u_long *addr;
389: {
390: struct netent *np = getnetbyname(name);
391: int n;
392:
393: if (np == 0) {
394: *addr = inet_network(name);
395: return (*addr != -1);
396: } else {
397: if (np->n_addrtype != AF_INET)
398: return (0);
399: *addr = np->n_net;
400: return (1);
401: }
402: }
403:
404: gethostaddr(name, addr)
405: char *name;
406: u_long *addr;
407: {
408: struct hostent *hp;
409:
410: hp = gethostbyname(name);
411: if (hp) {
412: *addr = *(u_long *)(hp->h_addr);
413: return (1);
414: }
415: *addr = inet_addr(name);
416: return (*addr != -1);
417: }
418:
419: (in, out, ccount)
420: FILE *in, *out;
421: int ccount;
422: {
423: char buf[BUFSIZ];
424: int length;
425: int count;
426: char *fgets();
427:
428: for (count=0; count < ccount; count++) {
429: if ((fgets(buf, sizeof(buf), in) == NULL) || (buf[0] != ';'))
430: return;
431: buf[0] = '#';
432: fputs(buf, out);
433: }
434: return;
435: }
436: #define UC(b) (((int)(b))&0xff)
437:
438: /*
439: * Print network number in internet-standard dot notation;
440: * v is in host byte order.
441: */
442: putnet(f, v)
443: FILE *f;
444: register u_long v;
445: {
446: if (v < 128)
447: fprintf(f, "%d", (int)v);
448: else if (v < 65536)
449: fprintf(f, "%d.%d", UC(v >> 8), UC(v));
450: else
451: fprintf(f, "%d.%d.%d", UC(v >> 16), UC(v >> 8), UC(v));
452: }
453:
454: putaddr(f, v)
455: FILE *f;
456: u_long v;
457: {
458: register char *a = (char *)&v;
459: char buf[32];
460:
461: sprintf(buf,"%d.%d.%d.%d", UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]));
462: fprintf(f, "%-16.16s", buf);
463: }
464:
465: freenames(list)
466: struct name *list;
467: {
468: register struct name *nl, *nl2;
469:
470: nl2 = list;
471: while (nl = nl2) {
472: nl2 = nl->name_link;
473: free(nl->name_val);
474: free((char *)nl);
475: }
476: }
477:
478: freeaddrs(list)
479: struct addr *list;
480: {
481: register struct addr *al, *al2;
482:
483: al2 = list;
484: while (al = al2)
485: al2 = al->addr_link, free((char *)al);
486: }
487:
488: struct gateway *gateways = 0;
489: struct gateway *lastgateway = 0;
490:
491: struct gateway *
492: gatewayto(net)
493: register u_long net;
494: {
495: register struct gateway *gp;
496:
497: for (gp = gateways; gp; gp = gp->g_link)
498: if ((gp->g_net == net) && (gp->g_metric > 0))
499: return (gp);
500: return ((struct gateway *) NULL);
501: }
502:
503: struct gateway *
504: savegateway(namelist, net, addr, metric)
505: struct name *namelist;
506: u_long addr, net;
507: int metric;
508: {
509: register struct gateway *gp;
510:
511: gp = (struct gateway *)malloc(sizeof (struct gateway));
512: if (gp == 0) {
513: fprintf(stderr, "htable: out of memory\n");
514: exit(1);
515: }
516: gp->g_link = (struct gateway *) NULL;
517: if (lastgateway)
518: lastgateway->g_link = gp;
519: else
520: gateways = gp;
521: lastgateway = gp;
522: gp->g_name = namelist;
523: gp->g_net = net;
524: gp->g_addr = addr;
525: gp->g_metric = metric;
526: if (metric == 1)
527: gp->g_dst = gp;
528: return (gp);
529: }
530:
531: connectedto(net)
532: u_long net;
533: {
534: register i;
535:
536: for (i = 0; i < nconnected; i++)
537: if (connected_nets[i] == net)
538: return(1);
539: return(0);
540: }
541:
542: local(net)
543: u_long net;
544: {
545: register i;
546:
547: for (i = 0; i < nlocal; i++)
548: if (local_nets[i] == net)
549: return(1);
550: return(0);
551: }
552:
553: #define MAXHOPS 10
554:
555: /*
556: * Go through list of gateways, finding connections for gateways
557: * that are not yet connected.
558: */
559: dogateways()
560: {
561: register struct gateway *gp, *gw, *ggp;
562: register int hops, changed = 1;
563: struct name *nl;
564: char *cp;
565:
566: for (hops = 0; hops < MAXHOPS && changed; hops++, changed = 0) {
567: for (gp = gateways; gp; gp = gp->g_link)
568: if ((gp->g_metric == 0) && (gw = gatewayto(gp->g_net))) {
569: /*
570: * Found a new connection.
571: * For each other network that this gateway is on,
572: * add a new gateway to that network.
573: */
574: changed = 1;
575: gp->g_dst = gw->g_dst;
576: gp->g_metric = gw->g_metric + 1;
577: for (ggp = gp->g_firstent; ggp->g_name == gp->g_name;
578: ggp = ggp->g_link) {
579: if (ggp == gp)
580: continue;
581: if (gatewayto(ggp->g_net))
582: continue;
583: ggp->g_dst = gp->g_dst;
584: ggp->g_metric = gp->g_metric;
585: printgateway(ggp->g_net,
586: gw->g_dst->g_name->name_val, gp->g_metric);
587: }
588: /*
589: * Put the gateway in the hosts file,
590: * using the address for the connected net.
591: */
592: putaddr(hf, gp->g_addr);
593: cp = "%s";
594: for (nl = gp->g_name; nl; nl = nl->name_link) {
595: fprintf(hf, cp, lower(nl->name_val));
596: cp = " %s";
597: }
598: fprintf(hf, "\t# gateway\n");
599: }
600: }
601: }