2 * Copyright (c) 1985, 1989, 1993
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
35 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
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.
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
55 * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
57 * Permission to use, copy, modify, and distribute this software for any
58 * purpose with or without fee is hereby granted, provided that the above
59 * copyright notice and this permission notice appear in all copies.
61 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
62 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
63 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
64 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
65 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
66 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
67 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
71 #if defined(LIBC_SCCS) && !defined(lint)
72 static const char sccsid
[] = "@(#)res_init.c 8.1 (Berkeley) 6/7/93";
73 static const char rcsid
[] = "$Id: res_init.c,v 1.1 2006/03/01 19:01:38 majka Exp $";
74 #endif /* LIBC_SCCS and not lint */
77 #include "port_before.h"
80 #include <sys/types.h>
81 #include <sys/param.h>
82 #include <sys/socket.h>
85 #include <netinet/in.h>
86 #include <arpa/inet.h>
87 #include <arpa/nameser.h>
101 #include "port_after.h"
104 /* ensure that sockaddr_in6 and IN6ADDR_ANY_INIT are declared / defined */
107 #include "res_private.h"
109 /* Options. Should all be left alone. */
113 static void res_setoptions
__P((res_state
, const char *, const char *));
114 extern res_state
res_state_new();
117 static const char sort_mask
[] = "/&";
118 #define ISSORTMASK(ch) (strchr(sort_mask, ch) != NULL)
119 static u_int32_t net_mask
__P((struct in_addr
));
122 #if !defined(isascii) /* XXX - could be a function */
123 # define isascii(c) (!(c & 0200))
126 #define INET_NTOP_AF_INET_OFFSET 4
127 #define INET_NTOP_AF_INET6_OFFSET 8
130 * Resolver state default settings.
134 res_build_start(res_state x
)
143 res
= res_state_new();
147 if ((x
->options
& RES_INIT
) != 0) res_ndestroy(x
);
151 if (res
== NULL
) return NULL
;
153 /* res_ndestroy frees _u._ext.ext so we create a new one if necessary */
154 if (res
->_u
._ext
.ext
== NULL
) res
->_u
._ext
.ext
= (struct __res_state_ext
*)calloc(1, sizeof(struct __res_state_ext
));
156 /* make sure version is set */
159 res
->retry
= RES_DFLRETRY
;
160 res
->options
= RES_DEFAULT
;
162 rf
= open("/dev/random", O_RDONLY
, 0);
163 read(rf
, &(res
->id
), 2);
169 if (res
->_u
._ext
.ext
!= NULL
)
171 strcpy(res
->_u
._ext
.ext
->nsuffix
, "ip6.arpa");
172 strcpy(res
->_u
._ext
.ext
->nsuffix2
, "ip6.int");
173 strcpy(res
->_u
._ext
.ext
->bsuffix
, "ip6.arpa");
180 res_build_finish(res_state res
, uint32_t timeout
, uint16_t port
)
182 if (res
== NULL
) return -1;
184 if (res
->nscount
== 0)
187 res
->nsaddr_list
[0].sin_addr
= inet_makeaddr(IN_LOOPBACKNET
, 1);
189 res
->nsaddr_list
[0].sin_addr
.s_addr
= INADDR_ANY
;
192 res
->nsaddr_list
[0].sin_family
= AF_INET
;
193 res
->nsaddr_list
[0].sin_port
= htons(port
);
195 res
->nsaddr_list
[0].sin_len
= sizeof(struct sockaddr_in
);
201 * Force loopback queries to use TCP
202 * so we don't take a timeout if named isn't running.
204 res
->options
|= RES_USEVC
;
207 if (timeout
== 0) res
->retrans
= RES_MAXRETRANS
;
208 else res
->retrans
= timeout
;
210 res
->options
|= RES_INIT
;
215 res_build_sortlist(res_state res
, struct in_addr addr
, struct in_addr mask
)
219 if (res
== NULL
) return -1;
222 if (n
>= MAXRESOLVSORT
) return -1;
224 res
->sort_list
[n
].addr
= addr
;
225 res
->sort_list
[n
].mask
= mask
.s_addr
;
233 res_next_word(char **p
)
237 if (p
== NULL
) return NULL
;
238 if (*p
== NULL
) return NULL
;
242 /* Skip leading white space */
243 while ((*s
== ' ') || (*s
== '\t') || (*s
== '\n')) s
++;
246 if (*s
== '\0') return NULL
;
248 /* Find end of word */
250 while ((*x
!= ' ') && (*x
!= '\t') && (*x
!= '\n') && (*x
!= '\0')) x
++;
259 if (s
== x
) return NULL
;
264 res_build(res_state res
, uint16_t port
, uint32_t *nsrch
, char *key
, char *val
)
266 int32_t dotcount
, semicount
, status
;
270 struct in_addr addr4
, mask
;
271 struct sockaddr_in sin4
;
272 struct in6_addr addr6
;
273 struct sockaddr_in6 sin6
;
275 if (res
== NULL
) return -1;
277 if (!strcmp(key
, "domain"))
279 strncpy(res
->defdname
, val
, sizeof(res
->defdname
) - 1);
280 res
->defdname
[sizeof(res
->defdname
) - 1] = '\0';
284 else if (!strcmp(key
, "search"))
286 len
= strlen(val
) + 1;
287 ival
= sizeof(res
->defdname
);
292 memset(res
->defdname
, 0, sizeof(res
->defdname
));
296 p
= res
->dnsrch
[*nsrch
- 1];
297 for (; (ival
> 0) && (*p
!= '\0'); ival
--) p
++;
301 if (len
> ival
) return -1;
304 res
->dnsrch
[*nsrch
] = p
;
309 else if (!strcmp(key
, "nameserver"))
316 for (p
= val
; *p
!= '\0'; p
++)
318 if (*p
== ':') semicount
++;
326 if ((dotcount
== 4) || ((semicount
> 0) && (lastdot
!= NULL
)))
328 aport
= atoi(lastdot
+ 1);
329 if (aport
== 0) aport
= port
;
333 memset(&addr4
, 0, sizeof(struct in_addr
));
334 memset(&sin4
, 0, sizeof(struct sockaddr_in
));
336 memset(&addr6
, 0, sizeof(struct in6_addr
));
337 memset(&sin6
, 0, sizeof(struct sockaddr_in6
));
339 status
= inet_pton(AF_INET6
, val
, &addr6
);
342 sin6
.sin6_addr
= addr6
;
343 sin6
.sin6_family
= AF_INET6
;
344 sin6
.sin6_port
= htons(aport
);
345 sin6
.sin6_len
= sizeof(struct sockaddr_in6
);
346 if (res
->_u
._ext
.ext
!= NULL
)
348 memcpy(&(res
->_u
._ext
.ext
->nsaddrs
[res
->nscount
]), &sin6
, sizeof(struct sockaddr_in6
));
350 res
->nsaddr_list
[res
->nscount
].sin_family
= 0;
355 status
= inet_pton(AF_INET
, val
, &addr4
);
358 sin4
.sin_addr
= addr4
;
359 sin4
.sin_family
= AF_INET
;
360 sin4
.sin_port
= htons(aport
);
361 sin4
.sin_len
= sizeof(struct sockaddr_in
);
362 if (res
->_u
._ext
.ext
!= NULL
)
364 memcpy(&(res
->_u
._ext
.ext
->nsaddrs
[res
->nscount
]), &sin4
, sizeof(struct sockaddr_in
));
366 memcpy(&(res
->nsaddr_list
[res
->nscount
]), &sin4
, sizeof(struct sockaddr_in
));
374 else if (!strcmp(key
, "sortlist"))
376 p
= strchr(val
, '/');
384 /* we use inet_aton rather than inet_pton to be compatible with res_init() */
385 status
= inet_aton(val
, &addr4
);
386 if (status
== 0) return -1;
389 if (p
!= NULL
) status
= inet_aton(p
, &mask
);
392 ival
= ntohl(addr4
.s_addr
);
394 if (IN_CLASSA(ival
)) mask
.s_addr
= htonl(IN_CLASSA_NET
);
395 else if (IN_CLASSB(ival
)) mask
.s_addr
= htonl(IN_CLASSB_NET
);
396 else mask
.s_addr
= htonl(IN_CLASSC_NET
);
399 return res_build_sortlist(res
, addr4
, mask
);
402 else if (!strcmp(key
, "ndots"))
405 if (ival
< 0) ival
= 0;
406 if (ival
> RES_MAXNDOTS
) ival
= RES_MAXNDOTS
;
411 else if (!strcmp(key
, "nibble"))
413 if ((strlen(val
) + 1) > RES_EXT_SUFFIX_LEN
) return -1;
414 if (res
->_u
._ext
.ext
== NULL
) return -1;
415 strcpy(res
->_u
._ext
.ext
->nsuffix
, val
);
419 else if (!strcmp(key
, "nibble2"))
421 if ((strlen(val
) + 1) > RES_EXT_SUFFIX_LEN
) return -1;
422 if (res
->_u
._ext
.ext
== NULL
) return -1;
423 strcpy(res
->_u
._ext
.ext
->nsuffix2
, val
);
427 else if (!strcmp(key
, "bitstring"))
429 if ((strlen(val
) + 1) > RES_EXT_SUFFIX_LEN
) return -1;
430 if (res
->_u
._ext
.ext
== NULL
) return -1;
431 strcpy(res
->_u
._ext
.ext
->bsuffix
, val
);
435 else if (!strcmp(key
, "attempts"))
438 if (ival
< 0) ival
= 0;
439 if (ival
> RES_MAXRETRY
) ival
= RES_MAXRETRY
;
444 else if (!strcmp(key
, "v6revmode"))
446 if (!strcmp(val
, "single")) res
->options
|= RES_NO_NIBBLE2
;
447 else if (!strcmp(val
, "both")) res
->options
&= ~RES_NO_NIBBLE2
;
451 else if (!strcmp(key
, "debug"))
453 res
->options
|= RES_DEBUG
;
457 else if (!strcmp(key
, "no_tld_query"))
459 res
->options
|= RES_NOTLDQUERY
;
463 else if (!strcmp(key
, "inet6"))
465 res
->options
|= RES_USE_INET6
;
469 else if (!strcmp(key
, "rotate"))
471 res
->options
|= RES_ROTATE
;
475 else if (!strcmp(key
, "no-check-names"))
477 res
->options
|= RES_NOCHECKNAME
;
482 else if (!strcmp(key
, "edns0"))
484 res
->options
|= RES_USE_EDNS0
;
489 else if (!strcmp(key
, "a6"))
491 res
->options
|= RES_USE_A6
;
495 else if (!strcmp(key
, "dname"))
497 res
->options
|= RES_USE_DNAME
;
505 * Set up default settings. If the configuration file exist, the values
506 * there will have precedence. Otherwise, the server address is set to
507 * INADDR_ANY and the default domain name comes from the gethostname().
509 * An interrim version of this code (BIND 4.9, pre-4.4BSD) used 127.0.0.1
510 * rather than INADDR_ANY ("0.0.0.0") as the default name server address
511 * since it was noted that INADDR_ANY actually meant ``the first interface
512 * you "ifconfig"'d at boot time'' and if this was a SLIP or PPP interface,
513 * it had to be "up" in order for you to reach your own name server. It
514 * was later decided that since the recommended practice is to always
515 * install local static routes through 127.0.0.1 for all your network
516 * interfaces, that we could solve this problem without a code change.
518 * The configuration file should always be used, since it is the only way
519 * to specify a default domain. If you are running a server on your local
520 * machine, you should say "nameserver 0.0.0.0" or "nameserver 127.0.0.1"
521 * in the configuration file.
523 * Return 0 if completes successfully, -1 on error
527 res_vinit_from_file(res_state statp
, int preinit
, char *resconf_file
)
530 register char *cp
, **pp
;
533 int nserv
= 0; /* number of nameserver records read from file */
536 int isresdefault
= 0;
537 unsigned short port
; /* HOST BYTE ORDER */
538 unsigned int i
, total_timeout
;
545 port
= NS_DEFAULTPORT
;
550 statp
->retrans
= RES_TIMEOUT
;
551 statp
->retry
= RES_DFLRETRY
;
552 statp
->options
= RES_DEFAULT
;
553 statp
->id
= res_randomid();
556 if ((statp
->options
& RES_INIT
) != 0) res_ndestroy(statp
);
558 /* N.B. we allocate a new statp->_u._ext.ext below */
560 /* make sure version is set */
565 if ((resconf_file
== NULL
) || (!strcmp(resconf_file
, _PATH_RESCONF
)))
570 statp
->nsaddr
.sin_addr
= inet_makeaddr(IN_LOOPBACKNET
, 1);
572 statp
->nsaddr
.sin_addr
.s_addr
= INADDR_ANY
;
574 statp
->nsaddr
.sin_family
= AF_INET
;
575 statp
->nsaddr
.sin_port
= htons(NS_DEFAULTPORT
);
577 statp
->nsaddr
.sin_len
= sizeof(struct sockaddr_in
);
582 * Force loopback queries to use TCP
583 * so we don't take a timeout if named isn't running.
585 statp
->options
|= RES_USEVC
;
595 statp
->_u
._ext
.nscount
= 0;
596 statp
->_u
._ext
.ext
= (struct __res_state_ext
*)calloc(1, sizeof(struct __res_state_ext
));
598 if (statp
->_u
._ext
.ext
!= NULL
)
600 memset(statp
->_u
._ext
.ext
, 0, sizeof(*statp
->_u
._ext
.ext
));
601 statp
->_u
._ext
.ext
->nsaddrs
[0].sin
= statp
->nsaddr
;
602 strcpy(statp
->_u
._ext
.ext
->nsuffix
, "ip6.arpa");
603 strcpy(statp
->_u
._ext
.ext
->nsuffix2
, "ip6.int");
604 strcpy(statp
->_u
._ext
.ext
->bsuffix
, "ip6.arpa");
611 /* Allow user to override the local domain definition */
612 cp
= getenv("LOCALDOMAIN");
613 if ((cp
!= NULL
) && (isresdefault
!= 0))
615 (void)strncpy(statp
->defdname
, cp
, sizeof(statp
->defdname
) - 1);
616 statp
->defdname
[sizeof(statp
->defdname
) - 1] = '\0';
620 * Set search list to be blank-separated strings
621 * from rest of env value. Permits users of LOCALDOMAIN
622 * to still have a search list, and anyone to set the
623 * one that they want to use as an individual (even more
624 * important now that the rfc1535 stuff restricts searches)
626 cp
= statp
->defdname
;
629 for (n
= 0; *cp
&& pp
< statp
->dnsrch
+ MAXDNSRCH
; cp
++)
631 if (*cp
== '\n') break;
632 else if (*cp
== ' ' || *cp
== '\t')
645 /* null terminate last domain if there are excess */
646 while ((*cp
!= '\0') && (*cp
!= ' ') && (*cp
!= '\t') && (*cp
!= '\n')) cp
++;
651 #define MATCH(line, name) \
652 (!strncmp(line, name, sizeof(name) - 1) && \
653 (line[sizeof(name) - 1] == ' ' || \
654 line[sizeof(name) - 1] == '\t'))
656 if (resconf_file
== NULL
) resconf_file
= _PATH_RESCONF
;
658 if ((fp
= fopen(resconf_file
, "r")) != NULL
)
660 /* look for port number */
661 while (fgets(buf
, sizeof(buf
), fp
) != NULL
)
664 if (*buf
== ';' || *buf
== '#') continue;
666 /* read default domain name */
667 if (MATCH(buf
, "port"))
669 cp
= buf
+ sizeof("port") - 1;
670 while (*cp
== ' ' || *cp
== '\t') cp
++;
671 if ((*cp
== '\0') || (*cp
== '\n')) continue;
679 if ((fp
= fopen(resconf_file
, "r")) != NULL
)
681 /* read the config file */
682 while (fgets(buf
, sizeof(buf
), fp
) != NULL
)
685 if ((*buf
== ';') || (*buf
== '#')) continue;
687 /* read default domain name */
688 if (MATCH(buf
, "domain"))
690 /* skip if have from environ */
691 if (haveenv
) continue;
693 cp
= buf
+ sizeof("domain") - 1;
694 while ((*cp
== ' ') || (*cp
== '\t')) cp
++;
695 if ((*cp
== '\0') || (*cp
== '\n')) continue;
697 strncpy(statp
->defdname
, cp
, sizeof(statp
->defdname
) - 1);
698 statp
->defdname
[sizeof(statp
->defdname
) - 1] = '\0';
699 cp
= strpbrk(statp
->defdname
, " \t\n");
700 if (cp
!= NULL
) *cp
= '\0';
705 /* set search list */
706 if (MATCH(buf
, "search"))
708 /* skip if have from environ */
709 if (haveenv
) continue;
711 cp
= buf
+ sizeof("search") - 1;
712 while ((*cp
== ' ') || (*cp
== '\t')) cp
++;
713 if ((*cp
== '\0') || (*cp
== '\n')) continue;
715 strncpy(statp
->defdname
, cp
, sizeof(statp
->defdname
) - 1);
716 statp
->defdname
[sizeof(statp
->defdname
) - 1] = '\0';
717 cp
= strchr(statp
->defdname
, '\n');
718 if (cp
!= NULL
) *cp
= '\0';
721 * Set search list to be blank-separated strings
724 cp
= statp
->defdname
;
727 for (n
= 0; *cp
&& pp
< statp
->dnsrch
+ MAXDNSRCH
; cp
++)
729 if ((*cp
== ' ') || (*cp
== '\t'))
741 /* null terminate last domain if there are excess */
742 while ((*cp
!= '\0') && (*cp
!= ' ') && (*cp
!= '\t')) cp
++;
749 /* read nameservers to query */
750 if (MATCH(buf
, "nameserver") && (nserv
< MAXNS
))
753 struct addrinfo hints
, *ai
;
755 int dotcount
, semicount
, status
;
756 struct in_addr addr4
;
757 struct sockaddr_in sin4
;
758 struct in6_addr addr6
;
759 struct sockaddr_in6 sin6
;
760 unsigned short aport
; /* HOST BYTE ORDER */
761 char *lastdot
, *checkp
;
762 char sbuf
[NI_MAXSERV
];
764 const size_t minsiz
= sizeof(statp
->_u
._ext
.ext
->nsaddrs
[0]);
767 cp
= buf
+ sizeof("nameserver") - 1;
768 while ((*cp
== ' ') || (*cp
== '\t')) cp
++;
769 cp
[strcspn(cp
, ";# \t\n")] = '\0';
770 if ((*cp
!= '\0') && (*cp
!= '\n'))
773 memset(&hints
, 0, sizeof(hints
));
774 hints
.ai_family
= PF_UNSPEC
;
775 hints
.ai_socktype
= SOCK_DGRAM
; /*dummy*/
776 hints
.ai_flags
= AI_NUMERICHOST
;
783 for (checkp
= cp
; *checkp
!= '\0'; checkp
++)
785 if (*checkp
== ':') semicount
++;
786 else if (*checkp
== '.')
793 if ((dotcount
== 4) || ((semicount
> 0) && (lastdot
!= NULL
)))
795 aport
= atoi(lastdot
+ 1);
796 if (aport
== 0) aport
= port
;
800 sprintf(sbuf
, "%u", aport
);
803 memset(&addr4
, 0, sizeof(struct in_addr
));
804 memset(&sin4
, 0, sizeof(struct sockaddr_in
));
806 memset(&addr6
, 0, sizeof(struct in6_addr
));
807 memset(&sin6
, 0, sizeof(struct sockaddr_in6
));
809 status
= inet_pton(AF_INET6
, cp
, &addr6
);
812 sin6
.sin6_addr
= addr6
;
813 sin6
.sin6_family
= AF_INET6
;
814 sin6
.sin6_port
= htons(aport
);
815 sin6
.sin6_len
= sizeof(struct sockaddr_in6
);
816 if (statp
->_u
._ext
.ext
!= NULL
)
818 memcpy(&statp
->_u
._ext
.ext
->nsaddrs
[nserv
], &sin6
, sizeof(struct sockaddr_in6
));
820 statp
->nsaddr_list
[nserv
].sin_family
= 0;
825 status
= inet_pton(AF_INET
, cp
, &addr4
);
828 sin4
.sin_addr
= addr4
;
829 sin4
.sin_family
= AF_INET
;
830 sin4
.sin_port
= htons(port
);
831 sin4
.sin_len
= sizeof(struct sockaddr_in
);
832 if (statp
->_u
._ext
.ext
!= NULL
)
834 memcpy(&statp
->_u
._ext
.ext
->nsaddrs
[nserv
], &sin4
, sizeof(struct sockaddr_in
));
836 memcpy(&statp
->nsaddr_list
[nserv
], &sin4
, sizeof(struct sockaddr_in
));
843 if (getaddrinfo(cp
, sbuf
, &hints
, &ai
) == 0 && ai
->ai_addrlen
<= minsiz
)
845 if (statp
->_u
._ext
.ext
!= NULL
)
847 memcpy(&statp
->_u
._ext
.ext
->nsaddrs
[nserv
], ai
->ai_addr
, ai
->ai_addrlen
);
850 if (ai
->ai_addrlen
<= sizeof(statp
->nsaddr_list
[nserv
]))
852 memcpy(&statp
->nsaddr_list
[nserv
], ai
->ai_addr
, ai
->ai_addrlen
);
856 statp
->nsaddr_list
[nserv
].sin_family
= 0;
869 if (MATCH(buf
, "sortlist"))
873 cp
= buf
+ sizeof("sortlist") - 1;
874 while (nsort
< MAXRESOLVSORT
)
876 while ((*cp
== ' ') || (*cp
== '\t')) cp
++;
877 if ((*cp
== '\0') || (*cp
== '\n') || (*cp
== ';')) break;
880 while (*cp
&& !ISSORTMASK(*cp
) && (*cp
!= ';') && isascii(*cp
) && !isspace((unsigned char)*cp
)) cp
++;
883 if (inet_aton(net
, &a
))
885 statp
->sort_list
[nsort
].addr
= a
;
890 while (*cp
&& (*cp
!= ';') && isascii(*cp
) && !isspace((unsigned char)*cp
)) cp
++;
893 if (inet_aton(net
, &a
))
895 statp
->sort_list
[nsort
].mask
= a
.s_addr
;
899 statp
->sort_list
[nsort
].mask
= net_mask(statp
->sort_list
[nsort
].addr
);
904 statp
->sort_list
[nsort
].mask
= net_mask(statp
->sort_list
[nsort
].addr
);
916 if (MATCH(buf
, "options"))
918 res_setoptions(statp
, buf
+ sizeof("options") - 1, "conf");
922 if (MATCH(buf
, "timeout"))
924 cp
= buf
+ sizeof("timeout") - 1;
925 while (*cp
== ' ' || *cp
== '\t') cp
++;
926 if ((*cp
== '\0') || (*cp
== '\n')) continue;
928 if (i
> RES_MAXRETRANS
) i
= RES_MAXRETRANS
;
934 if (nserv
> 1) statp
->nscount
= nserv
;
936 statp
->nsort
= nsort
;
942 * Last chance to get a nameserver. This should not normally
945 #ifdef NO_RESOLV_CONF
946 if(nserv
== 0) nserv
= get_nameservers(statp
);
949 if (isresdefault
!= 0)
951 if ((statp
->defdname
[0] == 0) && (gethostname(buf
, sizeof(statp
->defdname
) - 1) == 0) && ((cp
= strchr(buf
, '.')) != NULL
))
953 strcpy(statp
->defdname
, cp
+ 1);
957 /* find components of local domain that might be searched */
961 *pp
++ = statp
->defdname
;
965 for (cp
= statp
->defdname
; *cp
; cp
++)
967 if (*cp
== '.') dots
++;
970 /* Back up over any trailing dots and cut them out of the name */
971 for (cp
--; (cp
>= statp
->defdname
) && (*cp
== '.'); cp
--)
977 cp
= statp
->defdname
;
978 while (pp
< statp
->dnsrch
+ MAXDFLSRCH
)
980 if (dots
< LOCALDOMAINPARTS
) break;
982 /* we know there is a dot */
983 cp
= strchr(cp
, '.') + 1;
990 if (statp
->options
& RES_DEBUG
)
992 printf(";; res_init()... default dnsrch list:\n");
993 for (pp
= statp
->dnsrch
; *pp
; pp
++) printf(";;\t%s\n", *pp
);
994 printf(";;\t..END..\n");
999 cp
= getenv("RES_OPTIONS");
1000 if ((cp
!= NULL
) && (isresdefault
!= 0))
1002 res_setoptions(statp
, cp
, "env");
1007 * Post processing to set the timeout value.
1009 if (total_timeout
!= 0)
1011 /* Timeout was set with a "timeout" line in the file */
1012 statp
->retrans
= total_timeout
;
1017 * Timeout is default, or was set with "options timeout:"
1018 * This is a per-select timeout value. Calculate total timeout
1019 * and set statp->restrans which we (Apple) use to indicate
1020 * total time allowed for a query to be resolved.
1022 total_timeout
= statp
->retrans
* (statp
->retry
+ 1) * statp
->nscount
;
1023 statp
->retrans
= total_timeout
;
1027 statp
->options
|= RES_INIT
;
1032 res_setoptions(res_state statp
, const char *options
, const char *source
)
1034 const char *cp
= options
;
1036 struct __res_state_ext
*ext
= statp
->_u
._ext
.ext
;
1039 if (statp
->options
& RES_DEBUG
)
1040 printf(";; res_setoptions(\"%s\", \"%s\")...\n",
1044 /* skip leading and inner runs of spaces */
1045 while (*cp
== ' ' || *cp
== '\t')
1047 /* search for and process individual options */
1048 if (!strncmp(cp
, "ndots:", sizeof("ndots:") - 1)) {
1049 i
= atoi(cp
+ sizeof("ndots:") - 1);
1050 if (i
<= RES_MAXNDOTS
)
1053 statp
->ndots
= RES_MAXNDOTS
;
1055 if (statp
->options
& RES_DEBUG
)
1056 printf(";;\tndots=%d\n", statp
->ndots
);
1058 } else if (!strncmp(cp
, "timeout:", sizeof("timeout:") - 1)) {
1059 i
= atoi(cp
+ sizeof("timeout:") - 1);
1060 if (i
<= RES_MAXRETRANS
)
1063 statp
->retrans
= RES_MAXRETRANS
;
1064 } else if (!strncmp(cp
, "attempts:", sizeof("attempts:") - 1)){
1065 i
= atoi(cp
+ sizeof("attempts:") - 1);
1066 if (i
<= RES_MAXRETRY
)
1069 statp
->retry
= RES_MAXRETRY
;
1070 } else if (!strncmp(cp
, "debug", sizeof("debug") - 1)) {
1072 if (!(statp
->options
& RES_DEBUG
)) {
1073 printf(";; res_setoptions(\"%s\", \"%s\")..\n",
1075 statp
->options
|= RES_DEBUG
;
1077 printf(";;\tdebug\n");
1079 } else if (!strncmp(cp
, "no_tld_query",
1080 sizeof("no_tld_query") - 1) ||
1081 !strncmp(cp
, "no-tld-query",
1082 sizeof("no-tld-query") - 1)) {
1083 statp
->options
|= RES_NOTLDQUERY
;
1084 } else if (!strncmp(cp
, "inet6", sizeof("inet6") - 1)) {
1085 statp
->options
|= RES_USE_INET6
;
1086 } else if (!strncmp(cp
, "rotate", sizeof("rotate") - 1)) {
1087 statp
->options
|= RES_ROTATE
;
1088 } else if (!strncmp(cp
, "no-check-names",
1089 sizeof("no-check-names") - 1)) {
1090 statp
->options
|= RES_NOCHECKNAME
;
1092 #ifdef RES_USE_EDNS0
1093 else if (!strncmp(cp
, "edns0", sizeof("edns0") - 1)) {
1094 statp
->options
|= RES_USE_EDNS0
;
1097 else if (!strncmp(cp
, "a6", sizeof("a6") - 1)) {
1098 statp
->options
|= RES_USE_A6
;
1100 else if (!strncmp(cp
, "dname", sizeof("dname") - 1)) {
1101 statp
->options
|= RES_USE_DNAME
;
1103 else if (!strncmp(cp
, "nibble:", sizeof("nibble:") - 1)) {
1106 cp
+= sizeof("nibble:") - 1;
1107 i
= MIN(strcspn(cp
, " \t"), sizeof(ext
->nsuffix
) - 1);
1108 strncpy(ext
->nsuffix
, cp
, i
);
1109 ext
->nsuffix
[i
] = '\0';
1111 else if (!strncmp(cp
, "nibble2:", sizeof("nibble2:") - 1)) {
1114 cp
+= sizeof("nibble2:") - 1;
1115 i
= MIN(strcspn(cp
, " \t"), sizeof(ext
->nsuffix2
) - 1);
1116 strncpy(ext
->nsuffix2
, cp
, i
);
1117 ext
->nsuffix2
[i
] = '\0';
1119 else if (!strncmp(cp
, "bitstring:", sizeof("bitstring:") - 1)) {
1122 cp
+= sizeof("bitstring:") - 1;
1123 i
= MIN(strcspn(cp
, " \t"), sizeof(ext
->bsuffix
) - 1);
1124 strncpy(ext
->bsuffix
, cp
, i
);
1125 ext
->bsuffix
[i
] = '\0';
1127 else if (!strncmp(cp
, "v6revmode:", sizeof("v6revmode:") - 1)) {
1128 cp
+= sizeof("v6revmode:") - 1;
1129 /* "nibble" and "bitstring" used to be valid */
1130 if (!strncmp(cp
, "single", sizeof("single") - 1)) {
1131 statp
->options
|= RES_NO_NIBBLE2
;
1132 } else if (!strncmp(cp
, "both", sizeof("both") - 1)) {
1138 /* XXX - print a warning here? */
1141 /* skip to next run of spaces */
1142 while (*cp
&& *cp
!= ' ' && *cp
!= '\t')
1147 /* This function has to be reachable by res_data.c but not publically. */
1149 __res_vinit(res_state statp
, int preinit
)
1151 dns_config_t
*sc_dns
;
1152 dns_resolver_t
*sc_res
;
1153 char val
[256], *p
, *x
;
1155 uint32_t nsearch
, total_timeout
, send_timeout
;
1161 sc_dns
= dns_configuration_copy();
1162 if (sc_dns
== NULL
) return res_vinit_from_file(statp
, preinit
, _PATH_RESCONF
);
1164 sc_res
= sc_dns
->resolver
[0];
1165 port
= sc_res
->port
;
1166 if (port
== 0) port
= NS_DEFAULTPORT
;
1168 if ((statp
->options
& RES_INIT
) != 0) res_ndestroy(statp
);
1170 /* N.B. res_build_start will allocate statp->_u._ext.ext for us */
1171 statp
= res_build_start(statp
);
1173 p
= getenv("RES_RETRY_TIMEOUT");
1174 if (p
!= NULL
) send_timeout
= atoi(p
);
1176 p
= getenv("RES_RETRY");
1177 if (p
!= NULL
) statp
->retry
= atoi(p
);
1179 if (sc_res
->n_nameserver
> MAXNS
) sc_res
->n_nameserver
= MAXNS
;
1180 for (i
= 0; i
< sc_res
->n_nameserver
; i
++)
1182 if (sc_res
->nameserver
[i
]->sa_family
== AF_INET
)
1184 memset(val
, 0, sizeof(val
));
1185 inet_ntop(AF_INET
, (char *)(sc_res
->nameserver
[i
]) + INET_NTOP_AF_INET_OFFSET
, val
, sizeof(val
));
1186 res_build(statp
, port
, &nsearch
, "nameserver", val
);
1188 else if (sc_res
->nameserver
[i
]->sa_family
== AF_INET6
)
1190 memset(val
, 0, sizeof(val
));
1191 inet_ntop(AF_INET6
, (char *)(sc_res
->nameserver
[i
]) + INET_NTOP_AF_INET6_OFFSET
, val
, sizeof(val
));
1192 res_build(statp
, port
, &nsearch
, "nameserver", val
);
1196 if (sc_res
->n_search
> MAXDNSRCH
) sc_res
->n_search
= MAXDNSRCH
;
1197 for (i
= 0; i
< sc_res
->n_search
; i
++)
1199 res_build(statp
, port
, &nsearch
, "search", sc_res
->search
[i
]);
1202 /* If there was no search list, use "domain" */
1203 if ((sc_res
->n_search
== 0) && (sc_res
->domain
!= NULL
))
1207 for (p
= sc_res
->domain
; *p
!= '\0'; p
++)
1212 /* Back up over any trailing dots and cut them out of the name */
1213 for (p
--; (p
>= sc_res
->domain
) && (*p
== '.'); p
--)
1219 if (p
>= sc_res
->domain
) res_build(statp
, port
, &nsearch
, "search", sc_res
->domain
);
1221 /* dots are separators, so number of components is one larger */
1224 /* Include parent domains with at least LOCALDOMAINPARTS components */
1226 while ((n
> LOCALDOMAINPARTS
) && (nsearch
< MAXDFLSRCH
))
1228 /* Find next component */
1229 while (*p
!= '.') p
++;
1230 if (*p
== '\0') break;
1234 res_build(statp
, port
, &nsearch
, "search", p
);
1238 total_timeout
= sc_res
->timeout
;
1240 snprintf(val
, sizeof(val
), "%d", sc_res
->search_order
);
1241 res_build(statp
, port
, &nsearch
, "search_order", val
);
1243 if (sc_res
->n_sortaddr
> MAXRESOLVSORT
) sc_res
->n_sortaddr
= MAXRESOLVSORT
;
1244 for (i
= 0; i
< sc_res
->n_sortaddr
; i
++)
1246 res_build_sortlist(statp
, sc_res
->sortaddr
[i
]->address
, sc_res
->sortaddr
[i
]->mask
);
1249 p
= sc_res
->options
;
1250 while (NULL
!= (x
= res_next_word(&p
)))
1252 if (!strncmp(x
, "ndots:", 6))
1254 res_build(statp
, port
, &nsearch
, "ndots", x
+6);
1257 else if (!strncmp(x
, "nibble:", 7))
1259 res_build(statp
, port
, &nsearch
, "nibble", x
+7);
1262 else if (!strncmp(x
, "nibble2:", 8))
1264 res_build(statp
, port
, &nsearch
, "nibble2", x
+8);
1267 else if (!strncmp(x
, "timeout:", 8))
1269 send_timeout
= atoi(x
+8);
1272 else if (!strncmp(x
, "attempts:", 9))
1274 res_build(statp
, port
, &nsearch
, "attempts", x
+9);
1277 else if (!strncmp(x
, "bitstring:", 10))
1279 res_build(statp
, port
, &nsearch
, "bitstring", x
+10);
1282 else if (!strncmp(x
, "v6revmode:", 10))
1284 res_build(statp
, port
, &nsearch
, "v6revmode", x
+10);
1287 else if (!strcmp(x
, "debug"))
1289 res_build(statp
, port
, &nsearch
, "debug", NULL
);
1292 else if (!strcmp(x
, "no_tld_query"))
1294 res_build(statp
, port
, &nsearch
, "no_tld_query", NULL
);
1297 else if (!strcmp(x
, "inet6"))
1299 res_build(statp
, port
, &nsearch
, "inet6", NULL
);
1302 else if (!strcmp(x
, "rotate"))
1304 res_build(statp
, port
, &nsearch
, "rotate", NULL
);
1307 else if (!strcmp(x
, "no-check-names"))
1309 res_build(statp
, port
, &nsearch
, "no-check-names", NULL
);
1312 #ifdef RES_USE_EDNS0
1313 else if (!strcmp(x
, "edns0"))
1315 res_build(statp
, port
, &nsearch
, "edns0", NULL
);
1318 else if (!strcmp(x
, "a6"))
1320 res_build(statp
, port
, &nsearch
, "a6", NULL
);
1323 else if (!strcmp(x
, "dname"))
1325 res_build(statp
, port
, &nsearch
, "dname", NULL
);
1332 if (total_timeout
== 0)
1334 if (send_timeout
== 0) total_timeout
= RES_MAXRETRANS
;
1335 else total_timeout
= send_timeout
* statp
->retry
* n
;
1338 dns_configuration_free(sc_dns
);
1340 res_build_finish(statp
, total_timeout
, port
);
1346 res_ninit(res_state statp
)
1348 if (statp
== NULL
) return -1;
1349 memset(statp
, 0, sizeof(struct __res_state
));
1350 return __res_vinit(statp
, 0);
1354 /* XXX - should really support CIDR which means explicit masks always. */
1356 net_mask(in
) /* XXX - should really use system's version of this */
1359 register u_int32_t i
= ntohl(in
.s_addr
);
1362 return (htonl(IN_CLASSA_NET
));
1363 else if (IN_CLASSB(i
))
1364 return (htonl(IN_CLASSB_NET
));
1365 return (htonl(IN_CLASSC_NET
));
1370 res_randomid(void) {
1378 rf
= open("/dev/random", O_RDONLY
, 0);
1381 read(rf
, &x
, sizeof(u_int
));
1386 x
= (getpid() << 10) + time(NULL
);
1395 gettimeofday(&now
, NULL
);
1396 return (0xffff & (now
.tv_sec
^ now
.tv_usec
^ getpid()));
1400 * This routine is for closing the socket if a virtual circuit is used and
1401 * the program wants to close it. This provides support for endhostent()
1402 * which expects to close the socket.
1404 * This routine is not expected to be user visible.
1407 res_nclose(res_state statp
)
1411 if (statp
->_vcsock
>= 0)
1413 close(statp
->_vcsock
);
1414 statp
->_vcsock
= -1;
1415 statp
->_flags
&= ~(RES_F_VC
| RES_F_CONN
);
1418 if (statp
->_pad
>= 9)
1420 for (ns
= 0; ns
< statp
->_u
._ext
.nscount
; ns
++)
1422 if (statp
->_u
._ext
.nssocks
[ns
] != -1)
1424 close(statp
->_u
._ext
.nssocks
[ns
]);
1425 statp
->_u
._ext
.nssocks
[ns
] = -1;
1432 res_ndestroy(res_state statp
)
1435 statp
->options
&= ~RES_INIT
;
1438 * _pad (normally unused) is a version number.
1439 * We use it to prevent BIND_9 from trashing memory
1440 * if statp was created by BIND-8.
1442 if (statp
->_pad
>= 9)
1444 if (statp
->_u
._ext
.ext
!= NULL
) free(statp
->_u
._ext
.ext
);
1445 statp
->_u
._ext
.ext
= NULL
;
1451 res_get_nibblesuffix(res_state statp
) {
1452 if (statp
->_u
._ext
.ext
)
1453 return (statp
->_u
._ext
.ext
->nsuffix
);
1454 return ("ip6.arpa");
1458 res_get_nibblesuffix2(res_state statp
) {
1459 if (statp
->_u
._ext
.ext
)
1460 return (statp
->_u
._ext
.ext
->nsuffix2
);
1465 res_get_bitstringsuffix(res_state statp
) {
1466 if (statp
->_u
._ext
.ext
)
1467 return (statp
->_u
._ext
.ext
->bsuffix
);
1468 return ("ip6.arpa");
1472 res_setservers(res_state statp
, const union res_sockaddr_union
*set
, int cnt
) {
1476 /* close open servers */
1479 /* cause rtt times to be forgotten */
1480 statp
->_u
._ext
.nscount
= 0;
1483 for (i
= 0; i
< cnt
&& nserv
< MAXNS
; i
++) {
1484 switch (set
->sin
.sin_family
) {
1486 size
= sizeof(set
->sin
);
1487 if (statp
->_u
._ext
.ext
)
1488 memcpy(&statp
->_u
._ext
.ext
->nsaddrs
[nserv
],
1490 if (size
<= sizeof(statp
->nsaddr_list
[nserv
]))
1491 memcpy(&statp
->nsaddr_list
[nserv
],
1494 statp
->nsaddr_list
[nserv
].sin_family
= 0;
1499 size
= sizeof(set
->sin6
);
1500 if (statp
->_u
._ext
.ext
)
1501 memcpy(&statp
->_u
._ext
.ext
->nsaddrs
[nserv
],
1503 if (size
<= sizeof(statp
->nsaddr_list
[nserv
]))
1504 memcpy(&statp
->nsaddr_list
[nserv
],
1507 statp
->nsaddr_list
[nserv
].sin_family
= 0;
1517 statp
->nscount
= nserv
;
1521 res_getservers(res_state statp
, union res_sockaddr_union
*set
, int cnt
) {
1526 for (i
= 0; i
< statp
->nscount
&& i
< cnt
; i
++) {
1527 if (statp
->_u
._ext
.ext
)
1528 family
= statp
->_u
._ext
.ext
->nsaddrs
[i
].sin
.sin_family
;
1530 family
= statp
->nsaddr_list
[i
].sin_family
;
1534 size
= sizeof(set
->sin
);
1535 if (statp
->_u
._ext
.ext
)
1537 &statp
->_u
._ext
.ext
->nsaddrs
[i
],
1540 memcpy(&set
->sin
, &statp
->nsaddr_list
[i
],
1545 size
= sizeof(set
->sin6
);
1546 if (statp
->_u
._ext
.ext
)
1548 &statp
->_u
._ext
.ext
->nsaddrs
[i
],
1551 memcpy(&set
->sin6
, &statp
->nsaddr_list
[i
],
1556 set
->sin
.sin_family
= 0;
1561 return (statp
->nscount
);