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.6 (Berkeley) 10/22/87"; 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 cp++; 176 } 177 return (str); 178 } 179 180 do_entry(keyword, addrlist, namelist, cputype, opsys, protos) 181 int keyword; 182 struct addr *addrlist; 183 struct name *namelist, *cputype, *opsys, *protos; 184 { 185 register struct addr *al, *al2; 186 register struct name *nl; 187 struct addr *connect_addr; 188 char *cp; 189 190 switch (keyword) { 191 192 case KW_NET: 193 nl = namelist; 194 if (nl == NONAME) { 195 fprintf(stderr, "htable: net"); 196 putnet(stderr, inet_netof(addrlist->addr_val)); 197 fprintf(stderr, " missing names.\n"); 198 break; 199 } 200 fprintf(nf, "%-16.16s", lower(nl->name_val)); 201 al2 = addrlist; 202 while (al = al2) { 203 char *cp; 204 205 putnet(nf, inet_netof(al->addr_val)); 206 cp = "\t%s"; 207 while (nl = nl->name_link) { 208 fprintf(nf, cp, lower(nl->name_val)); 209 cp = " %s"; 210 } 211 putc('\n', nf); 212 al2 = al->addr_link; 213 free((char *)al); 214 } 215 break; 216 217 case KW_GATEWAY: 218 /* locate locally connected address, if one */ 219 for (al = addrlist; al; al = al->addr_link) 220 if (connectedto(inet_netof(al->addr_val))) 221 break; 222 if (al == NULL) { 223 /* 224 * Not connected to known networks. Save for later. 225 */ 226 struct gateway *gw, *firstgw = (struct gateway *) NULL; 227 228 for (al = addrlist; al; al = al->addr_link) { 229 register int net; 230 231 net = inet_netof(al->addr_val); 232 gw = savegateway(namelist, net, 233 al->addr_val, 0); 234 if (firstgw == (struct gateway *) NULL) 235 firstgw = gw; 236 gw->g_firstent = firstgw; 237 } 238 freeaddrs(addrlist); 239 goto dontfree; 240 } 241 /* 242 * Connected to a known network. 243 * Mark this as the gateway to all other networks 244 * that are on the addrlist (unless we already have 245 * gateways to them). 246 */ 247 connect_addr = al; 248 for (al = addrlist; al; al = al->addr_link) { 249 register int net; 250 251 /* suppress duplicates -- not optimal */ 252 net = inet_netof(al->addr_val); 253 if (connectedto(net) || gatewayto(net)) 254 continue; 255 printgateway(net, namelist->name_val, 1); 256 (void) savegateway(namelist, net, al->addr_val, 1); 257 } 258 /* 259 * Put the gateway in the hosts file. 260 */ 261 putaddr(hf, connect_addr->addr_val); 262 cp = "%s"; 263 for (nl = namelist; nl; nl = nl->name_link) { 264 fprintf(hf, cp, lower(nl->name_val)); 265 cp = " %s"; 266 } 267 fprintf(hf, "\t# gateway\n"); 268 freeaddrs(addrlist); 269 goto dontfree; 270 271 case KW_HOST: 272 al2 = addrlist; 273 while (al = al2) { 274 if (!local(inet_netof(al->addr_val))) { 275 char *cp; 276 277 putaddr(hf, al->addr_val); 278 cp = "%s"; 279 for (nl = namelist; nl; nl = nl->name_link) { 280 fprintf(hf, cp, lower(nl->name_val)); 281 cp = " %s"; 282 } 283 putc('\n', hf); 284 } 285 al2 = al->addr_link; 286 free((char *)al); 287 } 288 break; 289 290 default: 291 fprintf(stderr, "Unknown keyword: %d.\n", keyword); 292 } 293 freenames(namelist); 294 dontfree: 295 freenames(protos); 296 } 297 298 printgateway(net, name, metric) 299 int net; 300 char *name; 301 int metric; 302 { 303 struct netent *np; 304 305 fprintf(gf, "net "); 306 np = getnetbyaddr(net, AF_INET); 307 if (np) 308 fprintf(gf, "%s", np->n_name); 309 else 310 putnet(gf, net); 311 fprintf(gf, " gateway %s metric %d passive\n", 312 lower(name), metric); 313 } 314 315 copylocal(f, filename) 316 FILE *f; 317 char *filename; 318 { 319 register FILE *lhf; 320 register cc; 321 char buf[BUFSIZ]; 322 extern int errno; 323 324 lhf = fopen(filename, "r"); 325 if (lhf == NULL) { 326 if (errno != ENOENT) { 327 perror(filename); 328 exit(1); 329 } 330 fprintf(stderr, "Warning, no %s file.\n", filename); 331 return; 332 } 333 while (cc = fread(buf, 1, sizeof(buf), lhf)) 334 fwrite(buf, 1, cc, f); 335 fclose(lhf); 336 } 337 338 copygateways(f, filename) 339 FILE *f; 340 char *filename; 341 { 342 register FILE *lhf; 343 struct name *nl; 344 char type[80]; 345 char dname[80]; 346 char gname[80]; 347 char junk[80]; 348 char buf[500]; 349 u_long addr; 350 int net, metric; 351 extern int errno; 352 353 lhf = fopen(filename, "r"); 354 if (lhf == NULL) { 355 if (errno != ENOENT) { 356 perror(filename); 357 exit(1); 358 } 359 fprintf(stderr, "Warning, no %s file.\n", filename); 360 return; 361 } 362 /* format: {net | host} XX gateway XX metric DD [passive]\n */ 363 for (;;) { 364 junk[0] = 0; 365 if (fgets(buf, sizeof(buf), lhf) == (char *)NULL) 366 break; 367 fputs(buf, gf); 368 if (buf[0] == '#' || 369 sscanf(buf, "%s %s gateway %s metric %d %s", 370 type, dname, gname, &metric, junk) < 5) 371 continue; 372 if (strcmp(type, "net")) 373 continue; 374 if (!getnetaddr(dname, &net)) 375 continue; 376 if (!gethostaddr(gname, &addr)) 377 continue; 378 nl = newname(gname); 379 (void) savegateway(nl, net, addr, metric); 380 } 381 fclose(lhf); 382 } 383 384 getnetaddr(name, addr) 385 char *name; 386 int *addr; 387 { 388 struct netent *np = getnetbyname(name); 389 int n; 390 391 if (np == 0) { 392 *addr = inet_network(name); 393 return (*addr != -1); 394 } else { 395 if (np->n_addrtype != AF_INET) 396 return (0); 397 *addr = np->n_net; 398 return (1); 399 } 400 } 401 402 gethostaddr(name, addr) 403 char *name; 404 u_long *addr; 405 { 406 struct hostent *hp; 407 408 hp = gethostbyname(name); 409 if (hp) { 410 *addr = *(u_long *)(hp->h_addr); 411 return (1); 412 } 413 *addr = inet_addr(name); 414 return (*addr != -1); 415 } 416 417 copycomments(in, out, ccount) 418 FILE *in, *out; 419 int ccount; 420 { 421 char buf[BUFSIZ]; 422 int length; 423 int count; 424 char *fgets(); 425 426 for (count=0; count < ccount; count++) { 427 if ((fgets(buf, sizeof(buf), in) == NULL) || (buf[0] != ';')) 428 return; 429 buf[0] = '#'; 430 fputs(buf, out); 431 } 432 return; 433 } 434 #define UC(b) (((int)(b))&0xff) 435 436 /* 437 * Print network number in internet-standard dot notation; 438 * v is in host byte order. 439 */ 440 putnet(f, v) 441 FILE *f; 442 register int v; 443 { 444 if (v < 128) 445 fprintf(f, "%d", v); 446 else if (v < 65536) 447 fprintf(f, "%d.%d", UC(v >> 8), UC(v)); 448 else 449 fprintf(f, "%d.%d.%d", UC(v >> 16), UC(v >> 8), UC(v)); 450 } 451 452 putaddr(f, v) 453 FILE *f; 454 u_long v; 455 { 456 register char *a = (char *)&v; 457 char buf[32]; 458 459 (void) sprintf(buf,"%d.%d.%d.%d", 460 UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3])); 461 fprintf(f, "%-16.16s", buf); 462 } 463 464 freenames(list) 465 struct name *list; 466 { 467 register struct name *nl, *nl2; 468 469 nl2 = list; 470 while (nl = nl2) { 471 nl2 = nl->name_link; 472 free(nl->name_val); 473 free((char *)nl); 474 } 475 } 476 477 freeaddrs(list) 478 struct addr *list; 479 { 480 register struct addr *al, *al2; 481 482 al2 = list; 483 while (al = al2) 484 al2 = al->addr_link, free((char *)al); 485 } 486 487 struct gateway *gateways = 0; 488 struct gateway *lastgateway = 0; 489 490 struct gateway * 491 gatewayto(net) 492 register int net; 493 { 494 register struct gateway *gp; 495 496 for (gp = gateways; gp; gp = gp->g_link) 497 if ((gp->g_net == net) && (gp->g_metric > 0)) 498 return (gp); 499 return ((struct gateway *) NULL); 500 } 501 502 struct gateway * 503 savegateway(namelist, net, addr, metric) 504 struct name *namelist; 505 u_long addr; 506 int net, metric; 507 { 508 register struct gateway *gp; 509 510 gp = (struct gateway *)malloc(sizeof (struct gateway)); 511 if (gp == 0) { 512 fprintf(stderr, "htable: out of memory\n"); 513 exit(1); 514 } 515 gp->g_link = (struct gateway *) NULL; 516 if (lastgateway) 517 lastgateway->g_link = gp; 518 else 519 gateways = gp; 520 lastgateway = gp; 521 gp->g_name = namelist; 522 gp->g_net = net; 523 gp->g_addr = addr; 524 gp->g_metric = metric; 525 if (metric == 1) 526 gp->g_dst = gp; 527 return (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