|
|
1.1 root 1: #ifndef lint
2: static char sccsid[] = "@(#)ns_init.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 <errno.h>
16: #include <signal.h>
17: #include <syslog.h>
18: #include <ctype.h>
19: #include <arpa/nameser.h>
20: #include "ns.h"
21: #include "db.h"
22:
23: struct zoneinfo zones[MAXZONES]; /* zone information */
24: int nzones; /* number of zones in use */
25:
26: /*
27: * Read boot file for configuration info.
28: */
29: ns_init(bootfile)
30: char *bootfile;
31: {
32: register struct zoneinfo *zp;
33: char buf[BUFSIZ];
34: char *tm;
35: FILE *fp;
36: int type, first = 1;
37: time_t next_refresh;
38: struct itimerval ival;
39:
40: #ifdef DEBUG
41: if (debug >= 3)
42: fprintf(ddt,"ns_init(%s)\n", bootfile);
43: #endif
44:
45: if ((fp = fopen(bootfile, "r")) == NULL) {
46: syslog(LOG_ERR, "%s: %m", bootfile);
47: exit(1);
48: }
49:
50: /* allocate root hash table */
51: hashtab = savehash((struct hashbuf *)NULL);
52:
53: /* init zone data */
54: nzones = 1; /* zone zero is cache data */
55: while (getword(buf, sizeof(buf), fp)) {
56: /* read 'primary', 'secondary', 'cache' or 'domain' */
57: top:
58: if (cistrcmp(buf, "cache") == 0) {
59: type = Z_CACHE;
60: zp = zones;
61: } else {
62: if (cistrcmp(buf, "primary") == 0)
63: type = Z_PRIMARY;
64: else if (cistrcmp(buf, "secondary") == 0)
65: type = Z_SECONDARY;
66: else if (cistrcmp(buf, "domain") == 0)
67: type = Z_DOMAIN;
68: else {
69: syslog(LOG_ERR, "%s: unknown type", buf);
70: exit(1);
71: }
72: if (nzones >= MAXZONES) {
73: syslog(LOG_ERR, "too many zones");
74: exit(1);
75: }
76: zp = &zones[nzones++];
77: }
78: zp->z_type = type;
79: zp->z_addrcnt = 0;
80: /*
81: * read zone origin
82: */
83: (void) getword(buf, sizeof(buf), fp);
84: if (buf[0] == '.')
85: buf[0] = '\0';
86: zp->z_origin = savestr(buf);
87: /*
88: * read source file or host address
89: */
90: if (type != Z_DOMAIN) {
91: (void) getword(buf, sizeof(buf), fp);
92: zp->z_source = savestr(buf);
93: #ifdef DEBUG
94: if (debug) {
95: fprintf(ddt,"zone found (%d): ", zp->z_type);
96: if (zp->z_origin[0] == '\0')
97: fprintf(ddt,"'.'");
98: else
99: fprintf(ddt,"'%s'", zp->z_origin);
100: fprintf(ddt,", source = %s", zp->z_source);
101: }
102: #endif
103: }
104: #ifdef DEBUG
105: else if (debug)
106: fprintf(ddt,"zone found (%d): domain name = '%s'",
107: zp->z_type, zp->z_origin);
108: #endif
109: switch (zp->z_type) {
110: case Z_PRIMARY:
111: case Z_CACHE:
112: #ifdef DEBUG
113: if (debug)
114: fprintf(ddt,"\n");
115: #endif
116: (void) db_load(zp->z_source, zp->z_origin, zp - zones);
117: break;
118:
119: case Z_SECONDARY:
120: zp->z_addr[zp->z_addrcnt].s_addr =
121: inet_addr(zp->z_source);
122: if (zp->z_addr[zp->z_addrcnt].s_addr != (unsigned)-1)
123: zp->z_addrcnt++;
124: while (getword(buf, sizeof(buf), fp)) {
125: tm = savestr(buf);
126: zp->z_addr[zp->z_addrcnt].s_addr =
127: inet_addr(tm);
128: if (zp->z_addr[zp->z_addrcnt].s_addr ==
129: (unsigned)-1) {
130: #ifdef DEBUG
131: if (debug)
132: fprintf(ddt," (addrcnt) = %d\n",
133: zp->z_addrcnt);
134: #endif
135: zoneinit(zp);
136: if (first) {
137: next_refresh = zp->z_time;
138: first = 0;
139: } else
140: if (next_refresh > zp->z_time)
141: next_refresh = zp->z_time;
142: goto top;
143: }
144: #ifdef DEBUG
145: if (debug)
146: fprintf(ddt,", %s",buf);
147: #endif
148: if (++zp->z_addrcnt >= MAXNS) {
149: zp->z_addrcnt = MAXNS;
150: #ifdef DEBUG
151: if (debug)
152: fprintf(ddt,
153: "\nns.h MAXNS reached\n");
154: #endif
155: break;
156: }
157: }
158: #ifdef DEBUG
159: if (debug)
160: fprintf(ddt," addrcnt = %d\n", zp->z_addrcnt);
161: #endif
162: zoneinit(zp);
163: if (first) {
164: next_refresh = zp->z_time;
165: first = 0;
166: } else
167: if (next_refresh > zp->z_time)
168: next_refresh = zp->z_time;
169: break;
170:
171: case Z_DOMAIN:
172: while (getword(buf, sizeof(buf), fp)) {
173: tm = savestr(buf);
174: zp->z_addr[zp->z_addrcnt].s_addr =
175: inet_addr(tm);
176: if (zp->z_addr[zp->z_addrcnt].s_addr ==
177: (unsigned)-1) {
178: #ifdef DEBUG
179: if (debug)
180: fprintf(ddt," addrcnt = %d\n",
181: zp->z_addrcnt);
182: #endif
183: goto top;
184: }
185: #ifdef DEBUG
186: if (debug)
187: fprintf(ddt,", %s",buf);
188: #endif
189: if (++zp->z_addrcnt >= MAXNS) {
190: zp->z_addrcnt = MAXNS;
191: #ifdef DEBUG
192: if (debug)
193: fprintf(ddt,"\nns.h MAXNS reached\n");
194: #endif
195: break;
196: }
197: }
198: #ifdef DEBUG
199: if (debug)
200: fprintf(ddt," addrcnt = %d\n",
201: zp->z_addrcnt);
202: #endif
203: break;
204:
205: }
206: }
207: (void) fclose(fp);
208: if (!first) {
209: if (gettimeofday(&tt, (struct timezone *)0) < 0) {
210: syslog(LOG_ERR, "gettimeofday failed: %m");
211: ival.it_value.tv_sec = 5 * 60;
212: } else {
213: bzero((char *)&ival, sizeof(ival));
214: ival.it_value.tv_sec = next_refresh - tt.tv_sec;
215: if (ival.it_value.tv_sec < 0)
216: ival.it_value.tv_sec = 60;
217: }
218: } else
219: ival.it_value.tv_sec = 0;
220: (void) setitimer(ITIMER_REAL, &ival, (struct itimerval *)NULL);
221: #if DEBUG
222: if (debug)
223: fprintf(ddt,"exit ns_init() Next interupt in %d sec\n",
224: ival.it_value.tv_sec);
225: #endif
226: }
227:
228: zoneinit(zp)
229: struct zoneinfo *zp;
230: {
231: struct sockaddr_in sin;
232: HEADER *hp;
233: char buf[PACKETSZ];
234: u_short len;
235: char *cp;
236: char *tmp;
237: int s, n, l;
238: int cnt, soacnt, error = 0;
239: int zone = zp - zones;
240: u_long serial;
241: struct itimerval ival;
242: struct itimerval zeroival;
243: extern struct sockaddr_in nsaddr;
244: extern int errno;
245: extern int read_alarm();
246: struct sigvec sv, osv;
247: extern int read_interrupted;
248:
249: #ifdef DEBUG
250: if (debug)
251: fprintf(ddt,"zoneinit()\n");
252: #endif
253:
254: bzero((char *)&zeroival, sizeof(zeroival));
255: ival = zeroival;
256: ival.it_value.tv_sec = 2 * 60;
257: sv.sv_handler = read_alarm;
258: sv.sv_onstack = 0;
259: sv.sv_mask = ~0;
260: (void) sigvec(SIGALRM, &sv, &osv);
261:
262: for( cnt = 0; cnt < zp->z_addrcnt; cnt++) {
263: error = 0;
264: bzero((char *)&sin, sizeof(sin));
265: sin.sin_family = AF_INET;
266: sin.sin_port = nsaddr.sin_port;
267: sin.sin_addr = zp->z_addr[cnt];
268: if ((n = res_mkquery(QUERY, zp->z_origin, C_IN, T_AXFR,
269: (char *)NULL, 0, NULL, buf, sizeof(buf))) < 0) {
270: syslog(LOG_ERR, "zoneinit: res_mkquery failed");
271: (void) sigvec(SIGALRM, &osv, (struct sigvec *)0);
272: return;
273: }
274: if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
275: syslog(LOG_ERR, "zoneref: socket: %m");
276: exit(1);
277: }
278: #ifdef DEBUG
279: if (debug >= 2) {
280: fprintf(ddt,"connecting to server #%d %s, %d (%d)\n",
281: cnt+1, inet_ntoa(sin.sin_addr),
282: ntohs(sin.sin_port), n);
283: }
284: #endif
285: if (connect(s, &sin, sizeof(sin)) < 0) {
286: (void) close(s);
287: error++;
288: #ifdef DEBUG
289: if (debug >= 2)
290: fprintf(ddt,"connect failed\n");
291: #endif
292: continue;
293: }
294: /*
295: * Send length & message for zone transfer
296: */
297: if (writemsg(s, buf, n) < 0) {
298: (void) close(s);
299: error++;
300: #ifdef DEBUG
301: if (debug >= 2)
302: fprintf(ddt,"writemsg failed\n");
303: #endif
304: continue;
305: }
306:
307: hp = (HEADER *) buf;
308: soacnt = 0;
309:
310: for (;;) {
311: /*
312: * Receive length & response
313: */
314: cp = buf;
315: l = sizeof(u_short);
316: read_interrupted = 0;
317: while (l > 0) {
318: (void) setitimer(ITIMER_REAL, &ival,
319: (struct itimerval *)NULL);
320: if ((n = recv(s, cp, l, 0)) > 0) {
321: cp += n;
322: l -= n;
323: } else {
324: if (errno == EINTR && !read_interrupted)
325: continue;
326: error++;
327: break;
328: }
329: }
330: (void) setitimer(ITIMER_REAL, &zeroival,
331: (struct itimerval *)NULL);
332: if (error)
333: break;
334: if ((len = htons(*(u_short *)buf)) == 0)
335: break;
336: l = len;
337: cp = buf;
338: while (l > 0) {
339: (void) setitimer(ITIMER_REAL, &ival,
340: (struct itimerval *)NULL);
341: if ((n = recv(s, cp, l, 0)) > 0) {
342: cp += n;
343: l -= n;
344: } else {
345: if (errno == EINTR && !read_interrupted)
346: continue;
347: error++;
348: break;
349: }
350: }
351: (void) setitimer(ITIMER_REAL, &zeroival,
352: (struct itimerval *)NULL);
353: if (error)
354: break;
355: #ifdef DEBUG
356: if (debug >= 3) {
357: fprintf(ddt,"len = %d\n", len);
358: fp_query(buf, ddt);
359: }
360: #endif
361: cp = buf + sizeof(HEADER);
362: if (hp->qdcount)
363: cp += dn_skip(cp) + QFIXEDSZ;
364: tmp = cp + dn_skip(cp);
365: n = doupdate(buf, sizeof(buf), cp, zone, 0);
366: if ((cp - buf) + n != len) {
367: #ifdef DEBUG
368: if (debug)
369: fprintf(ddt,"zoneinit: doupdate failed (%d, %d)\n",
370: cp - buf, n);
371: #endif
372: error++;
373: break;
374: }
375: if ((getshort(tmp)) == T_SOA) {
376: if (soacnt == 0) {
377: soacnt++;
378: tmp += 3 * sizeof(u_short)
379: + sizeof(u_long);
380: tmp += dn_skip(tmp);
381: tmp += dn_skip(tmp);
382: serial = getlong(tmp);
383: continue;
384: }
385: soa_zinfo(zp, tmp);
386: if (serial != zp->z_serial)
387: soacnt = 0;
388: else {
389: break;
390: }
391: }
392: }
393: (void) close(s);
394: if ( error == 0) {
395: (void) sigvec(SIGALRM, &osv, (struct sigvec *)0);
396: return;
397: }
398: #ifdef DEBUG
399: if (debug >= 2)
400: fprintf(ddt,"error reciving zone transfer\n");
401: #endif
402: }
403: /*
404: * Freedom at last!!
405: *
406: * The land where all repressed slaves dream of.
407: *
408: * Can't find a master to talk to.
409: * syslog it and hope we can find a master during maintenance
410: */
411: if (error)
412: syslog(LOG_ERR, "zoneinit: Can't find Master for secondary zone %s",
413: zp->z_origin);
414: /*
415: * Set zone to be refreshed in 5 min.
416: * maybe by then we can refresh it.
417: */
418: zp->z_refresh = 300; /* 300 seconds = 5 Min. */
419: zp->z_retry = 300;
420: if (gettimeofday(&tt, (struct timezone *)0) < 0)
421: syslog(LOG_ERR, "gettimeofday failed: %m");
422: zp->z_time = tt.tv_sec + 300;
423: (void) sigvec(SIGALRM, &osv, (struct sigvec *)0);
424: return;
425: }
426: #ifdef notdef
427: /*
428: * Look for an authoritative zone that matches the RHS of dname
429: * and return is zone # or zero if not found.
430: */
431: findzone(dname, class)
432: char *dname;
433: int class;
434: {
435: register struct zoneinfo *zp;
436: register char *d1, *d2;
437: register int c;
438: char *end;
439:
440: end = dname + strlen(dname);
441: for (zp = &zones[1]; zp < &zones[nzones]; zp++) {
442: d1 = end;
443: d2 = zp->z_origin + strlen(zp->z_origin);
444: while (d2 > zp->z_origin) {
445: if ((c*--
446: }
447: return (zp - zones);
448: }
449: return (0);
450: }
451: #endif
452:
453: soa_zinfo(zp, cp)
454: struct zoneinfo *zp;
455: char *cp;
456: {
457: cp += 3 * sizeof(u_short);
458: cp += sizeof(u_long);
459: cp += dn_skip(cp);
460: cp += dn_skip(cp);
461: zp->z_serial = getlong(cp);
462: cp += sizeof(u_long);
463: zp->z_refresh = getlong(cp);
464: if (gettimeofday(&tt, (struct timezone *)0) < 0)
465: syslog(LOG_ERR, "gettimeofday failed: %m");
466: zp->z_time = tt.tv_sec + zp->z_refresh;
467: cp += sizeof(u_long);
468: zp->z_retry = getlong(cp);
469: cp += sizeof(u_long);
470: zp->z_expire = getlong(cp);
471: cp += sizeof(u_long);
472: zp->z_minimum = getlong(cp);
473: cp += sizeof(u_long);
474: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.