1 #ifndef lint 2 static char sccsid[] = "@(#)htable.c 4.6 (Berkeley) 11/03/83"; 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 } while (c); 135 return (nfound); 136 } 137 138 struct name * 139 newname(str) 140 char *str; 141 { 142 char *p; 143 struct name *nm; 144 145 p = malloc(strlen(str) + 1); 146 strcpy(p, str); 147 nm = (struct name *)malloc(sizeof (struct name)); 148 nm->name_val = p; 149 nm->name_link = NONAME; 150 return (nm); 151 } 152 153 char * 154 lower(str) 155 char *str; 156 { 157 register char *cp = str; 158 159 while (*cp) { 160 if (isupper(*cp)) 161 *cp = tolower(*cp); 162 cp++; 163 } 164 return (str); 165 } 166 167 do_entry(keyword, addrlist, namelist, cputype, opsys, protos) 168 int keyword; 169 struct addr *addrlist; 170 struct name *namelist, *cputype, *opsys, *protos; 171 { 172 register struct addr *al, *al2; 173 register struct name *nl; 174 struct addr *connect_addr; 175 char *cp; 176 177 switch (keyword) { 178 179 case KW_NET: 180 nl = namelist; 181 if (nl == NONAME) { 182 fprintf(stderr, "htable: net"); 183 putnet(stderr, addrlist->addr_val); 184 fprintf(stderr, " missing names.\n"); 185 break; 186 } 187 fprintf(nf, "%-16.16s", lower(nl->name_val)); 188 al2 = addrlist; 189 while (al = al2) { 190 char *cp; 191 192 putnet(nf, al->addr_val); 193 cp = "\t%s"; 194 while (nl = nl->name_link) { 195 fprintf(nf, cp, lower(nl->name_val)); 196 cp = " %s"; 197 } 198 putc('\n', nf); 199 al2 = al->addr_link; 200 free((char *)al); 201 } 202 break; 203 204 case KW_GATEWAY: 205 /* locate locally connected address, if one */ 206 for (al = addrlist; al; al = al->addr_link) 207 if (connectedto(inet_netof(al->addr_val))) 208 break; 209 if (al == NULL) { 210 /* 211 * Not connected to known networks. Save for later. 212 */ 213 struct gateway *gw, *firstgw = (struct gateway *) NULL; 214 215 for (al = addrlist; al; al = al->addr_link) { 216 register int net; 217 218 net = inet_netof(al->addr_val); 219 gw = savegateway(namelist, net, 220 al->addr_val, 0); 221 if (firstgw == (struct gateway *) NULL) 222 firstgw = gw; 223 gw->g_firstent = firstgw; 224 } 225 freeaddrs(addrlist); 226 goto dontfree; 227 } 228 /* 229 * Connected to a known network. 230 * Mark this as the gateway to all other networks 231 * that are on the addrlist (unless we already have 232 * gateways to them). 233 */ 234 connect_addr = al; 235 for (al = addrlist; al; al = al->addr_link) { 236 register int net; 237 238 if (al == connect_addr) 239 continue; 240 /* suppress duplicates -- not optimal */ 241 net = inet_netof(al->addr_val); 242 if (gatewayto(net)) 243 continue; 244 printgateway(net, namelist->name_val, 1); 245 (void) savegateway(namelist, net, al->addr_val, 1); 246 } 247 /* 248 * Put the gateway in the hosts file. 249 */ 250 putaddr(hf, connect_addr->addr_val); 251 cp = "%s"; 252 for (nl = namelist; nl; nl = nl->name_link) { 253 fprintf(hf, cp, lower(nl->name_val)); 254 cp = " %s"; 255 } 256 fprintf(hf, "\t# gateway\n"); 257 freeaddrs(addrlist); 258 goto dontfree; 259 260 case KW_HOST: 261 al2 = addrlist; 262 while (al = al2) { 263 if (!local(inet_netof(al->addr_val))) { 264 char *cp; 265 266 putaddr(hf, al->addr_val); 267 cp = "%s"; 268 for (nl = namelist; nl; nl = nl->name_link) { 269 fprintf(hf, cp, lower(nl->name_val)); 270 cp = " %s"; 271 } 272 putc('\n', hf); 273 } 274 al2 = al->addr_link; 275 free((char *)al); 276 } 277 break; 278 279 default: 280 fprintf(stderr, "Unknown keyword: %d.\n", keyword); 281 } 282 freenames(namelist); 283 dontfree: 284 freenames(protos); 285 } 286 287 printgateway(net, name, metric) 288 int net; 289 char *name; 290 int metric; 291 { 292 struct netent *np; 293 294 fprintf(gf, "net "); 295 np = getnetbyaddr(net, AF_INET); 296 if (np) 297 fprintf(gf, "%s", np->n_name); 298 else 299 putnet(gf, net); 300 fprintf(gf, " gateway %s metric %d passive\n", 301 lower(name), metric); 302 } 303 304 copylocal(f, filename) 305 FILE *f; 306 char *filename; 307 { 308 register FILE *lhf; 309 register cc; 310 char buf[BUFSIZ]; 311 extern int errno; 312 313 lhf = fopen(filename, "r"); 314 if (lhf == NULL) { 315 if (errno != ENOENT) { 316 perror(filename); 317 exit(1); 318 } 319 fprintf(stderr, "Warning, no %s file.\n", filename); 320 return; 321 } 322 while (cc = fread(buf, 1, sizeof(buf), lhf)) 323 fwrite(buf, 1, cc, f); 324 fclose(lhf); 325 } 326 327 copygateways(f, filename) 328 FILE *f; 329 char *filename; 330 { 331 register FILE *lhf; 332 register cc; 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 while (readentry(lhf) != EOF) { 356 if (strcmp(type, "net")) 357 goto dumpit; 358 if (!getnetaddr(dname, &net)) 359 goto dumpit; 360 if (!gethostaddr(gname, &addr)) 361 goto dumpit; 362 nl = newname(gname); 363 (void) savegateway(nl, net, addr, metric); 364 dumpit: 365 fprintf(gf, "%s %s gateway %s metric %d %s\n", 366 type, dname, gname, metric, junk); 367 } 368 fclose(lhf); 369 } 370 371 getnetaddr(name, addr) 372 char *name; 373 int *addr; 374 { 375 struct netent *np = getnetbyname(name); 376 int n; 377 378 if (np == 0) { 379 *addr = inet_network(name); 380 return (*addr != -1); 381 } else { 382 if (np->n_addrtype != AF_INET) 383 return (0); 384 *addr = np->n_net; 385 return (1); 386 } 387 } 388 389 gethostaddr(name, addr) 390 char *name; 391 u_long *addr; 392 { 393 struct hostent *hp; 394 395 hp = gethostbyname(name); 396 if (hp) { 397 *addr = *(u_long *)(hp->h_addr); 398 return (1); 399 } 400 *addr = inet_addr(name); 401 return (*addr != -1); 402 } 403 404 copycomments(in, out, ccount) 405 FILE *in, *out; 406 int ccount; 407 { 408 char buf[BUFSIZ]; 409 int length; 410 int count; 411 char *fgets(); 412 413 for (count=0; count < ccount; count++) { 414 if ((fgets(buf, sizeof(buf), in) == NULL) || (buf[0] != ';')) 415 return; 416 buf[0] = '#'; 417 fputs(buf, out); 418 } 419 return; 420 } 421 #define UC(b) (((int)(b))&0xff) 422 423 putnet(f, v) 424 FILE *f; 425 u_long v; 426 { 427 register char *a = (char *)&v; 428 429 if (UC(a[0]&0x80) == 0) 430 fprintf(f, "%d", UC(a[0])); 431 else if ((UC(a[0])&0x40) == 0) 432 fprintf(f, "%d.%d", UC(a[0]), UC(a[1])); 433 else 434 fprintf(f, "%d.%d.%d", UC(a[0]), UC(a[1]), UC(a[2])); 435 } 436 437 putaddr(f, v) 438 FILE *f; 439 u_long v; 440 { 441 register char *a = (char *)&v; 442 char buf[32]; 443 444 sprintf(buf,"%d.%d.%d.%d", UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3])); 445 fprintf(f, "%-16.16s", buf); 446 } 447 448 freenames(list) 449 struct name *list; 450 { 451 register struct name *nl, *nl2; 452 453 nl2 = list; 454 while (nl = nl2) { 455 nl2 = nl->name_link; 456 free(nl->name_val); 457 free((char *)nl); 458 } 459 } 460 461 freeaddrs(list) 462 struct addr *list; 463 { 464 register struct addr *al, *al2; 465 466 al2 = list; 467 while (al = al2) 468 al2 = al->addr_link, free((char *)al); 469 } 470 471 struct gateway *gateways = 0; 472 struct gateway *lastgateway = 0; 473 474 struct gateway * 475 gatewayto(net) 476 register int net; 477 { 478 register struct gateway *gp; 479 480 for (gp = gateways; gp; gp = gp->g_link) 481 if ((gp->g_net == net) && (gp->g_metric > 0)) 482 return (gp); 483 return ((struct gateway *) NULL); 484 } 485 486 struct gateway * 487 savegateway(namelist, net, addr, metric) 488 struct name *namelist; 489 u_long addr; 490 int net, metric; 491 { 492 register struct gateway *gp; 493 494 gp = (struct gateway *)malloc(sizeof (struct gateway)); 495 if (gp == 0) { 496 fprintf(stderr, "htable: out of memory\n"); 497 exit(1); 498 } 499 gp->g_link = (struct gateway *) NULL; 500 if (lastgateway) 501 lastgateway->g_link = gp; 502 else 503 gateways = gp; 504 lastgateway = gp; 505 gp->g_name = namelist; 506 gp->g_net = net; 507 gp->g_addr = addr; 508 gp->g_metric = metric; 509 if (metric == 1) 510 gp->g_dst = gp; 511 } 512 513 connectedto(net) 514 u_long net; 515 { 516 register i; 517 518 for (i = 0; i < nconnected; i++) 519 if (connected_nets[i] == net) 520 return(1); 521 return(0); 522 } 523 524 local(net) 525 u_long net; 526 { 527 register i; 528 529 for (i = 0; i < nlocal; i++) 530 if (local_nets[i] == net) 531 return(1); 532 return(0); 533 } 534 535 #define MAXHOPS 10 536 537 /* 538 * Go through list of gateways, finding connections for gateways 539 * that are not yet connected. 540 */ 541 dogateways() 542 { 543 register struct gateway *gp, *gw, *ggp; 544 register int hops, changed = 1; 545 struct name *nl; 546 char *cp; 547 548 for (hops = 0; hops < MAXHOPS && changed; hops++, changed = 0) { 549 for (gp = gateways; gp; gp = gp->g_link) 550 if ((gp->g_metric == 0) && (gw = gatewayto(gp->g_net))) { 551 /* 552 * Found a new connection. 553 * For each other network that this gateway is on, 554 * add a new gateway to that network. 555 */ 556 changed = 1; 557 gp->g_dst = gw->g_dst; 558 gp->g_metric = gw->g_metric + 1; 559 for (ggp = gp->g_firstent; ggp->g_name == gp->g_name; 560 ggp = ggp->g_link) { 561 if (ggp == gp) 562 continue; 563 if (gatewayto(ggp->g_net)) 564 continue; 565 ggp->g_dst = gp->g_dst; 566 ggp->g_metric = gp->g_metric; 567 printgateway(ggp->g_net, 568 gw->g_dst->g_name->name_val, gp->g_metric); 569 } 570 /* 571 * Put the gateway in the hosts file, 572 * using the address for the connected net. 573 */ 574 putaddr(hf, gp->g_addr); 575 cp = "%s"; 576 for (nl = gp->g_name; nl; nl = nl->name_link) { 577 fprintf(hf, cp, lower(nl->name_val)); 578 cp = " %s"; 579 } 580 fprintf(hf, "\t# gateway\n"); 581 } 582 } 583 } 584