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