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: }