1 /* $NetBSD: res_init.c,v 1.30 2015/02/24 17:56:20 christos Exp $ */
4 * Copyright (c) 1985, 1989, 1993
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
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
37 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
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.
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
57 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
58 * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
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.
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.
73 #include "port_before.h"
75 #include <sys/types.h>
76 #include <sys/param.h>
77 #include <sys/socket.h>
80 #include <netinet/in.h>
81 #include <arpa/inet.h>
82 #include <arpa/nameser.h>
93 # include "../dst/md5.h"
100 # define _MD5_H_ 1 /*%< make sure we do not include rsaref md5.h file */
103 #include "port_after.h"
105 /* ensure that sockaddr_in6 and IN6ADDR_ANY_INIT are declared / defined */
108 #include <FindDirectory.h>
110 #include "res_private.h"
113 /*% Options. Should all be left alone. */
119 #include <sys/systeminfo.h>
122 static void res_setoptions(res_state
, const char *, const char *);
125 static const char sort_mask
[] = "/&";
126 #define ISSORTMASK(ch) (strchr(sort_mask, ch) != NULL)
127 static uint32_t net_mask
__P((struct in_addr
));
130 #if !defined(isascii) /*%< XXX - could be a function */
131 # define isascii(c) (!(c & 0200))
134 static const struct timespec ts
= { 0, 0 };
137 * Resolver state default settings.
141 * Set up default settings. If the configuration file exist, the values
142 * there will have precedence. Otherwise, the server address is set to
143 * INADDR_ANY and the default domain name comes from the gethostname().
145 * An interrim version of this code (BIND 4.9, pre-4.4BSD) used 127.0.0.1
146 * rather than INADDR_ANY ("0.0.0.0") as the default name server address
147 * since it was noted that INADDR_ANY actually meant ``the first interface
148 * you "ifconfig"'d at boot time'' and if this was a SLIP or PPP interface,
149 * it had to be "up" in order for you to reach your own name server. It
150 * was later decided that since the recommended practice is to always
151 * install local static routes through 127.0.0.1 for all your network
152 * interfaces, that we could solve this problem without a code change.
154 * The configuration file should always be used, since it is the only way
155 * to specify a default domain. If you are running a server on your local
156 * machine, you should say "nameserver 0.0.0.0" or "nameserver 127.0.0.1"
157 * in the configuration file.
159 * Return 0 if completes successfully, -1 on error
162 res_ninit(res_state statp
) {
163 return (__res_vinit(statp
, 0));
166 /*% This function has to be reachable by res_data.c but not publically. */
168 __res_vinit(res_state statp
, int preinit
) {
170 register char *cp
, **pp
;
174 int nserv
= 0; /*%< number of nameserver records read from file */
182 union res_sockaddr_union u
[2];
185 RES_SET_H_ERRNO(statp
, 0);
187 if ((statp
->options
& RES_INIT
) != 0U)
191 statp
->retrans
= RES_TIMEOUT
;
192 statp
->retry
= RES_DFLRETRY
;
193 statp
->options
= RES_DEFAULT
;
196 statp
->id
= res_nrandomid(statp
);
198 memset(u
, 0, sizeof(u
));
200 u
[nserv
].sin
.sin_addr
= inet_makeaddr(IN_LOOPBACKNET
, 1);
202 u
[nserv
].sin
.sin_addr
.s_addr
= INADDR_ANY
;
204 u
[nserv
].sin
.sin_family
= AF_INET
;
205 u
[nserv
].sin
.sin_port
= htons(NAMESERVER_PORT
);
207 u
[nserv
].sin
.sin_len
= sizeof(struct sockaddr_in
);
210 #ifdef HAS_INET6_STRUCTS
212 u
[nserv
].sin6
.sin6_addr
= in6addr_loopback
;
214 u
[nserv
].sin6
.sin6_addr
= in6addr_any
;
216 u
[nserv
].sin6
.sin6_family
= AF_INET6
;
217 u
[nserv
].sin6
.sin6_port
= htons(NAMESERVER_PORT
);
219 u
[nserv
].sin6
.sin6_len
= sizeof(struct sockaddr_in6
);
230 statp
->_u
._ext
.nscount
= 0;
231 statp
->_u
._ext
.ext
= malloc(sizeof(*statp
->_u
._ext
.ext
));
232 if (statp
->_u
._ext
.ext
!= NULL
) {
233 memset(statp
->_u
._ext
.ext
, 0, sizeof(*statp
->_u
._ext
.ext
));
234 statp
->_u
._ext
.ext
->nsaddrs
[0].sin
= statp
->nsaddr
;
235 strcpy(statp
->_u
._ext
.ext
->nsuffix
, "ip6.arpa");
236 strcpy(statp
->_u
._ext
.ext
->nsuffix2
, "ip6.int");
239 * Historically res_init() rarely, if at all, failed.
240 * Examples and applications exist which do not check
241 * our return code. Furthermore several applications
242 * simply call us to get the systems domainname. So
243 * rather than immediately fail here we store the
244 * failure, which is returned later, in h_errno. And
245 * prevent the collection of 'nameserver' information
246 * by setting maxns to 0. Thus applications that fail
247 * to check our return code wont be able to make
250 RES_SET_H_ERRNO(statp
, NETDB_INTERNAL
);
256 res_setservers(statp
, u
, nserv
);
260 * The old libresolv derived the defaultdomain from NIS/NIS+.
261 * We want to keep this behaviour
264 char buf
[sizeof(statp
->defdname
)], *cp
;
267 if ((ret
= sysinfo(SI_SRPC_DOMAIN
, buf
, sizeof(buf
))) > 0 &&
268 (unsigned int)ret
<= sizeof(buf
)) {
271 cp
= strchr(buf
, '.');
272 cp
= (cp
== NULL
) ? buf
: (cp
+ 1);
273 (void)strlcpy(statp
->defdname
, cp
,
274 sizeof(statp
->defdname
));
277 #endif /* SOLARIS2 */
279 /* Allow user to override the local domain definition */
280 if ((cp
= getenv("LOCALDOMAIN")) != NULL
) {
281 (void)strncpy(statp
->defdname
, cp
, sizeof(statp
->defdname
) - 1);
282 statp
->defdname
[sizeof(statp
->defdname
) - 1] = '\0';
286 * Set search list to be blank-separated strings
287 * from rest of env value. Permits users of LOCALDOMAIN
288 * to still have a search list, and anyone to set the
289 * one that they want to use as an individual (even more
290 * important now that the rfc1535 stuff restricts searches)
292 cp
= statp
->defdname
;
295 for (n
= 0; *cp
&& pp
< statp
->dnsrch
+ MAXDNSRCH
; cp
++) {
296 if (*cp
== '\n') /*%< silly backwards compat */
298 else if (*cp
== ' ' || *cp
== '\t') {
307 /* null terminate last domain if there are excess */
308 while (*cp
!= '\0' && *cp
!= ' ' && *cp
!= '\t' && *cp
!= '\n')
314 #define MATCH(line, name) \
315 (!strncmp(line, name, sizeof(name) - 1) && \
316 (line[sizeof(name) - 1] == ' ' || \
317 line[sizeof(name) - 1] == '\t'))
319 if (find_directory(B_SYSTEM_SETTINGS_DIRECTORY
, -1, false, path
,
320 sizeof(path
)) == B_OK
)
321 strlcat(path
, "/network/resolv.conf", sizeof(path
));
324 if ((fp
= fopen(path
, "re")) != NULL
) {
325 /* read the config file */
326 while (fgets(buf
, (int)sizeof(buf
), fp
) != NULL
) {
328 if (*buf
== ';' || *buf
== '#')
330 /* read default domain name */
331 if (MATCH(buf
, "domain")) {
332 if (haveenv
) /*%< skip if have from environ */
334 cp
= buf
+ sizeof("domain") - 1;
335 while (*cp
== ' ' || *cp
== '\t')
337 if ((*cp
== '\0') || (*cp
== '\n'))
339 strncpy(statp
->defdname
, cp
, sizeof(statp
->defdname
) - 1);
340 statp
->defdname
[sizeof(statp
->defdname
) - 1] = '\0';
341 if ((cp
= strpbrk(statp
->defdname
, " \t\n")) != NULL
)
346 /* set search list */
347 if (MATCH(buf
, "search")) {
348 if (haveenv
) /*%< skip if have from environ */
350 cp
= buf
+ sizeof("search") - 1;
351 while (*cp
== ' ' || *cp
== '\t')
353 if ((*cp
== '\0') || (*cp
== '\n'))
355 strncpy(statp
->defdname
, cp
, sizeof(statp
->defdname
) - 1);
356 statp
->defdname
[sizeof(statp
->defdname
) - 1] = '\0';
357 if ((cp
= strchr(statp
->defdname
, '\n')) != NULL
)
360 * Set search list to be blank-separated strings
363 cp
= statp
->defdname
;
366 for (n
= 0; *cp
&& pp
< statp
->dnsrch
+ MAXDNSRCH
; cp
++) {
367 if (*cp
== ' ' || *cp
== '\t') {
375 /* null terminate last domain if there are excess */
376 while (*cp
!= '\0' && *cp
!= ' ' && *cp
!= '\t')
383 /* read nameservers to query */
384 if (MATCH(buf
, "nameserver") && nserv
< maxns
) {
385 struct addrinfo hints
, *ai
;
386 char sbuf
[NI_MAXSERV
];
387 const size_t minsiz
=
388 sizeof(statp
->_u
._ext
.ext
->nsaddrs
[0]);
390 cp
= buf
+ sizeof("nameserver") - 1;
391 while (*cp
== ' ' || *cp
== '\t')
393 cp
[strcspn(cp
, ";# \t\n")] = '\0';
394 if ((*cp
!= '\0') && (*cp
!= '\n')) {
395 memset(&hints
, 0, sizeof(hints
));
396 hints
.ai_family
= PF_UNSPEC
;
397 hints
.ai_socktype
= SOCK_DGRAM
; /*dummy*/
398 hints
.ai_flags
= AI_NUMERICHOST
;
399 sprintf(sbuf
, "%u", NAMESERVER_PORT
);
400 if (getaddrinfo(cp
, sbuf
, &hints
, &ai
) == 0 &&
401 ai
->ai_addrlen
<= minsiz
) {
402 if (statp
->_u
._ext
.ext
!= NULL
) {
403 memcpy(&statp
->_u
._ext
.ext
->nsaddrs
[nserv
],
404 ai
->ai_addr
, ai
->ai_addrlen
);
406 if (ai
->ai_addrlen
<=
407 sizeof(statp
->nsaddr_list
[nserv
])) {
408 memcpy(&statp
->nsaddr_list
[nserv
],
409 ai
->ai_addr
, ai
->ai_addrlen
);
411 statp
->nsaddr_list
[nserv
].sin_family
= 0;
419 if (MATCH(buf
, "sortlist")) {
422 cp
= buf
+ sizeof("sortlist") - 1;
423 while (nsort
< MAXRESOLVSORT
) {
424 while (*cp
== ' ' || *cp
== '\t')
426 if (*cp
== '\0' || *cp
== '\n' || *cp
== ';')
429 while (*cp
&& !ISSORTMASK(*cp
) && *cp
!= ';' &&
430 isascii(*cp
) && !isspace((unsigned char)*cp
))
434 if (inet_aton(net
, &a
)) {
435 statp
->sort_list
[nsort
].addr
= a
;
439 while (*cp
&& *cp
!= ';' &&
441 !isspace((unsigned char)*cp
))
445 if (inet_aton(net
, &a
)) {
446 statp
->sort_list
[nsort
].mask
= a
.s_addr
;
448 statp
->sort_list
[nsort
].mask
=
449 net_mask(statp
->sort_list
[nsort
].addr
);
452 statp
->sort_list
[nsort
].mask
=
453 net_mask(statp
->sort_list
[nsort
].addr
);
462 if (MATCH(buf
, "options")) {
463 res_setoptions(statp
, buf
+ sizeof("options") - 1, "conf");
468 statp
->nscount
= nserv
;
470 statp
->nsort
= nsort
;
475 * Last chance to get a nameserver. This should not normally
478 #ifdef NO_RESOLV_CONF
480 nserv
= get_nameservers(statp
);
483 if (statp
->defdname
[0] == 0 &&
484 gethostname(buf
, sizeof(statp
->defdname
) - 1) == 0 &&
485 (cp
= strchr(buf
, '.')) != NULL
)
486 strcpy(statp
->defdname
, cp
+ 1);
488 /* find components of local domain that might be searched */
489 if (havesearch
== 0) {
491 *pp
++ = statp
->defdname
;
495 for (cp
= statp
->defdname
; *cp
; cp
++)
496 dots
+= (*cp
== '.');
498 cp
= statp
->defdname
;
499 while (pp
< statp
->dnsrch
+ MAXDFLSRCH
) {
500 if (dots
< LOCALDOMAINPARTS
)
502 cp
= strchr(cp
, '.') + 1; /*%< we know there is one */
508 if (statp
->options
& RES_DEBUG
) {
509 printf(";; res_init()... default dnsrch list:\n");
510 for (pp
= statp
->dnsrch
; *pp
; pp
++)
511 printf(";;\t%s\n", *pp
);
512 printf(";;\t..END..\n");
517 if ((cp
= getenv("RES_OPTIONS")) != NULL
)
518 res_setoptions(statp
, cp
, "env");
519 statp
->options
|= RES_INIT
;
520 return (statp
->res_h_errno
);
524 res_setoptions(res_state statp
, const char *options
, const char *source
)
526 const char *cp
= options
;
529 struct __res_state_ext
*ext
= statp
->_u
._ext
.ext
;
532 if (statp
->options
& RES_DEBUG
)
533 printf(";; res_setoptions(\"%s\", \"%s\")...\n",
537 /* skip leading and inner runs of spaces */
538 while (*cp
== ' ' || *cp
== '\t')
540 /* search for and process individual options */
541 if (!strncmp(cp
, "ndots:", sizeof("ndots:") - 1)) {
542 i
= atoi(cp
+ sizeof("ndots:") - 1);
543 if (i
<= RES_MAXNDOTS
)
546 statp
->ndots
= RES_MAXNDOTS
;
548 if (statp
->options
& RES_DEBUG
)
549 printf(";;\tndots=%d\n", statp
->ndots
);
551 } else if (!strncmp(cp
, "timeout:", sizeof("timeout:") - 1)) {
552 i
= atoi(cp
+ sizeof("timeout:") - 1);
553 if (i
<= RES_MAXRETRANS
)
556 statp
->retrans
= RES_MAXRETRANS
;
558 if (statp
->options
& RES_DEBUG
)
559 printf(";;\ttimeout=%d\n", statp
->retrans
);
562 } else if (!strncmp(cp
, "retrans:", sizeof("retrans:") - 1)) {
564 * For backward compatibility, 'retrans' is
565 * supported as an alias for 'timeout', though
566 * without an imposed maximum.
568 statp
->retrans
= atoi(cp
+ sizeof("retrans:") - 1);
569 } else if (!strncmp(cp
, "retry:", sizeof("retry:") - 1)){
571 * For backward compatibility, 'retry' is
572 * supported as an alias for 'attempts', though
573 * without an imposed maximum.
575 statp
->retry
= atoi(cp
+ sizeof("retry:") - 1);
576 #endif /* SOLARIS2 */
577 } else if (!strncmp(cp
, "attempts:", sizeof("attempts:") - 1)){
578 i
= atoi(cp
+ sizeof("attempts:") - 1);
579 if (i
<= RES_MAXRETRY
)
582 statp
->retry
= RES_MAXRETRY
;
584 if (statp
->options
& RES_DEBUG
)
585 printf(";;\tattempts=%d\n", statp
->retry
);
587 } else if (!strncmp(cp
, "debug", sizeof("debug") - 1)) {
589 if (!(statp
->options
& RES_DEBUG
)) {
590 printf(";; res_setoptions(\"%s\", \"%s\")..\n",
592 statp
->options
|= RES_DEBUG
;
594 printf(";;\tdebug\n");
596 } else if (!strncmp(cp
, "no_tld_query",
597 sizeof("no_tld_query") - 1) ||
598 !strncmp(cp
, "no-tld-query",
599 sizeof("no-tld-query") - 1)) {
600 statp
->options
|= RES_NOTLDQUERY
;
601 } else if (!strncmp(cp
, "inet6", sizeof("inet6") - 1)) {
602 statp
->options
|= RES_USE_INET6
;
603 } else if (!strncmp(cp
, "inet4", sizeof("inet4") - 1)) {
604 statp
->options
|= RES_USE_INET4
;
605 } else if (!strncmp(cp
, "rotate", sizeof("rotate") - 1)) {
606 statp
->options
|= RES_ROTATE
;
607 } else if (!strncmp(cp
, "no-check-names",
608 sizeof("no-check-names") - 1)) {
609 statp
->options
|= RES_NOCHECKNAME
;
612 else if (!strncmp(cp
, "edns0", sizeof("edns0") - 1)) {
613 statp
->options
|= RES_USE_EDNS0
;
616 else if (!strncmp(cp
, "dname", sizeof("dname") - 1)) {
617 statp
->options
|= RES_USE_DNAME
;
619 else if (!strncmp(cp
, "nibble:", sizeof("nibble:") - 1)) {
622 cp
+= sizeof("nibble:") - 1;
623 j
= MIN(strcspn(cp
, " \t"), sizeof(ext
->nsuffix
) - 1);
624 strncpy(ext
->nsuffix
, cp
, j
);
625 ext
->nsuffix
[j
] = '\0';
627 else if (!strncmp(cp
, "nibble2:", sizeof("nibble2:") - 1)) {
630 cp
+= sizeof("nibble2:") - 1;
631 j
= MIN(strcspn(cp
, " \t"), sizeof(ext
->nsuffix2
) - 1);
632 strncpy(ext
->nsuffix2
, cp
, j
);
633 ext
->nsuffix2
[j
] = '\0';
635 else if (!strncmp(cp
, "v6revmode:", sizeof("v6revmode:") - 1)) {
636 cp
+= sizeof("v6revmode:") - 1;
637 /* "nibble" and "bitstring" used to be valid */
638 if (!strncmp(cp
, "single", sizeof("single") - 1)) {
639 statp
->options
|= RES_NO_NIBBLE2
;
640 } else if (!strncmp(cp
, "both", sizeof("both") - 1)) {
646 /* XXX - print a warning here? */
649 /* skip to next run of spaces */
650 while (*cp
&& *cp
!= ' ' && *cp
!= '\t')
656 /* XXX - should really support CIDR which means explicit masks always. */
658 net_mask(struct in_addr in
) /*!< XXX - should really use system's version of this */
660 register uint32_t i
= ntohl(in
.s_addr
);
663 return (htonl(IN_CLASSA_NET
));
664 else if (IN_CLASSB(i
))
665 return (htonl(IN_CLASSB_NET
));
666 return (htonl(IN_CLASSC_NET
));
671 res_rndinit(res_state statp
)
676 u_char
*rnd
= statp
->_rnd
;
678 gettimeofday(&now
, NULL
);
679 u32
= (uint32_t)now
.tv_sec
;
680 memcpy(rnd
, &u32
, 4);
682 memcpy(rnd
+ 4, &u32
, 4);
683 u32
+= (uint32_t)now
.tv_sec
;
684 memcpy(rnd
+ 8, &u32
, 4);
686 memcpy(rnd
+ 12, &u16
, 2);
690 res_nrandomid(res_state statp
)
695 u_char
*rnd
= statp
->_rnd
;
697 gettimeofday(&now
, NULL
);
698 u16
= (uint16_t) (now
.tv_sec
^ now
.tv_usec
);
699 memcpy(rnd
+ 14, &u16
, 2);
702 MD5_Update(&ctx
, rnd
, 16);
703 MD5_Final(rnd
, &ctx
);
706 MD5Update(&ctx
, rnd
, 16);
709 memcpy(&u16
, rnd
+ 14, 2);
710 return ((u_int
) u16
);
714 * This routine is for closing the socket if a virtual circuit is used and
715 * the program wants to close it. This provides support for endhostent()
716 * which expects to close the socket.
718 * This routine is not expected to be user visible.
721 res_nclose(res_state statp
)
725 if (statp
->_vcsock
>= 0) {
726 (void) close(statp
->_vcsock
);
728 statp
->_flags
&= ~(RES_F_VC
| RES_F_CONN
);
730 for (ns
= 0; ns
< statp
->_u
._ext
.nscount
; ns
++) {
731 if (statp
->_u
._ext
.nssocks
[ns
] != -1) {
732 (void) close(statp
->_u
._ext
.nssocks
[ns
]);
733 statp
->_u
._ext
.nssocks
[ns
] = -1;
739 res_ndestroy(res_state statp
)
742 if (statp
->_u
._ext
.ext
!= NULL
) {
743 if (statp
->_u
._ext
.ext
->kq
!= -1)
744 (void)close(statp
->_u
._ext
.ext
->kq
);
745 if (statp
->_u
._ext
.ext
->resfd
!= -1)
746 (void)close(statp
->_u
._ext
.ext
->resfd
);
747 free(statp
->_u
._ext
.ext
);
748 statp
->_u
._ext
.ext
= NULL
;
750 statp
->options
&= ~RES_INIT
;
754 res_get_nibblesuffix(res_state statp
)
756 if (statp
->_u
._ext
.ext
)
757 return (statp
->_u
._ext
.ext
->nsuffix
);
762 res_get_nibblesuffix2(res_state statp
)
764 if (statp
->_u
._ext
.ext
)
765 return (statp
->_u
._ext
.ext
->nsuffix2
);
770 res_setservers(res_state statp
, const union res_sockaddr_union
*set
, int cnt
)
775 /* close open servers */
778 /* cause rtt times to be forgotten */
779 statp
->_u
._ext
.nscount
= 0;
782 for (i
= 0; i
< cnt
&& nserv
< MAXNS
; i
++) {
783 switch (set
->sin
.sin_family
) {
785 size
= sizeof(set
->sin
);
786 if (statp
->_u
._ext
.ext
)
787 memcpy(&statp
->_u
._ext
.ext
->nsaddrs
[nserv
],
789 if (size
<= sizeof(statp
->nsaddr_list
[nserv
]))
790 memcpy(&statp
->nsaddr_list
[nserv
],
793 statp
->nsaddr_list
[nserv
].sin_family
= 0;
797 #ifdef HAS_INET6_STRUCTS
799 size
= sizeof(set
->sin6
);
800 if (statp
->_u
._ext
.ext
)
801 memcpy(&statp
->_u
._ext
.ext
->nsaddrs
[nserv
],
803 if (size
<= sizeof(statp
->nsaddr_list
[nserv
]))
804 memcpy(&statp
->nsaddr_list
[nserv
],
807 statp
->nsaddr_list
[nserv
].sin_family
= 0;
817 statp
->nscount
= nserv
;
822 res_getservers(res_state statp
, union res_sockaddr_union
*set
, int cnt
)
828 for (i
= 0; i
< statp
->nscount
&& i
< cnt
; i
++) {
829 if (statp
->_u
._ext
.ext
)
830 family
= statp
->_u
._ext
.ext
->nsaddrs
[i
].sin
.sin_family
;
832 family
= statp
->nsaddr_list
[i
].sin_family
;
836 size
= sizeof(set
->sin
);
837 if (statp
->_u
._ext
.ext
)
839 &statp
->_u
._ext
.ext
->nsaddrs
[i
],
842 memcpy(&set
->sin
, &statp
->nsaddr_list
[i
],
846 #ifdef HAS_INET6_STRUCTS
848 size
= sizeof(set
->sin6
);
849 if (statp
->_u
._ext
.ext
)
851 &statp
->_u
._ext
.ext
->nsaddrs
[i
],
854 memcpy(&set
->sin6
, &statp
->nsaddr_list
[i
],
860 set
->sin
.sin_family
= 0;
865 return (statp
->nscount
);