Annotation of embedaddon/dhcp/minires/res_init.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (c) 1985, 1989, 1993
3: * The Regents of the University of California. All rights reserved.
4: *
5: * Redistribution and use in source and binary forms, with or without
6: * modification, are permitted provided that the following conditions
7: * are met:
8: * 1. Redistributions of source code must retain the above copyright
9: * notice, this list of conditions and the following disclaimer.
10: * 2. Redistributions in binary form must reproduce the above copyright
11: * notice, this list of conditions and the following disclaimer in the
12: * documentation and/or other materials provided with the distribution.
13: * 3. All advertising materials mentioning features or use of this software
14: * must display the following acknowledgement:
15: * This product includes software developed by the University of
16: * California, Berkeley and its contributors.
17: * 4. Neither the name of the University nor the names of its contributors
18: * may be used to endorse or promote products derived from this software
19: * without specific prior written permission.
20: *
21: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31: * SUCH DAMAGE.
32: */
33:
34: /*
35: * Portions Copyright (c) 1993 by Digital Equipment Corporation.
36: *
37: * Permission to use, copy, modify, and distribute this software for any
38: * purpose with or without fee is hereby granted, provided that the above
39: * copyright notice and this permission notice appear in all copies, and that
40: * the name of Digital Equipment Corporation not be used in advertising or
41: * publicity pertaining to distribution of the document or software without
42: * specific, written prior permission.
43: *
44: * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
45: * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
46: * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
47: * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
48: * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
49: * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
50: * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
51: * SOFTWARE.
52: */
53:
54: /*
55: * Portions Copyright (c) 2004,2007,2009 by Internet Systems Consortium, Inc. ("ISC")
56: * Portions Copyright (c) 1995-2003 by Internet Software Consortium
57: *
58: * Permission to use, copy, modify, and distribute this software for any
59: * purpose with or without fee is hereby granted, provided that the above
60: * copyright notice and this permission notice appear in all copies.
61: *
62: * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
63: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
64: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
65: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
66: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
67: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
68: * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
69: *
70: * Internet Systems Consortium, Inc.
71: * 950 Charter Street
72: * Redwood City, CA 94063
73: * <info@isc.org>
74: * https://www.isc.org/
75: */
76:
77: #if defined(LIBC_SCCS) && !defined(lint)
78: static const char sccsid[] = "@(#)res_init.c 8.1 (Berkeley) 6/7/93";
1.1.1.1 ! misho 79: static const char rcsid[] = "$Id: res_init.c,v 1.11.74.2 2009/07/24 22:04:52 sar Exp $";
1.1 misho 80: #endif /* LIBC_SCCS and not lint */
81:
82: #include <sys/types.h>
83: #include <sys/param.h>
84: #include <sys/socket.h>
85: #include <sys/time.h>
86:
87: #include <netinet/in.h>
88: #include <arpa/inet.h>
89:
90: #include <ctype.h>
91: #include <stdio.h>
92: #include <stdlib.h>
93: #include <string.h>
94: #include <unistd.h>
95:
96: #include "minires/minires.h"
97: #include "arpa/nameser.h"
98:
99: /* Options. Should all be left alone. */
100: #define RESOLVSORT
101: #define RFC1535
102:
103: static void res_setoptions (res_state, const char *, const char *);
104:
105: #ifdef RESOLVSORT
106: static const char sort_mask[] = "/&";
107: #define ISSORTMASK(ch) (strchr(sort_mask, ch) != NULL)
108: static u_int32_t net_mask (struct in_addr);
109: #endif
110:
111: #if !defined(isascii) /* XXX - could be a function */
112: # define isascii(c) (!(c & 0200))
113: #endif
114:
115: /*
116: * Resolver state default settings.
117: */
118:
119: /*
120: * Set up default settings. If the configuration file exist, the values
121: * there will have precedence. Otherwise, the server address is set to
122: * INADDR_ANY and the default domain name comes from the gethostname().
123: *
124: * An interrim version of this code (BIND 4.9, pre-4.4BSD) used 127.0.0.1
125: * rather than INADDR_ANY ("0.0.0.0") as the default name server address
126: * since it was noted that INADDR_ANY actually meant ``the first interface
127: * you "ifconfig"'d at boot time'' and if this was a SLIP or PPP interface,
128: * it had to be "up" in order for you to reach your own name server. It
129: * was later decided that since the recommended practice is to always
130: * install local static routes through 127.0.0.1 for all your network
131: * interfaces, that we could solve this problem without a code change.
132: *
133: * The configuration file should always be used, since it is the only way
134: * to specify a default domain. If you are running a server on your local
135: * machine, you should say "nameserver 0.0.0.0" or "nameserver 127.0.0.1"
136: * in the configuration file.
137: *
138: * Return 0 if completes successfully, -1 on error
139: */
140: extern int minires_vinit(res_state, int);
141:
142: #if defined (TRACING)
143: u_int trace_mr_res_randomid(u_int);
144: #endif
145:
146: int
147: res_ninit(res_state statp) {
148:
149: return (minires_vinit(statp, 0));
150: }
151:
152: /* This function has to be reachable by res_data.c but not publically. */
153: int
154: minires_vinit(res_state statp, int preinit) {
155: register FILE *fp;
156: char *cp;
157: register char **pp;
158: register int n;
159: char buf[BUFSIZ];
160: int nserv = 0; /* number of nameserver records read from file */
161: int haveenv = 0;
162: int havesearch = 0;
163: #ifdef RESOLVSORT
164: int nsort = 0;
165: char *net;
166: #endif
167: #ifndef RFC1535
168: int dots;
169: #endif
170:
171: if (!preinit) {
172: statp->retrans = RES_TIMEOUT;
173: statp->retry = RES_DFLRETRY;
174: statp->options = RES_DEFAULT;
175: statp->id = res_randomid();
176: #if defined (TRACING)
177: statp->id = trace_mr_res_randomid (statp -> id);
178: #endif
179: }
180:
181: #ifdef USELOOPBACK
182: statp->nsaddr.sin_addr = inet_makeaddr(IN_LOOPBACKNET, 1);
183: #else
184: statp->nsaddr.sin_addr.s_addr = INADDR_ANY;
185: #endif
186: statp->nsaddr.sin_family = AF_INET;
187: statp->nsaddr.sin_port = htons(NAMESERVER_PORT);
188: statp->nscount = 1;
189: statp->ndots = 1;
190: statp->pfcode = 0;
191: statp->_sock = -1;
192: statp->_flags = 0;
193: statp->qhook = NULL;
194: statp->rhook = NULL;
195:
196: /* Allow user to override the local domain definition */
197: if ((cp = getenv("LOCALDOMAIN")) != NULL) {
198: (void)strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1);
199: statp->defdname[sizeof(statp->defdname) - 1] = '\0';
200: haveenv++;
201:
202: /*
203: * Set search list to be blank-separated strings
204: * from rest of env value. Permits users of LOCALDOMAIN
205: * to still have a search list, and anyone to set the
206: * one that they want to use as an individual (even more
207: * important now that the rfc1535 stuff restricts searches)
208: */
209: cp = statp->defdname;
210: pp = statp->dnsrch;
211: *pp++ = cp;
212: for (n = 0; *cp && pp < statp->dnsrch + MAXDNSRCH; cp++) {
213: if (*cp == '\n') /* silly backwards compat */
214: break;
215: else if (*cp == ' ' || *cp == '\t') {
216: *cp = 0;
217: n = 1;
218: } else if (n) {
219: *pp++ = cp;
220: n = 0;
221: havesearch = 1;
222: }
223: }
224: /* null terminate last domain if there are excess */
225: while (*cp != '\0' && *cp != ' ' && *cp != '\t' && *cp != '\n')
226: cp++;
227: *cp = '\0';
228: *pp++ = 0;
229: }
230:
231: #define MATCH(line, name) \
232: (!strncmp(line, name, sizeof(name) - 1) && \
233: (line[sizeof(name) - 1] == ' ' || \
234: line[sizeof(name) - 1] == '\t'))
235:
236: if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) {
237: /* read the config file */
238: while (fgets(buf, sizeof(buf), fp) != NULL) {
239: /* skip comments */
240: if (*buf == ';' || *buf == '#')
241: continue;
242: /* read default domain name */
243: if (MATCH(buf, "domain")) {
244: if (haveenv) /* skip if have from environ */
245: continue;
246: cp = buf + sizeof("domain") - 1;
247: while (*cp == ' ' || *cp == '\t')
248: cp++;
249: if ((*cp == '\0') || (*cp == '\n'))
250: continue;
251: strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1);
252: statp->defdname[sizeof(statp->defdname) - 1] = '\0';
253: if ((cp = strpbrk(statp->defdname, " \t\n")) != NULL)
254: *cp = '\0';
255: havesearch = 0;
256: continue;
257: }
258: /* set search list */
259: if (MATCH(buf, "search")) {
260: if (haveenv) /* skip if have from environ */
261: continue;
262: cp = buf + sizeof("search") - 1;
263: while (*cp == ' ' || *cp == '\t')
264: cp++;
265: if ((*cp == '\0') || (*cp == '\n'))
266: continue;
267: strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1);
268: statp->defdname[sizeof(statp->defdname) - 1] = '\0';
269: if ((cp = strchr(statp->defdname, '\n')) != NULL)
270: *cp = '\0';
271: /*
272: * Set search list to be blank-separated strings
273: * on rest of line.
274: */
275: cp = statp->defdname;
276: pp = statp->dnsrch;
277: *pp++ = cp;
278: for (n = 0; *cp && pp < statp->dnsrch + MAXDNSRCH; cp++) {
279: if (*cp == ' ' || *cp == '\t') {
280: *cp = 0;
281: n = 1;
282: } else if (n) {
283: *pp++ = cp;
284: n = 0;
285: }
286: }
287: /* null terminate last domain if there are excess */
288: while (*cp != '\0' && *cp != ' ' && *cp != '\t')
289: cp++;
290: *cp = '\0';
291: *pp++ = 0;
292: havesearch = 1;
293: continue;
294: }
295: /* read nameservers to query */
296: if (MATCH(buf, "nameserver") && nserv < MAXNS) {
297: struct in_addr a;
298:
299: cp = buf + sizeof("nameserver") - 1;
300: while (*cp == ' ' || *cp == '\t')
301: cp++;
302: if ((*cp != '\0') && (*cp != '\n') && inet_aton(cp, &a)) {
303: statp->nsaddr_list[nserv].sin_addr = a;
304: statp->nsaddr_list[nserv].sin_family = AF_INET;
305: statp->nsaddr_list[nserv].sin_port =
306: htons(NAMESERVER_PORT);
307: nserv++;
308: }
309: continue;
310: }
311: #ifdef RESOLVSORT
312: if (MATCH(buf, "sortlist")) {
313: struct in_addr a;
314:
315: cp = buf + sizeof("sortlist") - 1;
316: while (nsort < MAXRESOLVSORT) {
317: while (*cp == ' ' || *cp == '\t')
318: cp++;
319: if (*cp == '\0' || *cp == '\n' || *cp == ';')
320: break;
321: net = cp;
322: while (*cp && !ISSORTMASK(*cp) && *cp != ';' &&
323: isascii((int)*cp) && !isspace((int)*cp))
324: cp++;
325: n = *cp;
326: *cp = 0;
327: if (inet_aton(net, &a)) {
328: statp->sort_list[nsort].addr = a;
329: if (ISSORTMASK(n)) {
330: *cp++ = n;
331: net = cp;
332: while (*cp && *cp != ';' &&
333: isascii((int)*cp) && !isspace((int)*cp))
334: cp++;
335: n = *cp;
336: *cp = 0;
337: if (inet_aton(net, &a)) {
338: statp->sort_list[nsort].mask = a.s_addr;
339: } else {
340: statp->sort_list[nsort].mask =
341: net_mask(statp->sort_list[nsort].addr);
342: }
343: } else {
344: statp->sort_list[nsort].mask =
345: net_mask(statp->sort_list[nsort].addr);
346: }
347: nsort++;
348: }
349: *cp = n;
350: }
351: continue;
352: }
353: #endif
354: if (MATCH(buf, "options")) {
355: res_setoptions(statp, buf + sizeof("options") - 1, "conf");
356: continue;
357: }
358: }
359: if (nserv > 1)
360: statp->nscount = nserv;
361: #ifdef RESOLVSORT
362: statp->nsort = nsort;
363: #endif
364: (void) fclose(fp);
365: }
366: if (statp->defdname[0] == 0 &&
367: gethostname(buf, sizeof(statp->defdname) - 1) == 0 &&
368: (cp = strchr(buf, '.')) != NULL)
369: strcpy(statp->defdname, cp + 1);
370:
371: /* find components of local domain that might be searched */
372: if (havesearch == 0) {
373: pp = statp->dnsrch;
374: *pp++ = statp->defdname;
375: *pp = NULL;
376:
377: #ifndef RFC1535
378: dots = 0;
379: for (cp = statp->defdname; *cp; cp++)
380: dots += (*cp == '.');
381:
382: cp = statp->defdname;
383: while (pp < statp->dnsrch + MAXDFLSRCH) {
384: if (dots < LOCALDOMAINPARTS)
385: break;
386: cp = strchr(cp, '.') + 1; /* we know there is one */
387: *pp++ = cp;
388: dots--;
389: }
390: *pp = NULL;
391: if (statp->options & RES_DEBUG) {
392: printf(";; res_init()... default dnsrch list:\n");
393: for (pp = statp->dnsrch; *pp; pp++)
394: printf(";;\t%s\n", *pp);
395: printf(";;\t..END..\n");
396: }
397: #endif /* !RFC1535 */
398: }
399:
400: if ((cp = getenv("RES_OPTIONS")) != NULL)
401: res_setoptions(statp, cp, "env");
402: statp->options |= RES_INIT;
403: return (0);
404: }
405:
406: static void
407: res_setoptions(res_state statp, const char *options, const char *source) {
408: const char *cp = options;
409: int i;
410:
411: if (statp->options & RES_DEBUG)
412: printf(";; res_setoptions(\"%s\", \"%s\")...\n",
413: options, source);
414: while (*cp) {
415: /* skip leading and inner runs of spaces */
416: while (*cp == ' ' || *cp == '\t')
417: cp++;
418: /* search for and process individual options */
419: if (!strncmp(cp, "ndots:", sizeof("ndots:") - 1)) {
420: i = atoi(cp + sizeof("ndots:") - 1);
421: if (i <= RES_MAXNDOTS)
422: statp->ndots = i;
423: else
424: statp->ndots = RES_MAXNDOTS;
425: if (statp->options & RES_DEBUG)
426: printf(";;\tndots=%d\n", statp->ndots);
427: } else if (!strncmp(cp, "timeout:", sizeof("timeout:") - 1)) {
428: i = atoi(cp + sizeof("timeout:") - 1);
429: if (i <= RES_MAXRETRANS)
430: statp->retrans = i;
431: else
432: statp->retrans = RES_MAXRETRANS;
433: } else if (!strncmp(cp, "attempts:", sizeof("attempts:") - 1)){
434: i = atoi(cp + sizeof("attempts:") - 1);
435: if (i <= RES_MAXRETRY)
436: statp->retry = i;
437: else
438: statp->retry = RES_MAXRETRY;
439: } else if (!strncmp(cp, "debug", sizeof("debug") - 1)) {
440: if (!(statp->options & RES_DEBUG)) {
441: printf(";; res_setoptions(\"%s\", \"%s\")..\n",
442: options, source);
443: statp->options |= RES_DEBUG;
444: }
445: printf(";;\tdebug\n");
446: } else if (!strncmp(cp, "inet6", sizeof("inet6") - 1)) {
447: statp->options |= RES_USE_INET6;
448: } else if (!strncmp(cp, "rotate", sizeof("rotate") - 1)) {
449: statp->options |= RES_ROTATE;
450: } else if (!strncmp(cp, "no-check-names",
451: sizeof("no-check-names") - 1)) {
452: statp->options |= RES_NOCHECKNAME;
453: } else {
454: /* XXX - print a warning here? */
455: }
456: /* skip to next run of spaces */
457: while (*cp && *cp != ' ' && *cp != '\t')
458: cp++;
459: }
460: }
461:
462: #ifdef RESOLVSORT
463: /* XXX - should really support CIDR which means explicit masks always. */
464: static u_int32_t
465: net_mask(in) /* XXX - should really use system's version of this */
466: struct in_addr in;
467: {
468: register u_int32_t i = ntohl(in.s_addr);
469:
470: if (IN_CLASSA(i))
471: return (htonl(IN_CLASSA_NET));
472: else if (IN_CLASSB(i))
473: return (htonl(IN_CLASSB_NET));
474: return (htonl(IN_CLASSC_NET));
475: }
476: #endif
477:
478: u_int
479: res_randomid(void) {
480: struct timeval now;
481:
482: gettimeofday(&now, NULL);
483: return (0xffff & (now.tv_sec ^ now.tv_usec ^ getpid()));
484: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>