1 /* $KAME: name6.c,v 1.25 2000/06/26 16:44:40 itojun Exp $ */
4 * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
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. Neither the name of the project nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * ++Copyright++ 1985, 1988, 1993
34 * Copyright (c) 1985, 1988, 1993
35 * The Regents of the University of California. All rights reserved.
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions
40 * 1. Redistributions of source code must retain the above copyright
41 * notice, this list of conditions and the following disclaimer.
42 * 2. Redistributions in binary form must reproduce the above copyright
43 * notice, this list of conditions and the following disclaimer in the
44 * documentation and/or other materials provided with the distribution.
45 * 3. All advertising materials mentioning features or use of this software
46 * must display the following acknowledgement:
47 * This product includes software developed by the University of
48 * California, Berkeley and its contributors.
49 * 4. Neither the name of the University nor the names of its contributors
50 * may be used to endorse or promote products derived from this software
51 * without specific prior written permission.
53 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
54 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
55 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
56 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
57 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
58 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
59 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
60 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
61 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
62 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
65 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
67 * Permission to use, copy, modify, and distribute this software for any
68 * purpose with or without fee is hereby granted, provided that the above
69 * copyright notice and this permission notice appear in all copies, and that
70 * the name of Digital Equipment Corporation not be used in advertising or
71 * publicity pertaining to distribution of the document or software without
72 * specific, written prior permission.
74 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
75 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
76 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
77 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
78 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
79 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
80 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
87 * Atsushi Onoe <onoe@sm.sony.co.jp>
90 #include <sys/cdefs.h>
91 __FBSDID("$FreeBSD$");
93 #include "namespace.h"
95 #include "reentrant.h"
97 #include <sys/param.h>
98 #include <sys/socket.h>
100 #include <sys/queue.h>
101 #include <netinet/in.h>
104 #include <net/if_var.h>
105 #include <sys/sysctl.h>
106 #include <sys/ioctl.h>
107 #include <netinet6/in6_var.h> /* XXX */
110 #include <arpa/inet.h>
111 #include <arpa/nameser.h>
120 #include <nsswitch.h>
122 #include "un-namespace.h"
123 #include "netdb_private.h"
124 #include "res_config.h"
125 #include "res_private.h"
131 #define _PATH_HOSTS "/etc/hosts"
135 #define MAXALIASES 10
141 #define MAXDNAME 1025
145 #define ADDRLEN(af) ((af) == AF_INET6 ? sizeof(struct in6_addr) : \
146 sizeof(struct in_addr))
148 #define ADDRLEN(af) sizeof(struct in_addr)
151 #define MAPADDR(ab, ina) \
153 memcpy(&(ab)->map_inaddr, ina, sizeof(struct in_addr)); \
154 memset((ab)->map_zero, 0, sizeof((ab)->map_zero)); \
155 memset((ab)->map_one, 0xff, sizeof((ab)->map_one)); \
157 #define MAPADDRENABLED(flags) \
158 (((flags) & AI_V4MAPPED) || \
159 (((flags) & AI_V4MAPPED_CFG) && _mapped_addr_enabled()))
162 struct in_addr in_addr;
164 struct in6_addr in6_addr;
169 struct in_addr mau_inaddr;
171 #define map_zero map_addr_un.mau_zero
172 #define map_one map_addr_un.mau_one
173 #define map_inaddr map_addr_un.mau_inaddr
177 TAILQ_ENTRY(policyqueue) pc_entry;
179 struct in6_addrpolicy pc_policy;
182 TAILQ_HEAD(policyhead, policyqueue);
184 #define AIO_SRCFLAG_DEPRECATED 0x1
188 struct sockaddr_storage aiou_ss;
189 struct sockaddr aiou_sa;
191 #define aio_srcsa aio_src_un.aiou_sa
192 u_int32_t aio_srcflag;
195 struct policyqueue *aio_srcpolicy;
196 struct policyqueue *aio_dstpolicy;
198 struct sockaddr_storage aiou_ss;
199 struct sockaddr aiou_sa;
201 #define aio_sa aio_un.aiou_sa
206 static struct hostent *_hpcopy(struct hostent *, int *);
207 static struct hostent *_hpaddr(int, const char *, void *, int *);
208 static struct hostent *_hpmerge(struct hostent *, struct hostent *, int *);
210 static struct hostent *_hpmapv6(struct hostent *, int *);
212 static struct hostent *_hpsort(struct hostent *, res_state);
213 static struct hostent *_ghbyname(const char *, int, int, int *);
214 static char *_hgetword(char **);
215 static int _mapped_addr_enabled(void);
217 static struct hostent *_hpreorder(struct hostent *);
218 static int get_addrselectpolicy(struct policyhead *);
219 static void free_addrselectpolicy(struct policyhead *);
220 static struct policyqueue *match_addrselectpolicy(struct sockaddr *,
221 struct policyhead *);
222 static void set_source(struct hp_order *, struct policyhead *);
223 static int matchlen(struct sockaddr *, struct sockaddr *);
224 static int comp_dst(const void *, const void *);
225 static int gai_addr2scopetype(struct sockaddr *);
227 static FILE *_files_open(int *);
228 static int _files_ghbyname(void *, void *, va_list);
229 static int _files_ghbyaddr(void *, void *, va_list);
231 static int _nis_ghbyname(void *, void *, va_list);
232 static int _nis_ghbyaddr(void *, void *, va_list);
234 static int _dns_ghbyname(void *, void *, va_list);
235 static int _dns_ghbyaddr(void *, void *, va_list);
236 static void _dns_shent(int) __unused;
237 static void _dns_ehent(void) __unused;
239 static int _icmp_ghbyaddr(void *, void *, va_list);
242 static int ipnode_id_func(char *, size_t *, va_list, void *);
243 static int ipnode_marshal_func(char *, size_t *, void *, va_list, void *);
244 static int ipnode_unmarshal_func(char *, size_t, void *, va_list, void *);
248 static mutex_t _getipnodeby_thread_lock = MUTEX_INITIALIZER;
249 #define THREAD_LOCK() mutex_lock(&_getipnodeby_thread_lock);
250 #define THREAD_UNLOCK() mutex_unlock(&_getipnodeby_thread_lock);
253 /* Host lookup order if nsswitch.conf is broken or nonexistant */
254 static const ns_src default_src[] = {
255 { NSSRC_FILES, NS_SUCCESS },
256 { NSSRC_DNS, NS_SUCCESS },
258 #define NSSRC_ICMP "icmp"
259 { NSSRC_ICMP, NS_SUCCESS },
265 * Check if kernel supports mapped address.
266 * implementation dependent
269 #include <sys/sysctl.h>
270 #endif /* __KAME__ */
273 _mapped_addr_enabled(void)
275 /* implementation dependent check */
276 #if defined(__KAME__) && defined(IPV6CTL_MAPPED_ADDR)
283 mib[2] = IPPROTO_IPV6;
284 mib[3] = IPV6CTL_MAPPED_ADDR;
286 if (sysctl(mib, 4, &val, &len, 0, 0) == 0 && val != 0)
288 #endif /* __KAME__ && IPV6CTL_MAPPED_ADDR */
294 ipnode_id_func(char *buffer, size_t *buffer_size, va_list ap,
307 size_t desired_size, size;
308 enum nss_lookup_type lookup_type;
309 int res = NS_UNAVAIL;
311 statp = __res_state();
312 res_options = statp->options & (RES_RECURSE | RES_DEFNAMES |
313 RES_DNSRCH | RES_NOALIASES | RES_USE_INET6);
315 lookup_type = (enum nss_lookup_type)cache_mdata;
316 switch (lookup_type) {
318 name = va_arg(ap, char *);
319 af = va_arg(ap, int);
322 desired_size = sizeof(res_options) + sizeof(int) +
323 sizeof(enum nss_lookup_type) + sizeof(int) + size + 1;
325 if (desired_size > *buffer_size) {
331 memcpy(p, &res_options, sizeof(res_options));
332 p += sizeof(res_options);
334 memcpy(p, &op_id, sizeof(int));
337 memcpy(p, &lookup_type, sizeof(enum nss_lookup_type));
338 p += sizeof(enum nss_lookup_type);
340 memcpy(p, &af, sizeof(int));
343 memcpy(p, name, size + 1);
348 src = va_arg(ap, void *);
349 len = va_arg(ap, size_t);
350 af = va_arg(ap, int);
352 desired_size = sizeof(res_options) + sizeof(int) +
353 sizeof(enum nss_lookup_type) + sizeof(int) +
354 sizeof(size_t) + len;
356 if (desired_size > *buffer_size) {
362 memcpy(p, &res_options, sizeof(res_options));
363 p += sizeof(res_options);
365 memcpy(p, &op_id, sizeof(int));
368 memcpy(p, &lookup_type, sizeof(enum nss_lookup_type));
369 p += sizeof(enum nss_lookup_type);
371 memcpy(p, &af, sizeof(int));
374 memcpy(p, &len, sizeof(size_t));
382 /* should be unreachable */
387 *buffer_size = desired_size;
392 ipnode_marshal_func(char *buffer, size_t *buffer_size, void *retval,
393 va_list ap, void *cache_mdata)
397 struct hostent new_ht;
398 size_t desired_size, aliases_size, addr_size, size;
401 ht = *((struct hostent **)retval);
403 desired_size = _ALIGNBYTES + sizeof(struct hostent) + sizeof(char *);
404 if (ht->h_name != NULL)
405 desired_size += strlen(ht->h_name) + 1;
407 if (ht->h_aliases != NULL) {
409 for (iter = ht->h_aliases; *iter; ++iter) {
410 desired_size += strlen(*iter) + 1;
414 desired_size += _ALIGNBYTES +
415 (aliases_size + 1) * sizeof(char *);
418 if (ht->h_addr_list != NULL) {
420 for (iter = ht->h_addr_list; *iter; ++iter)
423 desired_size += addr_size * _ALIGN(ht->h_length);
424 desired_size += _ALIGNBYTES + (addr_size + 1) * sizeof(char *);
427 if (desired_size > *buffer_size) {
428 /* this assignment is here for future use */
429 *buffer_size = desired_size;
433 memcpy(&new_ht, ht, sizeof(struct hostent));
434 memset(buffer, 0, desired_size);
436 *buffer_size = desired_size;
437 p = buffer + sizeof(struct hostent) + sizeof(char *);
438 memcpy(buffer + sizeof(struct hostent), &p, sizeof(char *));
439 p = (char *)_ALIGN(p);
441 if (new_ht.h_name != NULL) {
442 size = strlen(new_ht.h_name);
443 memcpy(p, new_ht.h_name, size);
448 if (new_ht.h_aliases != NULL) {
449 p = (char *)_ALIGN(p);
450 memcpy(p, new_ht.h_aliases, sizeof(char *) * aliases_size);
451 new_ht.h_aliases = (char **)p;
452 p += sizeof(char *) * (aliases_size + 1);
454 for (iter = new_ht.h_aliases; *iter; ++iter) {
455 size = strlen(*iter);
456 memcpy(p, *iter, size);
462 if (new_ht.h_addr_list != NULL) {
463 p = (char *)_ALIGN(p);
464 memcpy(p, new_ht.h_addr_list, sizeof(char *) * addr_size);
465 new_ht.h_addr_list = (char **)p;
466 p += sizeof(char *) * (addr_size + 1);
468 size = _ALIGN(new_ht.h_length);
469 for (iter = new_ht.h_addr_list; *iter; ++iter) {
470 memcpy(p, *iter, size);
475 memcpy(buffer, &new_ht, sizeof(struct hostent));
480 ipnode_unmarshal_func(char *buffer, size_t buffer_size, void *retval,
481 va_list ap, void *cache_mdata)
483 struct hostent new_ht;
493 memcpy(ht, buffer, sizeof(struct hostent));
494 memcpy(&p, buffer + sizeof(struct hostent), sizeof(char *));
496 orig_buf = buffer + sizeof(struct hostent) + sizeof(char *) +
497 _ALIGN(p) - (size_t)p;
498 p = (char *)_ALIGN(p);
501 NS_APPLY_OFFSET(ht->h_name, orig_buf, p, char *);
502 if (ht->h_aliases != NULL) {
503 NS_APPLY_OFFSET(ht->h_aliases, orig_buf, p, char **);
505 for (iter = ht->h_aliases; *iter; ++iter)
506 NS_APPLY_OFFSET(*iter, orig_buf, p, char *);
509 if (ht->h_addr_list != NULL) {
510 NS_APPLY_OFFSET(ht->h_addr_list, orig_buf, p, char **);
512 for (iter = ht->h_addr_list; *iter; ++iter)
513 NS_APPLY_OFFSET(*iter, orig_buf, p, char *);
516 ht = _hpcopy(ht, &err);
520 *((struct hostent **)retval) = ht;
526 * Functions defined in RFC2553
527 * getipnodebyname, getipnodebyaddr, freehostent
530 static struct hostent *
531 _ghbyname(const char *name, int af, int flags, int *errp)
537 static const nss_cache_info cache_info =
538 NS_COMMON_CACHE_INFO_INITIALIZER(
539 hosts, (void *)nss_lt_name,
540 ipnode_id_func, ipnode_marshal_func, ipnode_unmarshal_func);
542 static const ns_dtab dtab[] = {
543 NS_FILES_CB(_files_ghbyname, NULL)
544 { NSSRC_DNS, _dns_ghbyname, NULL },
545 NS_NIS_CB(_nis_ghbyname, NULL)
547 NS_CACHE_CB(&cache_info)
552 if (flags & AI_ADDRCONFIG) {
555 if ((s = _socket(af, SOCK_DGRAM, 0)) < 0)
559 * Note that implementation dependent test for address
560 * configuration should be done everytime called
561 * (or apropriate interval),
562 * because addresses will be dynamically assigned or deleted.
567 rval = _nsdispatch(&hp, dtab, NSDB_HOSTS, "ghbyname", default_src,
569 return (rval == NS_SUCCESS) ? hp : NULL;
573 getipnodebyname(const char *name, int af, int flags, int *errp)
576 union inx_addr addrbuf;
591 /* special case for literal address */
592 if (inet_pton(AF_INET6, name, &addrbuf) == 1) {
593 if (af != AF_INET6) {
594 *errp = HOST_NOT_FOUND;
597 return _hpaddr(af, name, &addrbuf, errp);
600 if (inet_aton(name, (struct in_addr *)&addrbuf) == 1) {
602 if (MAPADDRENABLED(flags)) {
603 MAPADDR(&addrbuf, &addrbuf.in_addr);
605 *errp = HOST_NOT_FOUND;
609 return _hpaddr(af, name, &addrbuf, errp);
612 statp = __res_state();
613 if ((statp->options & RES_INIT) == 0) {
614 if (res_ninit(statp) < 0) {
615 *errp = NETDB_INTERNAL;
620 *errp = HOST_NOT_FOUND;
621 hp = _ghbyname(name, af, flags, errp);
624 if (af == AF_INET6 && ((flags & AI_ALL) || hp == NULL) &&
625 MAPADDRENABLED(flags)) {
626 struct hostent *hp2 = _ghbyname(name, AF_INET, flags, errp);
628 hp = _hpmapv6(hp2, errp);
630 if (hp2 && strcmp(hp->h_name, hp2->h_name) != 0) {
634 hp = _hpmerge(hp, hp2, errp);
638 return _hpreorder(_hpsort(hp, statp));
642 getipnodebyaddr(const void *src, size_t len, int af, int *errp)
647 struct in6_addr addrbuf;
649 struct in_addr addrbuf;
653 static const nss_cache_info cache_info =
654 NS_COMMON_CACHE_INFO_INITIALIZER(
655 hosts, (void *)nss_lt_id,
656 ipnode_id_func, ipnode_marshal_func, ipnode_unmarshal_func);
658 static const ns_dtab dtab[] = {
659 NS_FILES_CB(_files_ghbyaddr, NULL)
660 { NSSRC_DNS, _dns_ghbyaddr, NULL },
661 NS_NIS_CB(_nis_ghbyaddr, NULL)
663 { NSSRC_ICMP, _icmp_ghbyaddr, NULL },
666 NS_CACHE_CB(&cache_info)
671 *errp = HOST_NOT_FOUND;
675 if (len != sizeof(struct in_addr)) {
679 if ((long)src & ~(sizeof(struct in_addr) - 1)) {
680 memcpy(&addrbuf, src, len);
683 if (((struct in_addr *)src)->s_addr == 0)
688 if (len != sizeof(struct in6_addr)) {
692 if ((long)src & ~(sizeof(struct in6_addr) / 2 - 1)) { /*XXX*/
693 memcpy(&addrbuf, src, len);
696 if (IN6_IS_ADDR_UNSPECIFIED((struct in6_addr *)src))
698 if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)src)
699 || IN6_IS_ADDR_V4COMPAT((struct in6_addr *)src)) {
701 (sizeof(struct in6_addr) - sizeof(struct in_addr));
703 len = sizeof(struct in_addr);
712 rval = _nsdispatch(&hp, dtab, NSDB_HOSTS, "ghbyaddr", default_src,
714 return (rval == NS_SUCCESS) ? hp : NULL;
718 freehostent(struct hostent *ptr)
724 * Private utility functions
728 * _hpcopy: allocate and copy hostent structure
730 static struct hostent *
731 _hpcopy(struct hostent *hp, int *errp)
736 int nalias = 0, naddr = 0;
743 /* count size to be allocated */
744 size = sizeof(struct hostent);
745 if (hp->h_name != NULL)
746 size += strlen(hp->h_name) + 1;
747 if ((pp = hp->h_aliases) != NULL) {
748 for (i = 0; *pp != NULL; i++, pp++) {
750 size += strlen(*pp) + 1;
755 /* adjust alignment */
758 size += sizeof(char *) * (nalias + 1);
759 addrsize = ALIGN(hp->h_length);
760 if ((pp = hp->h_addr_list) != NULL) {
761 while (*pp++ != NULL)
764 size += addrsize * naddr;
765 size += sizeof(char *) * (naddr + 1);
768 if ((nhp = (struct hostent *)malloc(size)) == NULL) {
772 cp = (char *)&nhp[1];
773 if (hp->h_name != NULL) {
775 strcpy(cp, hp->h_name);
776 cp += strlen(cp) + 1;
779 nhp->h_aliases = (char **)((char *)nhp + al_off);
780 if ((pp = hp->h_aliases) != NULL) {
781 for (i = 0; *pp != NULL; pp++) {
783 nhp->h_aliases[i++] = cp;
785 cp += strlen(cp) + 1;
789 nhp->h_aliases[nalias] = NULL;
790 cp = (char *)&nhp->h_aliases[nalias + 1];
791 nhp->h_addrtype = hp->h_addrtype;
792 nhp->h_length = hp->h_length;
793 nhp->h_addr_list = (char **)cp;
794 if ((pp = hp->h_addr_list) != NULL) {
795 cp = (char *)&nhp->h_addr_list[naddr + 1];
796 for (i = 0; *pp != NULL; pp++) {
797 nhp->h_addr_list[i++] = cp;
798 memcpy(cp, *pp, hp->h_length);
802 nhp->h_addr_list[naddr] = NULL;
807 * _hpaddr: construct hostent structure with one address
809 static struct hostent *
810 _hpaddr(int af, const char *name, void *addr, int *errp)
812 struct hostent *hp, hpbuf;
816 hp->h_name = (char *)name;
817 hp->h_aliases = NULL;
819 hp->h_length = ADDRLEN(af);
820 hp->h_addr_list = addrs;
821 addrs[0] = (char *)addr;
823 return _hpcopy(hp, errp);
827 * _hpmerge: merge 2 hostent structure, arguments will be freed
829 static struct hostent *
830 _hpmerge(struct hostent *hp1, struct hostent *hp2, int *errp)
835 struct hostent *hp, hpbuf;
836 char *aliases[MAXALIASES + 1], *addrs[MAXADDRS + 1];
837 union inx_addr addrbuf[MAXADDRS];
844 #define HP(i) (i == 1 ? hp1 : hp2)
846 hp->h_name = (hp1->h_name != NULL ? hp1->h_name : hp2->h_name);
847 hp->h_aliases = aliases;
849 for (i = 1; i <= 2; i++) {
850 if ((pp = HP(i)->h_aliases) == NULL)
852 for (; nalias < MAXALIASES && *pp != NULL; pp++) {
853 /* check duplicates */
854 for (j = 0; j < nalias; j++)
855 if (strcasecmp(*pp, aliases[j]) == 0)
858 aliases[nalias++] = *pp;
861 aliases[nalias] = NULL;
863 if (hp1->h_length != hp2->h_length) {
864 hp->h_addrtype = AF_INET6;
865 hp->h_length = sizeof(struct in6_addr);
868 hp->h_addrtype = hp1->h_addrtype;
869 hp->h_length = hp1->h_length;
873 hp->h_addr_list = addrs;
875 for (i = 1; i <= 2; i++) {
876 if ((pp = HP(i)->h_addr_list) == NULL)
878 if (HP(i)->h_length == hp->h_length) {
879 while (naddr < MAXADDRS && *pp != NULL)
880 addrs[naddr++] = *pp++;
882 /* copy IPv4 addr as mapped IPv6 addr */
883 while (naddr < MAXADDRS && *pp != NULL) {
884 MAPADDR(&addrbuf[naddr], *pp++);
885 addrs[naddr] = (char *)&addrbuf[naddr];
891 hp = _hpcopy(hp, errp);
898 * _hpmapv6: convert IPv4 hostent into IPv4-mapped IPv6 addresses
901 static struct hostent *
902 _hpmapv6(struct hostent *hp, int *errp)
908 if (hp->h_addrtype == AF_INET6)
911 /* make dummy hostent to convert IPv6 address */
912 if ((hp6 = (struct hostent *)malloc(sizeof(struct hostent))) == NULL) {
917 hp6->h_aliases = NULL;
918 hp6->h_addrtype = AF_INET6;
919 hp6->h_length = sizeof(struct in6_addr);
920 hp6->h_addr_list = NULL;
921 return _hpmerge(hp6, hp, errp);
926 * _hpsort: sort address by sortlist
928 static struct hostent *
929 _hpsort(struct hostent *hp, res_state statp)
932 u_char *ap, *sp, *mp, **pp;
934 char order[MAXADDRS];
935 int nsort = statp->nsort;
937 if (hp == NULL || hp->h_addr_list[1] == NULL || nsort == 0)
939 for (i = 0; (ap = (u_char *)hp->h_addr_list[i]); i++) {
940 for (j = 0; j < nsort; j++) {
942 if (statp->_u._ext.ext->sort_list[j].af !=
945 sp = (u_char *)&statp->_u._ext.ext->sort_list[j].addr;
946 mp = (u_char *)&statp->_u._ext.ext->sort_list[j].mask;
948 sp = (u_char *)&statp->sort_list[j].addr;
949 mp = (u_char *)&statp->sort_list[j].mask;
951 for (n = 0; n < hp->h_length; n++) {
952 if ((ap[n] & mp[n]) != sp[n])
955 if (n == hp->h_length)
961 pp = (u_char **)hp->h_addr_list;
962 for (i = 0; i < n - 1; i++) {
963 for (j = i + 1; j < n; j++) {
964 if (order[i] > order[j]) {
982 static const char sep[] = "# \t\n";
985 for (p = *pp; (c = *p) != '\0'; p++) {
986 for (sp = sep; *sp != '\0'; sp++) {
991 p[1] = '\0'; /* ignore rest of line */
1003 if (ret == NULL || *ret == '\0')
1009 * _hpreorder: sort address by default address selection
1011 static struct hostent *
1012 _hpreorder(struct hostent *hp)
1014 struct hp_order *aio;
1017 struct sockaddr *sa;
1018 struct policyhead policyhead;
1023 switch (hp->h_addrtype) {
1030 free_addrselectpolicy(&policyhead);
1034 /* count the number of addrinfo elements for sorting. */
1035 for (n = 0; hp->h_addr_list[n] != NULL; n++)
1039 * If the number is small enough, we can skip the reordering process.
1044 /* allocate a temporary array for sort and initialization of it. */
1045 if ((aio = malloc(sizeof(*aio) * n)) == NULL)
1046 return hp; /* give up reordering */
1047 memset(aio, 0, sizeof(*aio) * n);
1049 /* retrieve address selection policy from the kernel */
1050 TAILQ_INIT(&policyhead);
1051 if (!get_addrselectpolicy(&policyhead)) {
1052 /* no policy is installed into kernel, we don't sort. */
1057 for (i = 0; i < n; i++) {
1058 ap = hp->h_addr_list[i];
1059 aio[i].aio_h_addr = ap;
1060 sa = &aio[i].aio_sa;
1061 switch (hp->h_addrtype) {
1063 sa->sa_family = AF_INET;
1064 sa->sa_len = sizeof(struct sockaddr_in);
1065 memcpy(&((struct sockaddr_in *)sa)->sin_addr, ap,
1066 sizeof(struct in_addr));
1070 if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)ap)) {
1071 sa->sa_family = AF_INET;
1072 sa->sa_len = sizeof(struct sockaddr_in);
1073 memcpy(&((struct sockaddr_in *)sa)->sin_addr,
1074 &ap[12], sizeof(struct in_addr));
1076 sa->sa_family = AF_INET6;
1077 sa->sa_len = sizeof(struct sockaddr_in6);
1078 memcpy(&((struct sockaddr_in6 *)sa)->sin6_addr,
1079 ap, sizeof(struct in6_addr));
1084 aio[i].aio_dstscope = gai_addr2scopetype(sa);
1085 aio[i].aio_dstpolicy = match_addrselectpolicy(sa, &policyhead);
1086 set_source(&aio[i], &policyhead);
1089 /* perform sorting. */
1090 qsort(aio, n, sizeof(*aio), comp_dst);
1092 /* reorder the h_addr_list. */
1093 for (i = 0; i < n; i++)
1094 hp->h_addr_list[i] = aio[i].aio_h_addr;
1096 /* cleanup and return */
1098 free_addrselectpolicy(&policyhead);
1103 get_addrselectpolicy(struct policyhead *head)
1106 int mib[] = { CTL_NET, PF_INET6, IPPROTO_IPV6, IPV6CTL_ADDRCTLPOLICY };
1109 struct in6_addrpolicy *pol, *ep;
1111 if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), NULL, &l, NULL, 0) < 0)
1113 if ((buf = malloc(l)) == NULL)
1115 if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), buf, &l, NULL, 0) < 0) {
1120 ep = (struct in6_addrpolicy *)(buf + l);
1121 for (pol = (struct in6_addrpolicy *)buf; pol + 1 <= ep; pol++) {
1122 struct policyqueue *new;
1124 if ((new = malloc(sizeof(*new))) == NULL) {
1125 free_addrselectpolicy(head); /* make the list empty */
1128 new->pc_policy = *pol;
1129 TAILQ_INSERT_TAIL(head, new, pc_entry);
1140 free_addrselectpolicy(struct policyhead *head)
1142 struct policyqueue *ent, *nent;
1144 for (ent = TAILQ_FIRST(head); ent; ent = nent) {
1145 nent = TAILQ_NEXT(ent, pc_entry);
1146 TAILQ_REMOVE(head, ent, pc_entry);
1151 static struct policyqueue *
1152 match_addrselectpolicy(struct sockaddr *addr, struct policyhead *head)
1155 struct policyqueue *ent, *bestent = NULL;
1156 struct in6_addrpolicy *pol;
1157 int matchlen, bestmatchlen = -1;
1158 u_char *mp, *ep, *k, *p, m;
1159 struct sockaddr_in6 key;
1161 switch(addr->sa_family) {
1163 key = *(struct sockaddr_in6 *)addr;
1166 /* convert the address into IPv4-mapped IPv6 address. */
1167 memset(&key, 0, sizeof(key));
1168 key.sin6_family = AF_INET6;
1169 key.sin6_len = sizeof(key);
1170 key.sin6_addr.s6_addr[10] = 0xff;
1171 key.sin6_addr.s6_addr[11] = 0xff;
1172 memcpy(&key.sin6_addr.s6_addr[12],
1173 &((struct sockaddr_in *)addr)->sin_addr, 4);
1179 for (ent = TAILQ_FIRST(head); ent; ent = TAILQ_NEXT(ent, pc_entry)) {
1180 pol = &ent->pc_policy;
1183 mp = (u_char *)&pol->addrmask.sin6_addr;
1184 ep = mp + 16; /* XXX: scope field? */
1185 k = (u_char *)&key.sin6_addr;
1186 p = (u_char *)&pol->addr.sin6_addr;
1187 for (; mp < ep && *mp; mp++, k++, p++) {
1190 goto next; /* not match */
1191 if (m == 0xff) /* short cut for a typical case */
1201 /* matched. check if this is better than the current best. */
1202 if (matchlen > bestmatchlen) {
1204 bestmatchlen = matchlen;
1219 set_source(struct hp_order *aio, struct policyhead *ph)
1221 struct sockaddr_storage ss = aio->aio_un.aiou_ss;
1225 /* set unspec ("no source is available"), just in case */
1226 aio->aio_srcsa.sa_family = AF_UNSPEC;
1227 aio->aio_srcscope = -1;
1229 switch(ss.ss_family) {
1231 ((struct sockaddr_in *)&ss)->sin_port = htons(1);
1235 ((struct sockaddr_in6 *)&ss)->sin6_port = htons(1);
1238 default: /* ignore unsupported AFs explicitly */
1242 /* open a socket to get the source address for the given dst */
1243 if ((s = _socket(ss.ss_family, SOCK_DGRAM, IPPROTO_UDP)) < 0)
1244 return; /* give up */
1245 if (_connect(s, (struct sockaddr *)&ss, ss.ss_len) < 0)
1248 if (_getsockname(s, &aio->aio_srcsa, &srclen) < 0) {
1249 aio->aio_srcsa.sa_family = AF_UNSPEC;
1252 aio->aio_srcscope = gai_addr2scopetype(&aio->aio_srcsa);
1253 aio->aio_srcpolicy = match_addrselectpolicy(&aio->aio_srcsa, ph);
1254 aio->aio_matchlen = matchlen(&aio->aio_srcsa, (struct sockaddr *)&ss);
1256 if (ss.ss_family == AF_INET6) {
1257 struct in6_ifreq ifr6;
1260 /* XXX: interface name should not be hardcoded */
1261 strncpy(ifr6.ifr_name, "lo0", sizeof(ifr6.ifr_name));
1262 memset(&ifr6, 0, sizeof(ifr6));
1263 memcpy(&ifr6.ifr_addr, &ss, ss.ss_len);
1264 if (_ioctl(s, SIOCGIFAFLAG_IN6, &ifr6) == 0) {
1265 flags6 = ifr6.ifr_ifru.ifru_flags6;
1266 if ((flags6 & IN6_IFF_DEPRECATED))
1267 aio->aio_srcflag |= AIO_SRCFLAG_DEPRECATED;
1278 matchlen(struct sockaddr *src, struct sockaddr *dst)
1285 switch (src->sa_family) {
1288 s = (u_char *)&((struct sockaddr_in6 *)src)->sin6_addr;
1289 d = (u_char *)&((struct sockaddr_in6 *)dst)->sin6_addr;
1290 addrlen = sizeof(struct in6_addr);
1295 s = (u_char *)&((struct sockaddr_in *)src)->sin_addr;
1296 d = (u_char *)&((struct sockaddr_in *)dst)->sin_addr;
1297 addrlen = sizeof(struct in_addr);
1305 if ((r = (*d++ ^ *s++)) != 0) {
1306 while (r < addrlen * 8) {
1317 comp_dst(const void *arg1, const void *arg2)
1319 const struct hp_order *dst1 = arg1, *dst2 = arg2;
1322 * Rule 1: Avoid unusable destinations.
1323 * XXX: we currently do not consider if an appropriate route exists.
1325 if (dst1->aio_srcsa.sa_family != AF_UNSPEC &&
1326 dst2->aio_srcsa.sa_family == AF_UNSPEC) {
1329 if (dst1->aio_srcsa.sa_family == AF_UNSPEC &&
1330 dst2->aio_srcsa.sa_family != AF_UNSPEC) {
1334 /* Rule 2: Prefer matching scope. */
1335 if (dst1->aio_dstscope == dst1->aio_srcscope &&
1336 dst2->aio_dstscope != dst2->aio_srcscope) {
1339 if (dst1->aio_dstscope != dst1->aio_srcscope &&
1340 dst2->aio_dstscope == dst2->aio_srcscope) {
1344 /* Rule 3: Avoid deprecated addresses. */
1345 if (dst1->aio_srcsa.sa_family != AF_UNSPEC &&
1346 dst2->aio_srcsa.sa_family != AF_UNSPEC) {
1347 if (!(dst1->aio_srcflag & AIO_SRCFLAG_DEPRECATED) &&
1348 (dst2->aio_srcflag & AIO_SRCFLAG_DEPRECATED)) {
1351 if ((dst1->aio_srcflag & AIO_SRCFLAG_DEPRECATED) &&
1352 !(dst2->aio_srcflag & AIO_SRCFLAG_DEPRECATED)) {
1357 /* Rule 4: Prefer home addresses. */
1358 /* XXX: not implemented yet */
1360 /* Rule 5: Prefer matching label. */
1362 if (dst1->aio_srcpolicy && dst1->aio_dstpolicy &&
1363 dst1->aio_srcpolicy->pc_policy.label ==
1364 dst1->aio_dstpolicy->pc_policy.label &&
1365 (dst2->aio_srcpolicy == NULL || dst2->aio_dstpolicy == NULL ||
1366 dst2->aio_srcpolicy->pc_policy.label !=
1367 dst2->aio_dstpolicy->pc_policy.label)) {
1370 if (dst2->aio_srcpolicy && dst2->aio_dstpolicy &&
1371 dst2->aio_srcpolicy->pc_policy.label ==
1372 dst2->aio_dstpolicy->pc_policy.label &&
1373 (dst1->aio_srcpolicy == NULL || dst1->aio_dstpolicy == NULL ||
1374 dst1->aio_srcpolicy->pc_policy.label !=
1375 dst1->aio_dstpolicy->pc_policy.label)) {
1380 /* Rule 6: Prefer higher precedence. */
1382 if (dst1->aio_dstpolicy &&
1383 (dst2->aio_dstpolicy == NULL ||
1384 dst1->aio_dstpolicy->pc_policy.preced >
1385 dst2->aio_dstpolicy->pc_policy.preced)) {
1388 if (dst2->aio_dstpolicy &&
1389 (dst1->aio_dstpolicy == NULL ||
1390 dst2->aio_dstpolicy->pc_policy.preced >
1391 dst1->aio_dstpolicy->pc_policy.preced)) {
1396 /* Rule 7: Prefer native transport. */
1397 /* XXX: not implemented yet */
1399 /* Rule 8: Prefer smaller scope. */
1400 if (dst1->aio_dstscope >= 0 &&
1401 dst1->aio_dstscope < dst2->aio_dstscope) {
1404 if (dst2->aio_dstscope >= 0 &&
1405 dst2->aio_dstscope < dst1->aio_dstscope) {
1410 * Rule 9: Use longest matching prefix.
1411 * We compare the match length in a same AF only.
1413 if (dst1->aio_sa.sa_family == dst2->aio_sa.sa_family) {
1414 if (dst1->aio_matchlen > dst2->aio_matchlen) {
1417 if (dst1->aio_matchlen < dst2->aio_matchlen) {
1422 /* Rule 10: Otherwise, leave the order unchanged. */
1427 * Copy from scope.c.
1428 * XXX: we should standardize the functions and link them as standard
1432 gai_addr2scopetype(struct sockaddr *sa)
1435 struct sockaddr_in6 *sa6;
1437 struct sockaddr_in *sa4;
1439 switch(sa->sa_family) {
1442 sa6 = (struct sockaddr_in6 *)sa;
1443 if (IN6_IS_ADDR_MULTICAST(&sa6->sin6_addr)) {
1444 /* just use the scope field of the multicast address */
1445 return(sa6->sin6_addr.s6_addr[2] & 0x0f);
1448 * Unicast addresses: map scope type to corresponding scope
1449 * value defined for multcast addresses.
1450 * XXX: hardcoded scope type values are bad...
1452 if (IN6_IS_ADDR_LOOPBACK(&sa6->sin6_addr))
1453 return(1); /* node local scope */
1454 if (IN6_IS_ADDR_LINKLOCAL(&sa6->sin6_addr))
1455 return(2); /* link-local scope */
1456 if (IN6_IS_ADDR_SITELOCAL(&sa6->sin6_addr))
1457 return(5); /* site-local scope */
1458 return(14); /* global scope */
1463 * IPv4 pseudo scoping according to RFC 3484.
1465 sa4 = (struct sockaddr_in *)sa;
1466 /* IPv4 autoconfiguration addresses have link-local scope. */
1467 if (((u_char *)&sa4->sin_addr)[0] == 169 &&
1468 ((u_char *)&sa4->sin_addr)[1] == 254)
1470 /* Private addresses have site-local scope. */
1471 if (((u_char *)&sa4->sin_addr)[0] == 10 ||
1472 (((u_char *)&sa4->sin_addr)[0] == 172 &&
1473 (((u_char *)&sa4->sin_addr)[1] & 0xf0) == 16) ||
1474 (((u_char *)&sa4->sin_addr)[0] == 192 &&
1475 ((u_char *)&sa4->sin_addr)[1] == 168))
1476 return(14); /* XXX: It should be 5 unless NAT */
1477 /* Loopback addresses have link-local scope. */
1478 if (((u_char *)&sa4->sin_addr)[0] == 127)
1483 errno = EAFNOSUPPORT; /* is this a good error? */
1489 * FILES (/etc/hosts)
1493 _files_open(int *errp)
1496 fp = fopen(_PATH_HOSTS, "r");
1498 *errp = NO_RECOVERY;
1503 _files_ghbyname(void *rval, void *cb_data, va_list ap)
1509 char *p, *line, *addrstr, *cname;
1511 struct hostent *rethp, *hp, hpbuf;
1512 char *aliases[MAXALIASES + 1], *addrs[2];
1513 union inx_addr addrbuf;
1516 name = va_arg(ap, const char *);
1517 af = va_arg(ap, int);
1518 errp = va_arg(ap, int *);
1520 *(struct hostent **)rval = NULL;
1522 if ((fp = _files_open(errp)) == NULL)
1526 while (fgets(buf, sizeof(buf), fp)) {
1528 if ((addrstr = _hgetword(&line)) == NULL
1529 || (cname = _hgetword(&line)) == NULL)
1531 match = (strcasecmp(cname, name) == 0);
1533 while ((p = _hgetword(&line)) != NULL) {
1535 match = (strcasecmp(p, name) == 0);
1536 if (nalias < MAXALIASES)
1537 aliases[nalias++] = p;
1543 if (inet_aton(addrstr, (struct in_addr *)&addrbuf)
1545 *errp = NO_DATA; /* name found */
1551 if (inet_pton(af, addrstr, &addrbuf) != 1) {
1552 *errp = NO_DATA; /* name found */
1560 hp->h_aliases = aliases;
1561 aliases[nalias] = NULL;
1562 hp->h_addrtype = af;
1563 hp->h_length = ADDRLEN(af);
1564 hp->h_addr_list = addrs;
1565 addrs[0] = (char *)&addrbuf;
1567 hp = _hpcopy(hp, errp);
1568 rethp = _hpmerge(rethp, hp, errp);
1571 *(struct hostent **)rval = rethp;
1572 return (rethp != NULL) ? NS_SUCCESS : NS_NOTFOUND;
1576 _files_ghbyaddr(void *rval, void *cb_data, va_list ap)
1585 struct hostent *hp, hpbuf;
1586 char *aliases[MAXALIASES + 1], *addrs[2];
1587 union inx_addr addrbuf;
1590 addr = va_arg(ap, const void *);
1591 addrlen = va_arg(ap, int);
1592 af = va_arg(ap, int);
1593 errp = va_arg(ap, int *);
1595 *(struct hostent**)rval = NULL;
1597 if ((fp = _files_open(errp)) == NULL)
1600 while (fgets(buf, sizeof(buf), fp)) {
1602 if ((p = _hgetword(&line)) == NULL
1604 ? inet_aton(p, (struct in_addr *)&addrbuf)
1605 : inet_pton(af, p, &addrbuf)) != 1
1606 || memcmp(addr, &addrbuf, addrlen) != 0
1607 || (p = _hgetword(&line)) == NULL)
1611 hp->h_aliases = aliases;
1613 while ((p = _hgetword(&line)) != NULL) {
1614 if (nalias < MAXALIASES)
1615 aliases[nalias++] = p;
1617 aliases[nalias] = NULL;
1618 hp->h_addrtype = af;
1619 hp->h_length = addrlen;
1620 hp->h_addr_list = addrs;
1621 addrs[0] = (char *)&addrbuf;
1623 hp = _hpcopy(hp, errp);
1627 *(struct hostent **)rval = hp;
1628 return (hp != NULL) ? NS_SUCCESS : NS_NOTFOUND;
1635 * XXX actually a hack.
1638 _nis_ghbyname(void *rval, void *cb_data, va_list ap)
1643 struct hostent *hp = NULL;
1645 name = va_arg(ap, const char *);
1646 af = va_arg(ap, int);
1647 errp = va_arg(ap, int *);
1649 hp = _gethostbynisname(name, af);
1651 hp = _hpcopy(hp, errp);
1653 *(struct hostent **)rval = hp;
1654 return (hp != NULL) ? NS_SUCCESS : NS_NOTFOUND;
1658 _nis_ghbyaddr(void *rval, void *cb_data, va_list ap)
1664 struct hostent *hp = NULL;
1666 addr = va_arg(ap, const void *);
1667 addrlen = va_arg(ap, int);
1668 af = va_arg(ap, int);
1670 hp = _gethostbynisaddr(addr, addrlen, af);
1672 hp = _hpcopy(hp, errp);
1673 *(struct hostent **)rval = hp;
1674 return (hp != NULL) ? NS_SUCCESS : NS_NOTFOUND;
1678 #define MAXPACKET (64*1024)
1682 u_char buf[MAXPACKET];
1685 static struct hostent *getanswer(const querybuf *, int, const char *, int,
1686 struct hostent *, int *);
1689 * we don't need to take care about sorting, nor IPv4 mapped address here.
1691 static struct hostent *
1692 getanswer(const querybuf *answer, int anslen, const char *qname, int qtype,
1693 struct hostent *template, int *errp)
1698 const u_char *eom, *erdata;
1699 char *bp, *ep, **ap, **hap;
1700 int type, class, ancount, qdcount;
1701 int haveanswer, had_error;
1702 char tbuf[MAXDNAME];
1704 int (*name_ok)(const char *);
1705 static char *h_addr_ptrs[MAXADDRS + 1];
1706 static char *host_aliases[MAXALIASES];
1707 static char hostbuf[8*1024];
1709 #define BOUNDED_INCR(x) \
1713 *errp = NO_RECOVERY; \
1718 #define BOUNDS_CHECK(ptr, count) \
1720 if ((ptr) + (count) > eom) { \
1721 *errp = NO_RECOVERY; \
1726 /* XXX do {} while (0) cannot be put here */
1727 #define DNS_ASSERT(x) \
1735 /* XXX do {} while (0) cannot be put here */
1736 #define DNS_FATAL(x) \
1745 template->h_name = NULL;
1746 eom = answer->buf + anslen;
1756 return (NULL); /* XXX should be abort(); */
1759 * find first satisfactory answer
1762 ancount = ntohs(hp->ancount);
1763 qdcount = ntohs(hp->qdcount);
1765 ep = hostbuf + sizeof hostbuf;
1767 BOUNDED_INCR(HFIXEDSZ);
1769 *errp = NO_RECOVERY;
1772 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
1773 if ((n < 0) || !(*name_ok)(bp)) {
1774 *errp = NO_RECOVERY;
1777 BOUNDED_INCR(n + QFIXEDSZ);
1778 if (qtype == T_A || qtype == T_AAAA) {
1779 /* res_send() has already verified that the query name is the
1780 * same as the one we sent; this just gets the expanded name
1781 * (i.e., with the succeeding search-domain tacked on).
1783 n = strlen(bp) + 1; /* for the \0 */
1784 if (n >= MAXHOSTNAMELEN) {
1785 *errp = NO_RECOVERY;
1788 template->h_name = bp;
1790 /* The qname can be abbreviated, but h_name is now absolute. */
1791 qname = template->h_name;
1795 template->h_aliases = host_aliases;
1798 template->h_addr_list = h_addr_ptrs;
1801 while (ancount-- > 0 && cp < eom && !had_error) {
1802 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
1804 DNS_FATAL((*name_ok)(bp));
1806 BOUNDS_CHECK(cp, 3 * INT16SZ + INT32SZ);
1807 type = _getshort(cp);
1808 cp += INT16SZ; /* type */
1809 class = _getshort(cp);
1810 cp += INT16SZ + INT32SZ; /* class, TTL */
1812 cp += INT16SZ; /* len */
1813 BOUNDS_CHECK(cp, n);
1815 DNS_ASSERT(class == C_IN);
1816 if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) {
1817 if (ap >= &host_aliases[MAXALIASES-1])
1819 n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
1821 DNS_FATAL((*name_ok)(tbuf));
1824 *errp = NO_RECOVERY;
1829 n = strlen(bp) + 1; /* for the \0 */
1830 DNS_FATAL(n < MAXHOSTNAMELEN);
1832 /* Get canonical name. */
1833 n = strlen(tbuf) + 1; /* for the \0 */
1834 DNS_FATAL(n <= ep - bp);
1835 DNS_FATAL(n < MAXHOSTNAMELEN);
1837 template->h_name = bp;
1841 if (qtype == T_PTR && type == T_CNAME) {
1842 n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
1843 if (n < 0 || !res_dnok(tbuf)) {
1849 *errp = NO_RECOVERY;
1852 /* Get canonical name. */
1853 n = strlen(tbuf) + 1; /* for the \0 */
1854 if (n > ep - bp || n >= MAXHOSTNAMELEN) {
1863 DNS_ASSERT(type == qtype);
1866 DNS_ASSERT(strcasecmp(tname, bp) == 0);
1867 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
1869 DNS_FATAL(res_hnok(bp));
1870 #if MULTI_PTRS_ARE_ALIASES
1873 *errp = NO_RECOVERY;
1877 template->h_name = bp;
1878 else if (ap < &host_aliases[MAXALIASES-1])
1883 n = strlen(bp) + 1; /* for the \0 */
1884 if (n >= MAXHOSTNAMELEN) {
1892 template->h_name = bp;
1893 *errp = NETDB_SUCCESS;
1898 DNS_ASSERT(strcasecmp(template->h_name, bp) == 0);
1899 DNS_ASSERT(n == template->h_length);
1903 template->h_name = bp;
1904 nn = strlen(bp) + 1; /* for the \0 */
1907 bp = (char *)ALIGN(bp);
1909 DNS_FATAL(bp + n < ep);
1910 DNS_ASSERT(hap < &h_addr_ptrs[MAXADDRS-1]);
1911 #ifdef FILTER_V4MAPPED
1912 if (type == T_AAAA) {
1913 struct in6_addr in6;
1914 memcpy(&in6, cp, sizeof(in6));
1915 DNS_ASSERT(IN6_IS_ADDR_V4MAPPED(&in6) == 0);
1918 bcopy(cp, *hap++ = bp, n);
1922 *errp = NO_RECOVERY;
1935 if (!template->h_name) {
1936 n = strlen(qname) + 1; /* for the \0 */
1937 if (n > ep - bp || n >= MAXHOSTNAMELEN)
1940 template->h_name = bp;
1943 *errp = NETDB_SUCCESS;
1947 *errp = NO_RECOVERY;
1957 _dns_ghbyname(void *rval, void *cb_data, va_list ap)
1965 struct hostent hbuf;
1969 name = va_arg(ap, const char *);
1970 af = va_arg(ap, int);
1971 errp = va_arg(ap, int *);
1973 statp = __res_state();
1975 memset(&hbuf, 0, sizeof(hbuf));
1976 hbuf.h_addrtype = af;
1977 hbuf.h_length = ADDRLEN(af);
1989 *errp = NO_RECOVERY;
1992 buf = malloc(sizeof(*buf));
1994 *errp = NETDB_INTERNAL;
1997 n = res_nsearch(statp, name, C_IN, qtype, buf->buf, sizeof(buf->buf));
2000 *errp = statp->res_h_errno;
2003 hp = getanswer(buf, n, name, qtype, &hbuf, errp);
2006 *errp = NO_RECOVERY;
2009 *(struct hostent **)rval = _hpcopy(&hbuf, errp);
2010 if (*(struct hostent **)rval != NULL)
2012 else if (*errp == TRY_AGAIN)
2019 _dns_ghbyaddr(void *rval, void *cb_data, va_list ap)
2030 struct hostent hbuf;
2032 static const char hex[] = "0123456789abcdef";
2035 char qbuf[MAXDNAME+1];
2037 char *tld6[] = { "ip6.arpa", NULL };
2038 char *tld4[] = { "in-addr.arpa", NULL };
2042 addr = va_arg(ap, const void *);
2043 addrlen = va_arg(ap, int);
2044 af = va_arg(ap, int);
2045 errp = va_arg(ap, int *);
2047 *(struct hostent **)rval = NULL;
2051 if (af == AF_INET6 && IN6_IS_ADDR_LINKLOCAL((struct in6_addr *)addr))
2068 statp = __res_state();
2069 if ((statp->options & RES_INIT) == 0) {
2070 if (res_ninit(statp) < 0) {
2071 *errp = NETDB_INTERNAL;
2075 memset(&hbuf, 0, sizeof(hbuf));
2077 hbuf.h_addrtype = af;
2078 hbuf.h_length = addrlen;
2080 buf = malloc(sizeof(*buf));
2082 *errp = NETDB_INTERNAL;
2086 for (/* nothing */; *tld; tld++) {
2088 * XXX assumes that MAXDNAME is big enough - error checks
2089 * has been made by callers
2093 cp = (u_char *)addr+addrlen-1;
2097 for (; n < addrlen; n++, cp--) {
2099 *bp++ = hex[c & 0xf];
2101 *bp++ = hex[c >> 4];
2108 for (; n < addrlen; n++, cp--) {
2111 *bp++ = '0' + c / 100;
2113 *bp++ = '0' + (c % 100) / 10;
2114 *bp++ = '0' + c % 10;
2121 n = res_nquery(statp, qbuf, C_IN, T_PTR, buf->buf,
2124 *errp = statp->res_h_errno;
2127 } else if (n > sizeof(buf->buf)) {
2129 errno = ERANGE; /* XXX is it OK to set errno here? */
2131 *errp = NETDB_INTERNAL;
2135 hp = getanswer(buf, n, qbuf, T_PTR, &hbuf, errp);
2141 hbuf.h_addrtype = af;
2142 hbuf.h_length = addrlen;
2143 hbuf.h_addr_list = hlist;
2144 hlist[0] = (char *)addr;
2146 *(struct hostent **)rval = _hpcopy(&hbuf, errp);
2154 _dns_shent(int stayopen)
2158 statp = __res_state();
2159 if ((statp->options & RES_INIT) == 0) {
2160 if (res_ninit(statp) < 0)
2164 statp->options |= RES_STAYOPEN | RES_USEVC;
2172 statp = __res_state();
2173 statp->options &= ~(RES_STAYOPEN | RES_USEVC);
2181 * draft-ietf-ipngwg-icmp-namelookups-02.txt
2182 * ifindex is assumed to be encoded in addr.
2184 #include <sys/uio.h>
2185 #include <netinet/ip6.h>
2186 #include <netinet/icmp6.h>
2188 struct _icmp_host_cache {
2189 struct _icmp_host_cache *hc_next;
2191 struct in6_addr hc_addr;
2196 _icmp_fqdn_query(const struct in6_addr *addr, int ifindex)
2199 struct icmp6_filter filter;
2201 struct cmsghdr *cmsg;
2202 struct in6_pktinfo *pkt;
2206 struct icmp6_fqdn_query *fq;
2207 struct icmp6_fqdn_reply *fr;
2208 struct _icmp_host_cache *hc;
2209 struct sockaddr_in6 sin6;
2212 struct timeval tout;
2215 static struct _icmp_host_cache *hc_head;
2218 for (hc = hc_head; hc; hc = hc->hc_next) {
2219 if (hc->hc_ifindex == ifindex
2220 && IN6_ARE_ADDR_EQUAL(&hc->hc_addr, addr)) {
2222 return hc->hc_name; /* XXX: never freed */
2227 ICMP6_FILTER_SETBLOCKALL(&filter);
2228 ICMP6_FILTER_SETPASS(ICMP6_FQDN_REPLY, &filter);
2232 tout.tv_usec = 200000; /*XXX: 200ms*/
2234 fq = (struct icmp6_fqdn_query *)buf;
2235 fq->icmp6_fqdn_type = ICMP6_FQDN_QUERY;
2236 fq->icmp6_fqdn_code = 0;
2237 fq->icmp6_fqdn_cksum = 0;
2238 fq->icmp6_fqdn_id = (u_short)getpid();
2239 fq->icmp6_fqdn_unused = 0;
2240 fq->icmp6_fqdn_cookie[0] = 0;
2241 fq->icmp6_fqdn_cookie[1] = 0;
2243 memset(&sin6, 0, sizeof(sin6));
2244 sin6.sin6_family = AF_INET6;
2245 sin6.sin6_addr = *addr;
2247 memset(&msg, 0, sizeof(msg));
2248 msg.msg_name = (caddr_t)&sin6;
2249 msg.msg_namelen = sizeof(sin6);
2252 msg.msg_control = NULL;
2253 msg.msg_controllen = 0;
2254 iov.iov_base = (caddr_t)buf;
2255 iov.iov_len = sizeof(struct icmp6_fqdn_query);
2258 msg.msg_control = cbuf;
2259 msg.msg_controllen = sizeof(cbuf);
2260 cmsg = CMSG_FIRSTHDR(&msg);
2261 cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
2262 cmsg->cmsg_level = IPPROTO_IPV6;
2263 cmsg->cmsg_type = IPV6_PKTINFO;
2264 pkt = (struct in6_pktinfo *)&cmsg[1];
2265 memset(&pkt->ipi6_addr, 0, sizeof(struct in6_addr));
2266 pkt->ipi6_ifindex = ifindex;
2267 cmsg = CMSG_NXTHDR(&msg, cmsg);
2268 msg.msg_controllen = (char *)cmsg - cbuf;
2271 if ((s = _socket(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0)
2273 (void)_setsockopt(s, IPPROTO_ICMPV6, ICMP6_FILTER,
2274 (char *)&filter, sizeof(filter));
2275 cc = _sendmsg(s, &msg, 0);
2283 if (_select(s + 1, &fds, NULL, NULL, &tout) <= 0) {
2288 cc = _recvfrom(s, buf, sizeof(buf), 0,
2289 (struct sockaddr *)&sin6, &len);
2294 if (cc < sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr))
2296 if (!IN6_ARE_ADDR_EQUAL(addr, &sin6.sin6_addr))
2298 fr = (struct icmp6_fqdn_reply *)(buf + sizeof(struct ip6_hdr));
2299 if (fr->icmp6_fqdn_type == ICMP6_FQDN_REPLY)
2303 if (fr->icmp6_fqdn_cookie[1] != 0) {
2305 name = buf + sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr) + 4;
2306 len = (buf + cc) - name;
2308 len = fr->icmp6_fqdn_namelen;
2309 name = fr->icmp6_fqdn_name;
2315 if ((hc = (struct _icmp_host_cache *)malloc(sizeof(*hc))) == NULL)
2317 /* XXX: limit number of cached entries */
2318 hc->hc_ifindex = ifindex;
2319 hc->hc_addr = *addr;
2320 hc->hc_name = strdup(name);
2322 hc->hc_next = hc_head;
2328 static struct hostent *
2329 _icmp_ghbyaddr(const void *addr, int addrlen, int af, int *errp)
2333 struct in6_addr addr6;
2335 if (af != AF_INET6) {
2337 * Note: rfc1788 defines Who Are You for IPv4,
2338 * but no one implements it.
2343 memcpy(&addr6, addr, addrlen);
2344 ifindex = (addr6.s6_addr[2] << 8) | addr6.s6_addr[3];
2345 addr6.s6_addr[2] = addr6.s6_addr[3] = 0;
2347 if (!IN6_IS_ADDR_LINKLOCAL(&addr6))
2348 return NULL; /*XXX*/
2350 if ((hname = _icmp_fqdn_query(&addr6, ifindex)) == NULL)
2352 return _hpaddr(af, hname, &addr6, errp);