1: #ifndef lint 2: static char sccsid[] = "@(#)ns_init.c 4.3 (Berkeley) 6/4/86"; 3: #endif 4: 5: /* 6: * Copyright (c) 1986 Regents of the University of California 7: * All Rights Reserved 8: */ 9: 10: #include <sys/types.h> 11: #include <sys/socket.h> 12: #include <sys/time.h> 13: #include <netinet/in.h> 14: #include <stdio.h> 15: #include <errno.h> 16: #include <signal.h> 17: #include <syslog.h> 18: #include <ctype.h> 19: #include <arpa/nameser.h> 20: #include "ns.h" 21: #include "db.h" 22: 23: struct zoneinfo zones[MAXZONES]; /* zone information */ 24: int nzones; /* number of zones in use */ 25: 26: /* 27: * Read boot file for configuration info. 28: */ 29: ns_init(bootfile) 30: char *bootfile; 31: { 32: register struct zoneinfo *zp; 33: char buf[BUFSIZ]; 34: char *tm; 35: FILE *fp; 36: int type, first = 1; 37: time_t next_refresh; 38: struct itimerval ival; 39: 40: #ifdef DEBUG 41: if (debug >= 3) 42: fprintf(ddt,"ns_init(%s)\n", bootfile); 43: #endif 44: 45: if ((fp = fopen(bootfile, "r")) == NULL) { 46: syslog(LOG_ERR, "%s: %m", bootfile); 47: exit(1); 48: } 49: 50: /* allocate root hash table */ 51: hashtab = savehash((struct hashbuf *)NULL); 52: 53: /* init zone data */ 54: nzones = 1; /* zone zero is cache data */ 55: while (getword(buf, sizeof(buf), fp)) { 56: /* read 'primary', 'secondary', 'cache' or 'domain' */ 57: top: 58: if (cistrcmp(buf, "cache") == 0) { 59: type = Z_CACHE; 60: zp = zones; 61: } else { 62: if (cistrcmp(buf, "primary") == 0) 63: type = Z_PRIMARY; 64: else if (cistrcmp(buf, "secondary") == 0) 65: type = Z_SECONDARY; 66: else if (cistrcmp(buf, "domain") == 0) 67: type = Z_DOMAIN; 68: else { 69: syslog(LOG_ERR, "%s: unknown type", buf); 70: exit(1); 71: } 72: if (nzones >= MAXZONES) { 73: syslog(LOG_ERR, "too many zones"); 74: exit(1); 75: } 76: zp = &zones[nzones++]; 77: } 78: zp->z_type = type; 79: zp->z_addrcnt = 0; 80: /* 81: * read zone origin 82: */ 83: (void) getword(buf, sizeof(buf), fp); 84: if (buf[0] == '.') 85: buf[0] = '\0'; 86: zp->z_origin = savestr(buf); 87: /* 88: * read source file or host address 89: */ 90: if (type != Z_DOMAIN) { 91: (void) getword(buf, sizeof(buf), fp); 92: zp->z_source = savestr(buf); 93: #ifdef DEBUG 94: if (debug) { 95: fprintf(ddt,"zone found (%d): ", zp->z_type); 96: if (zp->z_origin[0] == '\0') 97: fprintf(ddt,"'.'"); 98: else 99: fprintf(ddt,"'%s'", zp->z_origin); 100: fprintf(ddt,", source = %s", zp->z_source); 101: } 102: #endif 103: } 104: #ifdef DEBUG 105: else if (debug) 106: fprintf(ddt,"zone found (%d): domain name = '%s'", 107: zp->z_type, zp->z_origin); 108: #endif 109: switch (zp->z_type) { 110: case Z_PRIMARY: 111: case Z_CACHE: 112: #ifdef DEBUG 113: if (debug) 114: fprintf(ddt,"\n"); 115: #endif 116: (void) db_load(zp->z_source, zp->z_origin, zp - zones); 117: break; 118: 119: case Z_SECONDARY: 120: zp->z_addr[zp->z_addrcnt].s_addr = 121: inet_addr(zp->z_source); 122: if (zp->z_addr[zp->z_addrcnt].s_addr != (unsigned)-1) 123: zp->z_addrcnt++; 124: while (getword(buf, sizeof(buf), fp)) { 125: tm = savestr(buf); 126: zp->z_addr[zp->z_addrcnt].s_addr = 127: inet_addr(tm); 128: if (zp->z_addr[zp->z_addrcnt].s_addr == 129: (unsigned)-1) { 130: #ifdef DEBUG 131: if (debug) 132: fprintf(ddt," (addrcnt) = %d\n", 133: zp->z_addrcnt); 134: #endif 135: zoneinit(zp); 136: if (first) { 137: next_refresh = zp->z_time; 138: first = 0; 139: } else 140: if (next_refresh > zp->z_time) 141: next_refresh = zp->z_time; 142: goto top; 143: } 144: #ifdef DEBUG 145: if (debug) 146: fprintf(ddt,", %s",buf); 147: #endif 148: if (++zp->z_addrcnt >= MAXNS) { 149: zp->z_addrcnt = MAXNS; 150: #ifdef DEBUG 151: if (debug) 152: fprintf(ddt, 153: "\nns.h MAXNS reached\n"); 154: #endif 155: break; 156: } 157: } 158: #ifdef DEBUG 159: if (debug) 160: fprintf(ddt," addrcnt = %d\n", zp->z_addrcnt); 161: #endif 162: zoneinit(zp); 163: if (first) { 164: next_refresh = zp->z_time; 165: first = 0; 166: } else 167: if (next_refresh > zp->z_time) 168: next_refresh = zp->z_time; 169: break; 170: 171: case Z_DOMAIN: 172: while (getword(buf, sizeof(buf), fp)) { 173: tm = savestr(buf); 174: zp->z_addr[zp->z_addrcnt].s_addr = 175: inet_addr(tm); 176: if (zp->z_addr[zp->z_addrcnt].s_addr == 177: (unsigned)-1) { 178: #ifdef DEBUG 179: if (debug) 180: fprintf(ddt," addrcnt = %d\n", 181: zp->z_addrcnt); 182: #endif 183: goto top; 184: } 185: #ifdef DEBUG 186: if (debug) 187: fprintf(ddt,", %s",buf); 188: #endif 189: if (++zp->z_addrcnt >= MAXNS) { 190: zp->z_addrcnt = MAXNS; 191: #ifdef DEBUG 192: if (debug) 193: fprintf(ddt,"\nns.h MAXNS reached\n"); 194: #endif 195: break; 196: } 197: } 198: #ifdef DEBUG 199: if (debug) 200: fprintf(ddt," addrcnt = %d\n", 201: zp->z_addrcnt); 202: #endif 203: break; 204: 205: } 206: } 207: (void) fclose(fp); 208: if (!first) { 209: if (gettimeofday(&tt, (struct timezone *)0) < 0) { 210: syslog(LOG_ERR, "gettimeofday failed: %m"); 211: ival.it_value.tv_sec = 5 * 60; 212: } else { 213: bzero((char *)&ival, sizeof(ival)); 214: ival.it_value.tv_sec = next_refresh - tt.tv_sec; 215: if (ival.it_value.tv_sec < 0) 216: ival.it_value.tv_sec = 60; 217: } 218: } else 219: ival.it_value.tv_sec = 0; 220: (void) setitimer(ITIMER_REAL, &ival, (struct itimerval *)NULL); 221: #if DEBUG 222: if (debug) 223: fprintf(ddt,"exit ns_init() Next interupt in %d sec\n", 224: ival.it_value.tv_sec); 225: #endif 226: } 227: 228: zoneinit(zp) 229: struct zoneinfo *zp; 230: { 231: struct sockaddr_in sin; 232: HEADER *hp; 233: char buf[PACKETSZ]; 234: u_short len; 235: char *cp; 236: char *tmp; 237: int s, n, l; 238: int cnt, soacnt, error = 0; 239: int zone = zp - zones; 240: u_long serial; 241: struct itimerval ival; 242: struct itimerval zeroival; 243: extern struct sockaddr_in nsaddr; 244: extern int errno; 245: extern int read_alarm(); 246: struct sigvec sv, osv; 247: extern int read_interrupted; 248: 249: #ifdef DEBUG 250: if (debug) 251: fprintf(ddt,"zoneinit()\n"); 252: #endif 253: 254: bzero((char *)&zeroival, sizeof(zeroival)); 255: ival = zeroival; 256: ival.it_value.tv_sec = 2 * 60; 257: sv.sv_handler = read_alarm; 258: sv.sv_onstack = 0; 259: sv.sv_mask = ~0; 260: (void) sigvec(SIGALRM, &sv, &osv); 261: 262: for( cnt = 0; cnt < zp->z_addrcnt; cnt++) { 263: error = 0; 264: bzero((char *)&sin, sizeof(sin)); 265: sin.sin_family = AF_INET; 266: sin.sin_port = nsaddr.sin_port; 267: sin.sin_addr = zp->z_addr[cnt]; 268: if ((n = res_mkquery(QUERY, zp->z_origin, C_IN, T_AXFR, 269: (char *)NULL, 0, NULL, buf, sizeof(buf))) < 0) { 270: syslog(LOG_ERR, "zoneinit: res_mkquery failed"); 271: (void) sigvec(SIGALRM, &osv, (struct sigvec *)0); 272: return; 273: } 274: if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) { 275: syslog(LOG_ERR, "zoneref: socket: %m"); 276: exit(1); 277: } 278: #ifdef DEBUG 279: if (debug >= 2) { 280: fprintf(ddt,"connecting to server #%d %s, %d (%d)\n", 281: cnt+1, inet_ntoa(sin.sin_addr), 282: ntohs(sin.sin_port), n); 283: } 284: #endif 285: if (connect(s, &sin, sizeof(sin)) < 0) { 286: (void) close(s); 287: error++; 288: #ifdef DEBUG 289: if (debug >= 2) 290: fprintf(ddt,"connect failed\n"); 291: #endif 292: continue; 293: } 294: /* 295: * Send length & message for zone transfer 296: */ 297: if (writemsg(s, buf, n) < 0) { 298: (void) close(s); 299: error++; 300: #ifdef DEBUG 301: if (debug >= 2) 302: fprintf(ddt,"writemsg failed\n"); 303: #endif 304: continue; 305: } 306: 307: hp = (HEADER *) buf; 308: soacnt = 0; 309: 310: for (;;) { 311: /* 312: * Receive length & response 313: */ 314: cp = buf; 315: l = sizeof(u_short); 316: read_interrupted = 0; 317: while (l > 0) { 318: (void) setitimer(ITIMER_REAL, &ival, 319: (struct itimerval *)NULL); 320: if ((n = recv(s, cp, l, 0)) > 0) { 321: cp += n; 322: l -= n; 323: } else { 324: if (errno == EINTR && !read_interrupted) 325: continue; 326: error++; 327: break; 328: } 329: } 330: (void) setitimer(ITIMER_REAL, &zeroival, 331: (struct itimerval *)NULL); 332: if (error) 333: break; 334: if ((len = htons(*(u_short *)buf)) == 0) 335: break; 336: l = len; 337: cp = buf; 338: while (l > 0) { 339: (void) setitimer(ITIMER_REAL, &ival, 340: (struct itimerval *)NULL); 341: if ((n = recv(s, cp, l, 0)) > 0) { 342: cp += n; 343: l -= n; 344: } else { 345: if (errno == EINTR && !read_interrupted) 346: continue; 347: error++; 348: break; 349: } 350: } 351: (void) setitimer(ITIMER_REAL, &zeroival, 352: (struct itimerval *)NULL); 353: if (error) 354: break; 355: #ifdef DEBUG 356: if (debug >= 3) { 357: fprintf(ddt,"len = %d\n", len); 358: fp_query(buf, ddt); 359: } 360: #endif 361: cp = buf + sizeof(HEADER); 362: if (hp->qdcount) 363: cp += dn_skip(cp) + QFIXEDSZ; 364: tmp = cp + dn_skip(cp); 365: n = doupdate(buf, sizeof(buf), cp, zone, 0); 366: if ((cp - buf) + n != len) { 367: #ifdef DEBUG 368: if (debug) 369: fprintf(ddt,"zoneinit: doupdate failed (%d, %d)\n", 370: cp - buf, n); 371: #endif 372: error++; 373: break; 374: } 375: if ((getshort(tmp)) == T_SOA) { 376: if (soacnt == 0) { 377: soacnt++; 378: tmp += 3 * sizeof(u_short) 379: + sizeof(u_long); 380: tmp += dn_skip(tmp); 381: tmp += dn_skip(tmp); 382: serial = getlong(tmp); 383: continue; 384: } 385: soa_zinfo(zp, tmp); 386: if (serial != zp->z_serial) 387: soacnt = 0; 388: else { 389: break; 390: } 391: } 392: } 393: (void) close(s); 394: if ( error == 0) { 395: (void) sigvec(SIGALRM, &osv, (struct sigvec *)0); 396: return; 397: } 398: #ifdef DEBUG 399: if (debug >= 2) 400: fprintf(ddt,"error reciving zone transfer\n"); 401: #endif 402: } 403: /* 404: * Freedom at last!! 405: * 406: * The land where all repressed slaves dream of. 407: * 408: * Can't find a master to talk to. 409: * syslog it and hope we can find a master during maintenance 410: */ 411: if (error) 412: syslog(LOG_ERR, "zoneinit: Can't find Master for secondary zone %s", 413: zp->z_origin); 414: /* 415: * Set zone to be refreshed in 5 min. 416: * maybe by then we can refresh it. 417: */ 418: zp->z_refresh = 300; /* 300 seconds = 5 Min. */ 419: zp->z_retry = 300; 420: if (gettimeofday(&tt, (struct timezone *)0) < 0) 421: syslog(LOG_ERR, "gettimeofday failed: %m"); 422: zp->z_time = tt.tv_sec + 300; 423: (void) sigvec(SIGALRM, &osv, (struct sigvec *)0); 424: return; 425: } 426: #ifdef notdef 427: /* 428: * Look for an authoritative zone that matches the RHS of dname 429: * and return is zone # or zero if not found. 430: */ 431: findzone(dname, class) 432: char *dname; 433: int class; 434: { 435: register struct zoneinfo *zp; 436: register char *d1, *d2; 437: register int c; 438: char *end; 439: 440: end = dname + strlen(dname); 441: for (zp = &zones[1]; zp < &zones[nzones]; zp++) { 442: d1 = end; 443: d2 = zp->z_origin + strlen(zp->z_origin); 444: while (d2 > zp->z_origin) { 445: if ((c*-- 446: } 447: return (zp - zones); 448: } 449: return (0); 450: } 451: #endif 452: 453: soa_zinfo(zp, cp) 454: struct zoneinfo *zp; 455: char *cp; 456: { 457: cp += 3 * sizeof(u_short); 458: cp += sizeof(u_long); 459: cp += dn_skip(cp); 460: cp += dn_skip(cp); 461: zp->z_serial = getlong(cp); 462: cp += sizeof(u_long); 463: zp->z_refresh = getlong(cp); 464: if (gettimeofday(&tt, (struct timezone *)0) < 0) 465: syslog(LOG_ERR, "gettimeofday failed: %m"); 466: zp->z_time = tt.tv_sec + zp->z_refresh; 467: cp += sizeof(u_long); 468: zp->z_retry = getlong(cp); 469: cp += sizeof(u_long); 470: zp->z_expire = getlong(cp); 471: cp += sizeof(u_long); 472: zp->z_minimum = getlong(cp); 473: cp += sizeof(u_long); 474: }