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