|
|
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.