|
|
1.1 ! root 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 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: static char sccsid[] = "@(#)ns_init.c 4.24 (Berkeley) 6/18/88"; ! 20: #endif /* not lint */ ! 21: ! 22: #include <sys/types.h> ! 23: #include <sys/socket.h> ! 24: #include <sys/time.h> ! 25: #include <netinet/in.h> ! 26: #include <stdio.h> ! 27: #include <errno.h> ! 28: #include <signal.h> ! 29: #include <syslog.h> ! 30: #include <ctype.h> ! 31: #include <arpa/nameser.h> ! 32: #include "ns.h" ! 33: #include "db.h" ! 34: ! 35: struct zoneinfo zones[MAXZONES]; /* zone information */ ! 36: int nzones; /* number of zones in use */ ! 37: int forward_only = 0; /* run only as a slave */ ! 38: char *cache_file; ! 39: char *localdomain; /* "default" for non-dotted names */ ! 40: int maint_interval = 300; /* minimum ns_maint() interval */ ! 41: ! 42: extern int lineno; ! 43: ! 44: /* ! 45: * Read boot file for configuration info. ! 46: */ ! 47: ! 48: ns_init(bootfile) ! 49: char *bootfile; ! 50: { ! 51: register struct zoneinfo *zp; ! 52: char buf[BUFSIZ]; ! 53: FILE *fp; ! 54: int type; ! 55: time_t next_refresh = 0; ! 56: struct itimerval ival; ! 57: extern int needmaint; ! 58: ! 59: #ifdef DEBUG ! 60: if (debug >= 3) ! 61: fprintf(ddt,"ns_init(%s)\n", bootfile); ! 62: #endif ! 63: gettime(&tt); ! 64: ! 65: if ((fp = fopen(bootfile, "r")) == NULL) { ! 66: syslog(LOG_ERR, "%s: %m", bootfile); ! 67: exit(1); ! 68: } ! 69: lineno = 0; ! 70: ! 71: /* allocate cache hash table, formerly the root hash table. */ ! 72: hashtab = savehash((struct hashbuf *)NULL); ! 73: ! 74: /* allocate root-hints/file-cache hash table */ ! 75: fcachetab = savehash((struct hashbuf *)NULL); ! 76: ! 77: if (localdomain) ! 78: free(localdomain); ! 79: localdomain = NULL; ! 80: ! 81: /* init zone data */ ! 82: cache_file = NULL; ! 83: nzones = 1; /* zone zero is cache data */ ! 84: zones[0].z_type = Z_CACHE; ! 85: while (!feof(fp) && !ferror(fp)) { ! 86: if (!getword(buf, sizeof(buf), fp)) ! 87: continue; ! 88: /* read named.boot keyword and process args */ ! 89: if (strcasecmp(buf, "cache") == 0) { ! 90: type = Z_CACHE; ! 91: zp = zones; ! 92: } ! 93: else if (strcasecmp(buf, "primary") == 0) ! 94: type = Z_PRIMARY; ! 95: else if (strcasecmp(buf, "secondary") == 0) ! 96: type = Z_SECONDARY; ! 97: else if (strcasecmp(buf, "directory") == 0) { ! 98: (void) getword(buf, sizeof(buf), fp); ! 99: if (chdir(buf) < 0) { ! 100: syslog(LOG_CRIT, "directory %s: %m\n", ! 101: buf); ! 102: exit(1); ! 103: } ! 104: continue; ! 105: } ! 106: else if (strcasecmp(buf, "sortlist") == 0) { ! 107: get_sort_list(fp); ! 108: continue; ! 109: } ! 110: else if (strcasecmp(buf, "forwarders") == 0) { ! 111: get_forwarders(fp); ! 112: continue; ! 113: } ! 114: else if (strcasecmp(buf, "slave") == 0) { ! 115: forward_only++; ! 116: endline(fp); ! 117: continue; ! 118: } ! 119: else if (strcasecmp(buf, "domain") == 0) { ! 120: if (getword(buf, sizeof(buf), fp)) ! 121: localdomain = savestr(buf); ! 122: endline(fp); ! 123: continue; ! 124: } else { ! 125: syslog(LOG_ERR, "%s: line %d: unknown field '%s'\n", ! 126: bootfile, lineno, buf); ! 127: endline(fp); ! 128: continue; ! 129: } ! 130: if (nzones >= MAXZONES) { ! 131: syslog(LOG_ERR, "too many zones (MAXZONES=%d)\n", ! 132: MAXZONES); ! 133: endline(fp); ! 134: continue; ! 135: } ! 136: if (type != Z_CACHE) ! 137: zp = &zones[nzones++]; ! 138: if (zp->z_origin) { ! 139: free(zp->z_origin); ! 140: zp->z_origin = 0; ! 141: } ! 142: if (zp->z_source) { ! 143: free(zp->z_source); ! 144: zp->z_source = 0; ! 145: } ! 146: zp->z_type = type; ! 147: zp->z_addrcnt = 0; ! 148: zp->z_auth = 0; ! 149: /* ! 150: * read zone origin ! 151: */ ! 152: if (!getword(buf, sizeof(buf), fp)) { ! 153: syslog(LOG_ERR, "%s: line %d: missing origin\n", ! 154: bootfile, lineno); ! 155: continue; ! 156: } ! 157: if (buf[0] == '.') ! 158: buf[0] = '\0'; ! 159: zp->z_origin = savestr(buf); ! 160: /* ! 161: * read source file or host address ! 162: */ ! 163: if (!getword(buf, sizeof(buf), fp)) { ! 164: syslog(LOG_ERR, "%s: line %d: missing origin\n", ! 165: bootfile, lineno); ! 166: continue; ! 167: } ! 168: #ifdef DEBUG ! 169: if (debug) ! 170: fprintf(ddt,"zone[%d] type %d: '%s'", ! 171: zp-zones, zp->z_type, ! 172: *(zp->z_origin) == '\0' ? "." : zp->z_origin); ! 173: #endif ! 174: zp->z_time = 0; ! 175: zp->z_refresh = 0; /* by default, no dumping */ ! 176: switch (type) { ! 177: case Z_CACHE: ! 178: zp->z_source = savestr(buf); ! 179: #ifdef DEBUG ! 180: if (debug) ! 181: fprintf(ddt,", source = %s\n", zp->z_source); ! 182: #endif ! 183: if (getword(buf, sizeof(buf), fp)) { ! 184: #ifdef notyet ! 185: zp->z_refresh = atoi(buf); ! 186: if (zp->z_refresh <= 0) { ! 187: syslog(LOG_ERR, ! 188: "%s: line %d: bad refresh '%s', ignored\n", ! 189: bootfile, lineno, buf); ! 190: zp->z_refresh = 0; ! 191: } else if (cache_file == NULL) ! 192: cache_file = zp->z_source; ! 193: #else ! 194: syslog(LOG_WARNING, ! 195: "%s: line %d: cache refresh ignored\n", ! 196: bootfile, lineno); ! 197: #endif ! 198: endline(fp); ! 199: } ! 200: (void) db_load(zp->z_source, zp->z_origin, zp); ! 201: break; ! 202: ! 203: case Z_PRIMARY: ! 204: zp->z_source = savestr(buf); ! 205: #ifdef DEBUG ! 206: if (debug) ! 207: fprintf(ddt,", source = %s\n", zp->z_source); ! 208: #endif ! 209: if (db_load(zp->z_source, zp->z_origin, zp) == 0) ! 210: zp->z_auth = 1; ! 211: #ifdef ALLOW_UPDATES ! 212: /* Guarantee calls to ns_maint() */ ! 213: zp->z_refresh = maint_interval; ! 214: #else ! 215: zp->z_refresh = 0; ! 216: zp->z_time = 0; ! 217: #endif ALLOW_UPDATES ! 218: break; ! 219: ! 220: case Z_SECONDARY: ! 221: #ifdef DEBUG ! 222: if (debug) ! 223: fprintf(ddt,"\n\taddrs: %s, ", buf); ! 224: #endif ! 225: zp->z_addr[zp->z_addrcnt].s_addr = ! 226: inet_addr(buf); ! 227: /* Indicate no cache for this zone yet */ ! 228: zp->z_source = (char *) NULL; ! 229: if (zp->z_addr[zp->z_addrcnt].s_addr != (unsigned)-1) ! 230: zp->z_addrcnt++; ! 231: while (getword(buf, sizeof(buf), fp)) { ! 232: zp->z_addr[zp->z_addrcnt].s_addr = ! 233: inet_addr(buf); ! 234: if (zp->z_addr[zp->z_addrcnt].s_addr == ! 235: (unsigned)-1) { ! 236: zp->z_source = savestr(buf); ! 237: break; ! 238: } ! 239: #ifdef DEBUG ! 240: if (debug) ! 241: fprintf(ddt,"%s, ",buf); ! 242: #endif ! 243: if (++zp->z_addrcnt >= NSMAX) { ! 244: zp->z_addrcnt = NSMAX; ! 245: #ifdef DEBUG ! 246: if (debug) ! 247: fprintf(ddt, ! 248: "\nns.h NSMAX reached\n"); ! 249: #endif ! 250: break; ! 251: } ! 252: } ! 253: #ifdef DEBUG ! 254: if (debug) ! 255: fprintf(ddt,"addrcnt = %d\n", zp->z_addrcnt); ! 256: #endif ! 257: zoneinit(zp); ! 258: break; ! 259: ! 260: } ! 261: if (zp->z_refresh && zp->z_time == 0) ! 262: zp->z_time = zp->z_refresh + tt.tv_sec; ! 263: #ifdef DEBUG ! 264: if (debug) ! 265: fprintf(ddt, "z_time %d, z_refresh %d\n", ! 266: zp->z_time, zp->z_refresh); ! 267: #endif ! 268: if (zp->z_time != 0 && ! 269: (next_refresh == 0 || next_refresh > zp->z_time)) ! 270: next_refresh = zp->z_time; ! 271: } ! 272: (void) fclose(fp); ! 273: ! 274: /* ! 275: * Schedule calls to ns_maint(). ! 276: */ ! 277: bzero((char *)&ival, sizeof(ival)); ! 278: if (next_refresh) { ! 279: gettime(&tt); ! 280: if (next_refresh <= tt.tv_sec) ! 281: needmaint = 1; ! 282: else { ! 283: ival.it_value.tv_sec = next_refresh - tt.tv_sec; ! 284: if (ival.it_value.tv_sec < maint_interval) ! 285: ival.it_value.tv_sec = maint_interval; ! 286: } ! 287: } ! 288: (void) setitimer(ITIMER_REAL, &ival, (struct itimerval *)NULL); ! 289: #ifdef DEBUG ! 290: if (debug) { ! 291: fprintf(ddt,"exit ns_init() "); ! 292: if (needmaint || ival.it_value.tv_sec) ! 293: fprintf(ddt,"Next interrupt in %d sec\n", ! 294: ival.it_value.tv_sec); ! 295: else ! 296: fprintf(ddt,"No maintenance scheduled\n"); ! 297: } ! 298: #endif ! 299: } ! 300: ! 301: zoneinit(zp) ! 302: register struct zoneinfo *zp; ! 303: { ! 304: ! 305: #ifdef DEBUG ! 306: if (debug) ! 307: fprintf(ddt,"zoneinit()\n"); ! 308: #endif ! 309: ! 310: /* ! 311: * Try to load zone from backup file, ! 312: * if one was specified and it exists. ! 313: * If not, or if the data are out of date, ! 314: * we will refresh the zone from a primary ! 315: * immediately. ! 316: */ ! 317: if (zp->z_source == NULL || ! 318: db_load(zp->z_source, zp->z_origin, zp) != 0) { ! 319: /* ! 320: * Set zone to be refreshed immediately. ! 321: */ ! 322: zp->z_refresh = INIT_REFRESH; ! 323: zp->z_retry = INIT_REFRESH; ! 324: zp->z_time = tt.tv_sec; ! 325: } else ! 326: zp->z_auth = 1; ! 327: } ! 328: ! 329: #ifdef ALLOW_UPDATES ! 330: /* ! 331: * Look for the authoritative zone with the longest matching RHS of dname ! 332: * and return its zone # or zero if not found. ! 333: */ ! 334: findzone(dname, class) ! 335: char *dname; ! 336: int class; ! 337: { ! 338: char *dZoneName, *zoneName, *index(), *dotPos; ! 339: int dZoneNameLen, zoneNameLen; ! 340: int maxMatchLen = 0; ! 341: int maxMatchZoneNum = 0; ! 342: int zoneNum; ! 343: ! 344: #ifdef DEBUG ! 345: if (debug >= 4) ! 346: fprintf(ddt, "findzone(dname=%s, class=%d)\n", dname, class); ! 347: if (debug >= 5) { ! 348: fprintf(ddt, "zone dump:\n"); ! 349: for (zoneNum = 1; zoneNum < nzones; zoneNum++) ! 350: printzoneinfo(zoneNum); ! 351: } ! 352: #endif DEBUG ! 353: ! 354: dZoneName = index(dname, '.'); ! 355: if (dZoneName == NULL) ! 356: dZoneName = ""; /* root */ ! 357: else ! 358: dZoneName++; /* There is a '.' in dname, so use remainder of ! 359: string as the zone name */ ! 360: dZoneNameLen = strlen(dZoneName); ! 361: for (zoneNum = 1; zoneNum < nzones; zoneNum++) { ! 362: zoneName = (zones[zoneNum]).z_origin; ! 363: zoneNameLen = strlen(zoneName); ! 364: /* The zone name may or may not end with a '.' */ ! 365: dotPos = index(zoneName, '.'); ! 366: if (dotPos) ! 367: zoneNameLen--; ! 368: if (dZoneNameLen != zoneNameLen) ! 369: continue; ! 370: #ifdef DEBUG ! 371: if (debug >= 5) ! 372: fprintf(ddt, "about to strncasecmp('%s', '%s', %d)\n", ! 373: dZoneName, zoneName, dZoneNameLen); ! 374: #endif ! 375: if (strncasecmp(dZoneName, zoneName, dZoneNameLen) == 0) { ! 376: #ifdef DEBUG ! 377: if (debug >= 5) ! 378: fprintf(ddt, "match\n"); ! 379: #endif ! 380: /* ! 381: * See if this is as long a match as any so far. ! 382: * Check if "<=" instead of just "<" so that if ! 383: * root domain (whose name length is 0) matches, ! 384: * we use it's zone number instead of just 0 ! 385: */ ! 386: if (maxMatchLen <= zoneNameLen) { ! 387: maxMatchZoneNum = zoneNum; ! 388: maxMatchLen = zoneNameLen; ! 389: } ! 390: } ! 391: #ifdef DEBUG ! 392: else ! 393: if (debug >= 5) ! 394: fprintf(ddt, "no match\n"); ! 395: #endif ! 396: } ! 397: #ifdef DEBUG ! 398: if (debug >= 4) ! 399: fprintf(ddt, "findzone: returning %d\n", maxMatchZoneNum); ! 400: #endif DEBUG ! 401: return (maxMatchZoneNum); ! 402: } ! 403: #endif ALLOW_UPDATES ! 404: ! 405: soa_zinfo(zp, cp, eom) ! 406: register struct zoneinfo *zp; ! 407: register u_char *cp; ! 408: u_char *eom; ! 409: { ! 410: cp += 3 * sizeof(u_short); ! 411: cp += sizeof(u_long); ! 412: cp += dn_skipname(cp, eom); ! 413: cp += dn_skipname(cp, eom); ! 414: GETLONG(zp->z_serial, cp); ! 415: GETLONG(zp->z_refresh, cp); ! 416: gettime(&tt); ! 417: zp->z_time = tt.tv_sec + zp->z_refresh; ! 418: GETLONG(zp->z_retry, cp); ! 419: GETLONG(zp->z_expire, cp); ! 420: GETLONG(zp->z_minimum, cp); ! 421: } ! 422: ! 423: get_forwarders(fp) ! 424: FILE *fp; ! 425: { ! 426: char buf[BUFSIZ]; ! 427: struct fwdinfo *fip = NULL, *ftp = NULL; ! 428: ! 429: extern struct sockaddr_in nsaddr; ! 430: extern struct fwdinfo *fwdtab; ! 431: ! 432: #ifdef DEBUG ! 433: if (debug) ! 434: fprintf(ddt,"forwarders "); ! 435: #endif ! 436: while (getword(buf, sizeof(buf), fp)) { ! 437: if (strlen(buf) == 0) ! 438: break; ! 439: #ifdef DEBUG ! 440: if (debug) ! 441: fprintf(ddt," %s",buf); ! 442: #endif ! 443: if (ftp == NULL) ! 444: ftp = (struct fwdinfo *)malloc(sizeof(struct fwdinfo)); ! 445: if ( isdigit(buf[0]) && ! 446: (ftp->fwdaddr.sin_addr.s_addr = inet_addr(buf)) ! 447: != (unsigned)-1) { ! 448: ftp->fwdaddr.sin_port = nsaddr.sin_port; ! 449: ftp->fwdaddr.sin_family = AF_INET; ! 450: } else { ! 451: syslog(LOG_ERR, "'%s' (ignored, NOT dotted quad)", buf); ! 452: #ifdef DEBUG ! 453: if (debug) ! 454: fprintf(ddt," (ignored, NOT dotted quad)"); ! 455: #endif ! 456: continue; ! 457: } ! 458: ftp->next = NULL; ! 459: if (fwdtab == NULL) ! 460: fwdtab = ftp; /* First time only */ ! 461: else ! 462: fip->next = ftp; ! 463: fip = ftp; ! 464: ftp = NULL; ! 465: } ! 466: if (ftp) ! 467: free((char *)ftp); ! 468: ! 469: #ifdef DEBUG ! 470: if (debug) ! 471: fprintf(ddt,"\n"); ! 472: if (debug > 2) ! 473: for (ftp = fwdtab; ftp != NULL; ftp = ftp->next) ! 474: fprintf(ddt,"ftp x%x %s next x%x\n", ftp, ! 475: inet_ntoa(ftp->fwdaddr.sin_addr), ftp->next); ! 476: #endif ! 477: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.