1: /* 2: * Copyright (c) 1986 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 this notice is preserved and that due credit is given 7: * to the University of California at Berkeley. The name of the University 8: * may not be used to endorse or promote products derived from this 9: * software without specific prior written permission. This software 10: * is provided ``as is'' without express or implied warranty. 11: */ 12: 13: #ifndef lint 14: static char sccsid[] = "@(#)db_load.c 4.26 (Berkeley) 2/28/88"; 15: #endif /* not lint */ 16: 17: /* 18: * Load data base from ascii backupfile. Format similar to RFC 883. 19: */ 20: 21: #include <sys/param.h> 22: #include <sys/time.h> 23: #include <sys/stat.h> 24: #include <netinet/in.h> 25: #include <stdio.h> 26: #include <syslog.h> 27: #include <ctype.h> 28: #include <netdb.h> 29: #include <arpa/nameser.h> 30: #include "ns.h" 31: #include "db.h" 32: 33: extern char *index(); 34: u_long getnum(); 35: extern u_long net_mask(); 36: extern u_long max_cache_ttl; 37: 38: /* 39: * Map class and type names to number 40: */ 41: struct map { 42: char token[8]; 43: int val; 44: }; 45: 46: struct map m_class[] = { 47: "in", C_IN, 48: #ifdef notdef 49: "any", C_ANY, /* any is a QCLASS, not CLASS */ 50: #endif 51: "chaos", C_CHAOS, 52: }; 53: #define NCLASS (sizeof(m_class)/sizeof(struct map)) 54: 55: struct map m_type[] = { 56: "a", T_A, 57: "ns", T_NS, 58: "cname", T_CNAME, 59: "soa", T_SOA, 60: "mb", T_MB, 61: "mg", T_MG, 62: "mr", T_MR, 63: "null", T_NULL, 64: "wks", T_WKS, 65: "ptr", T_PTR, 66: "hinfo", T_HINFO, 67: "minfo", T_MINFO, 68: "mx", T_MX, 69: "uinfo", T_UINFO, 70: "uid", T_UID, 71: "gid", T_GID, 72: #ifdef notdef 73: "any", T_ANY, /* any is a QTYPE, not TYPE */ 74: #endif 75: #ifdef ALLOW_T_UNSPEC 76: "unspec", T_UNSPEC, 77: #endif ALLOW_T_UNSPEC 78: }; 79: #define NTYPE (sizeof(m_type)/sizeof(struct map)) 80: 81: /* 82: * Parser token values 83: */ 84: #define CURRENT 1 85: #define DOT 2 86: #define AT 3 87: #define DNAME 4 88: #define INCLUDE 5 89: #define ORIGIN 6 90: #define ERROR 7 91: 92: int lineno; /* current line number */ 93: 94: struct valuelist { 95: struct valuelist *next, *prev; 96: char *name; 97: char *proto; 98: short port; 99: } *servicelist, *protolist; 100: 101: /* 102: * Load the database from 'filename'. Origin is appended to all domain 103: * names in the file. 104: */ 105: db_load(filename, in_origin, zp) 106: char *filename, *in_origin; 107: struct zoneinfo *zp; 108: { 109: register u_char *cp; 110: register struct map *mp; 111: char domain[MAXDNAME]; 112: char origin[MAXDNAME]; 113: char tmporigin[MAXDNAME]; 114: u_char buf[BUFSIZ]; 115: u_char data[MAXDATA]; 116: char *op; 117: int c; 118: int class, type, dbflags, dataflags; 119: u_long ttl; 120: struct databuf *dp; 121: FILE *fp; 122: int slineno, i, errs = 0, didinclude = 0; 123: register u_long n; 124: struct stat sb; 125: 126: #ifdef DEBUG 127: if (debug) 128: fprintf(ddt,"db_load(%s, %s, %d)\n", 129: filename, in_origin, zp - zones); 130: #endif 131: 132: (void) strcpy(origin, in_origin); 133: if ((fp = fopen(filename, "r")) == NULL) { 134: if (zp->z_type != Z_SECONDARY) 135: syslog(LOG_ERR, "%s: %m", filename); 136: #ifdef DEBUG 137: if (debug) 138: fprintf(ddt,"db_load: error opening file %s\n", filename); 139: #endif 140: return (-1); 141: } 142: if (zp->z_type == Z_CACHE) { 143: dbflags = DB_NODATA | DB_NOHINTS; 144: dataflags = DB_F_HINT; 145: } else { 146: dbflags = DB_NODATA; 147: dataflags = 0; 148: } 149: gettime(&tt); 150: if (fstat(fileno(fp), &sb) < 0) { 151: syslog(LOG_ERR, "%s: %m", filename); 152: sb.st_mtime = (int)tt.tv_sec; 153: } 154: slineno = lineno; 155: lineno = 1; 156: domain[0] = '\0'; 157: class = C_IN; 158: while ((c = gettoken(fp)) != EOF) { 159: switch (c) { 160: case INCLUDE: 161: if (!getword(buf, sizeof(buf), fp)) /* file name */ 162: break; 163: if (!getword(tmporigin, sizeof(tmporigin), fp)) 164: strcpy(tmporigin, origin); 165: else { 166: makename(tmporigin, origin); 167: endline(fp); 168: } 169: didinclude = 1; 170: errs += db_load(buf, tmporigin, zp); 171: continue; 172: 173: case ORIGIN: 174: (void) strcpy(buf, origin); 175: if (!getword(origin, sizeof(origin), fp)) 176: break; 177: #ifdef DEBUG 178: if (debug > 3) 179: fprintf(ddt,"db_load: origin %s, buf %s\n", 180: origin, buf); 181: #endif 182: makename(origin, buf); 183: #ifdef DEBUG 184: if (debug > 3) 185: fprintf(ddt,"db_load: origin now %s\n", origin); 186: #endif 187: continue; 188: 189: case DNAME: 190: if (!getword(domain, sizeof(domain), fp)) 191: break; 192: n = strlen(domain) - 1; 193: if (domain[n] == '.') 194: domain[n] = '\0'; 195: else if (*origin) { 196: (void) strcat(domain, "."); 197: (void) strcat(domain, origin); 198: } 199: goto gotdomain; 200: 201: case AT: 202: (void) strcpy(domain, origin); 203: goto gotdomain; 204: 205: case DOT: 206: domain[0] = '\0'; 207: /* fall thru ... */ 208: case CURRENT: 209: gotdomain: 210: if (!getword(buf, sizeof(buf), fp)) { 211: if (c == CURRENT) 212: continue; 213: break; 214: } 215: cp = buf; 216: ttl = 0; 217: if (isdigit(*cp)) { 218: n = 0; 219: do 220: n = n * 10 + (*cp++ - '0'); 221: while (isdigit(*cp)); 222: if (zp->z_type == Z_CACHE) { 223: /* this allows the cache entry to age */ 224: /* while sitting on disk (powered off) */ 225: if (n > max_cache_ttl) 226: n = max_cache_ttl; 227: n += sb.st_mtime; 228: } 229: ttl = n; 230: if (!getword(buf, sizeof(buf), fp)) 231: break; 232: } 233: for (mp = m_class; mp < m_class+NCLASS; mp++) 234: if (!strcasecmp(buf, mp->token)) { 235: class = mp->val; 236: (void) getword(buf, sizeof(buf), fp); 237: break; 238: } 239: for (mp = m_type; mp < m_type+NTYPE; mp++) 240: if (!strcasecmp(buf, mp->token)) { 241: type = mp->val; 242: goto fndtype; 243: } 244: #ifdef DEBUG 245: if (debug) 246: fprintf(ddt,"Line %d: Unknown type: %s.\n", 247: lineno, buf); 248: #endif 249: errs++; 250: syslog(LOG_ERR, "Line %d: Unknown type: %s.\n", 251: lineno, buf); 252: break; 253: fndtype: 254: #ifdef ALLOW_T_UNSPEC 255: /* Don't do anything here for T_UNSPEC... 256: * read input separately later 257: */ 258: if (type != T_UNSPEC) { 259: #endif ALLOW_T_UNSPEC 260: if (!getword(buf, sizeof(buf), fp)) 261: break; 262: #ifdef DEBUG 263: if (debug >= 3) 264: fprintf(ddt, 265: "d='%s', c=%d, t=%d, ttl=%ld, data='%s'\n", 266: domain, class, type, ttl, buf); 267: #endif 268: #ifdef ALLOW_T_UNSPEC 269: } 270: #endif ALLOW_T_UNSPEC 271: /* 272: * Convert the ascii data 'buf' to the proper format 273: * based on the type and pack into 'data'. 274: */ 275: switch (type) { 276: case T_A: 277: n = ntohl((u_long)inet_addr((char *)buf)); 278: cp = data; 279: PUTLONG(n, cp); 280: n = sizeof(u_long); 281: break; 282: 283: case T_HINFO: 284: n = strlen(buf); 285: if (n > 255) { 286: syslog(LOG_WARNING, 287: "%s: line %d: CPU type too long", 288: filename, lineno); 289: n = 255; 290: } 291: data[0] = n; 292: bcopy(buf, (char *)data + 1, (int)n); 293: n++; 294: if (!getword(buf, sizeof(buf), fp)) 295: break; 296: i = strlen(buf); 297: if (i > 255) { 298: syslog(LOG_WARNING, 299: "%s: line %d: OS type too long", 300: filename, lineno); 301: i = 255; 302: } 303: data[n] = i; 304: bcopy(buf, (char *)data + n + 1, i); 305: n += i + 1; 306: endline(fp); 307: break; 308: 309: case T_SOA: 310: case T_MINFO: 311: (void) strcpy(data, buf); 312: makename(data, origin); 313: cp = data + strlen(data) + 1; 314: if (!getword(cp, sizeof(data) - (cp - data),fp)) { 315: n = cp - data; 316: break; 317: } 318: makename(cp, origin); 319: cp += strlen(cp) + 1; 320: if (type == T_MINFO) { 321: n = cp - data; 322: break; 323: } 324: if (getnonblank(fp) != '(') 325: goto err; 326: zp->z_serial = getnum(fp); 327: n = (u_long) zp->z_serial; 328: PUTLONG(n, cp); 329: zp->z_refresh = getnum(fp); 330: n = (u_long) zp->z_refresh; 331: PUTLONG(n, cp); 332: zp->z_time = sb.st_mtime + zp->z_refresh; 333: zp->z_retry = getnum(fp); 334: n = (u_long) zp->z_retry; 335: PUTLONG(n, cp); 336: zp->z_expire = getnum(fp); 337: n = (u_long) zp->z_expire; 338: PUTLONG (n, cp); 339: zp->z_minimum = getnum(fp); 340: n = (u_long) zp->z_minimum; 341: PUTLONG (n, cp); 342: n = cp - data; 343: if (getnonblank(fp) != ')') 344: goto err; 345: endline(fp); 346: break; 347: 348: case T_UID: 349: case T_GID: 350: n = 0; 351: cp = buf; 352: while (isdigit(*cp)) 353: n = n * 10 + (*cp++ - '0'); 354: if (cp == buf) 355: goto err; 356: cp = data; 357: PUTLONG(n, cp); 358: n = sizeof(long); 359: break; 360: 361: case T_WKS: 362: /* Address */ 363: n = ntohl((u_long)inet_addr((char *)buf)); 364: cp = data; 365: PUTLONG(n, cp); 366: *cp = getprotocol(fp, filename); 367: /* Protocol */ 368: n = sizeof(u_long) + sizeof(char); 369: /* Services */ 370: n = getservices((int)n, data, fp, filename); 371: break; 372: 373: case T_NS: 374: case T_CNAME: 375: case T_MB: 376: case T_MG: 377: case T_MR: 378: case T_PTR: 379: (void) strcpy(data, buf); 380: makename(data, origin); 381: n = strlen(data) + 1; 382: break; 383: 384: case T_UINFO: 385: cp = (u_char *)index(buf, '&'); 386: bzero(data, sizeof(data)); 387: if ( cp != NULL) { 388: (void) strncpy(data, buf, cp - buf); 389: op = index(domain, '.'); 390: if ( op != NULL) 391: (void) strncat(data, 392: domain,op-domain); 393: else 394: (void) strcat(data, domain); 395: (void) strcat(data, ++cp); 396: } else 397: (void) strcpy(data, buf); 398: n = strlen(data) + 1; 399: break; 400: case T_MX: 401: n = 0; 402: cp = buf; 403: while (isdigit(*cp)) 404: n = n * 10 + (*cp++ - '0'); 405: /* catch bad values */ 406: if ((cp == buf) || (n > 64535)) 407: goto err; 408: 409: cp = data; 410: PUTSHORT((u_short)n, cp); 411: 412: if (!getword(buf, sizeof(buf), fp)) 413: break; 414: (void) strcpy(cp,buf); 415: makename(cp, origin); 416: /* get pointer to place in data */ 417: cp += strlen(cp) +1; 418: 419: /* now save length */ 420: n = (cp - data); 421: break; 422: #ifdef ALLOW_T_UNSPEC 423: case T_UNSPEC: 424: { 425: int rcode; 426: fgets(buf, sizeof(buf), fp); 427: #ifdef DEBUG 428: if (debug) 429: fprintf(ddt, "loading T_UNSPEC\n"); 430: #endif DEBUG 431: if (rcode = atob(buf, strlen(buf), data, MAXDATA, &n)) { 432: if (rcode == CONV_OVERFLOW) { 433: #ifdef DEBUG 434: if (debug) 435: fprintf(ddt, 436: "Load T_UNSPEC: input buffer overflow\n"); 437: #endif DEBUG 438: errs++; 439: syslog(LOG_ERR, 440: "Load T_UNSPEC: input buffer overflow"); 441: } else { 442: #ifdef DEBUG 443: if (debug) 444: fprintf(ddt, 445: "Load T_UNSPEC: Data in bad atob format\n"); 446: #endif DEBUG 447: errs++; 448: syslog(LOG_ERR, 449: "Load T_UNSPEC: Data in bad atob format"); 450: } 451: } 452: } 453: break; 454: #endif ALLOW_T_UNSPEC 455: 456: default: 457: goto err; 458: } 459: dp = savedata(class, type, (u_long)ttl, data, (int)n); 460: dp->d_zone = zp - zones; 461: dp->d_flags = dataflags; 462: if ((c = db_update(domain, dp, dp, dbflags, 463: (zp->z_type == Z_CACHE)? fcachetab : hashtab)) < 0) { 464: #ifdef DEBUG 465: if (debug && (c != DATAEXISTS)) 466: fprintf(ddt,"update failed\n"); 467: #endif 468: } 469: continue; 470: 471: case ERROR: 472: break; 473: } 474: err: 475: errs++; 476: syslog(LOG_ERR, "%s: line %d: database format error (%s)", 477: filename, lineno, buf); 478: #ifdef DEBUG 479: if (debug) 480: fprintf(ddt,"%s: line %d: database format error ('%s', %d)\n", 481: filename, lineno, buf, n); 482: #endif 483: while ((c = getc(fp)) != EOF && c != '\n') 484: ; 485: if (c == '\n') 486: lineno++; 487: } 488: (void) fclose(fp); 489: if (didinclude) 490: zp->z_ftime = 0; 491: else 492: zp->z_ftime = sb.st_mtime; 493: zp->z_lastupdate = sb.st_mtime; 494: lineno = slineno; 495: return (errs); 496: } 497: 498: int gettoken(fp) 499: register FILE *fp; 500: { 501: register int c; 502: char op[32]; 503: 504: for (;;) { 505: c = getc(fp); 506: top: 507: switch (c) { 508: case EOF: 509: return (EOF); 510: 511: case '$': 512: if (getword(op, sizeof(op), fp)) { 513: if (!strcasecmp("include", op)) 514: return (INCLUDE); 515: if (!strcasecmp("origin", op)) 516: return (ORIGIN); 517: } 518: #ifdef DEBUG 519: if (debug) 520: fprintf(ddt,"Line %d: Unknown $ option: $%s\n", 521: lineno, op); 522: #endif 523: syslog(LOG_ERR,"Line %d: Unknown $ option: $%s\n", 524: lineno, op); 525: return (ERROR); 526: 527: case ';': 528: while ((c = getc(fp)) != EOF && c != '\n') 529: ; 530: goto top; 531: 532: case ' ': 533: case '\t': 534: return (CURRENT); 535: 536: case '.': 537: return (DOT); 538: 539: case '@': 540: return (AT); 541: 542: case '\n': 543: lineno++; 544: continue; 545: 546: default: 547: (void) ungetc(c, fp); 548: return (DNAME); 549: } 550: } 551: } 552: 553: /* 554: * Get next word, skipping blanks & comments. 555: */ 556: getword(buf, size, fp) 557: char *buf; 558: int size; 559: FILE *fp; 560: { 561: register char *cp; 562: register int c; 563: 564: for (cp = buf; (c = getc(fp)) != EOF; ) { 565: if (c == ';') { 566: while ((c = getc(fp)) != EOF && c != '\n') 567: ; 568: c = '\n'; 569: } 570: if (c == '\n') { 571: if (cp != buf) 572: ungetc(c, fp); 573: else 574: lineno++; 575: break; 576: } 577: if (isspace(c)) { 578: while (isspace(c = getc(fp)) && c != '\n') 579: ; 580: ungetc(c, fp); 581: if (cp != buf) /* Trailing whitespace */ 582: break; 583: continue; /* Leading whitespace */ 584: } 585: if (c == '"') { 586: while ((c = getc(fp)) != EOF && c != '"' && c != '\n') { 587: if (c == '\\') { 588: if ((c = getc(fp)) == EOF) 589: c = '\\'; 590: if (c == '\n') 591: lineno++; 592: } 593: if (cp >= buf+size-1) 594: break; 595: *cp++ = c; 596: } 597: if (c == '\n') { 598: lineno++; 599: break; 600: } 601: continue; 602: } 603: if (c == '\\') { 604: if ((c = getc(fp)) == EOF) 605: c = '\\'; 606: if (c == '\n') 607: lineno++; 608: } 609: if (cp >= buf+size-1) 610: break; 611: *cp++ = c; 612: } 613: *cp = '\0'; 614: return (cp != buf); 615: } 616: 617: u_long 618: getnum(fp) 619: FILE *fp; 620: { 621: register int c; 622: u_long n; 623: int seendigit = 0; 624: int seendecimal = 0; 625: 626: for (n = 0; (c = getc(fp)) != EOF; ) { 627: if (isspace(c)) { 628: if (c == '\n') 629: lineno++; 630: if (seendigit) 631: break; 632: continue; 633: } 634: if (c == ';') { 635: while ((c = getc(fp)) != EOF && c != '\n') 636: ; 637: if (c == '\n') 638: lineno++; 639: if (seendigit) 640: break; 641: continue; 642: } 643: if (!isdigit(c)) { 644: if (seendecimal || c != '.') { 645: syslog(LOG_ERR, "line %d: expected a number", 646: lineno); 647: #ifdef DEBUG 648: if (debug) 649: fprintf(ddt,"line %d: expected a number", 650: lineno); 651: #endif 652: exit(1); 653: } else { 654: if (!seendigit) 655: n = 1; 656: n = n * 1000 ; 657: seendigit = 1; 658: seendecimal = 1; 659: } 660: continue; 661: } 662: n = n * 10 + (c - '0'); 663: seendigit = 1; 664: } 665: return (n); 666: } 667: 668: getnonblank(fp) 669: FILE *fp; 670: { 671: register int c; 672: 673: while ( (c = getc(fp)) != EOF ) { 674: if (isspace(c)) { 675: if (c == '\n') 676: lineno++; 677: continue; 678: } 679: if (c == ';') { 680: while ((c = getc(fp)) != EOF && c != '\n') 681: ; 682: if (c == '\n') 683: lineno++; 684: continue; 685: } 686: return(c); 687: } 688: syslog(LOG_ERR, "line %d: unexpected EOF", lineno); 689: #ifdef DEBUG 690: if (debug) 691: fprintf(ddt, "line %d: unexpected EOF", lineno); 692: #endif 693: return (EOF); 694: } 695: 696: /* 697: * Take name and fix it according to following rules: 698: * "." means root. 699: * "@" means current origin. 700: * "name." means no changes. 701: * "name" means append origin. 702: */ 703: makename(name, origin) 704: char *name, *origin; 705: { 706: int n; 707: 708: if (origin[0] == '.') 709: origin++; 710: n = strlen(name); 711: if (n == 1) { 712: if (name[0] == '.') { 713: name[0] = '\0'; 714: return; 715: } 716: if (name[0] == '@') { 717: (void) strcpy(name, origin); 718: return; 719: } 720: } 721: if (n > 0) { 722: if (name[n - 1] == '.') 723: name[n - 1] = '\0'; 724: else if (origin[0] != '\0') { 725: name[n] = '.'; 726: (void) strcpy(name + n + 1, origin); 727: } 728: } 729: } 730: 731: endline(fp) 732: register FILE *fp; 733: { 734: register int c; 735: while (c = getc(fp)) 736: if (c == '\n') { 737: (void) ungetc(c,fp); 738: break; 739: } else if (c == EOF) 740: break; 741: } 742: 743: #define MAXPORT 256 744: #define MAXLEN 24 745: 746: getprotocol(fp, src) 747: FILE *fp; 748: char *src; 749: { 750: int k; 751: char b[MAXLEN]; 752: 753: (void) getword(b, sizeof(b), fp); 754: 755: k = findservice(b, &protolist); 756: if(k == -1) { 757: (void) sscanf(b,"%d",&k); 758: if(k <= 0) 759: syslog(LOG_ERR, "%s: line %d: unknown protocol: %s.", 760: src, lineno, b); 761: } 762: return(k); 763: } 764: 765: int 766: getservices(n, data, fp, src) 767: int n; 768: char *data, *src; 769: FILE *fp; 770: { 771: int j, ch; 772: int k; 773: int maxl; 774: int bracket; 775: char b[MAXLEN]; 776: char bm[MAXPORT/8]; 777: 778: for (j = 0; j < MAXPORT/8; j++) 779: bm[j] = 0; 780: maxl = 0; 781: bracket = 0; 782: while (getword(b, sizeof(b), fp) || bracket) { 783: if (feof(fp) || ferror(fp)) 784: break; 785: if (strlen(b) == 0) 786: continue; 787: if ( b[0] == '(') { 788: bracket++; 789: continue; 790: } 791: if ( b[0] == ')') { 792: bracket = 0; 793: while ((ch = getc(fp)) != EOF && ch != '\n') 794: ; 795: if (ch == '\n') 796: lineno++; 797: break; 798: } 799: k = findservice(b, &servicelist); 800: if (k == -1) { 801: (void) sscanf(b,"%d",&k); 802: if (k <= 0) { 803: syslog(LOG_WARNING, 804: "%s: line %d: Unknown service '%s'", src, lineno, b); 805: continue; 806: } 807: } 808: if ((k < MAXPORT) && (k)) { 809: bm[k/8] |= (0x80>>(k%8)); 810: if (k > maxl) 811: maxl=k; 812: } 813: else { 814: syslog(LOG_WARNING, 815: "%s: line %d: port no. (%d) too big\n", 816: src, lineno, k); 817: #ifdef DEBUG 818: if (debug) 819: fprintf(ddt, 820: "%s: line %d: port no. (%d) too big\n", 821: src, lineno, k); 822: #endif 823: } 824: } 825: if (bracket) 826: syslog(LOG_WARNING, "%s: line %d: missing close paren\n", 827: src, lineno); 828: maxl = maxl/8+1; 829: bcopy(bm, data+n, maxl); 830: return(maxl+n); 831: } 832: 833: get_sort_list(fp) 834: FILE *fp; 835: { 836: struct netinfo *tp; 837: struct netinfo *ntp = NULL; 838: struct netinfo *ntip = NULL; 839: char buf[BUFSIZ]; 840: 841: extern struct netinfo *fnettab; 842: 843: #ifdef DEBUG 844: if (debug) 845: fprintf(ddt,"sortlist "); 846: #endif 847: if (fnettab) { 848: #ifdef DEBUG 849: /* We can only handle the sortlist at startup. see ns_main */ 850: if (debug) 851: fprintf(ddt," (reloading, therefore ignored)\n"); 852: #endif 853: (void) endline(fp); 854: return; 855: } 856: 857: while (getword(buf, sizeof(buf), fp)) { 858: if (strlen(buf) == 0) 859: break; 860: #ifdef DEBUG 861: if (debug) 862: fprintf(ddt," %s",buf); 863: #endif 864: if (ntp == NULL) 865: ntp = (struct netinfo *)malloc(sizeof(struct netinfo)); 866: ntp->my_addr.s_addr = inet_addr(buf); 867: if ( ntp->my_addr.s_addr == (unsigned)-1) { 868: /* resolve name to address - XXX */ 869: continue; 870: } 871: ntp->next = NULL; 872: ntp->mask = net_mask(ntp->my_addr); 873: ntp->net = ntp->my_addr.s_addr & ntp->mask; 874: 875: /* Check for duplicates, then add to linked list */ 876: for (tp = fnettab; tp != NULL; tp = tp->next) { 877: if ((ntp->mask == tp->mask) && 878: (ntp->net == tp->net)) 879: continue; 880: } 881: if (fnettab == NULL) 882: fnettab = ntp; 883: else 884: ntip->next = ntp; 885: ntip = ntp; 886: ntp = NULL; 887: } 888: if (ntp) 889: free((char *)ntp); 890: 891: #ifdef DEBUG 892: if (debug) 893: fprintf(ddt,"\n"); 894: if (debug > 2) 895: for (ntp = fnettab; ntp != NULL; ntp = ntp->next) { 896: fprintf(ddt,"ntp x%x net x%lx mask x%lx", ntp, 897: ntp->net, ntp->mask); 898: fprintf(ddt," my_addr x%lx", ntp->my_addr); 899: fprintf(ddt," %s",inet_ntoa(ntp->my_addr)); 900: fprintf(ddt," next x%x\n", ntp->next); 901: } 902: #endif 903: } 904: 905: buildservicelist() 906: { 907: struct servent *sp; 908: struct valuelist *slp; 909: 910: setservent(1); 911: while (sp = getservent()) { 912: slp = (struct valuelist *)malloc(sizeof(struct valuelist)); 913: slp->name = savestr(sp->s_name); 914: slp->proto = savestr(sp->s_proto); 915: slp->port = ntohs((u_short)sp->s_port); 916: slp->next = servicelist; 917: slp->prev = NULL; 918: if (servicelist) { 919: servicelist->prev = slp; 920: } 921: servicelist = slp; 922: } 923: endservent(); 924: } 925: 926: buildprotolist() 927: { 928: struct protoent *pp; 929: struct valuelist *slp; 930: 931: setprotoent(1); 932: while (pp = getprotoent()) { 933: slp = (struct valuelist *)malloc(sizeof(struct valuelist)); 934: slp->name = savestr(pp->p_name); 935: slp->port = pp->p_proto; 936: slp->next = protolist; 937: slp->prev = NULL; 938: if (protolist) { 939: protolist->prev = slp; 940: } 941: protolist = slp; 942: } 943: endprotoent(); 944: } 945: 946: findservice(s, list) 947: register char *s; 948: register struct valuelist **list; 949: { 950: register struct valuelist *lp = *list; 951: 952: for (; lp != NULL; lp = lp->next) 953: if (strcasecmp(lp->name, s) == 0) { 954: if (lp != *list) { 955: lp->prev->next = lp->next; 956: if (lp->next) 957: lp->next->prev = lp->prev; 958: (*list)->prev = lp; 959: lp->next = *list; 960: *list = lp; 961: } 962: return(lp->port); 963: } 964: return(-1); 965: } 966: 967: struct servent * 968: cgetservbyport(port, proto) 969: u_short port; 970: char *proto; 971: { 972: register struct valuelist **list = &servicelist; 973: register struct valuelist *lp = *list; 974: static struct servent serv; 975: 976: port = htons(port); 977: for (; lp != NULL; lp = lp->next) { 978: if (port != lp->port) 979: continue; 980: if (strcasecmp(lp->proto, proto) == 0) { 981: if (lp != *list) { 982: lp->prev->next = lp->next; 983: if (lp->next) 984: lp->next->prev = lp->prev; 985: (*list)->prev = lp; 986: lp->next = *list; 987: *list = lp; 988: } 989: serv.s_name = lp->name; 990: serv.s_port = htons((u_short)lp->port); 991: serv.s_proto = lp->proto; 992: return(&serv); 993: } 994: } 995: return(0); 996: } 997: 998: struct protoent * 999: cgetprotobynumber(proto) 1000: register int proto; 1001: { 1002: 1003: register struct valuelist **list = &protolist; 1004: register struct valuelist *lp = *list; 1005: static struct protoent prot; 1006: 1007: for (; lp != NULL; lp = lp->next) 1008: if (lp->port == proto) { 1009: if (lp != *list) { 1010: lp->prev->next = lp->next; 1011: if (lp->next) 1012: lp->next->prev = lp->prev; 1013: (*list)->prev = lp; 1014: lp->next = *list; 1015: *list = lp; 1016: } 1017: prot.p_name = lp->name; 1018: prot.p_proto = lp->port; 1019: return(&prot); 1020: } 1021: return(0); 1022: }