|
|
1.1 root 1: /*
2: * Copyright (c) 1986, 1988 Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms are permitted provided
6: * that: (1) source distributions retain this entire copyright notice and
7: * comment, and (2) distributions including binaries display the following
8: * acknowledgement: ``This product includes software developed by the
9: * University of California, Berkeley and its contributors'' in the
10: * documentation or other materials provided with the distribution and in
11: * all advertising materials mentioning features or use of this software.
12: * Neither the name of the University nor the names of its contributors may
13: * be used to endorse or promote products derived from this software without
14: * specific prior written permission.
15: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
16: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
17: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
18: */
19:
20: #ifndef lint
21: static char sccsid[] = "@(#)ns_maint.c 4.37 (Berkeley) 6/1/90";
22: #endif /* not lint */
23:
24: #include <sys/param.h>
25: #include <sys/socket.h>
26: #include <sys/time.h>
27: #if defined(SYSV)
28: #include <unistd.h>
29: #endif SYSV
30: #include <netinet/in.h>
31: #include <stdio.h>
32: #include <syslog.h>
33: #include <signal.h>
34: #include <errno.h>
35: #include <arpa/nameser.h>
36: #include <sys/wait.h>
37: #include "ns.h"
38: #include "db.h"
39: #include "pathnames.h"
40:
41: extern int errno;
42: extern int maint_interval;
43: extern int needzoneload;
44: extern u_short ns_port;
45: extern char *ctime();
46:
47: int xfers_running; /* number of xfers running */
48: int xfers_deferred; /* number of needed xfers not run yet */
49: static int alarm_pending;
50:
51:
52: /*
53: * Invoked at regular intervals by signal interrupt; refresh all secondary
54: * zones from primary name server and remove old cache entries. Also,
55: * ifdef'd ALLOW_UPDATES, dump database if it has changed since last
56: * dump/bootup.
57: */
58: ns_maint()
59: {
60: register struct zoneinfo *zp;
61: struct itimerval ival;
62: time_t next_refresh = 0;
63: int zonenum;
64:
65: gettime(&tt);
66:
67: #ifdef DEBUG
68: if (debug)
69: fprintf(ddt,"\nns_maint(); now %s", ctime(&tt.tv_sec));
70: #endif
71:
72: xfers_deferred = 0;
73: alarm_pending = 0;
74: for (zp = zones, zonenum = 0; zp < &zones[nzones]; zp++, zonenum++) {
75: #ifdef DEBUG
76: if (debug >= 2)
77: printzoneinfo(zonenum);
78: #endif
79: if (tt.tv_sec >= zp->z_time && zp->z_refresh > 0) {
80: /*
81: * Set default time for next action first,
82: * so that it can be changed later if necessary.
83: */
84: zp->z_time = tt.tv_sec + zp->z_refresh;
85:
86: switch (zp->z_type) {
87:
88: case Z_CACHE:
89: doachkpt();
90: break;
91:
92: case Z_SECONDARY:
93: if ((zp->z_state & Z_NEED_RELOAD) == 0) {
94: if (zp->z_state & Z_XFER_RUNNING)
95: abortxfer(zp);
96: else if (xfers_running < MAX_XFERS_RUNNING)
97: startxfer(zp);
98: else {
99: zp->z_state |= Z_NEED_XFER;
100: ++xfers_deferred;
101: #ifdef DEBUG
102: if (debug > 1)
103: fprintf(ddt,
104: "xfer deferred for %s\n",
105: zp->z_origin);
106: #endif
107: }
108: }
109: break;
110: #ifdef ALLOW_UPDATES
111: case Z_PRIMARY:
112: /*
113: * Checkpoint the zone if it has changed
114: * since we last checkpointed
115: */
116: if (zp->hasChanged)
117: zonedump(zp);
118: break;
119: #endif ALLOW_UPDATES
120: }
121: gettime(&tt);
122: }
123: }
124: sched_maint();
125: #ifdef DEBUG
126: if (debug)
127: fprintf(ddt,"exit ns_maint()\n");
128: #endif
129: }
130:
131: /*
132: * Find when the next refresh needs to be and set
133: * interrupt time accordingly.
134: */
135: sched_maint()
136: {
137: register struct zoneinfo *zp;
138: struct itimerval ival;
139: time_t next_refresh = 0;
140: static time_t next_alarm;
141:
142: for (zp = zones; zp < &zones[nzones]; zp++)
143: if (zp->z_time != 0 &&
144: (next_refresh == 0 || next_refresh > zp->z_time))
145: next_refresh = zp->z_time;
146: /*
147: * Schedule the next call to ns_maint.
148: * Don't visit any sooner than maint_interval.
149: */
150: bzero((char *)&ival, sizeof (ival));
151: if (next_refresh != 0) {
152: if (next_refresh == next_alarm && alarm_pending) {
153: #ifdef DEBUG
154: if (debug)
155: fprintf(ddt,"sched_maint: no schedule change\n");
156: #endif
157: return;
158: }
159: ival.it_value.tv_sec = next_refresh - tt.tv_sec;
160: if (ival.it_value.tv_sec < maint_interval)
161: ival.it_value.tv_sec = maint_interval;
162: next_alarm = next_refresh;
163: alarm_pending = 1;
164: }
165: (void) setitimer(ITIMER_REAL, &ival, (struct itimerval *)NULL);
166: #ifdef DEBUG
167: if (debug)
168: fprintf(ddt,"sched_maint: Next interrupt in %d sec\n",
169: ival.it_value.tv_sec);
170: #endif
171: }
172:
173: /*
174: * Start an asynchronous zone transfer for a zone.
175: * Depends on current time being in tt.
176: * The caller must call sched_maint after startxfer.
177: */
178: startxfer(zp)
179: struct zoneinfo *zp;
180: {
181: static char *argv[NSMAX + 20], argv_ns[NSMAX][MAXDNAME];
182: int cnt, argc = 0, argc_ns = 0, pid, omask;
183: char debug_str[10];
184: char serial_str[10];
185: char port_str[10];
186:
187: #ifdef DEBUG
188: if (debug)
189: fprintf(ddt,"startxfer() %s\n", zp->z_origin);
190: #endif
191:
192: argv[argc++] = "named-xfer";
193: argv[argc++] = "-z";
194: argv[argc++] = zp->z_origin;
195: argv[argc++] = "-f";
196: argv[argc++] = zp->z_source;
197: argv[argc++] = "-s";
198: sprintf(serial_str, "%d", zp->z_serial);
199: argv[argc++] = serial_str;
200: if (zp->z_state & Z_SYSLOGGED)
201: argv[argc++] = "-q";
202: argv[argc++] = "-P";
203: sprintf(port_str, "%d", ns_port);
204: argv[argc++] = port_str;
205: #ifdef DEBUG
206: if (debug) {
207: argv[argc++] = "-d";
208: sprintf(debug_str, "%d", debug);
209: argv[argc++] = debug_str;
210: argv[argc++] = "-l";
211: argv[argc++] = "/usr/tmp/xfer.ddt";
212: if (debug > 5) {
213: argv[argc++] = "-t";
214: argv[argc++] = "/usr/tmp/xfer.trace";
215: }
216: }
217: #endif
218:
219: /*
220: * Copy the server ip addresses into argv, after converting
221: * to ascii and saving the static inet_ntoa result
222: */
223: for (cnt = 0; cnt < zp->z_addrcnt; cnt++)
224: argv[argc++] = strcpy(argv_ns[argc_ns++],
225: inet_ntoa(zp->z_addr[cnt]));
226:
227: argv[argc] = 0;
228:
229: #ifdef DEBUG
230: #ifdef ECHOARGS
231: if (debug) {
232: int i;
233: for (i = 0; i < argc; i++)
234: fprintf(ddt, "Arg %d=%s\n", i, argv[i]);
235: }
236: #endif /* ECHOARGS */
237: #endif /* DEBUG */
238:
239: #ifdef SYSV
240: #define vfork fork
241: #else
242: gettime(&tt);
243: omask = sigblock(sigmask(SIGCHLD));
244: #endif
245: if ((pid = vfork()) == -1) {
246: #ifdef DEBUG
247: if (debug)
248: fprintf(ddt, "xfer [v]fork: %d\n", errno);
249: #endif
250: syslog(LOG_ERR, "xfer [v]fork: %m");
251: #ifndef SYSV
252: (void) sigsetmask(omask);
253: #endif
254: zp->z_time = tt.tv_sec + 10;
255: return;
256: }
257:
258: if (pid) {
259: #ifdef DEBUG
260: if (debug)
261: fprintf(ddt, "started xfer child %d\n", pid);
262: #endif
263: zp->z_state &= ~Z_NEED_XFER;
264: zp->z_state |= Z_XFER_RUNNING;
265: zp->z_xferpid = pid;
266: xfers_running++;
267: zp->z_time = tt.tv_sec + MAX_XFER_TIME;
268: #ifndef SYSV
269: (void) sigsetmask(omask);
270: #endif
271: } else {
272: execve(_PATH_XFER, argv, NULL);
273: syslog(LOG_ERR, "can't exec %s: %m", _PATH_XFER);
274: _exit(XFER_FAIL); /* avoid duplicate buffer flushes */
275: }
276: }
277:
278: #ifdef DEBUG
279: printzoneinfo(zonenum)
280: int zonenum;
281: {
282: struct timeval tt;
283: struct zoneinfo *zp = &zones[zonenum];
284: char *ZoneType;
285:
286: if (!debug)
287: return; /* Else fprintf to ddt will bomb */
288: fprintf(ddt, "printzoneinfo(%d):\n", zonenum);
289:
290: gettime(&tt);
291: switch (zp->z_type) {
292: case Z_PRIMARY: ZoneType = "Primary"; break;
293: case Z_SECONDARY: ZoneType = "Secondary"; break;
294: case Z_CACHE: ZoneType = "Cache"; break;
295: default: ZoneType = "Unknown";
296: }
297: if (zp->z_origin[0] == '\0')
298: fprintf(ddt,"origin ='.'");
299: else
300: fprintf(ddt,"origin ='%s'", zp->z_origin);
301: fprintf(ddt,", type = %s", ZoneType);
302: fprintf(ddt,", source = %s\n", zp->z_source);
303: fprintf(ddt,"z_refresh = %ld", zp->z_refresh);
304: fprintf(ddt,", retry = %ld", zp->z_retry);
305: fprintf(ddt,", expire = %ld", zp->z_expire);
306: fprintf(ddt,", minimum = %ld", zp->z_minimum);
307: fprintf(ddt,", serial = %ld\n", zp->z_serial);
308: fprintf(ddt,"z_time = %d", zp->z_time);
309: if (zp->z_time) {
310: fprintf(ddt,", now time : %d sec", tt.tv_sec);
311: fprintf(ddt,", time left: %d sec", zp->z_time - tt.tv_sec);
312: }
313: fprintf(ddt,"; state %x\n", zp->z_state);
314: }
315: #endif DEBUG
316:
317: /*
318: * remove_zone (htp, zone) --
319: * Delete all RR's in the zone "zone" under specified hash table.
320: */
321: remove_zone(htp, zone)
322: register struct hashbuf *htp;
323: register int zone;
324: {
325: register struct databuf *dp, *pdp;
326: register struct namebuf *np;
327: struct namebuf **npp, **nppend;
328:
329: nppend = htp->h_tab + htp->h_size;
330: for (npp = htp->h_tab; npp < nppend; npp++)
331: for (np = *npp; np != NULL; np = np->n_next) {
332: for (pdp = NULL, dp = np->n_data; dp != NULL; ) {
333: if (dp->d_zone == zone)
334: dp = rm_datum(dp, np, pdp);
335: else {
336: pdp = dp;
337: dp = dp->d_next;
338: }
339: }
340: /* Call recursively to remove subdomains. */
341: if (np->n_hash)
342: remove_zone(np->n_hash, zone);
343: }
344: }
345:
346: /*
347: * Abort an xfer that has taken too long.
348: */
349: abortxfer(zp)
350: register struct zoneinfo *zp;
351: {
352:
353: kill(zp->z_xferpid, SIGKILL); /* don't trust it at all */
354: #ifdef DEBUG
355: if (debug)
356: fprintf(ddt, "Killed child %d (zone %s) due to timeout\n",
357: zp->z_xferpid, zp->z_origin);
358: #endif /* DEBUG */
359: zp->z_time = tt.tv_sec + zp->z_retry;
360: }
361:
362: #ifdef SYSV
363: union wait {
364: unsigned short w_termsig:7; /* termination signal */
365: unsigned short w_coredump:1; /* core dump indicator */
366: unsigned short w_retcode:8; /* exit code if w_termsig==0 */
367: };
368: #endif
369:
370: /*
371: * SIGCHLD signal handler: process exit of xfer's.
372: * (Note: also called when outgoing transfer completes.)
373: */
374: VOID
375: endxfer()
376: {
377: register struct zoneinfo *zp;
378: int pid, xfers = 0;
379: union wait status;
380:
381: gettime(&tt);
382: #if defined(SYSV)
383: { int stat;
384: pid = wait(&stat);
385: status.w_termsig = stat & 0x7f;
386: status.w_retcode = stat >> 8;
387: }
388: #else /* SYSV */
389: while ((pid = wait3(&status, WNOHANG, (struct rusage *)NULL)) > 0) {
390: #endif /* SYSV */
391: for (zp = zones; zp < &zones[nzones]; zp++)
392: if (zp->z_xferpid == pid) {
393: xfers++;
394: xfers_running--;
395: zp->z_xferpid = 0;
396: zp->z_state &= ~Z_XFER_RUNNING;
397: #ifdef DEBUG
398: if (debug)
399: fprintf(ddt,
400: "\nendxfer: child %d zone %s returned status=%d termsig=%d\n",
401: pid, zp->z_origin, status.w_retcode,
402: status.w_termsig);
403: #endif
404: if (status.w_termsig != 0) {
405: if (status.w_termsig != SIGKILL) {
406: syslog(LOG_ERR,
407: "named-xfer exited with signal %d\n",
408: status.w_termsig);
409: #ifdef DEBUG
410: if (debug)
411: fprintf(ddt,
412: "\tchild termination with signal %d\n",
413: status.w_termsig);
414: #endif
415: }
416: zp->z_time = tt.tv_sec + zp->z_retry;
417: } else switch (status.w_retcode) {
418: case XFER_UPTODATE:
419: zp->z_state &= ~Z_SYSLOGGED;
420: zp->z_lastupdate = tt.tv_sec;
421: zp->z_time = tt.tv_sec + zp->z_refresh;
422: /*
423: * Restore z_auth in case expired,
424: * but only if there were no errors
425: * in the zone file.
426: */
427: if ((zp->z_state & Z_DB_BAD) == 0)
428: zp->z_auth = 1;
429: if (zp->z_source) {
430: #if defined(SYSV)
431: struct utimbuf t;
432:
433: t.actime = tt.tv_sec;
434: t.modtime = tt.tv_sec;
435: (void) utime(zp->z_source, &t);
436: #else
437: struct timeval t[2];
438:
439: t[0] = tt;
440: t[1] = tt;
441: (void) utimes(zp->z_source, t);
442: #endif /* SYSV */
443: }
444: break;
445:
446: case XFER_SUCCESS:
447: zp->z_state |= Z_NEED_RELOAD;
448: zp->z_state &= ~Z_SYSLOGGED;
449: needzoneload++;
450: break;
451:
452: case XFER_TIMEOUT:
453: #ifdef DEBUG
454: if (debug) fprintf(ddt,
455: "zoneref: Masters for secondary zone %s unreachable\n",
456: zp->z_origin);
457: #endif
458: if ((zp->z_state & Z_SYSLOGGED) == 0) {
459: zp->z_state |= Z_SYSLOGGED;
460: syslog(LOG_WARNING,
461: "zoneref: Masters for secondary zone %s unreachable",
462: zp->z_origin);
463: }
464: zp->z_time = tt.tv_sec + zp->z_retry;
465: break;
466:
467: default:
468: if ((zp->z_state & Z_SYSLOGGED) == 0) {
469: zp->z_state |= Z_SYSLOGGED;
470: syslog(LOG_ERR,
471: "named-xfer exit code %d",
472: status.w_retcode);
473: }
474: /* FALLTHROUGH */
475: case XFER_FAIL:
476: zp->z_state |= Z_SYSLOGGED;
477: zp->z_time = tt.tv_sec + zp->z_retry;
478: break;
479: }
480: break;
481: }
482: #ifndef SYSV
483: }
484: #endif /* SYSV */
485: if (xfers) {
486: for (zp = zones;
487: xfers_deferred != 0 && xfers_running < MAX_XFERS_RUNNING &&
488: zp < &zones[nzones]; zp++)
489: if (zp->z_state & Z_NEED_XFER) {
490: xfers_deferred--;
491: startxfer(zp);
492: }
493: sched_maint();
494: }
495: #if defined(SYSV)
496: (void)signal(SIGCLD, endxfer);
497: #endif
498: }
499:
500: /*
501: * Reload zones whose transfers have completed.
502: */
503: loadxfer()
504: {
505: register struct zoneinfo *zp;
506:
507: gettime(&tt);
508: for (zp = zones; zp < &zones[nzones]; zp++)
509: if (zp->z_state & Z_NEED_RELOAD) {
510: #ifdef DEBUG
511: if (debug)
512: fprintf(ddt, "loadxfer() '%s'\n",
513: zp->z_origin[0] ? zp->z_origin : ".");
514: #endif
515: zp->z_state &= ~Z_NEED_RELOAD;
516: zp->z_auth = 0;
517: remove_zone(hashtab, zp - zones);
518: if (db_load(zp->z_source, zp->z_origin, zp, 0) == 0)
519: zp->z_auth = 1;
520: if (zp->z_state & Z_TMP_FILE)
521: (void) unlink(zp->z_source);
522: }
523: sched_maint();
524: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.