|
|
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_init.c 4.24 (Berkeley) 6/18/88";
20: #endif /* not lint */
21:
22: #include <sys/types.h>
23: #include <sys/socket.h>
24: #include <sys/time.h>
25: #include <netinet/in.h>
26: #include <stdio.h>
27: #include <errno.h>
28: #include <signal.h>
29: #include <syslog.h>
30: #include <ctype.h>
31: #include <arpa/nameser.h>
32: #include "ns.h"
33: #include "db.h"
34:
35: struct zoneinfo zones[MAXZONES]; /* zone information */
36: int nzones; /* number of zones in use */
37: int forward_only = 0; /* run only as a slave */
38: char *cache_file;
39: char *localdomain; /* "default" for non-dotted names */
40: int maint_interval = 300; /* minimum ns_maint() interval */
41:
42: extern int lineno;
43:
44: /*
45: * Read boot file for configuration info.
46: */
47:
48: ns_init(bootfile)
49: char *bootfile;
50: {
51: register struct zoneinfo *zp;
52: char buf[BUFSIZ];
53: FILE *fp;
54: int type;
55: time_t next_refresh = 0;
56: struct itimerval ival;
57: extern int needmaint;
58:
59: #ifdef DEBUG
60: if (debug >= 3)
61: fprintf(ddt,"ns_init(%s)\n", bootfile);
62: #endif
63: gettime(&tt);
64:
65: if ((fp = fopen(bootfile, "r")) == NULL) {
66: syslog(LOG_ERR, "%s: %m", bootfile);
67: exit(1);
68: }
69: lineno = 0;
70:
71: /* allocate cache hash table, formerly the root hash table. */
72: hashtab = savehash((struct hashbuf *)NULL);
73:
74: /* allocate root-hints/file-cache hash table */
75: fcachetab = savehash((struct hashbuf *)NULL);
76:
77: if (localdomain)
78: free(localdomain);
79: localdomain = NULL;
80:
81: /* init zone data */
82: cache_file = NULL;
83: nzones = 1; /* zone zero is cache data */
84: zones[0].z_type = Z_CACHE;
85: while (!feof(fp) && !ferror(fp)) {
86: if (!getword(buf, sizeof(buf), fp))
87: continue;
88: /* read named.boot keyword and process args */
89: if (strcasecmp(buf, "cache") == 0) {
90: type = Z_CACHE;
91: zp = zones;
92: }
93: else if (strcasecmp(buf, "primary") == 0)
94: type = Z_PRIMARY;
95: else if (strcasecmp(buf, "secondary") == 0)
96: type = Z_SECONDARY;
97: else if (strcasecmp(buf, "directory") == 0) {
98: (void) getword(buf, sizeof(buf), fp);
99: if (chdir(buf) < 0) {
100: syslog(LOG_CRIT, "directory %s: %m\n",
101: buf);
102: exit(1);
103: }
104: continue;
105: }
106: else if (strcasecmp(buf, "sortlist") == 0) {
107: get_sort_list(fp);
108: continue;
109: }
110: else if (strcasecmp(buf, "forwarders") == 0) {
111: get_forwarders(fp);
112: continue;
113: }
114: else if (strcasecmp(buf, "slave") == 0) {
115: forward_only++;
116: endline(fp);
117: continue;
118: }
119: else if (strcasecmp(buf, "domain") == 0) {
120: if (getword(buf, sizeof(buf), fp))
121: localdomain = savestr(buf);
122: endline(fp);
123: continue;
124: } else {
125: syslog(LOG_ERR, "%s: line %d: unknown field '%s'\n",
126: bootfile, lineno, buf);
127: endline(fp);
128: continue;
129: }
130: if (nzones >= MAXZONES) {
131: syslog(LOG_ERR, "too many zones (MAXZONES=%d)\n",
132: MAXZONES);
133: endline(fp);
134: continue;
135: }
136: if (type != Z_CACHE)
137: zp = &zones[nzones++];
138: if (zp->z_origin) {
139: free(zp->z_origin);
140: zp->z_origin = 0;
141: }
142: if (zp->z_source) {
143: free(zp->z_source);
144: zp->z_source = 0;
145: }
146: zp->z_type = type;
147: zp->z_addrcnt = 0;
148: zp->z_auth = 0;
149: /*
150: * read zone origin
151: */
152: if (!getword(buf, sizeof(buf), fp)) {
153: syslog(LOG_ERR, "%s: line %d: missing origin\n",
154: bootfile, lineno);
155: continue;
156: }
157: if (buf[0] == '.')
158: buf[0] = '\0';
159: zp->z_origin = savestr(buf);
160: /*
161: * read source file or host address
162: */
163: if (!getword(buf, sizeof(buf), fp)) {
164: syslog(LOG_ERR, "%s: line %d: missing origin\n",
165: bootfile, lineno);
166: continue;
167: }
168: #ifdef DEBUG
169: if (debug)
170: fprintf(ddt,"zone[%d] type %d: '%s'",
171: zp-zones, zp->z_type,
172: *(zp->z_origin) == '\0' ? "." : zp->z_origin);
173: #endif
174: zp->z_time = 0;
175: zp->z_refresh = 0; /* by default, no dumping */
176: switch (type) {
177: case Z_CACHE:
178: zp->z_source = savestr(buf);
179: #ifdef DEBUG
180: if (debug)
181: fprintf(ddt,", source = %s\n", zp->z_source);
182: #endif
183: if (getword(buf, sizeof(buf), fp)) {
184: #ifdef notyet
185: zp->z_refresh = atoi(buf);
186: if (zp->z_refresh <= 0) {
187: syslog(LOG_ERR,
188: "%s: line %d: bad refresh '%s', ignored\n",
189: bootfile, lineno, buf);
190: zp->z_refresh = 0;
191: } else if (cache_file == NULL)
192: cache_file = zp->z_source;
193: #else
194: syslog(LOG_WARNING,
195: "%s: line %d: cache refresh ignored\n",
196: bootfile, lineno);
197: #endif
198: endline(fp);
199: }
200: (void) db_load(zp->z_source, zp->z_origin, zp);
201: break;
202:
203: case Z_PRIMARY:
204: zp->z_source = savestr(buf);
205: #ifdef DEBUG
206: if (debug)
207: fprintf(ddt,", source = %s\n", zp->z_source);
208: #endif
209: if (db_load(zp->z_source, zp->z_origin, zp) == 0)
210: zp->z_auth = 1;
211: #ifdef ALLOW_UPDATES
212: /* Guarantee calls to ns_maint() */
213: zp->z_refresh = maint_interval;
214: #else
215: zp->z_refresh = 0;
216: zp->z_time = 0;
217: #endif ALLOW_UPDATES
218: break;
219:
220: case Z_SECONDARY:
221: #ifdef DEBUG
222: if (debug)
223: fprintf(ddt,"\n\taddrs: %s, ", buf);
224: #endif
225: zp->z_addr[zp->z_addrcnt].s_addr =
226: inet_addr(buf);
227: /* Indicate no cache for this zone yet */
228: zp->z_source = (char *) NULL;
229: if (zp->z_addr[zp->z_addrcnt].s_addr != (unsigned)-1)
230: zp->z_addrcnt++;
231: while (getword(buf, sizeof(buf), fp)) {
232: zp->z_addr[zp->z_addrcnt].s_addr =
233: inet_addr(buf);
234: if (zp->z_addr[zp->z_addrcnt].s_addr ==
235: (unsigned)-1) {
236: zp->z_source = savestr(buf);
237: break;
238: }
239: #ifdef DEBUG
240: if (debug)
241: fprintf(ddt,"%s, ",buf);
242: #endif
243: if (++zp->z_addrcnt >= NSMAX) {
244: zp->z_addrcnt = NSMAX;
245: #ifdef DEBUG
246: if (debug)
247: fprintf(ddt,
248: "\nns.h NSMAX reached\n");
249: #endif
250: break;
251: }
252: }
253: #ifdef DEBUG
254: if (debug)
255: fprintf(ddt,"addrcnt = %d\n", zp->z_addrcnt);
256: #endif
257: zoneinit(zp);
258: break;
259:
260: }
261: if (zp->z_refresh && zp->z_time == 0)
262: zp->z_time = zp->z_refresh + tt.tv_sec;
263: #ifdef DEBUG
264: if (debug)
265: fprintf(ddt, "z_time %d, z_refresh %d\n",
266: zp->z_time, zp->z_refresh);
267: #endif
268: if (zp->z_time != 0 &&
269: (next_refresh == 0 || next_refresh > zp->z_time))
270: next_refresh = zp->z_time;
271: }
272: (void) fclose(fp);
273:
274: /*
275: * Schedule calls to ns_maint().
276: */
277: bzero((char *)&ival, sizeof(ival));
278: if (next_refresh) {
279: gettime(&tt);
280: if (next_refresh <= tt.tv_sec)
281: needmaint = 1;
282: else {
283: ival.it_value.tv_sec = next_refresh - tt.tv_sec;
284: if (ival.it_value.tv_sec < maint_interval)
285: ival.it_value.tv_sec = maint_interval;
286: }
287: }
288: (void) setitimer(ITIMER_REAL, &ival, (struct itimerval *)NULL);
289: #ifdef DEBUG
290: if (debug) {
291: fprintf(ddt,"exit ns_init() ");
292: if (needmaint || ival.it_value.tv_sec)
293: fprintf(ddt,"Next interrupt in %d sec\n",
294: ival.it_value.tv_sec);
295: else
296: fprintf(ddt,"No maintenance scheduled\n");
297: }
298: #endif
299: }
300:
301: zoneinit(zp)
302: register struct zoneinfo *zp;
303: {
304:
305: #ifdef DEBUG
306: if (debug)
307: fprintf(ddt,"zoneinit()\n");
308: #endif
309:
310: /*
311: * Try to load zone from backup file,
312: * if one was specified and it exists.
313: * If not, or if the data are out of date,
314: * we will refresh the zone from a primary
315: * immediately.
316: */
317: if (zp->z_source == NULL ||
318: db_load(zp->z_source, zp->z_origin, zp) != 0) {
319: /*
320: * Set zone to be refreshed immediately.
321: */
322: zp->z_refresh = INIT_REFRESH;
323: zp->z_retry = INIT_REFRESH;
324: zp->z_time = tt.tv_sec;
325: } else
326: zp->z_auth = 1;
327: }
328:
329: #ifdef ALLOW_UPDATES
330: /*
331: * Look for the authoritative zone with the longest matching RHS of dname
332: * and return its zone # or zero if not found.
333: */
334: findzone(dname, class)
335: char *dname;
336: int class;
337: {
338: char *dZoneName, *zoneName, *index(), *dotPos;
339: int dZoneNameLen, zoneNameLen;
340: int maxMatchLen = 0;
341: int maxMatchZoneNum = 0;
342: int zoneNum;
343:
344: #ifdef DEBUG
345: if (debug >= 4)
346: fprintf(ddt, "findzone(dname=%s, class=%d)\n", dname, class);
347: if (debug >= 5) {
348: fprintf(ddt, "zone dump:\n");
349: for (zoneNum = 1; zoneNum < nzones; zoneNum++)
350: printzoneinfo(zoneNum);
351: }
352: #endif DEBUG
353:
354: dZoneName = index(dname, '.');
355: if (dZoneName == NULL)
356: dZoneName = ""; /* root */
357: else
358: dZoneName++; /* There is a '.' in dname, so use remainder of
359: string as the zone name */
360: dZoneNameLen = strlen(dZoneName);
361: for (zoneNum = 1; zoneNum < nzones; zoneNum++) {
362: zoneName = (zones[zoneNum]).z_origin;
363: zoneNameLen = strlen(zoneName);
364: /* The zone name may or may not end with a '.' */
365: dotPos = index(zoneName, '.');
366: if (dotPos)
367: zoneNameLen--;
368: if (dZoneNameLen != zoneNameLen)
369: continue;
370: #ifdef DEBUG
371: if (debug >= 5)
372: fprintf(ddt, "about to strncasecmp('%s', '%s', %d)\n",
373: dZoneName, zoneName, dZoneNameLen);
374: #endif
375: if (strncasecmp(dZoneName, zoneName, dZoneNameLen) == 0) {
376: #ifdef DEBUG
377: if (debug >= 5)
378: fprintf(ddt, "match\n");
379: #endif
380: /*
381: * See if this is as long a match as any so far.
382: * Check if "<=" instead of just "<" so that if
383: * root domain (whose name length is 0) matches,
384: * we use it's zone number instead of just 0
385: */
386: if (maxMatchLen <= zoneNameLen) {
387: maxMatchZoneNum = zoneNum;
388: maxMatchLen = zoneNameLen;
389: }
390: }
391: #ifdef DEBUG
392: else
393: if (debug >= 5)
394: fprintf(ddt, "no match\n");
395: #endif
396: }
397: #ifdef DEBUG
398: if (debug >= 4)
399: fprintf(ddt, "findzone: returning %d\n", maxMatchZoneNum);
400: #endif DEBUG
401: return (maxMatchZoneNum);
402: }
403: #endif ALLOW_UPDATES
404:
405: soa_zinfo(zp, cp, eom)
406: register struct zoneinfo *zp;
407: register u_char *cp;
408: u_char *eom;
409: {
410: cp += 3 * sizeof(u_short);
411: cp += sizeof(u_long);
412: cp += dn_skipname(cp, eom);
413: cp += dn_skipname(cp, eom);
414: GETLONG(zp->z_serial, cp);
415: GETLONG(zp->z_refresh, cp);
416: gettime(&tt);
417: zp->z_time = tt.tv_sec + zp->z_refresh;
418: GETLONG(zp->z_retry, cp);
419: GETLONG(zp->z_expire, cp);
420: GETLONG(zp->z_minimum, cp);
421: }
422:
423: get_forwarders(fp)
424: FILE *fp;
425: {
426: char buf[BUFSIZ];
427: struct fwdinfo *fip = NULL, *ftp = NULL;
428:
429: extern struct sockaddr_in nsaddr;
430: extern struct fwdinfo *fwdtab;
431:
432: #ifdef DEBUG
433: if (debug)
434: fprintf(ddt,"forwarders ");
435: #endif
436: while (getword(buf, sizeof(buf), fp)) {
437: if (strlen(buf) == 0)
438: break;
439: #ifdef DEBUG
440: if (debug)
441: fprintf(ddt," %s",buf);
442: #endif
443: if (ftp == NULL)
444: ftp = (struct fwdinfo *)malloc(sizeof(struct fwdinfo));
445: if ( isdigit(buf[0]) &&
446: (ftp->fwdaddr.sin_addr.s_addr = inet_addr(buf))
447: != (unsigned)-1) {
448: ftp->fwdaddr.sin_port = nsaddr.sin_port;
449: ftp->fwdaddr.sin_family = AF_INET;
450: } else {
451: syslog(LOG_ERR, "'%s' (ignored, NOT dotted quad)", buf);
452: #ifdef DEBUG
453: if (debug)
454: fprintf(ddt," (ignored, NOT dotted quad)");
455: #endif
456: continue;
457: }
458: ftp->next = NULL;
459: if (fwdtab == NULL)
460: fwdtab = ftp; /* First time only */
461: else
462: fip->next = ftp;
463: fip = ftp;
464: ftp = NULL;
465: }
466: if (ftp)
467: free((char *)ftp);
468:
469: #ifdef DEBUG
470: if (debug)
471: fprintf(ddt,"\n");
472: if (debug > 2)
473: for (ftp = fwdtab; ftp != NULL; ftp = ftp->next)
474: fprintf(ddt,"ftp x%x %s next x%x\n", ftp,
475: inet_ntoa(ftp->fwdaddr.sin_addr), ftp->next);
476: #endif
477: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.