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: #ifndef lint
8: char copyright[] =
9: "@(#) Copyright (c) 1983 Regents of the University of California.\n\
10: All rights reserved.\n";
11: #endif not lint
12:
13: #ifndef lint
14: static char sccsid[] = "@(#)htable.c 5.5 (Berkeley) 4/15/86";
15: #endif not lint
16:
17: /*
18: * htable - convert NIC host table into a UNIX format.
19: * NIC format is described in RFC 810, 1 March 1982.
20: */
21: #include <stdio.h>
22: #include <ctype.h>
23: #include <errno.h>
24: #include <netdb.h>
25:
26: #include "htable.h" /* includes <sys/types.h> */
27:
28: #include <sys/socket.h>
29: #include <netinet/in.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: int connected_nets[MAXNETS];
40: int nconnected;
41: int 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 int 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 int 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(protos);
296: }
297:
298: printgateway(net, name, metric)
299: int net;
300: char *name;
301: int metric;
302: {
303: struct netent *np;
304:
305: fprintf(gf, "net ");
306: np = getnetbyaddr(net, AF_INET);
307: if (np)
308: fprintf(gf, "%s", np->n_name);
309: else
310: putnet(gf, net);
311: fprintf(gf, " gateway %s metric %d passive\n",
312: lower(name), metric);
313: }
314:
315: copylocal(f, filename)
316: FILE *f;
317: char *filename;
318: {
319: register FILE *lhf;
320: register cc;
321: char buf[BUFSIZ];
322: extern int errno;
323:
324: lhf = fopen(filename, "r");
325: if (lhf == NULL) {
326: if (errno != ENOENT) {
327: perror(filename);
328: exit(1);
329: }
330: fprintf(stderr, "Warning, no %s file.\n", filename);
331: return;
332: }
333: while (cc = fread(buf, 1, sizeof(buf), lhf))
334: fwrite(buf, 1, cc, f);
335: fclose(lhf);
336: }
337:
338: copygateways(f, filename)
339: FILE *f;
340: char *filename;
341: {
342: register FILE *lhf;
343: struct name *nl;
344: char type[80];
345: char dname[80];
346: char gname[80];
347: char junk[80];
348: char buf[500];
349: u_long addr;
350: int net, metric;
351: extern int errno;
352:
353: lhf = fopen(filename, "r");
354: if (lhf == NULL) {
355: if (errno != ENOENT) {
356: perror(filename);
357: exit(1);
358: }
359: fprintf(stderr, "Warning, no %s file.\n", filename);
360: return;
361: }
362: /* format: {net | host} XX gateway XX metric DD [passive]\n */
363: for (;;) {
364: junk[0] = 0;
365: if (fgets(buf, sizeof(buf), lhf) == (char *)NULL)
366: break;
367: fputs(buf, gf);
368: if (buf[0] == '#' ||
369: sscanf(buf, "%s %s gateway %s metric %d %s",
370: type, dname, gname, &metric, junk) < 5)
371: continue;
372: if (strcmp(type, "net"))
373: continue;
374: if (!getnetaddr(dname, &net))
375: continue;
376: if (!gethostaddr(gname, &addr))
377: continue;
378: nl = newname(gname);
379: (void) savegateway(nl, net, addr, metric);
380: }
381: fclose(lhf);
382: }
383:
384: getnetaddr(name, addr)
385: char *name;
386: int *addr;
387: {
388: struct netent *np = getnetbyname(name);
389: int n;
390:
391: if (np == 0) {
392: *addr = inet_network(name);
393: return (*addr != -1);
394: } else {
395: if (np->n_addrtype != AF_INET)
396: return (0);
397: *addr = np->n_net;
398: return (1);
399: }
400: }
401:
402: gethostaddr(name, addr)
403: char *name;
404: u_long *addr;
405: {
406: struct hostent *hp;
407:
408: hp = gethostbyname(name);
409: if (hp) {
410: *addr = *(u_long *)(hp->h_addr);
411: return (1);
412: }
413: *addr = inet_addr(name);
414: return (*addr != -1);
415: }
416:
417: (in, out, ccount)
418: FILE *in, *out;
419: int ccount;
420: {
421: char buf[BUFSIZ];
422: int length;
423: int count;
424: char *fgets();
425:
426: for (count=0; count < ccount; count++) {
427: if ((fgets(buf, sizeof(buf), in) == NULL) || (buf[0] != ';'))
428: return;
429: buf[0] = '#';
430: fputs(buf, out);
431: }
432: return;
433: }
434: #define UC(b) (((int)(b))&0xff)
435:
436: /*
437: * Print network number in internet-standard dot notation;
438: * v is in host byte order.
439: */
440: putnet(f, v)
441: FILE *f;
442: register int v;
443: {
444: if (v < 128)
445: fprintf(f, "%d", v);
446: else if (v < 65536)
447: fprintf(f, "%d.%d", UC(v >> 8), UC(v));
448: else
449: fprintf(f, "%d.%d.%d", UC(v >> 16), UC(v >> 8), UC(v));
450: }
451:
452: putaddr(f, v)
453: FILE *f;
454: u_long v;
455: {
456: register char *a = (char *)&v;
457: char buf[32];
458:
459: sprintf(buf,"%d.%d.%d.%d", UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]));
460: fprintf(f, "%-16.16s", buf);
461: }
462:
463: freenames(list)
464: struct name *list;
465: {
466: register struct name *nl, *nl2;
467:
468: nl2 = list;
469: while (nl = nl2) {
470: nl2 = nl->name_link;
471: free(nl->name_val);
472: free((char *)nl);
473: }
474: }
475:
476: freeaddrs(list)
477: struct addr *list;
478: {
479: register struct addr *al, *al2;
480:
481: al2 = list;
482: while (al = al2)
483: al2 = al->addr_link, free((char *)al);
484: }
485:
486: struct gateway *gateways = 0;
487: struct gateway *lastgateway = 0;
488:
489: struct gateway *
490: gatewayto(net)
491: register int net;
492: {
493: register struct gateway *gp;
494:
495: for (gp = gateways; gp; gp = gp->g_link)
496: if ((gp->g_net == net) && (gp->g_metric > 0))
497: return (gp);
498: return ((struct gateway *) NULL);
499: }
500:
501: struct gateway *
502: savegateway(namelist, net, addr, metric)
503: struct name *namelist;
504: u_long addr;
505: int net, metric;
506: {
507: register struct gateway *gp;
508:
509: gp = (struct gateway *)malloc(sizeof (struct gateway));
510: if (gp == 0) {
511: fprintf(stderr, "htable: out of memory\n");
512: exit(1);
513: }
514: gp->g_link = (struct gateway *) NULL;
515: if (lastgateway)
516: lastgateway->g_link = gp;
517: else
518: gateways = gp;
519: lastgateway = gp;
520: gp->g_name = namelist;
521: gp->g_net = net;
522: gp->g_addr = addr;
523: gp->g_metric = metric;
524: if (metric == 1)
525: gp->g_dst = gp;
526: return (gp);
527: }
528:
529: connectedto(net)
530: u_long net;
531: {
532: register i;
533:
534: for (i = 0; i < nconnected; i++)
535: if (connected_nets[i] == net)
536: return(1);
537: return(0);
538: }
539:
540: local(net)
541: u_long net;
542: {
543: register i;
544:
545: for (i = 0; i < nlocal; i++)
546: if (local_nets[i] == net)
547: return(1);
548: return(0);
549: }
550:
551: #define MAXHOPS 10
552:
553: /*
554: * Go through list of gateways, finding connections for gateways
555: * that are not yet connected.
556: */
557: dogateways()
558: {
559: register struct gateway *gp, *gw, *ggp;
560: register int hops, changed = 1;
561: struct name *nl;
562: char *cp;
563:
564: for (hops = 0; hops < MAXHOPS && changed; hops++, changed = 0) {
565: for (gp = gateways; gp; gp = gp->g_link)
566: if ((gp->g_metric == 0) && (gw = gatewayto(gp->g_net))) {
567: /*
568: * Found a new connection.
569: * For each other network that this gateway is on,
570: * add a new gateway to that network.
571: */
572: changed = 1;
573: gp->g_dst = gw->g_dst;
574: gp->g_metric = gw->g_metric + 1;
575: for (ggp = gp->g_firstent; ggp->g_name == gp->g_name;
576: ggp = ggp->g_link) {
577: if (ggp == gp)
578: continue;
579: if (gatewayto(ggp->g_net))
580: continue;
581: ggp->g_dst = gp->g_dst;
582: ggp->g_metric = gp->g_metric;
583: printgateway(ggp->g_net,
584: gw->g_dst->g_name->name_val, gp->g_metric);
585: }
586: /*
587: * Put the gateway in the hosts file,
588: * using the address for the connected net.
589: */
590: putaddr(hf, gp->g_addr);
591: cp = "%s";
592: for (nl = gp->g_name; nl; nl = nl->name_link) {
593: fprintf(hf, cp, lower(nl->name_val));
594: cp = " %s";
595: }
596: fprintf(hf, "\t# gateway\n");
597: }
598: }
599: }