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