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.3 (Berkeley) 06/21/85"; 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 if (*cp == '.') 176 break; 177 cp++; 178 } 179 return (str); 180 } 181 182 do_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; 188 register struct name *nl; 189 struct addr *connect_addr; 190 char *cp; 191 192 switch (keyword) { 193 194 case KW_NET: 195 nl = namelist; 196 if (nl == NONAME) { 197 fprintf(stderr, "htable: net"); 198 putnet(stderr, inet_netof(addrlist->addr_val)); 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 207 putnet(nf, inet_netof(al->addr_val)); 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 } 217 break; 218 219 case KW_GATEWAY: 220 /* locate locally connected address, if one */ 221 for (al = addrlist; al; al = al->addr_link) 222 if (connectedto(inet_netof(al->addr_val))) 223 break; 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) { 251 register int net; 252 253 /* suppress duplicates -- not optimal */ 254 net = inet_netof(al->addr_val); 255 if (connectedto(net) || gatewayto(net)) 256 continue; 257 printgateway(net, namelist->name_val, 1); 258 (void) savegateway(namelist, net, al->addr_val, 1); 259 } 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"; 268 } 269 fprintf(hf, "\t# gateway\n"); 270 freeaddrs(addrlist); 271 goto dontfree; 272 273 case KW_HOST: 274 al2 = addrlist; 275 while (al = al2) { 276 if (!local(inet_netof(al->addr_val))) { 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 } 285 putc('\n', hf); 286 } 287 al2 = al->addr_link; 288 free((char *)al); 289 } 290 break; 291 292 default: 293 fprintf(stderr, "Unknown keyword: %d.\n", keyword); 294 } 295 freenames(namelist); 296 dontfree: 297 freenames(protos); 298 } 299 300 printgateway(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 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; 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 */ 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 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 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 copycomments(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 int v; 445 { 446 if (v < 128) 447 fprintf(f, "%d", 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 int 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; 507 int net, 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 } 529 530 connectedto(net) 531 u_long net; 532 { 533 register i; 534 535 for (i = 0; i < nconnected; i++) 536 if (connected_nets[i] == net) 537 return(1); 538 return(0); 539 } 540 541 local(net) 542 u_long net; 543 { 544 register i; 545 546 for (i = 0; i < nlocal; i++) 547 if (local_nets[i] == net) 548 return(1); 549 return(0); 550 } 551 552 #define MAXHOPS 10 553 554 /* 555 * Go through list of gateways, finding connections for gateways 556 * that are not yet connected. 557 */ 558 dogateways() 559 { 560 register struct gateway *gp, *gw, *ggp; 561 register int hops, changed = 1; 562 struct name *nl; 563 char *cp; 564 565 for (hops = 0; hops < MAXHOPS && changed; hops++, changed = 0) { 566 for (gp = gateways; gp; gp = gp->g_link) 567 if ((gp->g_metric == 0) && (gw = gatewayto(gp->g_net))) { 568 /* 569 * Found a new connection. 570 * For each other network that this gateway is on, 571 * add a new gateway to that network. 572 */ 573 changed = 1; 574 gp->g_dst = gw->g_dst; 575 gp->g_metric = gw->g_metric + 1; 576 for (ggp = gp->g_firstent; ggp->g_name == gp->g_name; 577 ggp = ggp->g_link) { 578 if (ggp == gp) 579 continue; 580 if (gatewayto(ggp->g_net)) 581 continue; 582 ggp->g_dst = gp->g_dst; 583 ggp->g_metric = gp->g_metric; 584 printgateway(ggp->g_net, 585 gw->g_dst->g_name->name_val, gp->g_metric); 586 } 587 /* 588 * Put the gateway in the hosts file, 589 * using the address for the connected net. 590 */ 591 putaddr(hf, gp->g_addr); 592 cp = "%s"; 593 for (nl = gp->g_name; nl; nl = nl->name_link) { 594 fprintf(hf, cp, lower(nl->name_val)); 595 cp = " %s"; 596 } 597 fprintf(hf, "\t# gateway\n"); 598 } 599 } 600 } 601