|
|
1.1 ! root 1: #ifndef lint ! 2: static char sccsid[] = "@(#)ns_maint.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 <syslog.h> ! 16: #include <signal.h> ! 17: #include <errno.h> ! 18: #include <arpa/nameser.h> ! 19: #include "ns.h" ! 20: #include "db.h" ! 21: ! 22: /* ! 23: * Invoked at regular intervals by signal interrupt; refresh all secondary ! 24: * zones from primary name server and remove old cache entries. ! 25: */ ! 26: ns_maint() ! 27: { ! 28: register struct zoneinfo *zp; ! 29: struct itimerval ival; ! 30: time_t now, next_refresh; ! 31: int first; ! 32: extern errno; ! 33: #ifdef DEBUG ! 34: if (debug) ! 35: fprintf(ddt,"ns_maint()\n"); ! 36: #endif ! 37: ! 38: ! 39: first = 1; ! 40: for (zp = zones; zp < &zones[nzones]; zp++) { ! 41: if (zp->z_type != Z_SECONDARY) ! 42: continue; ! 43: if (gettimeofday(&tt, (struct timezone *)0) < 0) ! 44: syslog(LOG_ERR, "gettimeofday failed: %m"); ! 45: now = tt.tv_sec; ! 46: #ifdef DEBUG ! 47: if (debug >=2) { ! 48: if (zp->z_origin[0] == '\0') ! 49: fprintf(ddt,"origin ='.'"); ! 50: else ! 51: fprintf(ddt,"origin ='%s'", zp->z_origin); ! 52: fprintf(ddt,", source = %s\n", zp->z_source); ! 53: fprintf(ddt,"z_refresh = %ld", zp->z_refresh); ! 54: fprintf(ddt,", retry = %ld", zp->z_retry); ! 55: fprintf(ddt,", expire = %ld", zp->z_expire); ! 56: fprintf(ddt,", minimum = %ld", zp->z_minimum); ! 57: fprintf(ddt,", serial = %ld\n", zp->z_serial); ! 58: fprintf(ddt,"z_time = %d", zp->z_time); ! 59: fprintf(ddt,", now time : %d sec", now); ! 60: fprintf(ddt,", time left: %d sec\n", zp->z_time - now); ! 61: } ! 62: #endif ! 63: if (now >= zp->z_time) { ! 64: zoneref(zp); ! 65: zp->z_time = tt.tv_sec + zp->z_refresh; ! 66: } ! 67: /* ! 68: * Find when the next refresh needs to be and set ! 69: * interupt time accordingly. ! 70: * Why have needless intruptions. ! 71: * I just hate it when the cleaning crew come early. ! 72: */ ! 73: if (first) { ! 74: next_refresh = zp->z_time; ! 75: first = 0; ! 76: } ! 77: else if (next_refresh > zp->z_time) ! 78: next_refresh = zp->z_time; ! 79: } ! 80: /* ! 81: * If first is still true, no secondary zones were found ! 82: * therefore refreshes aren't needed and interupts are turned off ! 83: * This needs to be changed when we have refreshes for co-masters ! 84: */ ! 85: if (!first) { ! 86: bzero((char *)&ival, sizeof (ival)); ! 87: ival.it_value.tv_sec = next_refresh - now; ! 88: if (ival.it_value.tv_sec < 0) ! 89: ival.it_value.tv_sec = 60; ! 90: (void) setitimer(ITIMER_REAL, &ival, (struct itimerval *)NULL); ! 91: #ifdef DEBUG ! 92: if (debug) ! 93: fprintf(ddt,"exit ns_maint() Next interupt in %d sec\n", ! 94: ival.it_value.tv_sec); ! 95: #endif ! 96: } ! 97: } ! 98: ! 99: zoneref(zp) ! 100: struct zoneinfo *zp; ! 101: { ! 102: register struct databuf *dp; ! 103: HEADER *hp; ! 104: u_short len; ! 105: u_long serial; ! 106: int s, n, l; ! 107: int cnt, soacnt, error = 0; ! 108: int zone = zp - zones; ! 109: char *cp; ! 110: char *tmp; ! 111: char *fname; ! 112: char buf[PACKETSZ]; ! 113: struct sockaddr_in sin; ! 114: struct zoneinfo zp_start, zp_finish; ! 115: struct databuf *pdp, *tdp; ! 116: struct namebuf *np; ! 117: struct hashbuf *htp; ! 118: struct itimerval ival; ! 119: struct itimerval zeroival; ! 120: extern struct sockaddr_in nsaddr; ! 121: extern int errno; ! 122: extern int read_interrupted; ! 123: extern int read_alarm(); ! 124: struct sigvec sv, osv; ! 125: ! 126: #ifdef DEBUG ! 127: if (debug) ! 128: fprintf(ddt,"zoneref()\n"); ! 129: #endif ! 130: bzero((char *)&zeroival, sizeof(zeroival)); ! 131: ival = zeroival; ! 132: ival.it_value.tv_sec = 30; ! 133: sv.sv_handler = read_alarm; ! 134: sv.sv_onstack = 0; ! 135: sv.sv_mask = ~0; ! 136: (void) sigvec(SIGALRM, &sv, &osv); ! 137: ! 138: for( cnt = 0; cnt < zp->z_addrcnt; cnt++) { ! 139: error = 0; ! 140: bzero((char *)&sin, sizeof(sin)); ! 141: sin.sin_family = AF_INET; ! 142: sin.sin_port = nsaddr.sin_port; ! 143: sin.sin_addr = zp->z_addr[cnt]; ! 144: if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) { ! 145: syslog(LOG_ERR, "zoneref: socket: %m"); ! 146: exit(1); ! 147: } ! 148: #ifdef DEBUG ! 149: if (debug >= 2) { ! 150: fprintf(ddt,"connecting to server #%d %s, %d\n", ! 151: cnt+1, inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); ! 152: } ! 153: #endif ! 154: if (connect(s, &sin, sizeof(sin)) < 0) { ! 155: (void) close(s); ! 156: error++; ! 157: #ifdef DEBUG ! 158: if (debug >= 2) ! 159: fprintf(ddt,"connect failed\n"); ! 160: #endif ! 161: continue; ! 162: } ! 163: if ((n = res_mkquery(QUERY, zp->z_origin, C_IN, ! 164: T_SOA, (char *)NULL, 0, NULL, buf, sizeof(buf))) < 0) { ! 165: syslog(LOG_ERR, "zoneref: res_mkquery failed"); ! 166: (void) close(s); ! 167: (void) sigvec(SIGALRM, &osv, (struct sigvec *)0); ! 168: return; ! 169: } ! 170: /* ! 171: * Send length & message for zone transfer ! 172: */ ! 173: if (writemsg(s, buf, n) < 0) { ! 174: (void) close(s); ! 175: error++; ! 176: #ifdef DEBUG ! 177: if (debug >= 2) ! 178: fprintf(ddt,"writemsg failed\n"); ! 179: #endif ! 180: continue; ! 181: } ! 182: /* ! 183: * Get out your butterfly net and catch the SOA ! 184: */ ! 185: cp = buf; ! 186: l = sizeof(u_short); ! 187: read_interrupted = 0; ! 188: while (l > 0) { ! 189: (void) setitimer(ITIMER_REAL, &ival, ! 190: (struct itimerval *)NULL); ! 191: if ((n = recv(s, cp, l, 0)) > 0) { ! 192: cp += n; ! 193: l -= n; ! 194: } else { ! 195: if (errno == EINTR && !read_interrupted) ! 196: continue; ! 197: error++; ! 198: break; ! 199: } ! 200: } ! 201: (void) setitimer(ITIMER_REAL, &zeroival, ! 202: (struct itimerval *)NULL); ! 203: if (error) { ! 204: (void) close(s); ! 205: continue; ! 206: } ! 207: if ((len = htons(*(u_short *)buf)) == 0) { ! 208: (void) close(s); ! 209: continue; ! 210: } ! 211: l = len; ! 212: cp = buf; ! 213: while (l > 0) { ! 214: (void) setitimer(ITIMER_REAL, &ival, ! 215: (struct itimerval *)NULL); ! 216: if ((n = recv(s, cp, l, 0)) > 0) { ! 217: cp += n; ! 218: l -= n; ! 219: } else { ! 220: if (errno == EINTR && !read_interrupted) ! 221: continue; ! 222: error++; ! 223: break; ! 224: } ! 225: } ! 226: (void) setitimer(ITIMER_REAL, &zeroival, ! 227: (struct itimerval *)NULL); ! 228: if (error) { ! 229: (void) close(s); ! 230: continue; ! 231: } ! 232: #ifdef DEBUG ! 233: if (debug >= 3) { ! 234: fprintf(ddt,"len = %d\n", len); ! 235: fp_query(buf, ddt); ! 236: } ! 237: #endif DEBUG ! 238: zp_start = *zp; ! 239: tmp = buf + sizeof(HEADER); ! 240: tmp += dn_skip(tmp) + QFIXEDSZ; ! 241: tmp += dn_skip(tmp); ! 242: soa_zinfo(&zp_start, tmp); ! 243: if (zp->z_serial >= zp_start.z_serial) { ! 244: (void) close(s); ! 245: (void) sigvec(SIGALRM, &osv, (struct sigvec *)0); ! 246: return; ! 247: } ! 248: zp_finish = *zp; ! 249: hp = (HEADER *) buf; ! 250: soacnt = 0; ! 251: for(;;) { ! 252: if (soacnt == 0) { ! 253: if ((n = res_mkquery(QUERY, zp->z_origin, C_IN, ! 254: T_AXFR, (char *)NULL, 0, NULL, ! 255: buf, sizeof(buf))) < 0) { ! 256: syslog(LOG_ERR, "zoneref: res_mkquery failed"); ! 257: (void) close(s); ! 258: (void) sigvec(SIGALRM, &osv, ! 259: (struct sigvec *)0); ! 260: return; ! 261: } ! 262: /* ! 263: * Send length & message for zone transfer ! 264: */ ! 265: if (writemsg(s, buf, n) < 0) { ! 266: (void) close(s); ! 267: error++; ! 268: #ifdef DEBUG ! 269: if (debug >= 2) ! 270: fprintf(ddt,"writemsg failed\n"); ! 271: #endif ! 272: break; ! 273: } ! 274: } ! 275: /* ! 276: * Receive length & response ! 277: */ ! 278: cp = buf; ! 279: l = sizeof(u_short); ! 280: while (l > 0) { ! 281: (void) setitimer(ITIMER_REAL, &ival, ! 282: (struct itimerval *)NULL); ! 283: if ((n = recv(s, cp, l, 0)) > 0) { ! 284: cp += n; ! 285: l -= n; ! 286: } else { ! 287: if (errno == EINTR && !read_interrupted) ! 288: continue; ! 289: error++; ! 290: break; ! 291: } ! 292: } ! 293: (void) setitimer(ITIMER_REAL, &zeroival, ! 294: (struct itimerval *)NULL); ! 295: if (error) ! 296: break; ! 297: if ((len = htons(*(u_short *)buf)) == 0) ! 298: break; ! 299: l = len; ! 300: cp = buf; ! 301: while (l > 0) { ! 302: (void) setitimer(ITIMER_REAL, &ival, ! 303: (struct itimerval *)NULL); ! 304: if ((n = recv(s, cp, l, 0)) > 0) { ! 305: cp += n; ! 306: l -= n; ! 307: } else { ! 308: if (errno == EINTR && !read_interrupted) ! 309: continue; ! 310: error++; ! 311: break; ! 312: } ! 313: } ! 314: (void) setitimer(ITIMER_REAL, &zeroival, ! 315: (struct itimerval *)NULL); ! 316: if (error) ! 317: break; ! 318: #ifdef DEBUG ! 319: if (debug >= 3) { ! 320: fprintf(ddt,"len = %d\n", len); ! 321: fp_query(buf, ddt); ! 322: } ! 323: #endif ! 324: cp = buf + sizeof(HEADER); ! 325: if (hp->qdcount) ! 326: cp += dn_skip(cp) + QFIXEDSZ; ! 327: tmp = cp + dn_skip(cp); ! 328: n = doupdate(buf, sizeof(buf), cp, zone, 0); ! 329: if ((cp - buf) + n != len) { ! 330: #ifdef DEBUG ! 331: if (debug) ! 332: fprintf(ddt,"zoneref: doupdate failed (%d, %d)\n", ! 333: cp - buf, n); ! 334: #endif ! 335: error++; ! 336: break; ! 337: } ! 338: if ((getshort(tmp)) == T_SOA) { ! 339: if (soacnt == 0) { ! 340: soacnt++; ! 341: tmp += 3 * sizeof(u_short) ! 342: + sizeof(u_long); ! 343: tmp += dn_skip(tmp); ! 344: tmp += dn_skip(tmp); ! 345: serial = getlong(tmp); ! 346: continue; ! 347: } ! 348: soa_zinfo(zp, tmp); ! 349: if (serial != zp->z_serial) ! 350: soacnt = 0; ! 351: else { ! 352: break; ! 353: } ! 354: } ! 355: } ! 356: (void) close(s); ! 357: if ( error == 0) { ! 358: htp = hashtab; ! 359: np = nlookup(zp->z_origin, &htp, &fname, 0); ! 360: if (np == NULL || fname != zp->z_origin) { ! 361: (void) sigvec(SIGALRM, &osv, (struct sigvec *)0); ! 362: return; ! 363: } ! 364: pdp = NULL; ! 365: dp = np->n_data; ! 366: while (dp != NULL) { ! 367: if (!match(dp, C_ANY, T_SOA)) { ! 368: pdp = dp; ! 369: dp = dp->d_next; ! 370: continue; ! 371: } ! 372: /* find serial number */ ! 373: cp = dp->d_data; ! 374: cp += strlen(cp) + 1; /* origin */ ! 375: cp += strlen(cp) + 1; /* address */ ! 376: serial = getlong(cp); ! 377: #ifdef DEBUG ! 378: if (debug >= 2) ! 379: fprintf(ddt,"Found serial = %d\n",serial); ! 380: #endif ! 381: ! 382: /* remove data if not = current serial number */ ! 383: if (serial != zp->z_serial) { ! 384: #ifdef DEBUG ! 385: if (debug >= 2) ! 386: fprintf(ddt,"deleting SOA serial #%d\n", ! 387: serial); ! 388: #endif ! 389: tdp = dp->d_next; ! 390: free((char *)dp); ! 391: dp = tdp; ! 392: if (pdp == NULL) ! 393: np->n_data = dp; ! 394: else ! 395: pdp->d_next = dp; ! 396: continue; ! 397: } ! 398: pdp = dp; ! 399: dp = dp->d_next; ! 400: } ! 401: (void) sigvec(SIGALRM, &osv, (struct sigvec *)0); ! 402: return; ! 403: } ! 404: #ifdef DEBUG ! 405: if (debug >= 2) ! 406: fprintf(ddt,"error reciving zone transfer\n"); ! 407: #endif ! 408: } ! 409: (void) sigvec(SIGALRM, &osv, (struct sigvec *)0); ! 410: /* ! 411: * Freedom at last!! ! 412: * ! 413: * The land where all repressed slaves dream of. ! 414: * ! 415: * Can't find a master to talk to. ! 416: * syslog it and hope we can find a master during maintenance ! 417: */ ! 418: if (error) ! 419: syslog(LOG_ERR, "zoneref: Can't find Master for secondary zone %s", ! 420: zp->z_origin); ! 421: zp->z_refresh = zp->z_retry; ! 422: if (gettimeofday(&tt, (struct timezone *)0) < 0) ! 423: syslog(LOG_ERR, "gettimeofday failed: %m"); ! 424: zp->z_time = tt.tv_sec + zp->z_retry; ! 425: return; ! 426: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.