Annotation of src/lib/libc/resolv/res_init.c, Revision 1.1.1.3
1.1.1.3 ! ghen 1: /* $NetBSD$ */
1.1 christos 2:
3: /*
4: * Copyright (c) 1985, 1989, 1993
5: * The Regents of the University of California. All rights reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: * 3. All advertising materials mentioning features or use of this software
16: * must display the following acknowledgement:
17: * This product includes software developed by the University of
18: * California, Berkeley and its contributors.
19: * 4. Neither the name of the University nor the names of its contributors
20: * may be used to endorse or promote products derived from this software
21: * without specific prior written permission.
22: *
23: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33: * SUCH DAMAGE.
34: */
35:
36: /*
37: * Portions Copyright (c) 1993 by Digital Equipment Corporation.
38: *
39: * Permission to use, copy, modify, and distribute this software for any
40: * purpose with or without fee is hereby granted, provided that the above
41: * copyright notice and this permission notice appear in all copies, and that
42: * the name of Digital Equipment Corporation not be used in advertising or
43: * publicity pertaining to distribution of the document or software without
44: * specific, written prior permission.
45: *
46: * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
47: * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
48: * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
49: * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
50: * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
51: * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
52: * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
53: * SOFTWARE.
54: */
55:
56: /*
57: * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
58: * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
59: *
60: * Permission to use, copy, modify, and distribute this software for any
61: * purpose with or without fee is hereby granted, provided that the above
62: * copyright notice and this permission notice appear in all copies.
63: *
64: * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
65: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
66: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
67: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
68: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
69: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
70: * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
71: */
72:
73: #if defined(LIBC_SCCS) && !defined(lint)
74: static const char sccsid[] = "@(#)res_init.c 8.1 (Berkeley) 6/7/93";
1.1.1.2 christos 75: static const char rcsid[] = "Id: res_init.c,v 1.16.18.5 2006/08/30 23:23:13 marka Exp";
1.1 christos 76: #endif /* LIBC_SCCS and not lint */
77:
78: #include "port_before.h"
79:
80: #include <sys/types.h>
81: #include <sys/param.h>
82: #include <sys/socket.h>
83: #include <sys/time.h>
84:
85: #include <netinet/in.h>
86: #include <arpa/inet.h>
87: #include <arpa/nameser.h>
88:
89: #include <ctype.h>
90: #include <stdio.h>
91: #include <stdlib.h>
92: #include <string.h>
93: #include <unistd.h>
94: #include <netdb.h>
95:
96: #include "port_after.h"
97:
98: /* ensure that sockaddr_in6 and IN6ADDR_ANY_INIT are declared / defined */
99: #include <resolv.h>
100:
101: #include "res_private.h"
102:
1.1.1.2 christos 103: /*% Options. Should all be left alone. */
1.1 christos 104: #define RESOLVSORT
105: #define DEBUG
106:
1.1.1.2 christos 107: #ifdef SOLARIS2
108: #include <sys/systeminfo.h>
109: #endif
110:
1.1 christos 111: static void res_setoptions __P((res_state, const char *, const char *));
112:
113: #ifdef RESOLVSORT
114: static const char sort_mask[] = "/&";
115: #define ISSORTMASK(ch) (strchr(sort_mask, ch) != NULL)
116: static u_int32_t net_mask __P((struct in_addr));
117: #endif
118:
1.1.1.2 christos 119: #if !defined(isascii) /*%< XXX - could be a function */
1.1 christos 120: # define isascii(c) (!(c & 0200))
121: #endif
122:
123: /*
124: * Resolver state default settings.
125: */
126:
1.1.1.2 christos 127: /*%
1.1 christos 128: * Set up default settings. If the configuration file exist, the values
129: * there will have precedence. Otherwise, the server address is set to
130: * INADDR_ANY and the default domain name comes from the gethostname().
131: *
132: * An interrim version of this code (BIND 4.9, pre-4.4BSD) used 127.0.0.1
133: * rather than INADDR_ANY ("0.0.0.0") as the default name server address
134: * since it was noted that INADDR_ANY actually meant ``the first interface
135: * you "ifconfig"'d at boot time'' and if this was a SLIP or PPP interface,
136: * it had to be "up" in order for you to reach your own name server. It
137: * was later decided that since the recommended practice is to always
138: * install local static routes through 127.0.0.1 for all your network
139: * interfaces, that we could solve this problem without a code change.
140: *
141: * The configuration file should always be used, since it is the only way
142: * to specify a default domain. If you are running a server on your local
143: * machine, you should say "nameserver 0.0.0.0" or "nameserver 127.0.0.1"
144: * in the configuration file.
145: *
146: * Return 0 if completes successfully, -1 on error
147: */
148: int
149: res_ninit(res_state statp) {
150: extern int __res_vinit(res_state, int);
151:
152: return (__res_vinit(statp, 0));
153: }
154:
1.1.1.2 christos 155: /*% This function has to be reachable by res_data.c but not publically. */
1.1 christos 156: int
157: __res_vinit(res_state statp, int preinit) {
158: register FILE *fp;
159: register char *cp, **pp;
160: register int n;
161: char buf[BUFSIZ];
1.1.1.2 christos 162: int nserv = 0; /*%< number of nameserver records read from file */
1.1 christos 163: int haveenv = 0;
164: int havesearch = 0;
165: #ifdef RESOLVSORT
166: int nsort = 0;
167: char *net;
168: #endif
169: int dots;
170: union res_sockaddr_union u[2];
171:
1.1.1.2 christos 172: if (statp->_u._ext.ext != NULL)
173: res_ndestroy(statp);
174:
1.1 christos 175: if (!preinit) {
176: statp->retrans = RES_TIMEOUT;
177: statp->retry = RES_DFLRETRY;
178: statp->options = RES_DEFAULT;
179: statp->id = res_randomid();
180: }
181:
182: memset(u, 0, sizeof(u));
183: #ifdef USELOOPBACK
184: u[nserv].sin.sin_addr = inet_makeaddr(IN_LOOPBACKNET, 1);
185: #else
186: u[nserv].sin.sin_addr.s_addr = INADDR_ANY;
187: #endif
188: u[nserv].sin.sin_family = AF_INET;
189: u[nserv].sin.sin_port = htons(NAMESERVER_PORT);
190: #ifdef HAVE_SA_LEN
191: u[nserv].sin.sin_len = sizeof(struct sockaddr_in);
192: #endif
193: nserv++;
194: #ifdef HAS_INET6_STRUCTS
195: #ifdef USELOOPBACK
196: u[nserv].sin6.sin6_addr = in6addr_loopback;
197: #else
198: u[nserv].sin6.sin6_addr = in6addr_any;
199: #endif
200: u[nserv].sin6.sin6_family = AF_INET6;
201: u[nserv].sin6.sin6_port = htons(NAMESERVER_PORT);
202: #ifdef HAVE_SA_LEN
203: u[nserv].sin6.sin6_len = sizeof(struct sockaddr_in6);
204: #endif
205: nserv++;
206: #endif
207: statp->nscount = 0;
208: statp->ndots = 1;
209: statp->pfcode = 0;
210: statp->_vcsock = -1;
211: statp->_flags = 0;
212: statp->qhook = NULL;
213: statp->rhook = NULL;
214: statp->_u._ext.nscount = 0;
215: statp->_u._ext.ext = malloc(sizeof(*statp->_u._ext.ext));
216: if (statp->_u._ext.ext != NULL) {
217: memset(statp->_u._ext.ext, 0, sizeof(*statp->_u._ext.ext));
218: statp->_u._ext.ext->nsaddrs[0].sin = statp->nsaddr;
219: strcpy(statp->_u._ext.ext->nsuffix, "ip6.arpa");
220: strcpy(statp->_u._ext.ext->nsuffix2, "ip6.int");
1.1.1.2 christos 221: } else
222: return (-1);
1.1 christos 223: #ifdef RESOLVSORT
224: statp->nsort = 0;
225: #endif
226: res_setservers(statp, u, nserv);
227:
1.1.1.2 christos 228: #ifdef SOLARIS2
229: /*
230: * The old libresolv derived the defaultdomain from NIS/NIS+.
231: * We want to keep this behaviour
232: */
233: {
234: char buf[sizeof(statp->defdname)], *cp;
235: int ret;
236:
237: if ((ret = sysinfo(SI_SRPC_DOMAIN, buf, sizeof(buf))) > 0 &&
238: (unsigned int)ret <= sizeof(buf)) {
239: if (buf[0] == '+')
240: buf[0] = '.';
241: cp = strchr(buf, '.');
242: cp = (cp == NULL) ? buf : (cp + 1);
243: if (strlen(cp) >= sizeof(statp->defdname))
244: goto freedata;
245: strcpy(statp->defdname, cp);
246: }
247: }
248: #endif /* SOLARIS2 */
249:
1.1 christos 250: /* Allow user to override the local domain definition */
251: if ((cp = getenv("LOCALDOMAIN")) != NULL) {
252: (void)strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1);
253: statp->defdname[sizeof(statp->defdname) - 1] = '\0';
254: haveenv++;
255:
256: /*
257: * Set search list to be blank-separated strings
258: * from rest of env value. Permits users of LOCALDOMAIN
259: * to still have a search list, and anyone to set the
260: * one that they want to use as an individual (even more
261: * important now that the rfc1535 stuff restricts searches)
262: */
263: cp = statp->defdname;
264: pp = statp->dnsrch;
265: *pp++ = cp;
266: for (n = 0; *cp && pp < statp->dnsrch + MAXDNSRCH; cp++) {
1.1.1.2 christos 267: if (*cp == '\n') /*%< silly backwards compat */
1.1 christos 268: break;
269: else if (*cp == ' ' || *cp == '\t') {
270: *cp = 0;
271: n = 1;
272: } else if (n) {
273: *pp++ = cp;
274: n = 0;
275: havesearch = 1;
276: }
277: }
278: /* null terminate last domain if there are excess */
279: while (*cp != '\0' && *cp != ' ' && *cp != '\t' && *cp != '\n')
280: cp++;
281: *cp = '\0';
282: *pp++ = 0;
283: }
284:
285: #define MATCH(line, name) \
286: (!strncmp(line, name, sizeof(name) - 1) && \
287: (line[sizeof(name) - 1] == ' ' || \
288: line[sizeof(name) - 1] == '\t'))
289:
290: nserv = 0;
291: if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) {
292: /* read the config file */
293: while (fgets(buf, sizeof(buf), fp) != NULL) {
294: /* skip comments */
295: if (*buf == ';' || *buf == '#')
296: continue;
297: /* read default domain name */
298: if (MATCH(buf, "domain")) {
1.1.1.2 christos 299: if (haveenv) /*%< skip if have from environ */
1.1 christos 300: continue;
301: cp = buf + sizeof("domain") - 1;
302: while (*cp == ' ' || *cp == '\t')
303: cp++;
304: if ((*cp == '\0') || (*cp == '\n'))
305: continue;
306: strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1);
307: statp->defdname[sizeof(statp->defdname) - 1] = '\0';
308: if ((cp = strpbrk(statp->defdname, " \t\n")) != NULL)
309: *cp = '\0';
310: havesearch = 0;
311: continue;
312: }
313: /* set search list */
314: if (MATCH(buf, "search")) {
1.1.1.2 christos 315: if (haveenv) /*%< skip if have from environ */
1.1 christos 316: continue;
317: cp = buf + sizeof("search") - 1;
318: while (*cp == ' ' || *cp == '\t')
319: cp++;
320: if ((*cp == '\0') || (*cp == '\n'))
321: continue;
322: strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1);
323: statp->defdname[sizeof(statp->defdname) - 1] = '\0';
324: if ((cp = strchr(statp->defdname, '\n')) != NULL)
325: *cp = '\0';
326: /*
327: * Set search list to be blank-separated strings
328: * on rest of line.
329: */
330: cp = statp->defdname;
331: pp = statp->dnsrch;
332: *pp++ = cp;
333: for (n = 0; *cp && pp < statp->dnsrch + MAXDNSRCH; cp++) {
334: if (*cp == ' ' || *cp == '\t') {
335: *cp = 0;
336: n = 1;
337: } else if (n) {
338: *pp++ = cp;
339: n = 0;
340: }
341: }
342: /* null terminate last domain if there are excess */
343: while (*cp != '\0' && *cp != ' ' && *cp != '\t')
344: cp++;
345: *cp = '\0';
346: *pp++ = 0;
347: havesearch = 1;
348: continue;
349: }
350: /* read nameservers to query */
351: if (MATCH(buf, "nameserver") && nserv < MAXNS) {
352: struct addrinfo hints, *ai;
353: char sbuf[NI_MAXSERV];
354: const size_t minsiz =
355: sizeof(statp->_u._ext.ext->nsaddrs[0]);
356:
357: cp = buf + sizeof("nameserver") - 1;
358: while (*cp == ' ' || *cp == '\t')
359: cp++;
360: cp[strcspn(cp, ";# \t\n")] = '\0';
361: if ((*cp != '\0') && (*cp != '\n')) {
362: memset(&hints, 0, sizeof(hints));
363: hints.ai_family = PF_UNSPEC;
364: hints.ai_socktype = SOCK_DGRAM; /*dummy*/
365: hints.ai_flags = AI_NUMERICHOST;
366: sprintf(sbuf, "%u", NAMESERVER_PORT);
367: if (getaddrinfo(cp, sbuf, &hints, &ai) == 0 &&
368: ai->ai_addrlen <= minsiz) {
369: if (statp->_u._ext.ext != NULL) {
370: memcpy(&statp->_u._ext.ext->nsaddrs[nserv],
371: ai->ai_addr, ai->ai_addrlen);
372: }
373: if (ai->ai_addrlen <=
374: sizeof(statp->nsaddr_list[nserv])) {
375: memcpy(&statp->nsaddr_list[nserv],
376: ai->ai_addr, ai->ai_addrlen);
377: } else
378: statp->nsaddr_list[nserv].sin_family = 0;
379: freeaddrinfo(ai);
380: nserv++;
381: }
382: }
383: continue;
384: }
385: #ifdef RESOLVSORT
386: if (MATCH(buf, "sortlist")) {
387: struct in_addr a;
388:
389: cp = buf + sizeof("sortlist") - 1;
390: while (nsort < MAXRESOLVSORT) {
391: while (*cp == ' ' || *cp == '\t')
392: cp++;
393: if (*cp == '\0' || *cp == '\n' || *cp == ';')
394: break;
395: net = cp;
396: while (*cp && !ISSORTMASK(*cp) && *cp != ';' &&
397: isascii(*cp) && !isspace((unsigned char)*cp))
398: cp++;
399: n = *cp;
400: *cp = 0;
401: if (inet_aton(net, &a)) {
402: statp->sort_list[nsort].addr = a;
403: if (ISSORTMASK(n)) {
404: *cp++ = n;
405: net = cp;
406: while (*cp && *cp != ';' &&
407: isascii(*cp) &&
408: !isspace((unsigned char)*cp))
409: cp++;
410: n = *cp;
411: *cp = 0;
412: if (inet_aton(net, &a)) {
413: statp->sort_list[nsort].mask = a.s_addr;
414: } else {
415: statp->sort_list[nsort].mask =
416: net_mask(statp->sort_list[nsort].addr);
417: }
418: } else {
419: statp->sort_list[nsort].mask =
420: net_mask(statp->sort_list[nsort].addr);
421: }
422: nsort++;
423: }
424: *cp = n;
425: }
426: continue;
427: }
428: #endif
429: if (MATCH(buf, "options")) {
430: res_setoptions(statp, buf + sizeof("options") - 1, "conf");
431: continue;
432: }
433: }
434: if (nserv > 0)
435: statp->nscount = nserv;
436: #ifdef RESOLVSORT
437: statp->nsort = nsort;
438: #endif
439: (void) fclose(fp);
440: }
441: /*
442: * Last chance to get a nameserver. This should not normally
443: * be necessary
444: */
445: #ifdef NO_RESOLV_CONF
446: if(nserv == 0)
447: nserv = get_nameservers(statp);
448: #endif
449:
450: if (statp->defdname[0] == 0 &&
451: gethostname(buf, sizeof(statp->defdname) - 1) == 0 &&
452: (cp = strchr(buf, '.')) != NULL)
453: strcpy(statp->defdname, cp + 1);
454:
455: /* find components of local domain that might be searched */
456: if (havesearch == 0) {
457: pp = statp->dnsrch;
458: *pp++ = statp->defdname;
459: *pp = NULL;
460:
461: dots = 0;
462: for (cp = statp->defdname; *cp; cp++)
463: dots += (*cp == '.');
464:
465: cp = statp->defdname;
466: while (pp < statp->dnsrch + MAXDFLSRCH) {
467: if (dots < LOCALDOMAINPARTS)
468: break;
1.1.1.2 christos 469: cp = strchr(cp, '.') + 1; /*%< we know there is one */
1.1 christos 470: *pp++ = cp;
471: dots--;
472: }
473: *pp = NULL;
474: #ifdef DEBUG
475: if (statp->options & RES_DEBUG) {
476: printf(";; res_init()... default dnsrch list:\n");
477: for (pp = statp->dnsrch; *pp; pp++)
478: printf(";;\t%s\n", *pp);
479: printf(";;\t..END..\n");
480: }
481: #endif
482: }
483:
484: if ((cp = getenv("RES_OPTIONS")) != NULL)
485: res_setoptions(statp, cp, "env");
486: statp->options |= RES_INIT;
487: return (0);
1.1.1.2 christos 488:
489: #ifdef SOLARIS2
490: freedata:
491: if (statp->_u._ext.ext != NULL) {
492: free(statp->_u._ext.ext);
493: statp->_u._ext.ext = NULL;
494: }
495: return (-1);
496: #endif
1.1 christos 497: }
498:
499: static void
500: res_setoptions(res_state statp, const char *options, const char *source)
501: {
502: const char *cp = options;
503: int i;
504: struct __res_state_ext *ext = statp->_u._ext.ext;
505:
506: #ifdef DEBUG
507: if (statp->options & RES_DEBUG)
508: printf(";; res_setoptions(\"%s\", \"%s\")...\n",
509: options, source);
510: #endif
511: while (*cp) {
512: /* skip leading and inner runs of spaces */
513: while (*cp == ' ' || *cp == '\t')
514: cp++;
515: /* search for and process individual options */
516: if (!strncmp(cp, "ndots:", sizeof("ndots:") - 1)) {
517: i = atoi(cp + sizeof("ndots:") - 1);
518: if (i <= RES_MAXNDOTS)
519: statp->ndots = i;
520: else
521: statp->ndots = RES_MAXNDOTS;
522: #ifdef DEBUG
523: if (statp->options & RES_DEBUG)
524: printf(";;\tndots=%d\n", statp->ndots);
525: #endif
526: } else if (!strncmp(cp, "timeout:", sizeof("timeout:") - 1)) {
527: i = atoi(cp + sizeof("timeout:") - 1);
528: if (i <= RES_MAXRETRANS)
529: statp->retrans = i;
530: else
531: statp->retrans = RES_MAXRETRANS;
532: #ifdef DEBUG
533: if (statp->options & RES_DEBUG)
534: printf(";;\ttimeout=%d\n", statp->retrans);
535: #endif
1.1.1.2 christos 536: #ifdef SOLARIS2
537: } else if (!strncmp(cp, "retrans:", sizeof("retrans:") - 1)) {
538: /*
539: * For backward compatibility, 'retrans' is
540: * supported as an alias for 'timeout', though
541: * without an imposed maximum.
542: */
543: statp->retrans = atoi(cp + sizeof("retrans:") - 1);
544: } else if (!strncmp(cp, "retry:", sizeof("retry:") - 1)){
545: /*
546: * For backward compatibility, 'retry' is
547: * supported as an alias for 'attempts', though
548: * without an imposed maximum.
549: */
550: statp->retry = atoi(cp + sizeof("retry:") - 1);
551: #endif /* SOLARIS2 */
1.1 christos 552: } else if (!strncmp(cp, "attempts:", sizeof("attempts:") - 1)){
553: i = atoi(cp + sizeof("attempts:") - 1);
554: if (i <= RES_MAXRETRY)
555: statp->retry = i;
556: else
557: statp->retry = RES_MAXRETRY;
558: #ifdef DEBUG
559: if (statp->options & RES_DEBUG)
560: printf(";;\tattempts=%d\n", statp->retry);
561: #endif
562: } else if (!strncmp(cp, "debug", sizeof("debug") - 1)) {
563: #ifdef DEBUG
564: if (!(statp->options & RES_DEBUG)) {
565: printf(";; res_setoptions(\"%s\", \"%s\")..\n",
566: options, source);
567: statp->options |= RES_DEBUG;
568: }
569: printf(";;\tdebug\n");
570: #endif
571: } else if (!strncmp(cp, "no_tld_query",
572: sizeof("no_tld_query") - 1) ||
573: !strncmp(cp, "no-tld-query",
574: sizeof("no-tld-query") - 1)) {
575: statp->options |= RES_NOTLDQUERY;
576: } else if (!strncmp(cp, "inet6", sizeof("inet6") - 1)) {
577: statp->options |= RES_USE_INET6;
578: } else if (!strncmp(cp, "rotate", sizeof("rotate") - 1)) {
579: statp->options |= RES_ROTATE;
580: } else if (!strncmp(cp, "no-check-names",
581: sizeof("no-check-names") - 1)) {
582: statp->options |= RES_NOCHECKNAME;
583: }
584: #ifdef RES_USE_EDNS0
585: else if (!strncmp(cp, "edns0", sizeof("edns0") - 1)) {
586: statp->options |= RES_USE_EDNS0;
587: }
588: #endif
589: else if (!strncmp(cp, "dname", sizeof("dname") - 1)) {
590: statp->options |= RES_USE_DNAME;
591: }
592: else if (!strncmp(cp, "nibble:", sizeof("nibble:") - 1)) {
593: if (ext == NULL)
594: goto skip;
595: cp += sizeof("nibble:") - 1;
596: i = MIN(strcspn(cp, " \t"), sizeof(ext->nsuffix) - 1);
597: strncpy(ext->nsuffix, cp, i);
598: ext->nsuffix[i] = '\0';
599: }
600: else if (!strncmp(cp, "nibble2:", sizeof("nibble2:") - 1)) {
601: if (ext == NULL)
602: goto skip;
603: cp += sizeof("nibble2:") - 1;
604: i = MIN(strcspn(cp, " \t"), sizeof(ext->nsuffix2) - 1);
605: strncpy(ext->nsuffix2, cp, i);
606: ext->nsuffix2[i] = '\0';
607: }
608: else if (!strncmp(cp, "v6revmode:", sizeof("v6revmode:") - 1)) {
609: cp += sizeof("v6revmode:") - 1;
610: /* "nibble" and "bitstring" used to be valid */
611: if (!strncmp(cp, "single", sizeof("single") - 1)) {
612: statp->options |= RES_NO_NIBBLE2;
613: } else if (!strncmp(cp, "both", sizeof("both") - 1)) {
614: statp->options &=
615: ~RES_NO_NIBBLE2;
616: }
617: }
618: else {
619: /* XXX - print a warning here? */
620: }
621: skip:
622: /* skip to next run of spaces */
623: while (*cp && *cp != ' ' && *cp != '\t')
624: cp++;
625: }
626: }
627:
628: #ifdef RESOLVSORT
629: /* XXX - should really support CIDR which means explicit masks always. */
630: static u_int32_t
1.1.1.2 christos 631: net_mask(in) /*!< XXX - should really use system's version of this */
1.1 christos 632: struct in_addr in;
633: {
634: register u_int32_t i = ntohl(in.s_addr);
635:
636: if (IN_CLASSA(i))
637: return (htonl(IN_CLASSA_NET));
638: else if (IN_CLASSB(i))
639: return (htonl(IN_CLASSB_NET));
640: return (htonl(IN_CLASSC_NET));
641: }
642: #endif
643:
644: u_int
645: res_randomid(void) {
646: struct timeval now;
647:
648: gettimeofday(&now, NULL);
649: return (0xffff & (now.tv_sec ^ now.tv_usec ^ getpid()));
650: }
651:
1.1.1.2 christos 652: /*%
1.1 christos 653: * This routine is for closing the socket if a virtual circuit is used and
654: * the program wants to close it. This provides support for endhostent()
655: * which expects to close the socket.
656: *
657: * This routine is not expected to be user visible.
658: */
659: void
660: res_nclose(res_state statp) {
661: int ns;
662:
663: if (statp->_vcsock >= 0) {
664: (void) close(statp->_vcsock);
665: statp->_vcsock = -1;
666: statp->_flags &= ~(RES_F_VC | RES_F_CONN);
667: }
668: for (ns = 0; ns < statp->_u._ext.nscount; ns++) {
669: if (statp->_u._ext.nssocks[ns] != -1) {
670: (void) close(statp->_u._ext.nssocks[ns]);
671: statp->_u._ext.nssocks[ns] = -1;
672: }
673: }
674: }
675:
676: void
677: res_ndestroy(res_state statp) {
678: res_nclose(statp);
679: if (statp->_u._ext.ext != NULL)
680: free(statp->_u._ext.ext);
681: statp->options &= ~RES_INIT;
682: statp->_u._ext.ext = NULL;
683: }
684:
685: const char *
686: res_get_nibblesuffix(res_state statp) {
687: if (statp->_u._ext.ext)
688: return (statp->_u._ext.ext->nsuffix);
689: return ("ip6.arpa");
690: }
691:
692: const char *
693: res_get_nibblesuffix2(res_state statp) {
694: if (statp->_u._ext.ext)
695: return (statp->_u._ext.ext->nsuffix2);
696: return ("ip6.int");
697: }
698:
699: void
700: res_setservers(res_state statp, const union res_sockaddr_union *set, int cnt) {
701: int i, nserv;
702: size_t size;
703:
704: /* close open servers */
705: res_nclose(statp);
706:
707: /* cause rtt times to be forgotten */
708: statp->_u._ext.nscount = 0;
709:
710: nserv = 0;
711: for (i = 0; i < cnt && nserv < MAXNS; i++) {
712: switch (set->sin.sin_family) {
713: case AF_INET:
714: size = sizeof(set->sin);
715: if (statp->_u._ext.ext)
716: memcpy(&statp->_u._ext.ext->nsaddrs[nserv],
717: &set->sin, size);
718: if (size <= sizeof(statp->nsaddr_list[nserv]))
719: memcpy(&statp->nsaddr_list[nserv],
720: &set->sin, size);
721: else
722: statp->nsaddr_list[nserv].sin_family = 0;
723: nserv++;
724: break;
725:
726: #ifdef HAS_INET6_STRUCTS
727: case AF_INET6:
728: size = sizeof(set->sin6);
729: if (statp->_u._ext.ext)
730: memcpy(&statp->_u._ext.ext->nsaddrs[nserv],
731: &set->sin6, size);
732: if (size <= sizeof(statp->nsaddr_list[nserv]))
733: memcpy(&statp->nsaddr_list[nserv],
734: &set->sin6, size);
735: else
736: statp->nsaddr_list[nserv].sin_family = 0;
737: nserv++;
738: break;
739: #endif
740:
741: default:
742: break;
743: }
744: set++;
745: }
746: statp->nscount = nserv;
747:
748: }
749:
750: int
751: res_getservers(res_state statp, union res_sockaddr_union *set, int cnt) {
752: int i;
753: size_t size;
754: u_int16_t family;
755:
756: for (i = 0; i < statp->nscount && i < cnt; i++) {
757: if (statp->_u._ext.ext)
758: family = statp->_u._ext.ext->nsaddrs[i].sin.sin_family;
759: else
760: family = statp->nsaddr_list[i].sin_family;
761:
762: switch (family) {
763: case AF_INET:
764: size = sizeof(set->sin);
765: if (statp->_u._ext.ext)
766: memcpy(&set->sin,
767: &statp->_u._ext.ext->nsaddrs[i],
768: size);
769: else
770: memcpy(&set->sin, &statp->nsaddr_list[i],
771: size);
772: break;
773:
774: #ifdef HAS_INET6_STRUCTS
775: case AF_INET6:
776: size = sizeof(set->sin6);
777: if (statp->_u._ext.ext)
778: memcpy(&set->sin6,
779: &statp->_u._ext.ext->nsaddrs[i],
780: size);
781: else
782: memcpy(&set->sin6, &statp->nsaddr_list[i],
783: size);
784: break;
785: #endif
786:
787: default:
788: set->sin.sin_family = 0;
789: break;
790: }
791: set++;
792: }
793: return (statp->nscount);
794: }
1.1.1.2 christos 795:
796: /*! \file */
CVSweb <webmaster@jp.NetBSD.org>