1: #ifndef lint 2: static char sccsid[] = "@(#)db_load.c 4.3 (Berkeley) 5/30/86"; 3: #endif 4: 5: /* 6: * Copyright (c) 1986 Regents of the University of California 7: * All Rights Reserved 8: */ 9: 10: /* 11: * Load data base from ascii backupfile. Format similar to RFC 883. 12: */ 13: 14: #include <sys/types.h> 15: #include <sys/time.h> 16: #include <netinet/in.h> 17: #include <stdio.h> 18: #include <syslog.h> 19: #include <ctype.h> 20: #include <netdb.h> 21: #include <arpa/nameser.h> 22: #include "ns.h" 23: #include "db.h" 24: 25: extern char *index(); 26: 27: /* 28: * Map class and type names to number 29: */ 30: struct map { 31: char token[8]; 32: int val; 33: }; 34: 35: struct map m_class[] = { 36: "in", C_IN, 37: "any", C_ANY, 38: }; 39: #define NCLASS (sizeof(m_class)/sizeof(struct map)) 40: 41: struct map m_type[] = { 42: "a", T_A, 43: "ns", T_NS, 44: "cname", T_CNAME, 45: "soa", T_SOA, 46: "mb", T_MB, 47: "mg", T_MG, 48: "mr", T_MR, 49: "null", T_NULL, 50: "wks", T_WKS, 51: "ptr", T_PTR, 52: "hinfo", T_HINFO, 53: "minfo", T_MINFO, 54: "mx", T_MX, 55: "uinfo", T_UINFO, 56: "uid", T_UID, 57: "gid", T_GID, 58: "any", T_ANY, 59: }; 60: #define NTYPE (sizeof(m_type)/sizeof(struct map)) 61: 62: /* 63: * Parser token values 64: */ 65: #define CURRENT 1 66: #define DOT 2 67: #define AT 3 68: #define DNAME 4 69: #define INCLUDE 5 70: #define ORIGIN 6 71: 72: int lineno = 1; /* current line number */ 73: 74: /* 75: * Load the database from 'filename'. Origin is appended to all domain 76: * names in the file. 77: */ 78: db_load(filename, in_origin, zone) 79: char *filename, *in_origin; 80: int zone; 81: { 82: register char *cp; 83: register struct map *mp; 84: char domain[MAXDNAME]; 85: char origin[MAXDNAME]; 86: char buf[BUFSIZ]; 87: char data[MAXDATA]; 88: char *op; 89: int class, type, ttl; 90: struct databuf *dp; 91: FILE *fp; 92: int slineno, i; 93: long n; 94: 95: #ifdef DEBUG 96: if (debug) 97: fprintf(ddt,"db_load(%s, %s, %d)\n", filename, in_origin, zone); 98: #endif 99: 100: (void) strcpy(origin, in_origin); 101: if ((fp = fopen(filename, "r")) == NULL) { 102: syslog(LOG_ERR, "%s: %m", filename); 103: return (NODBFILE); 104: } 105: lineno = 1; 106: domain[0] = '\0'; 107: class = C_IN; 108: while ((n = gettoken(fp)) != EOF) { 109: switch ((int)n) { 110: case INCLUDE: 111: if (!getword(buf, sizeof(buf), fp)) /* file name */ 112: break; 113: slineno = lineno; 114: (void) db_load(buf, origin, zone); 115: lineno = slineno; 116: continue; 117: 118: case ORIGIN: 119: (void) strcpy(buf, origin); 120: if (!getword(origin, sizeof(origin), fp)) 121: break; 122: makename(origin, buf); 123: continue; 124: 125: case DNAME: 126: if (!getword(domain, sizeof(domain), fp)) 127: break; 128: n = strlen(domain) - 1; 129: if (domain[n] == '.') 130: domain[n] = '\0'; 131: else if (*origin) { 132: (void) strcat(domain, "."); 133: (void) strcat(domain, origin); 134: } 135: goto gotdomain; 136: 137: case AT: 138: (void) strcpy(domain, origin); 139: goto gotdomain; 140: 141: case DOT: 142: domain[0] = '\0'; 143: /* fall thru ... */ 144: case CURRENT: 145: gotdomain: 146: if (!getword(buf, sizeof(buf), fp)) 147: break; 148: cp = buf; 149: if (isdigit(*cp)) { 150: n = 0; 151: do 152: n = n * 10 + (*cp++ - '0'); 153: while (isdigit(*cp)); 154: if (zone == 0) { 155: if (gettimeofday(&tt, 156: (struct timezone *)0) < 0) 157: syslog(LOG_ERR, 158: "gettimeofday failed: %m"); 159: n += (long) tt.tv_sec; 160: } 161: ttl = n; 162: if (!getword(buf, sizeof(buf), fp)) 163: break; 164: } else 165: ttl = 0; 166: for (mp = m_class; mp < m_class+NCLASS; mp++) 167: if (!cistrcmp(buf, mp->token)) { 168: class = mp->val; 169: (void) getword(buf, sizeof(buf), fp); 170: break; 171: } 172: for (mp = m_type; mp < m_type+NTYPE; mp++) 173: if (!cistrcmp(buf, mp->token)) { 174: type = mp->val; 175: goto fndtype; 176: } 177: #ifdef DEBUG 178: if (debug) 179: fprintf(ddt,"Unknown type: %s.\n", buf); 180: #endif 181: break; 182: fndtype: 183: if (!getword(buf, sizeof(buf), fp)) 184: break; 185: #ifdef DEBUG 186: if (debug >= 3) 187: fprintf(ddt,"d='%s',c=%d,t=%d, ttl=%d, data='%s'\n", 188: domain, class, type, ttl, buf); 189: #endif 190: /* 191: * Convert the ascii data 'buf' to the proper format 192: * based on the type and pack into 'data'. 193: */ 194: switch (type) { 195: case T_A: 196: n = ntohl((u_long)inet_addr((char *)buf)); 197: putlong((u_long)n, data); 198: n = sizeof(u_long); 199: break; 200: 201: case T_HINFO: 202: n = strlen(buf); 203: if (n > 255) { 204: syslog(LOG_WARNING, "CPU too large (%d)",n); 205: n = 255; 206: } 207: data[0] = n; 208: bcopy(buf, (char *)data + 1, (int)n); 209: n++; 210: if (!getword(buf, sizeof(buf), fp)) 211: break; 212: i = strlen(buf); 213: if (i > 255) { 214: syslog(LOG_WARNING, "OS too large (%d)", i); 215: i = 255; 216: } 217: data[n] = i; 218: bcopy(buf, data + n + 1, i); 219: n += i + 1; 220: break; 221: 222: case T_SOA: 223: case T_MINFO: 224: (void) strcpy(data, buf); 225: makename(data, origin); 226: cp = data + strlen(data) + 1; 227: if (!getword(cp, sizeof(data) - (cp - data),fp)) 228: break; 229: makename(cp, origin); 230: cp += strlen(cp) + 1; 231: if (type == T_MINFO) { 232: n = cp - data; 233: break; 234: } 235: if (getnonblank(fp) != '(') 236: goto err; 237: putlong((u_long)(zones[zone].z_serial = 238: getnum(fp)), cp); 239: cp += sizeof(u_long); 240: putlong((u_long)(zones[zone].z_refresh = 241: getnum(fp)), cp); 242: cp += sizeof(u_long); 243: putlong((u_long)(zones[zone].z_retry = 244: getnum(fp)), cp); 245: cp += sizeof(u_long); 246: putlong ((u_long)(zones[zone].z_expire = 247: getnum(fp)), cp); 248: cp += sizeof(u_long); 249: putlong ((u_long)(zones[zone].z_minimum = 250: getnum(fp)), cp); 251: cp += sizeof(u_long); 252: n = cp - data; 253: if (getnonblank(fp) != ')') 254: goto err; 255: endline(fp); 256: break; 257: 258: case T_UID: 259: case T_GID: 260: n = 0; 261: cp = buf; 262: while (isdigit(*cp)) 263: n = n * 10 + (*cp++ - '0'); 264: if (cp == buf) 265: goto err; 266: putlong((u_long)n, data); 267: n = sizeof(long); 268: break; 269: 270: case T_WKS: 271: /* Address */ 272: n = ntohl((u_long)inet_addr((char *)buf)); 273: putlong((u_long)n, data); 274: data[sizeof(u_long)] = getprotocol(fp); 275: /* Protocol */ 276: n = sizeof(u_long) + sizeof(char); 277: /* Services */ 278: n = getservices((int)n, data, fp); 279: break; 280: 281: case T_NS: 282: case T_CNAME: 283: case T_MB: 284: case T_MG: 285: case T_MR: 286: case T_PTR: 287: (void) strcpy(data, buf); 288: makename(data, origin); 289: n = strlen(data) + 1; 290: break; 291: 292: case T_UINFO: 293: cp = index(buf, '&'); 294: bzero(data, sizeof(data)); 295: if ( cp != NULL) { 296: (void) strncpy(data, buf, cp - buf); 297: op = index(domain, '.'); 298: if ( op != NULL) 299: (void) strncat(data, 300: domain,op-domain); 301: else 302: (void) strcat(data, domain); 303: (void) strcat(data, ++cp); 304: } else 305: (void) strcpy(data, buf); 306: n = strlen(data) + 1; 307: break; 308: case T_MX: 309: n = 0; 310: cp = buf; 311: while (isdigit(*cp)) 312: n = n * 10 + (*cp++ - '0'); 313: /* catch bad values */ 314: if ((cp == buf) || (n & ~0xffff)) 315: goto err; 316: 317: putshort((u_short)n, data); 318: cp = data + sizeof(u_short); 319: 320: if (!getword(buf, sizeof(buf), fp)) 321: break; 322: (void) strcpy(cp,buf); 323: makename(cp, origin); 324: /* get pointer to place in data */ 325: cp += strlen(cp) +1; 326: 327: /* now save length */ 328: n = (cp - data); 329: break; 330: 331: default: 332: goto err; 333: } 334: dp = savedata(class, type, (u_long)ttl, data, (int)n); 335: dp->d_zone = zone; 336: if ((n = db_update(domain, dp, dp, DB_NODATA)) < 0) { 337: #ifdef DEBUG 338: if (debug && (n != DATAEXISTS)) 339: fprintf(ddt,"update failed\n"); 340: #endif 341: } 342: continue; 343: } 344: err: 345: syslog(LOG_ERR, "%s: line %d: database format error (%s)", 346: filename, lineno, buf); 347: (void) fclose(fp); 348: return (-1); 349: } 350: (void) fclose(fp); 351: return (OK); 352: } 353: 354: int gettoken(fp) 355: register FILE *fp; 356: { 357: register int c; 358: char op[32]; 359: 360: for (;;) { 361: c = getc(fp); 362: top: 363: switch (c) { 364: case EOF: 365: return (EOF); 366: 367: case '$': 368: if (!getword(op, sizeof(op), fp)) 369: return (EOF); 370: if (!cistrcmp("include", op)) 371: return (INCLUDE); 372: if (!cistrcmp("origin", op)) 373: return (ORIGIN); 374: printf("Unknown $ option: %s\n", op); 375: /* fall through... */ 376: 377: case ';': 378: while ((c = getc(fp)) != EOF && c != '\n') 379: ; 380: goto top; 381: 382: case ' ': 383: case '\t': 384: return (CURRENT); 385: 386: case '.': 387: return (DOT); 388: 389: case '@': 390: return (AT); 391: 392: case '\n': 393: lineno++; 394: continue; 395: 396: default: 397: (void) ungetc(c, fp); 398: return (DNAME); 399: } 400: } 401: } 402: 403: /* 404: * Get next word, skipping blanks & comments. 405: */ 406: getword(buf, size, fp) 407: char *buf; 408: int size; 409: FILE *fp; 410: { 411: register char *cp; 412: register int c; 413: 414: for (cp = buf; (c = getc(fp)) != EOF; ) { 415: if (isspace(c)) { 416: if (c == '\n') 417: lineno++; 418: if (cp != buf) 419: break; 420: continue; 421: } 422: if (c == ';') { 423: while ((c = getc(fp)) != EOF && c != '\n') 424: ; 425: if (c == '\n') 426: lineno++; 427: if (cp != buf) 428: break; 429: continue; 430: } 431: if (c == '"') { 432: while ((c = getc(fp)) != EOF && c != '"' && c != '\n') { 433: if (c == '\\') { 434: if ((c = getc(fp)) == EOF) 435: c = '\\'; 436: if (c == '\n') 437: lineno++; 438: } 439: if (cp >= buf+size-1) 440: break; 441: *cp++ = c; 442: } 443: if (c == '\n') { 444: lineno++; 445: break; 446: } 447: continue; 448: } 449: if (c == '\\') { 450: if ((c = getc(fp)) == EOF) 451: c = '\\'; 452: if (c == '\n') 453: lineno++; 454: } 455: if (cp >= buf+size-1) 456: break; 457: *cp++ = c; 458: } 459: *cp = '\0'; 460: return (cp != buf); 461: } 462: 463: getw_b_nl(buf, size, fp) 464: char *buf; 465: int size; 466: FILE *fp; 467: { 468: register char *cp; 469: register int c; 470: 471: for (cp = buf; (c = getc(fp)) != EOF; ) { 472: if (isspace(c)) { 473: if (c == '\n') { 474: *cp = '\0'; 475: return (0); 476: } 477: if (cp != buf) 478: break; 479: continue; 480: } 481: if (c == ';') { 482: while ((c = getc(fp)) != EOF && c != '\n') 483: ; 484: if (c == '\n') 485: lineno++; 486: if (cp != buf) 487: break; 488: continue; 489: } 490: if (cp >= buf+size-1) 491: break; 492: *cp++ = c; 493: } 494: *cp = '\0'; 495: return (cp != buf); 496: } 497: 498: getnum(fp) 499: FILE *fp; 500: { 501: register int c, n; 502: int seendigit = 0; 503: int seendecimal = 0; 504: 505: for (n = 0; (c = getc(fp)) != EOF; ) { 506: if (isspace(c)) { 507: if (c == '\n') 508: lineno++; 509: if (seendigit) 510: break; 511: continue; 512: } 513: if (c == ';') { 514: while ((c = getc(fp)) != EOF && c != '\n') 515: ; 516: if (c == '\n') 517: lineno++; 518: if (seendigit) 519: break; 520: continue; 521: } 522: if (!isdigit(c)) { 523: if (c != '.') { 524: syslog(LOG_ERR, "line %d: expected a number", 525: lineno); 526: exit(1); 527: } 528: if (!seendigit) 529: n = 1; 530: if (seendecimal) { 531: syslog(LOG_ERR, "line %d: expected a number", 532: lineno); 533: exit(1); 534: } else { 535: n = n * 1000 ; 536: seendigit = 1; 537: seendecimal = 1; 538: } 539: continue; 540: } 541: n = n * 10 + (c - '0'); 542: seendigit = 1; 543: } 544: return (n); 545: } 546: 547: getnonblank(fp) 548: FILE *fp; 549: { 550: register int c; 551: 552: while ( (c = getc(fp)) != EOF ) { 553: if (isspace(c)) { 554: if (c == '\n') 555: lineno++; 556: continue; 557: } 558: if (c == ';') { 559: while ((c = getc(fp)) != EOF && c != '\n') 560: ; 561: if (c == '\n') 562: lineno++; 563: continue; 564: } 565: return(c); 566: } 567: syslog(LOG_ERR, "line %d: unexpected EOF", lineno); 568: return (EOF); 569: } 570: 571: /* 572: * Take name and fix it according to following rules: 573: * "." means root. 574: * "@" means current origin. 575: * "name." means no changes. 576: * "name" means append origin. 577: */ 578: makename(name, origin) 579: char *name, *origin; 580: { 581: int n; 582: 583: if (origin[0] == '.') 584: origin++; 585: n = strlen(name); 586: if (n == 1) { 587: if (name[0] == '.') { 588: name[0] = '\0'; 589: return; 590: } 591: if (name[0] == '@') { 592: (void) strcpy(name, origin); 593: return; 594: } 595: } 596: if (n > 0) { 597: if (name[n - 1] == '.') 598: name[n - 1] = '\0'; 599: else if (origin[0] != '\0') { 600: name[n] = '.'; 601: (void) strcpy(name + n + 1, origin); 602: } 603: } 604: } 605: 606: endline(fp) 607: register FILE *fp; 608: { 609: register int c; 610: while (c = getc(fp)) 611: if ((c == EOF) || (c == '\n')) { 612: (void) ungetc(c,fp); 613: break; 614: } 615: } 616: 617: #define MAXPORT 256 618: #define MAXLEN 24 619: 620: getprotocol(fp) 621: FILE *fp; 622: { 623: int k; 624: char b[MAXLEN]; 625: struct protoent *proto; 626: 627: (void) getword(b, sizeof(b), fp); 628: 629: proto = getprotobyname(b); 630: if(proto == NULL) { 631: k = 0; 632: (void) sscanf(b,"%d",&k); 633: } 634: else 635: k = proto->p_proto; 636: return(k); 637: } 638: 639: int getservices(n, data, fp) 640: int n; 641: char *data; 642: FILE *fp; 643: { 644: int j, ch; 645: u_short k; 646: int maxl; 647: int bracket, eol; 648: char b[MAXLEN]; 649: char bm[MAXPORT/8]; 650: struct servent *service; 651: 652: for (j = 0; j < MAXPORT/8; j++) 653: bm[j] = 0; 654: maxl = 0; 655: bracket = eol = 0; 656: while (1) { 657: if (!getw_b_nl(b, sizeof(b), fp) && (!bracket)) { 658: if (strlen(b) == 0) 659: break; 660: eol++; 661: } 662: if ( b[0] == '(') { 663: bracket++; 664: continue; 665: } 666: if ( b[0] == ')') { 667: bracket = 0; 668: while ((ch = getc(fp)) != EOF && ch != '\n') 669: ; 670: break; 671: } 672: service = getservbyname(b, (char *)NULL); 673: if (service == NULL) { 674: k=0; 675: (void) sscanf(b,"%d",&k); 676: if (k == 0) 677: continue; 678: } 679: else 680: k = ntohs((u_short)service->s_port); 681: if ((k < MAXPORT) && (k)) { 682: bm[k/8] |= (0x80>>(k%8)); 683: if (k > maxl) 684: maxl=k; 685: } 686: else 687: syslog(LOG_WARNING,"port no.(%d) too big\n",k); 688: if(eol) 689: break; 690: } 691: maxl = maxl/8+1; 692: bcopy(bm, data+n, maxl); 693: return(maxl+n); 694: }