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