AT&T doesn't use the man macros...
[unix-history] / usr / src / old / htable / htable.c
CommitLineData
ab6da654
DF
1/*
2 * Copyright (c) 1983 Regents of the University of California.
8f66080b
KB
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms are permitted
6 * provided that this notice is preserved and that due credit is given
7 * to the University of California at Berkeley. The name of the University
8 * may not be used to endorse or promote products derived from this
9 * software without specific prior written permission. This software
10 * is provided ``as is'' without express or implied warranty.
ab6da654
DF
11 */
12
dd020e70 13#ifndef lint
2de3e885
KM
14char copyright[] =
15"@(#) Copyright (c) 1983 Regents of the University of California.\n\
16 All rights reserved.\n";
8f66080b 17#endif /* not lint */
2de3e885
KM
18
19#ifndef lint
8f66080b
KB
20static char sccsid[] = "@(#)htable.c 5.7 (Berkeley) %G%";
21#endif /* not lint */
dd020e70
SL
22
23/*
24 * htable - convert NIC host table into a UNIX format.
25 * NIC format is described in RFC 810, 1 March 1982.
26 */
27#include <stdio.h>
28#include <ctype.h>
5494cf94 29#include <errno.h>
7df00d98 30#include <netdb.h>
7df00d98 31
5494cf94 32#include "htable.h" /* includes <sys/types.h> */
dd020e70 33
f7a7a9a9 34#include <sys/socket.h>
8f66080b 35#include <arpa/inet.h>
5494cf94 36
1750308c 37#define DATELINES 3 /* these lines usually contain the date */
99d3ae94 38#define MAXNETS 30 /* array size for local, connected nets */
1750308c 39
5494cf94
SL
40FILE *hf; /* hosts file */
41FILE *gf; /* gateways file */
42FILE *nf; /* networks file */
99d3ae94
MK
43struct gateway *savegateway(), *gatewayto();
44
45int connected_nets[MAXNETS];
46int nconnected;
47int local_nets[MAXNETS];
48int nlocal;
49char *myname;
dd020e70
SL
50
51main(argc, argv)
52 int argc;
53 char *argv[];
54{
99d3ae94
MK
55 int errs;
56
dd020e70 57 infile = "(stdin)";
99d3ae94
MK
58 myname = argv[0];
59 argc--;
60 argv++;
61 while (argc--) {
62 if (*argv[0] == '-') {
63 switch (argv[0][1]) {
64 case 'c':
65 nconnected = addlocal(argv[1], connected_nets);
66 argv++;
67 argc--;
68 break;
69 case 'l':
70 nlocal = addlocal(argv[1], local_nets);
71 argv++;
72 argc--;
73 break;
74 default:
75 usage();
76 /*NOTREACHED*/
77 }
78 } else {
79 infile = argv[0];
80 if (freopen(infile, "r", stdin) == NULL) {
81 perror(infile);
82 exit(1);
83 }
dd020e70 84 }
99d3ae94 85 argv++;
dd020e70
SL
86 }
87 hf = fopen("hosts", "w");
88 if (hf == NULL) {
89 perror("hosts");
90 exit(1);
91 }
5494cf94
SL
92 copylocal(hf, "localhosts");
93 gf = fopen("gateways", "w");
94 if (gf == NULL) {
dd020e70
SL
95 perror("gateways");
96 exit(1);
97 }
8f66080b 98 copygateways("localgateways");
5494cf94
SL
99 nf = fopen("networks", "w");
100 if (nf == NULL) {
101 perror("networks");
102 exit(1);
103 }
104 copylocal(nf, "localnetworks");
1750308c 105 copycomments(stdin, hf, DATELINES);
99d3ae94
MK
106 errs = yyparse();
107 dogateways();
108 exit(errs);
109}
110
111usage()
112{
113 fprintf(stderr,
114 "usage: %s [ -c connected-nets ] [-l local-nets ] [ input-file ]\n",
115 myname);
116 exit(1);
117}
118
119/*
120 * Turn a comma-separated list of network names or numbers in dot notation
121 * (e.g. "arpanet, 128.32") into an array of net numbers.
122 */
123addlocal(arg, nets)
124 char *arg;
125 int *nets;
126{
127 register char *p, c;
128 register int nfound = 0;
129
130 do {
131 p = arg;
132 while (*p && *p != ',' && !isspace(*p))
133 p++;
134 c = *p;
135 *p = 0;
136 while (*arg && isspace(*arg))
137 arg++;
138 if (*arg == 0)
139 continue;
140 if (nfound == MAXNETS) {
141 fprintf(stderr, "%s: Too many networks in list\n",
142 myname);
143 return (nfound);
144 }
145 if (getnetaddr(arg, &nets[nfound]))
146 nfound++;
147 else {
148 fprintf(stderr, "%s: %s: unknown network\n",
149 myname, arg);
150 exit(1);
151 }
573c06ae 152 arg = p + 1;
99d3ae94
MK
153 } while (c);
154 return (nfound);
dd020e70
SL
155}
156
157struct name *
158newname(str)
159 char *str;
160{
161 char *p;
162 struct name *nm;
163
164 p = malloc(strlen(str) + 1);
165 strcpy(p, str);
5494cf94 166 nm = (struct name *)malloc(sizeof (struct name));
dd020e70
SL
167 nm->name_val = p;
168 nm->name_link = NONAME;
169 return (nm);
170}
171
172char *
173lower(str)
174 char *str;
175{
176 register char *cp = str;
177
178 while (*cp) {
179 if (isupper(*cp))
180 *cp = tolower(*cp);
1bcba0d9
MK
181 if (*cp == '.')
182 break;
dd020e70
SL
183 cp++;
184 }
185 return (str);
186}
187
188do_entry(keyword, addrlist, namelist, cputype, opsys, protos)
189 int keyword;
190 struct addr *addrlist;
191 struct name *namelist, *cputype, *opsys, *protos;
192{
193 register struct addr *al, *al2;
5494cf94 194 register struct name *nl;
99d3ae94
MK
195 struct addr *connect_addr;
196 char *cp;
dd020e70
SL
197
198 switch (keyword) {
199
200 case KW_NET:
5494cf94
SL
201 nl = namelist;
202 if (nl == NONAME) {
203 fprintf(stderr, "htable: net");
6e2735e4 204 putnet(stderr, inet_netof(addrlist->addr_val));
5494cf94
SL
205 fprintf(stderr, " missing names.\n");
206 break;
207 }
208 fprintf(nf, "%-16.16s", lower(nl->name_val));
209 al2 = addrlist;
210 while (al = al2) {
211 char *cp;
212
6e2735e4 213 putnet(nf, inet_netof(al->addr_val));
5494cf94
SL
214 cp = "\t%s";
215 while (nl = nl->name_link) {
216 fprintf(nf, cp, lower(nl->name_val));
217 cp = " %s";
218 }
219 putc('\n', nf);
220 al2 = al->addr_link;
221 free((char *)al);
222 }
99d3ae94 223 break;
dd020e70
SL
224
225 case KW_GATEWAY:
99d3ae94 226 /* locate locally connected address, if one */
7df00d98 227 for (al = addrlist; al; al = al->addr_link)
99d3ae94 228 if (connectedto(inet_netof(al->addr_val)))
7df00d98 229 break;
99d3ae94
MK
230 if (al == NULL) {
231 /*
232 * Not connected to known networks. Save for later.
233 */
234 struct gateway *gw, *firstgw = (struct gateway *) NULL;
235
236 for (al = addrlist; al; al = al->addr_link) {
237 register int net;
238
239 net = inet_netof(al->addr_val);
240 gw = savegateway(namelist, net,
241 al->addr_val, 0);
242 if (firstgw == (struct gateway *) NULL)
243 firstgw = gw;
244 gw->g_firstent = firstgw;
245 }
246 freeaddrs(addrlist);
247 goto dontfree;
248 }
249 /*
250 * Connected to a known network.
251 * Mark this as the gateway to all other networks
252 * that are on the addrlist (unless we already have
253 * gateways to them).
254 */
255 connect_addr = al;
256 for (al = addrlist; al; al = al->addr_link) {
7df00d98 257 register int net;
5494cf94
SL
258
259 /* suppress duplicates -- not optimal */
7df00d98 260 net = inet_netof(al->addr_val);
49cdcf9f 261 if (connectedto(net) || gatewayto(net))
99d3ae94
MK
262 continue;
263 printgateway(net, namelist->name_val, 1);
264 (void) savegateway(namelist, net, al->addr_val, 1);
7df00d98 265 }
99d3ae94
MK
266 /*
267 * Put the gateway in the hosts file.
268 */
269 putaddr(hf, connect_addr->addr_val);
270 cp = "%s";
271 for (nl = namelist; nl; nl = nl->name_link) {
272 fprintf(hf, cp, lower(nl->name_val));
273 cp = " %s";
5494cf94 274 }
99d3ae94
MK
275 fprintf(hf, "\t# gateway\n");
276 freeaddrs(addrlist);
277 goto dontfree;
dd020e70
SL
278
279 case KW_HOST:
5494cf94
SL
280 al2 = addrlist;
281 while (al = al2) {
99d3ae94 282 if (!local(inet_netof(al->addr_val))) {
5494cf94
SL
283 char *cp;
284
285 putaddr(hf, al->addr_val);
286 cp = "%s";
287 for (nl = namelist; nl; nl = nl->name_link) {
288 fprintf(hf, cp, lower(nl->name_val));
289 cp = " %s";
290 }
dd020e70
SL
291 putc('\n', hf);
292 }
293 al2 = al->addr_link;
5494cf94 294 free((char *)al);
dd020e70 295 }
99d3ae94 296 break;
dd020e70
SL
297
298 default:
299 fprintf(stderr, "Unknown keyword: %d.\n", keyword);
300 }
5494cf94 301 freenames(namelist);
99d3ae94 302dontfree:
5494cf94 303 freenames(protos);
dd020e70
SL
304}
305
99d3ae94
MK
306printgateway(net, name, metric)
307 int net;
308 char *name;
309 int metric;
310{
311 struct netent *np;
312
313 fprintf(gf, "net ");
314 np = getnetbyaddr(net, AF_INET);
315 if (np)
316 fprintf(gf, "%s", np->n_name);
317 else
318 putnet(gf, net);
319 fprintf(gf, " gateway %s metric %d passive\n",
320 lower(name), metric);
321}
322
5494cf94
SL
323copylocal(f, filename)
324 FILE *f;
325 char *filename;
dd020e70
SL
326{
327 register FILE *lhf;
328 register cc;
329 char buf[BUFSIZ];
5494cf94 330 extern int errno;
dd020e70 331
5494cf94 332 lhf = fopen(filename, "r");
dd020e70 333 if (lhf == NULL) {
5494cf94
SL
334 if (errno != ENOENT) {
335 perror(filename);
336 exit(1);
337 }
338 fprintf(stderr, "Warning, no %s file.\n", filename);
dd020e70
SL
339 return;
340 }
341 while (cc = fread(buf, 1, sizeof(buf), lhf))
5494cf94 342 fwrite(buf, 1, cc, f);
dd020e70
SL
343 fclose(lhf);
344}
5494cf94 345
8f66080b 346copygateways(filename)
99d3ae94
MK
347 char *filename;
348{
349 register FILE *lhf;
99d3ae94
MK
350 struct name *nl;
351 char type[80];
352 char dname[80];
353 char gname[80];
354 char junk[80];
581d366a 355 char buf[500];
8f66080b 356 struct in_addr addr;
99d3ae94
MK
357 int net, metric;
358 extern int errno;
359
360 lhf = fopen(filename, "r");
361 if (lhf == NULL) {
362 if (errno != ENOENT) {
363 perror(filename);
364 exit(1);
365 }
366 fprintf(stderr, "Warning, no %s file.\n", filename);
367 return;
368 }
369 /* format: {net | host} XX gateway XX metric DD [passive]\n */
6e2735e4
MK
370 for (;;) {
371 junk[0] = 0;
581d366a 372 if (fgets(buf, sizeof(buf), lhf) == (char *)NULL)
6e2735e4 373 break;
581d366a
MK
374 fputs(buf, gf);
375 if (buf[0] == '#' ||
376 sscanf(buf, "%s %s gateway %s metric %d %s",
377 type, dname, gname, &metric, junk) < 5)
378 continue;
99d3ae94 379 if (strcmp(type, "net"))
581d366a 380 continue;
99d3ae94 381 if (!getnetaddr(dname, &net))
581d366a 382 continue;
8f66080b 383 if (!gethostaddr(gname, &addr.s_addr))
581d366a 384 continue;
99d3ae94
MK
385 nl = newname(gname);
386 (void) savegateway(nl, net, addr, metric);
99d3ae94
MK
387 }
388 fclose(lhf);
389}
390
391getnetaddr(name, addr)
392 char *name;
393 int *addr;
394{
395 struct netent *np = getnetbyname(name);
99d3ae94
MK
396
397 if (np == 0) {
398 *addr = inet_network(name);
399 return (*addr != -1);
400 } else {
401 if (np->n_addrtype != AF_INET)
402 return (0);
403 *addr = np->n_net;
404 return (1);
405 }
406}
407
408gethostaddr(name, addr)
409 char *name;
410 u_long *addr;
411{
412 struct hostent *hp;
413
414 hp = gethostbyname(name);
415 if (hp) {
416 *addr = *(u_long *)(hp->h_addr);
417 return (1);
418 }
419 *addr = inet_addr(name);
420 return (*addr != -1);
421}
422
1750308c
MD
423copycomments(in, out, ccount)
424 FILE *in, *out;
425 int ccount;
426{
1750308c 427 int count;
8f66080b 428 char buf[BUFSIZ], *fgets();
1750308c
MD
429
430 for (count=0; count < ccount; count++) {
431 if ((fgets(buf, sizeof(buf), in) == NULL) || (buf[0] != ';'))
432 return;
433 buf[0] = '#';
434 fputs(buf, out);
435 }
436 return;
437}
5494cf94
SL
438#define UC(b) (((int)(b))&0xff)
439
3dbccebd
MK
440/*
441 * Print network number in internet-standard dot notation;
442 * v is in host byte order.
443 */
5494cf94
SL
444putnet(f, v)
445 FILE *f;
6e2735e4 446 register int v;
5494cf94 447{
3dbccebd
MK
448 if (v < 128)
449 fprintf(f, "%d", v);
450 else if (v < 65536)
6e2735e4 451 fprintf(f, "%d.%d", UC(v >> 8), UC(v));
5494cf94 452 else
6e2735e4 453 fprintf(f, "%d.%d.%d", UC(v >> 16), UC(v >> 8), UC(v));
5494cf94
SL
454}
455
456putaddr(f, v)
457 FILE *f;
8f66080b 458 struct in_addr v;
5494cf94 459{
8f66080b 460 fprintf(f, "%-16.16s", inet_ntoa(v));
5494cf94
SL
461}
462
463freenames(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}
99d3ae94
MK
475
476freeaddrs(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}
5494cf94
SL
485
486struct gateway *gateways = 0;
99d3ae94 487struct gateway *lastgateway = 0;
5494cf94 488
99d3ae94
MK
489struct gateway *
490gatewayto(net)
5494cf94
SL
491 register int net;
492{
493 register struct gateway *gp;
494
495 for (gp = gateways; gp; gp = gp->g_link)
99d3ae94
MK
496 if ((gp->g_net == net) && (gp->g_metric > 0))
497 return (gp);
498 return ((struct gateway *) NULL);
5494cf94
SL
499}
500
99d3ae94
MK
501struct gateway *
502savegateway(namelist, net, addr, metric)
503 struct name *namelist;
8f66080b 504 struct in_addr addr;
99d3ae94 505 int net, metric;
5494cf94
SL
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 }
99d3ae94
MK
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;
5494cf94 521 gp->g_net = net;
99d3ae94
MK
522 gp->g_addr = addr;
523 gp->g_metric = metric;
524 if (metric == 1)
525 gp->g_dst = gp;
2d474861 526 return (gp);
99d3ae94
MK
527}
528
529connectedto(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
540local(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 */
557dogateways()
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 }
5494cf94 599}