add proper return to savegateway() from Mike Muuss (mike@brl.mil)
[unix-history] / usr / src / old / htable / htable.c
CommitLineData
ab6da654
DF
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
dd020e70 7#ifndef lint
2de3e885
KM
8char 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
2d474861 14static char sccsid[] = "@(#)htable.c 5.5 (Berkeley) %G%";
ab6da654 15#endif not lint
dd020e70
SL
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>
5494cf94 23#include <errno.h>
7df00d98 24#include <netdb.h>
7df00d98 25
5494cf94 26#include "htable.h" /* includes <sys/types.h> */
dd020e70 27
f7a7a9a9 28#include <sys/socket.h>
5494cf94
SL
29#include <netinet/in.h>
30
1750308c 31#define DATELINES 3 /* these lines usually contain the date */
99d3ae94 32#define MAXNETS 30 /* array size for local, connected nets */
1750308c 33
5494cf94
SL
34FILE *hf; /* hosts file */
35FILE *gf; /* gateways file */
36FILE *nf; /* networks file */
99d3ae94
MK
37struct gateway *savegateway(), *gatewayto();
38
39int connected_nets[MAXNETS];
40int nconnected;
41int local_nets[MAXNETS];
42int nlocal;
43char *myname;
dd020e70
SL
44
45main(argc, argv)
46 int argc;
47 char *argv[];
48{
99d3ae94
MK
49 int errs;
50
dd020e70 51 infile = "(stdin)";
99d3ae94
MK
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 }
dd020e70 78 }
99d3ae94 79 argv++;
dd020e70
SL
80 }
81 hf = fopen("hosts", "w");
82 if (hf == NULL) {
83 perror("hosts");
84 exit(1);
85 }
5494cf94
SL
86 copylocal(hf, "localhosts");
87 gf = fopen("gateways", "w");
88 if (gf == NULL) {
dd020e70
SL
89 perror("gateways");
90 exit(1);
91 }
99d3ae94 92 copygateways(gf, "localgateways");
5494cf94
SL
93 nf = fopen("networks", "w");
94 if (nf == NULL) {
95 perror("networks");
96 exit(1);
97 }
98 copylocal(nf, "localnetworks");
1750308c 99 copycomments(stdin, hf, DATELINES);
99d3ae94
MK
100 errs = yyparse();
101 dogateways();
102 exit(errs);
103}
104
105usage()
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 */
117addlocal(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 }
573c06ae 146 arg = p + 1;
99d3ae94
MK
147 } while (c);
148 return (nfound);
dd020e70
SL
149}
150
151struct name *
152newname(str)
153 char *str;
154{
155 char *p;
156 struct name *nm;
157
158 p = malloc(strlen(str) + 1);
159 strcpy(p, str);
5494cf94 160 nm = (struct name *)malloc(sizeof (struct name));
dd020e70
SL
161 nm->name_val = p;
162 nm->name_link = NONAME;
163 return (nm);
164}
165
166char *
167lower(str)
168 char *str;
169{
170 register char *cp = str;
171
172 while (*cp) {
173 if (isupper(*cp))
174 *cp = tolower(*cp);
1bcba0d9
MK
175 if (*cp == '.')
176 break;
dd020e70
SL
177 cp++;
178 }
179 return (str);
180}
181
182do_entry(keyword, addrlist, namelist, cputype, opsys, protos)
183 int keyword;
184 struct addr *addrlist;
185 struct name *namelist, *cputype, *opsys, *protos;
186{
187 register struct addr *al, *al2;
5494cf94 188 register struct name *nl;
99d3ae94
MK
189 struct addr *connect_addr;
190 char *cp;
dd020e70
SL
191
192 switch (keyword) {
193
194 case KW_NET:
5494cf94
SL
195 nl = namelist;
196 if (nl == NONAME) {
197 fprintf(stderr, "htable: net");
6e2735e4 198 putnet(stderr, inet_netof(addrlist->addr_val));
5494cf94
SL
199 fprintf(stderr, " missing names.\n");
200 break;
201 }
202 fprintf(nf, "%-16.16s", lower(nl->name_val));
203 al2 = addrlist;
204 while (al = al2) {
205 char *cp;
206
6e2735e4 207 putnet(nf, inet_netof(al->addr_val));
5494cf94
SL
208 cp = "\t%s";
209 while (nl = nl->name_link) {
210 fprintf(nf, cp, lower(nl->name_val));
211 cp = " %s";
212 }
213 putc('\n', nf);
214 al2 = al->addr_link;
215 free((char *)al);
216 }
99d3ae94 217 break;
dd020e70
SL
218
219 case KW_GATEWAY:
99d3ae94 220 /* locate locally connected address, if one */
7df00d98 221 for (al = addrlist; al; al = al->addr_link)
99d3ae94 222 if (connectedto(inet_netof(al->addr_val)))
7df00d98 223 break;
99d3ae94
MK
224 if (al == NULL) {
225 /*
226 * Not connected to known networks. Save for later.
227 */
228 struct gateway *gw, *firstgw = (struct gateway *) NULL;
229
230 for (al = addrlist; al; al = al->addr_link) {
231 register int net;
232
233 net = inet_netof(al->addr_val);
234 gw = savegateway(namelist, net,
235 al->addr_val, 0);
236 if (firstgw == (struct gateway *) NULL)
237 firstgw = gw;
238 gw->g_firstent = firstgw;
239 }
240 freeaddrs(addrlist);
241 goto dontfree;
242 }
243 /*
244 * Connected to a known network.
245 * Mark this as the gateway to all other networks
246 * that are on the addrlist (unless we already have
247 * gateways to them).
248 */
249 connect_addr = al;
250 for (al = addrlist; al; al = al->addr_link) {
7df00d98 251 register int net;
5494cf94
SL
252
253 /* suppress duplicates -- not optimal */
7df00d98 254 net = inet_netof(al->addr_val);
49cdcf9f 255 if (connectedto(net) || gatewayto(net))
99d3ae94
MK
256 continue;
257 printgateway(net, namelist->name_val, 1);
258 (void) savegateway(namelist, net, al->addr_val, 1);
7df00d98 259 }
99d3ae94
MK
260 /*
261 * Put the gateway in the hosts file.
262 */
263 putaddr(hf, connect_addr->addr_val);
264 cp = "%s";
265 for (nl = namelist; nl; nl = nl->name_link) {
266 fprintf(hf, cp, lower(nl->name_val));
267 cp = " %s";
5494cf94 268 }
99d3ae94
MK
269 fprintf(hf, "\t# gateway\n");
270 freeaddrs(addrlist);
271 goto dontfree;
dd020e70
SL
272
273 case KW_HOST:
5494cf94
SL
274 al2 = addrlist;
275 while (al = al2) {
99d3ae94 276 if (!local(inet_netof(al->addr_val))) {
5494cf94
SL
277 char *cp;
278
279 putaddr(hf, al->addr_val);
280 cp = "%s";
281 for (nl = namelist; nl; nl = nl->name_link) {
282 fprintf(hf, cp, lower(nl->name_val));
283 cp = " %s";
284 }
dd020e70
SL
285 putc('\n', hf);
286 }
287 al2 = al->addr_link;
5494cf94 288 free((char *)al);
dd020e70 289 }
99d3ae94 290 break;
dd020e70
SL
291
292 default:
293 fprintf(stderr, "Unknown keyword: %d.\n", keyword);
294 }
5494cf94 295 freenames(namelist);
99d3ae94 296dontfree:
5494cf94 297 freenames(protos);
dd020e70
SL
298}
299
99d3ae94
MK
300printgateway(net, name, metric)
301 int 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
5494cf94
SL
317copylocal(f, filename)
318 FILE *f;
319 char *filename;
dd020e70
SL
320{
321 register FILE *lhf;
322 register cc;
323 char buf[BUFSIZ];
5494cf94 324 extern int errno;
dd020e70 325
5494cf94 326 lhf = fopen(filename, "r");
dd020e70 327 if (lhf == NULL) {
5494cf94
SL
328 if (errno != ENOENT) {
329 perror(filename);
330 exit(1);
331 }
332 fprintf(stderr, "Warning, no %s file.\n", filename);
dd020e70
SL
333 return;
334 }
335 while (cc = fread(buf, 1, sizeof(buf), lhf))
5494cf94 336 fwrite(buf, 1, cc, f);
dd020e70
SL
337 fclose(lhf);
338}
5494cf94 339
99d3ae94
MK
340copygateways(f, filename)
341 FILE *f;
342 char *filename;
343{
344 register FILE *lhf;
99d3ae94
MK
345 struct name *nl;
346 char type[80];
347 char dname[80];
348 char gname[80];
349 char junk[80];
581d366a 350 char buf[500];
99d3ae94
MK
351 u_long addr;
352 int net, 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 */
6e2735e4
MK
365 for (;;) {
366 junk[0] = 0;
581d366a 367 if (fgets(buf, sizeof(buf), lhf) == (char *)NULL)
6e2735e4 368 break;
581d366a
MK
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;
99d3ae94 374 if (strcmp(type, "net"))
581d366a 375 continue;
99d3ae94 376 if (!getnetaddr(dname, &net))
581d366a 377 continue;
99d3ae94 378 if (!gethostaddr(gname, &addr))
581d366a 379 continue;
99d3ae94
MK
380 nl = newname(gname);
381 (void) savegateway(nl, net, addr, metric);
99d3ae94
MK
382 }
383 fclose(lhf);
384}
385
386getnetaddr(name, addr)
387 char *name;
388 int *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
404gethostaddr(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
1750308c
MD
419copycomments(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}
5494cf94
SL
436#define UC(b) (((int)(b))&0xff)
437
3dbccebd
MK
438/*
439 * Print network number in internet-standard dot notation;
440 * v is in host byte order.
441 */
5494cf94
SL
442putnet(f, v)
443 FILE *f;
6e2735e4 444 register int v;
5494cf94 445{
3dbccebd
MK
446 if (v < 128)
447 fprintf(f, "%d", v);
448 else if (v < 65536)
6e2735e4 449 fprintf(f, "%d.%d", UC(v >> 8), UC(v));
5494cf94 450 else
6e2735e4 451 fprintf(f, "%d.%d.%d", UC(v >> 16), UC(v >> 8), UC(v));
5494cf94
SL
452}
453
454putaddr(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
465freenames(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}
99d3ae94
MK
477
478freeaddrs(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}
5494cf94
SL
487
488struct gateway *gateways = 0;
99d3ae94 489struct gateway *lastgateway = 0;
5494cf94 490
99d3ae94
MK
491struct gateway *
492gatewayto(net)
5494cf94
SL
493 register int net;
494{
495 register struct gateway *gp;
496
497 for (gp = gateways; gp; gp = gp->g_link)
99d3ae94
MK
498 if ((gp->g_net == net) && (gp->g_metric > 0))
499 return (gp);
500 return ((struct gateway *) NULL);
5494cf94
SL
501}
502
99d3ae94
MK
503struct gateway *
504savegateway(namelist, net, addr, metric)
505 struct name *namelist;
506 u_long addr;
507 int net, metric;
5494cf94
SL
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 }
99d3ae94
MK
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;
5494cf94 523 gp->g_net = net;
99d3ae94
MK
524 gp->g_addr = addr;
525 gp->g_metric = metric;
526 if (metric == 1)
527 gp->g_dst = gp;
2d474861 528 return (gp);
99d3ae94
MK
529}
530
531connectedto(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
542local(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 */
559dogateways()
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 }
5494cf94 601}