|
|
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_maint.c 4.24 (Berkeley) 6/18/88";
20: #endif /* not lint */
21:
22: #include <sys/param.h>
23: #include <sys/socket.h>
24: #include <sys/time.h>
25: #if defined(SYSV)
26: #include <unistd.h>
27: #endif SYSV
28: #include <netinet/in.h>
29: #include <stdio.h>
30: #include <syslog.h>
31: #include <signal.h>
32: #include <errno.h>
33: #include <arpa/nameser.h>
34: #include "ns.h"
35: #include "db.h"
36:
37: extern int errno;
38: extern int maint_interval;
39:
40:
41: /*
42: * Invoked at regular intervals by signal interrupt; refresh all secondary
43: * zones from primary name server and remove old cache entries. Also,
44: * ifdef'd ALLOW_UPDATES, dump database if it has changed since last
45: * dump/bootup.
46: */
47: ns_maint()
48: {
49: register struct zoneinfo *zp;
50: struct itimerval ival;
51: time_t next_refresh = 0;
52: int zonenum;
53:
54: #ifdef DEBUG
55: if (debug)
56: fprintf(ddt,"ns_maint()\n");
57: #endif
58:
59: for (zp = zones, zonenum = 0; zp < &zones[nzones]; zp++, zonenum++) {
60: switch(zp->z_type) {
61: #ifdef ALLOW_UPDATES
62: case Z_PRIMARY:
63: #endif ALLOW_UPDATES
64: case Z_SECONDARY:
65: case Z_CACHE:
66: break;
67:
68: default:
69: continue;
70: }
71: gettime(&tt);
72: #ifdef DEBUG
73: if (debug >= 2)
74: printzoneinfo(zonenum);
75: #endif
76: if (tt.tv_sec >= zp->z_time && zp->z_refresh > 0) {
77: if (zp->z_type == Z_CACHE)
78: doachkpt();
79: if (zp->z_type == Z_SECONDARY)
80: zoneref(zp);
81: #ifdef ALLOW_UPDATES
82: /*
83: * Checkpoint the zone if it has changed
84: * since we last checkpointed
85: */
86: if (zp->z_type == Z_PRIMARY && zp->hasChanged)
87: zonedump(zp);
88: #endif ALLOW_UPDATES
89: zp->z_time = tt.tv_sec + zp->z_refresh;
90: }
91:
92: /*
93: * Find when the next refresh needs to be and set
94: * interrupt time accordingly.
95: */
96: if (next_refresh == 0 ||
97: (zp->z_time != 0 && next_refresh > zp->z_time))
98: next_refresh = zp->z_time;
99: }
100:
101: /*
102: * Schedule the next call to this function.
103: * Don't visit any sooner than maint_interval.
104: */
105: bzero((char *)&ival, sizeof (ival));
106: ival.it_value.tv_sec = next_refresh - tt.tv_sec;
107: if (ival.it_value.tv_sec < maint_interval)
108: ival.it_value.tv_sec = maint_interval;
109: (void) setitimer(ITIMER_REAL, &ival, (struct itimerval *)NULL);
110: #ifdef DEBUG
111: if (debug)
112: fprintf(ddt,"exit ns_maint() Next interrupt in %d sec\n",
113: ival.it_value.tv_sec);
114: #endif
115: }
116:
117: zoneref(zp)
118: struct zoneinfo *zp;
119: {
120: HEADER *hp;
121: u_short len;
122: u_long serial;
123: int s, n, l, tries;
124: int cnt, soacnt, error = 0;
125: int zone = zp - zones;
126: u_char *cp, *nmp, *eom;
127: u_char *tmp;
128: u_char buf[PACKETSZ];
129: char name[MAXDNAME], name2[MAXDNAME];
130: struct sockaddr_in sin;
131: struct zoneinfo zp_start, zp_finish;
132: struct itimerval ival;
133: struct itimerval zeroival;
134: extern struct sockaddr_in nsaddr;
135: extern int errno;
136: extern int read_interrupted;
137: extern int read_alarm();
138: struct sigvec sv, osv;
139:
140: #ifdef DEBUG
141: if (debug)
142: fprintf(ddt,"zoneref() %s\n", zp->z_origin);
143: #endif
144: bzero((char *)&zeroival, sizeof(zeroival));
145: ival = zeroival;
146: ival.it_value.tv_sec = 30;
147: sv.sv_handler = read_alarm;
148: sv.sv_onstack = 0;
149: sv.sv_mask = ~0;
150: (void) sigvec(SIGALRM, &sv, &osv);
151:
152: for( cnt = 0; cnt < zp->z_addrcnt; cnt++) {
153: error = 0;
154: bzero((char *)&sin, sizeof(sin));
155: sin.sin_family = AF_INET;
156: sin.sin_port = nsaddr.sin_port;
157: sin.sin_addr = zp->z_addr[cnt];
158: if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
159: syslog(LOG_ERR, "zoneref: socket: %m");
160: error++;
161: break;
162: }
163: #ifdef DEBUG
164: if (debug >= 2) {
165: fprintf(ddt,"connecting to server #%d %s, %d\n",
166: cnt+1, inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
167: }
168: #endif
169: if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
170: (void) close(s);
171: error++;
172: #ifdef DEBUG
173: if (debug >= 2)
174: fprintf(ddt,"connect failed, errno %d\n", errno);
175: #endif
176: continue;
177: }
178: if ((n = res_mkquery(QUERY, zp->z_origin, C_IN,
179: T_SOA, (char *)NULL, 0, NULL, buf, sizeof(buf))) < 0) {
180: syslog(LOG_ERR, "zoneref: res_mkquery failed");
181: (void) close(s);
182: (void) sigvec(SIGALRM, &osv, (struct sigvec *)0);
183: return;
184: }
185: /*
186: * Send length & message for zone transfer
187: */
188: if (writemsg(s, buf, n) < 0) {
189: (void) close(s);
190: error++;
191: #ifdef DEBUG
192: if (debug >= 2)
193: fprintf(ddt,"writemsg failed\n");
194: #endif
195: continue;
196: }
197: /*
198: * Get out your butterfly net and catch the SOA
199: */
200: cp = buf;
201: l = sizeof(u_short);
202: read_interrupted = 0;
203: while (l > 0) {
204: (void) setitimer(ITIMER_REAL, &ival,
205: (struct itimerval *)NULL);
206: if ((n = recv(s, cp, l, 0)) > 0) {
207: cp += n;
208: l -= n;
209: } else {
210: if (errno == EINTR && !read_interrupted)
211: continue;
212: error++;
213: break;
214: }
215: }
216: (void) setitimer(ITIMER_REAL, &zeroival,
217: (struct itimerval *)NULL);
218: if (error) {
219: (void) close(s);
220: continue;
221: }
222: if ((len = htons(*(u_short *)buf)) == 0) {
223: (void) close(s);
224: if (zp->z_sysloged == 0)
225: syslog(LOG_ERR,
226: "no SOA from server %s, zone %s (len 0)\n",
227: inet_ntoa(sin.sin_addr), zp->z_origin);
228: continue;
229: }
230: l = len;
231: cp = buf;
232: while (l > 0) {
233: (void) setitimer(ITIMER_REAL, &ival,
234: (struct itimerval *)NULL);
235: if ((n = recv(s, cp, l, 0)) > 0) {
236: cp += n;
237: l -= n;
238: } else {
239: if (errno == EINTR && !read_interrupted)
240: continue;
241: error++;
242: break;
243: }
244: }
245: (void) setitimer(ITIMER_REAL, &zeroival,
246: (struct itimerval *)NULL);
247: if (error) {
248: (void) close(s);
249: continue;
250: }
251: #ifdef DEBUG
252: if (debug >= 3) {
253: fprintf(ddt,"len = %d\n", len);
254: fp_query(buf, ddt);
255: }
256: #endif DEBUG
257: zp_start = *zp;
258: tmp = buf + sizeof(HEADER);
259: eom = buf + len;
260: /* NEED TO CHECK MESSAGE LENGTH, ANCOUNT, AA */
261: tmp += dn_skipname(tmp, eom) + QFIXEDSZ;
262: tmp += dn_skipname(tmp, eom);
263: soa_zinfo(&zp_start, tmp, eom);
264: if (zp->z_serial >= zp_start.z_serial && zp->z_auth) {
265: #ifdef DEBUG
266: if (debug)
267: fprintf(ddt,"zoneref: up to date (%d >= %d)\n",
268: zp->z_serial, zp_start.z_serial);
269: #endif DEBUG
270: zp->z_lastupdate = tt.tv_sec;
271: zp->z_refresh = zp_start.z_refresh;
272: (void) close(s);
273: (void) sigvec(SIGALRM, &osv, (struct sigvec *)0);
274: if (zp->z_source) {
275: #if defined(SYSV)
276: struct utimbuf t;
277:
278: t.actime = t.modtime = tt.tv_sec;
279: (void) utime(zp->z_source, &t);
280: #else
281: struct timeval t[2];
282:
283: t[0] = tt;
284: t[1] = tt;
285: (void) utimes(zp->z_source, t);
286: #endif /* SYSV */
287: }
288: return;
289: }
290: #ifdef DEBUG
291: if (debug)
292: fprintf(ddt,"zoneref: need xfer (%d < %d)\n",
293: zp->z_serial, zp_start.z_serial);
294: #endif DEBUG
295: hp = (HEADER *) buf;
296: soacnt = 0;
297: /* mark all existing RR's for zone as "old" */
298: mark_zone (hashtab, zone, 1);
299: for (tries = 0; ; tries++) {
300: if (soacnt == 0) {
301: /* delete unmarked (new) RR's for zone */
302: if (tries)
303: clean_zone (hashtab, zone, 0);
304: if ((n = res_mkquery(QUERY, zp->z_origin, C_IN,
305: T_AXFR, (char *)NULL, 0, NULL,
306: buf, sizeof(buf))) < 0) {
307: syslog(LOG_ERR, "zoneref: res_mkquery failed");
308: (void) close(s);
309: (void) sigvec(SIGALRM, &osv,
310: (struct sigvec *)0);
311: return;
312: }
313: /*
314: * Send length & message for zone transfer
315: */
316: if (writemsg(s, buf, n) < 0) {
317: (void) close(s);
318: error++;
319: #ifdef DEBUG
320: if (debug >= 2)
321: fprintf(ddt,"writemsg failed\n");
322: #endif
323: break;
324: }
325: }
326: /*
327: * Receive length & response
328: */
329: cp = buf;
330: l = sizeof(u_short);
331: while (l > 0) {
332: (void) setitimer(ITIMER_REAL, &ival,
333: (struct itimerval *)NULL);
334: if ((n = recv(s, cp, l, 0)) > 0) {
335: cp += n;
336: l -= n;
337: } else {
338: if (errno == EINTR && !read_interrupted)
339: continue;
340: error++;
341: break;
342: }
343: }
344: (void) setitimer(ITIMER_REAL, &zeroival,
345: (struct itimerval *)NULL);
346: if (error)
347: break;
348: if ((len = htons(*(u_short *)buf)) == 0)
349: break;
350: l = len;
351: cp = buf;
352: eom = buf + len;
353: while (l > 0) {
354: (void) setitimer(ITIMER_REAL, &ival,
355: (struct itimerval *)NULL);
356: if ((n = recv(s, cp, l, 0)) > 0) {
357: cp += n;
358: l -= n;
359: } else {
360: if (errno == EINTR && !read_interrupted)
361: continue;
362: error++;
363: break;
364: }
365: }
366: (void) setitimer(ITIMER_REAL, &zeroival,
367: (struct itimerval *)NULL);
368: if (error)
369: break;
370: #ifdef DEBUG
371: if (debug >= 3) {
372: fprintf(ddt,"len = %d\n", len);
373: fp_query(buf, ddt);
374: }
375: #endif
376: cp = buf + sizeof(HEADER);
377: if (hp->qdcount)
378: cp += dn_skipname(cp, eom) + QFIXEDSZ;
379: nmp = cp;
380: tmp = cp + dn_skipname(cp, eom);
381: n = doupdate(buf, sizeof(buf), cp, zone,
382: (struct databuf **)0, DB_NODATA);
383: if (cp + n != eom) {
384: #ifdef DEBUG
385: if (debug)
386: fprintf(ddt,"zoneref: doupdate failed (%d, %d)\n",
387: cp - buf, n);
388: #endif
389: error++;
390: break;
391: }
392: GETSHORT(n, tmp);
393: if (n == T_SOA) {
394: if (soacnt == 0) {
395: soacnt++;
396: dn_expand(buf, buf + 512, nmp, name,
397: sizeof(name));
398: tmp += 2 * sizeof(u_short)
399: + sizeof(u_long);
400: tmp += dn_skipname(tmp, eom);
401: tmp += dn_skipname(tmp, eom);
402: GETLONG(serial, tmp);
403: #ifdef DEBUG
404: if (debug)
405: fprintf(ddt,
406: "first SOA for %s, serial %d\n",
407: name, serial);
408: #endif DEBUG
409: continue;
410: }
411: dn_expand(buf, buf + 512, nmp, name2,
412: sizeof(name2));
413: if (strcasecmp(name, name2) !=0) {
414: #ifdef DEBUG
415: if (debug)
416: fprintf(ddt,
417: "extraneous SOA for %s\n",
418: name2);
419: #endif DEBUG
420: continue;
421: }
422: tmp -= sizeof(u_short);
423: soa_zinfo(&zp_finish, tmp, eom);
424: #ifdef DEBUG
425: if (debug)
426: fprintf(ddt,
427: "SOA, serial %d\n", zp_finish.z_serial);
428: #endif DEBUG
429: if (serial != zp_finish.z_serial) {
430: soacnt = 0;
431: #ifdef DEBUG
432: if (debug)
433: fprintf(ddt,
434: "serial changed, restart\n");
435: #endif DEBUG
436: } else
437: break;
438: }
439: }
440: (void) close(s);
441: if ( error == 0) {
442: zp->z_refresh = zp_finish.z_refresh;
443: zp->z_retry = zp_finish.z_retry;
444: zp->z_expire = zp_finish.z_expire;
445: zp->z_minimum = zp_finish.z_minimum;
446: zp->z_serial = zp_finish.z_serial;
447: zp->z_lastupdate = tt.tv_sec;
448: zp->z_sysloged = 0;
449: zp->z_auth = 1;
450: /* delete previously marked RR's here, then dump */
451: clean_zone (hashtab, zone, 1);
452: zonedump(zp);
453: (void) sigvec(SIGALRM, &osv, (struct sigvec *)0);
454: return;
455: }
456: /* error: delete unmarked RR's here; remove old marks */
457: clean_zone (hashtab, zone, 0);
458: mark_zone (hashtab, zone, 0);
459: #ifdef DEBUG
460: if (debug >= 2)
461: fprintf(ddt,"error receiving zone transfer\n");
462: #endif
463: }
464: (void) sigvec(SIGALRM, &osv, (struct sigvec *)0);
465: /*
466: * Freedom at last!!
467: *
468: * The land where all repressed slaves dream of.
469: *
470: * Can't find a master to talk to.
471: * syslog it and hope we can find a master during next maintenance.
472: */
473: if (error && (!zp->z_sysloged)) {
474: syslog(LOG_WARNING,
475: "zoneref: Masters for secondary zone %s unreachable",
476: zp->z_origin);
477: zp->z_sysloged++;
478: }
479: zp->z_refresh = zp->z_retry;
480: if (tt.tv_sec - zp->z_lastupdate > zp->z_expire)
481: zp->z_auth = 0;
482: }
483:
484: #ifdef unused
485: /*
486: * Recursively delete all domains (except for root SOA records),
487: * starting from head of list pointed to by np.
488: */
489: static DelDom(fnp, isroot)
490: struct namebuf *fnp;
491: int isroot;
492: {
493: register struct databuf *dp, *pdp = NULL;
494: register struct namebuf *np = fnp;
495: struct namebuf **npp, **nppend;
496:
497: #ifdef DEBUG
498: if (debug >= 3)
499: fprintf(ddt, "DelDom('%s', %d)\n", fnp->n_dname, isroot);
500: #endif DEBUG
501:
502: /* first do data records */
503: for (dp = np->n_data; dp != NULL; ) {
504: /* skip the root SOA record (marks end of data) */
505: if (isroot && dp->d_type == T_SOA) {
506: pdp = dp;
507: dp = dp->d_next;
508: continue;
509: }
510: dp = rm_datum(dp, np, pdp);
511: }
512:
513: /* next do subdomains */
514: if (np->n_hash == NULL)
515: return;
516: npp = np->n_hash->h_tab;
517: nppend = npp + np->n_hash->h_size;
518: while (npp < nppend) {
519: for (np = *npp++; np != NULL; np = np->n_next) {
520: DelDom(np, 0);
521: }
522: }
523: }
524: #endif unused
525:
526: #ifdef DEBUG
527: printzoneinfo(zonenum)
528: int zonenum;
529: {
530: struct timeval tt;
531: struct zoneinfo *zp = &zones[zonenum];
532: char *ZoneType;
533:
534: if (!debug)
535: return; /* Else fprintf to ddt will bomb */
536: fprintf(ddt, "printzoneinfo(%d):\n", zonenum);
537:
538: gettime(&tt);
539: switch (zp->z_type) {
540: case Z_PRIMARY: ZoneType = "Primary"; break;
541: case Z_SECONDARY: ZoneType = "Secondary"; break;
542: case Z_CACHE: ZoneType = "Cache"; break;
543: default: ZoneType = "Unknown";
544: }
545: if (zp->z_origin[0] == '\0')
546: fprintf(ddt,"origin ='.'");
547: else
548: fprintf(ddt,"origin ='%s'", zp->z_origin);
549: fprintf(ddt,", type = %s", ZoneType);
550: fprintf(ddt,", source = %s\n", zp->z_source);
551: fprintf(ddt,"z_refresh = %ld", zp->z_refresh);
552: fprintf(ddt,", retry = %ld", zp->z_retry);
553: fprintf(ddt,", expire = %ld", zp->z_expire);
554: fprintf(ddt,", minimum = %ld", zp->z_minimum);
555: fprintf(ddt,", serial = %ld\n", zp->z_serial);
556: fprintf(ddt,"z_time = %d", zp->z_time);
557: fprintf(ddt,", now time : %d sec", tt.tv_sec);
558: fprintf(ddt,", time left: %d sec\n", zp->z_time - tt.tv_sec);
559: }
560: #endif DEBUG
561:
562: /*
563: * New code added by Rich Wales (UCLA), October 1986:
564: *
565: * The following routines manipulate the d_mark field. When a zone
566: * is being refreshed, the old RR's are marked. This allows old RR's to
567: * be cleaned up after the new copy of the zone has been completely read
568: * -- or new RR's to be cleaned up if an error prevents transfer of a
569: * new zone copy.
570: *
571: */
572:
573: /*
574: * Set the "d_mark" field to on each RR in the zone "zone".
575: * Initially called with "htp" equal to "hashtab", this routine
576: * calls itself recursively in order to traverse all subdomains.
577: */
578: mark_zone (htp, zone, flag)
579: struct hashbuf *htp;
580: register int zone;
581: register int flag;
582: {
583: register struct databuf *dp;
584: register struct namebuf *np;
585: register struct namebuf **npp, **nppend;
586:
587: nppend = htp->h_tab + htp->h_size;
588: for (npp = htp->h_tab; npp < nppend; npp++) {
589: for (np = *npp; np != NULL; np = np->n_next) {
590: for (dp = np->n_data; dp != NULL; dp = dp->d_next)
591: if (dp->d_zone == zone)
592: dp->d_mark = flag;
593: if (np->n_hash != NULL) /* mark subdomains */
594: mark_zone (np->n_hash, zone, flag);
595: }
596: }
597: }
598:
599: /*
600: * clean_zone (htp, zone, flag) --
601: * Delete all RR's in the zone "zone" whose "d_mark" values are
602: * equal to "flag". Originally called with "htp" equal to
603: * "hashtab", this routine calls itself recursively in order to
604: * traverse all subdomains.
605: */
606: clean_zone (htp, zone, flag)
607: register struct hashbuf *htp;
608: register int zone;
609: register int flag;
610: {
611: register struct databuf *dp, *pdp;
612: register struct namebuf *np;
613: struct namebuf **npp, **nppend;
614:
615: nppend = htp->h_tab + htp->h_size;
616: for (npp = htp->h_tab; npp < nppend; npp++) {
617: for (np = *npp; np != NULL; np = np->n_next) {
618: for (pdp = NULL, dp = np->n_data; dp != NULL; ) {
619: if (dp->d_zone == zone && dp->d_mark == flag)
620: dp = rm_datum(dp, np, pdp);
621: else {
622: pdp = dp;
623: dp = dp->d_next;
624: }
625: }
626: /* Call recursively to clean up subdomains. */
627: if (np->n_hash != NULL)
628: clean_zone (np->n_hash, zone, flag);
629: }
630: }
631: }
632:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.