xref: /freebsd/lib/libc/net/name6.c (revision 7bd6fde3)
1 /*	$KAME: name6.c,v 1.25 2000/06/26 16:44:40 itojun Exp $	*/
2 
3 /*
4  * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. 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.
18  *
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
29  * SUCH DAMAGE.
30  */
31 /*
32  * ++Copyright++ 1985, 1988, 1993
33  * -
34  * Copyright (c) 1985, 1988, 1993
35  *    The Regents of the University of California.  All rights reserved.
36  *
37  * Redistribution and use in source and binary forms, with or without
38  * modification, are permitted provided that the following conditions
39  * are met:
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.
52  *
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
63  * SUCH DAMAGE.
64  * -
65  * Portions Copyright (c) 1993 by Digital Equipment Corporation.
66  *
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.
73  *
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
81  * SOFTWARE.
82  * -
83  * --Copyright--
84  */
85 
86 /*
87  *	Atsushi Onoe <onoe@sm.sony.co.jp>
88  */
89 
90 #include <sys/cdefs.h>
91 __FBSDID("$FreeBSD$");
92 
93 #include "namespace.h"
94 #include <sys/param.h>
95 #include <sys/socket.h>
96 #include <sys/time.h>
97 #include <sys/queue.h>
98 #include <netinet/in.h>
99 #ifdef INET6
100 #include <net/if.h>
101 #include <net/if_var.h>
102 #include <sys/sysctl.h>
103 #include <sys/ioctl.h>
104 #include <netinet6/in6_var.h>	/* XXX */
105 #endif
106 
107 #include <arpa/inet.h>
108 #include <arpa/nameser.h>
109 
110 #include <errno.h>
111 #include <netdb.h>
112 #include <resolv.h>
113 #include <stdio.h>
114 #include <stdlib.h>
115 #include <string.h>
116 #include <stdarg.h>
117 #include <nsswitch.h>
118 #include <unistd.h>
119 #include "un-namespace.h"
120 #include "netdb_private.h"
121 #include "res_config.h"
122 #include "res_private.h"
123 #ifdef NS_CACHING
124 #include "nscache.h"
125 #endif
126 
127 #ifndef _PATH_HOSTS
128 #define	_PATH_HOSTS	"/etc/hosts"
129 #endif
130 
131 #ifndef MAXALIASES
132 #define	MAXALIASES	10
133 #endif
134 #ifndef	MAXADDRS
135 #define	MAXADDRS	20
136 #endif
137 #ifndef MAXDNAME
138 #define	MAXDNAME	1025
139 #endif
140 
141 #ifdef INET6
142 #define	ADDRLEN(af)	((af) == AF_INET6 ? sizeof(struct in6_addr) : \
143 					    sizeof(struct in_addr))
144 #else
145 #define	ADDRLEN(af)	sizeof(struct in_addr)
146 #endif
147 
148 #define	MAPADDR(ab, ina) \
149 do {									\
150 	memcpy(&(ab)->map_inaddr, ina, sizeof(struct in_addr));		\
151 	memset((ab)->map_zero, 0, sizeof((ab)->map_zero));		\
152 	memset((ab)->map_one, 0xff, sizeof((ab)->map_one));		\
153 } while (0)
154 #define	MAPADDRENABLED(flags) \
155 	(((flags) & AI_V4MAPPED) || \
156 	 (((flags) & AI_V4MAPPED_CFG) && _mapped_addr_enabled()))
157 
158 union inx_addr {
159 	struct in_addr	in_addr;
160 #ifdef INET6
161 	struct in6_addr	in6_addr;
162 #endif
163 	struct {
164 		u_char	mau_zero[10];
165 		u_char	mau_one[2];
166 		struct in_addr mau_inaddr;
167 	}		map_addr_un;
168 #define	map_zero	map_addr_un.mau_zero
169 #define	map_one		map_addr_un.mau_one
170 #define	map_inaddr	map_addr_un.mau_inaddr
171 };
172 
173 struct policyqueue {
174 	TAILQ_ENTRY(policyqueue) pc_entry;
175 #ifdef INET6
176 	struct in6_addrpolicy pc_policy;
177 #endif
178 };
179 TAILQ_HEAD(policyhead, policyqueue);
180 
181 #define AIO_SRCFLAG_DEPRECATED	0x1
182 
183 struct hp_order {
184 	union {
185 		struct sockaddr_storage aiou_ss;
186 		struct sockaddr aiou_sa;
187 	} aio_src_un;
188 #define aio_srcsa aio_src_un.aiou_sa
189 	u_int32_t aio_srcflag;
190 	int aio_srcscope;
191 	int aio_dstscope;
192 	struct policyqueue *aio_srcpolicy;
193 	struct policyqueue *aio_dstpolicy;
194 	union {
195 		struct sockaddr_storage aiou_ss;
196 		struct sockaddr aiou_sa;
197 	} aio_un;
198 #define aio_sa aio_un.aiou_sa
199 	int aio_matchlen;
200 	char *aio_h_addr;
201 };
202 
203 static struct	 hostent *_hpcopy(struct hostent *, int *);
204 static struct	 hostent *_hpaddr(int, const char *, void *, int *);
205 static struct	 hostent *_hpmerge(struct hostent *, struct hostent *, int *);
206 #ifdef INET6
207 static struct	 hostent *_hpmapv6(struct hostent *, int *);
208 #endif
209 static struct	 hostent *_hpsort(struct hostent *, res_state);
210 static struct	 hostent *_ghbyname(const char *, int, int, int *);
211 static char	*_hgetword(char **);
212 static int	 _mapped_addr_enabled(void);
213 
214 static struct	 hostent *_hpreorder(struct hostent *);
215 static int	 get_addrselectpolicy(struct policyhead *);
216 static void	 free_addrselectpolicy(struct policyhead *);
217 static struct	 policyqueue *match_addrselectpolicy(struct sockaddr *,
218 	struct policyhead *);
219 static void	 set_source(struct hp_order *, struct policyhead *);
220 static int	 matchlen(struct sockaddr *, struct sockaddr *);
221 static int	 comp_dst(const void *, const void *);
222 static int	 gai_addr2scopetype(struct sockaddr *);
223 
224 static FILE	*_files_open(int *);
225 static int	 _files_ghbyname(void *, void *, va_list);
226 static int	 _files_ghbyaddr(void *, void *, va_list);
227 #ifdef YP
228 static int	 _nis_ghbyname(void *, void *, va_list);
229 static int	 _nis_ghbyaddr(void *, void *, va_list);
230 #endif
231 static int	 _dns_ghbyname(void *, void *, va_list);
232 static int	 _dns_ghbyaddr(void *, void *, va_list);
233 static void	 _dns_shent(int) __unused;
234 static void	 _dns_ehent(void) __unused;
235 #ifdef ICMPNL
236 static int	 _icmp_ghbyaddr(void *, void *, va_list);
237 #endif /* ICMPNL */
238 #ifdef NS_CACHING
239 static int ipnode_id_func(char *, size_t *, va_list, void *);
240 static int ipnode_marshal_func(char *, size_t *, void *, va_list, void *);
241 static int ipnode_unmarshal_func(char *, size_t, void *, va_list, void *);
242 #endif
243 
244 /* Host lookup order if nsswitch.conf is broken or nonexistant */
245 static const ns_src default_src[] = {
246 	{ NSSRC_FILES, NS_SUCCESS },
247 	{ NSSRC_DNS, NS_SUCCESS },
248 #ifdef ICMPNL
249 #define NSSRC_ICMP "icmp"
250 	{ NSSRC_ICMP, NS_SUCCESS },
251 #endif
252 	{ 0 }
253 };
254 
255 /*
256  * Check if kernel supports mapped address.
257  *	implementation dependent
258  */
259 #ifdef __KAME__
260 #include <sys/sysctl.h>
261 #endif /* __KAME__ */
262 
263 static int
264 _mapped_addr_enabled(void)
265 {
266 	/* implementation dependent check */
267 #if defined(__KAME__) && defined(IPV6CTL_MAPPED_ADDR)
268 	int mib[4];
269 	size_t len;
270 	int val;
271 
272 	mib[0] = CTL_NET;
273 	mib[1] = PF_INET6;
274 	mib[2] = IPPROTO_IPV6;
275 	mib[3] = IPV6CTL_MAPPED_ADDR;
276 	len = sizeof(val);
277 	if (sysctl(mib, 4, &val, &len, 0, 0) == 0 && val != 0)
278 		return 1;
279 #endif /* __KAME__ && IPV6CTL_MAPPED_ADDR */
280 	return 0;
281 }
282 
283 #ifdef NS_CACHING
284 static int
285 ipnode_id_func(char *buffer, size_t *buffer_size, va_list ap,
286     void *cache_mdata)
287 {
288 	res_state statp;
289 	u_long res_options;
290 
291 	const int op_id = 2;
292 	char *name;
293 	int af;
294 	size_t len;
295 	void *src;
296 
297 	char *p;
298 	size_t desired_size, size;
299 	enum nss_lookup_type lookup_type;
300 	int res = NS_UNAVAIL;
301 
302 	statp = __res_state();
303 	res_options = statp->options & (RES_RECURSE | RES_DEFNAMES |
304 	    RES_DNSRCH | RES_NOALIASES | RES_USE_INET6);
305 
306 	lookup_type = (enum nss_lookup_type)cache_mdata;
307 	switch (lookup_type) {
308 	case nss_lt_name:
309 		name = va_arg(ap, char *);
310 		af = va_arg(ap, int);
311 
312 		size = strlen(name);
313 		desired_size = sizeof(res_options) + sizeof(int) +
314 		    sizeof(enum nss_lookup_type) + sizeof(int) + size + 1;
315 
316 		if (desired_size > *buffer_size) {
317 			res = NS_RETURN;
318 			goto fin;
319 		}
320 
321 		p = buffer;
322 		memcpy(p, &res_options, sizeof(res_options));
323 		p += sizeof(res_options);
324 
325 		memcpy(p, &op_id, sizeof(int));
326 		p += sizeof(int);
327 
328 		memcpy(p, &lookup_type, sizeof(enum nss_lookup_type));
329 		p += sizeof(enum nss_lookup_type);
330 
331 		memcpy(p, &af, sizeof(int));
332 		p += sizeof(int);
333 
334 		memcpy(p, name, size + 1);
335 
336 		res = NS_SUCCESS;
337 		break;
338 	case nss_lt_id:
339 		src = va_arg(ap, void *);
340 		len = va_arg(ap, size_t);
341 		af = va_arg(ap, int);
342 
343 		desired_size = sizeof(res_options) + sizeof(int) +
344 		    sizeof(enum nss_lookup_type) + sizeof(int) +
345 		    sizeof(size_t) + len;
346 
347 		if (desired_size > *buffer_size) {
348 			res = NS_RETURN;
349 			goto fin;
350 		}
351 
352 		p = buffer;
353 		memcpy(p, &res_options, sizeof(res_options));
354 		p += sizeof(res_options);
355 
356 		memcpy(p, &op_id, sizeof(int));
357 		p += sizeof(int);
358 
359 		memcpy(p, &lookup_type, sizeof(enum nss_lookup_type));
360 		p += sizeof(enum nss_lookup_type);
361 
362 		memcpy(p, &af, sizeof(int));
363 		p += sizeof(int);
364 
365 		memcpy(p, &len, sizeof(size_t));
366 		p += sizeof(size_t);
367 
368 		memcpy(p, src, len);
369 
370 		res = NS_SUCCESS;
371 		break;
372 	default:
373 		/* should be unreachable */
374 		return (NS_UNAVAIL);
375 	}
376 
377 fin:
378 	*buffer_size = desired_size;
379 	return (res);
380 }
381 
382 static int
383 ipnode_marshal_func(char *buffer, size_t *buffer_size, void *retval,
384     va_list ap, void *cache_mdata)
385 {
386 	struct hostent *ht;
387 
388 	struct hostent new_ht;
389 	size_t desired_size, aliases_size, addr_size, size;
390 	char *p, **iter;
391 
392 	ht = *((struct hostent **)retval);
393 
394 	desired_size = _ALIGNBYTES + sizeof(struct hostent) + sizeof(char *);
395 	if (ht->h_name != NULL)
396 		desired_size += strlen(ht->h_name) + 1;
397 
398 	if (ht->h_aliases != NULL) {
399 		aliases_size = 0;
400 		for (iter = ht->h_aliases; *iter; ++iter) {
401 			desired_size += strlen(*iter) + 1;
402 			++aliases_size;
403 		}
404 
405 		desired_size += _ALIGNBYTES +
406 		    (aliases_size + 1) * sizeof(char *);
407 	}
408 
409 	if (ht->h_addr_list != NULL) {
410 		addr_size = 0;
411 		for (iter = ht->h_addr_list; *iter; ++iter)
412 			++addr_size;
413 
414 		desired_size += addr_size * _ALIGN(ht->h_length);
415 		desired_size += _ALIGNBYTES + (addr_size + 1) * sizeof(char *);
416 	}
417 
418 	if (desired_size > *buffer_size) {
419 		/* this assignment is here for future use */
420 		*buffer_size = desired_size;
421 		return (NS_RETURN);
422 	}
423 
424 	memcpy(&new_ht, ht, sizeof(struct hostent));
425 	memset(buffer, 0, desired_size);
426 
427 	*buffer_size = desired_size;
428 	p = buffer + sizeof(struct hostent) + sizeof(char *);
429 	memcpy(buffer + sizeof(struct hostent), &p, sizeof(char *));
430 	p = (char *)_ALIGN(p);
431 
432 	if (new_ht.h_name != NULL) {
433 		size = strlen(new_ht.h_name);
434 		memcpy(p, new_ht.h_name, size);
435 		new_ht.h_name = p;
436 		p += size + 1;
437 	}
438 
439 	if (new_ht.h_aliases != NULL) {
440 		p = (char *)_ALIGN(p);
441 		memcpy(p, new_ht.h_aliases, sizeof(char *) * aliases_size);
442 		new_ht.h_aliases = (char **)p;
443 		p += sizeof(char *) * (aliases_size + 1);
444 
445 		for (iter = new_ht.h_aliases; *iter; ++iter) {
446 			size = strlen(*iter);
447 			memcpy(p, *iter, size);
448 			*iter = p;
449 			p += size + 1;
450 		}
451 	}
452 
453 	if (new_ht.h_addr_list != NULL) {
454 		p = (char *)_ALIGN(p);
455 		memcpy(p, new_ht.h_addr_list, sizeof(char *) * addr_size);
456 		new_ht.h_addr_list = (char **)p;
457 		p += sizeof(char *) * (addr_size + 1);
458 
459 		size = _ALIGN(new_ht.h_length);
460 		for (iter = new_ht.h_addr_list; *iter; ++iter) {
461 			memcpy(p, *iter, size);
462 			*iter = p;
463 			p += size + 1;
464 		}
465 	}
466 	memcpy(buffer, &new_ht, sizeof(struct hostent));
467 	return (NS_SUCCESS);
468 }
469 
470 static int
471 ipnode_unmarshal_func(char *buffer, size_t buffer_size, void *retval,
472     va_list ap, void *cache_mdata)
473 {
474 	struct hostent new_ht;
475 	struct hostent *ht;
476 
477 	char *p;
478 	char **iter;
479 	char *orig_buf;
480 	int err;
481 
482 	ht = &new_ht;
483 
484 	memcpy(ht, buffer, sizeof(struct hostent));
485 	memcpy(&p, buffer + sizeof(struct hostent), sizeof(char *));
486 
487 	orig_buf = buffer + sizeof(struct hostent) + sizeof(char *) +
488 	    _ALIGN(p) - (size_t)p;
489 	p = (char *)_ALIGN(p);
490 
491 
492 	NS_APPLY_OFFSET(ht->h_name, orig_buf, p, char *);
493 	if (ht->h_aliases != NULL) {
494 		NS_APPLY_OFFSET(ht->h_aliases, orig_buf, p, char **);
495 
496 		for (iter = ht->h_aliases; *iter; ++iter)
497 			NS_APPLY_OFFSET(*iter, orig_buf, p, char *);
498 	}
499 
500 	if (ht->h_addr_list != NULL) {
501 		NS_APPLY_OFFSET(ht->h_addr_list, orig_buf, p, char **);
502 
503 		for (iter = ht->h_addr_list; *iter; ++iter)
504 			NS_APPLY_OFFSET(*iter, orig_buf, p, char *);
505 	}
506 
507 	ht = _hpcopy(ht, &err);
508 	if (ht == NULL)
509 		return (NS_UNAVAIL);
510 
511 	*((struct hostent **)retval) = ht;
512 	return (NS_SUCCESS);
513 }
514 #endif
515 
516 /*
517  * Functions defined in RFC2553
518  *	getipnodebyname, getipnodebyaddr, freehostent
519  */
520 
521 static struct hostent *
522 _ghbyname(const char *name, int af, int flags, int *errp)
523 {
524 	struct hostent *hp;
525 	int rval;
526 
527 #ifdef NS_CACHING
528 	static const nss_cache_info cache_info =
529 	NS_COMMON_CACHE_INFO_INITIALIZER(
530 		hosts, (void *)nss_lt_name,
531 		ipnode_id_func, ipnode_marshal_func, ipnode_unmarshal_func);
532 #endif
533 	static const ns_dtab dtab[] = {
534 		NS_FILES_CB(_files_ghbyname, NULL)
535 		{ NSSRC_DNS, _dns_ghbyname, NULL },
536 		NS_NIS_CB(_nis_ghbyname, NULL)
537 #ifdef NS_CACHING
538 		NS_CACHE_CB(&cache_info)
539 #endif
540 		{ 0 }
541 	};
542 
543 	if (flags & AI_ADDRCONFIG) {
544 		int s;
545 
546 		if ((s = _socket(af, SOCK_DGRAM, 0)) < 0)
547 			return NULL;
548 		/*
549 		 * TODO:
550 		 * Note that implementation dependent test for address
551 		 * configuration should be done everytime called
552 		 * (or apropriate interval),
553 		 * because addresses will be dynamically assigned or deleted.
554 		 */
555 		_close(s);
556 	}
557 
558 	rval = _nsdispatch(&hp, dtab, NSDB_HOSTS, "ghbyname", default_src,
559 			  name, af, errp);
560 	return (rval == NS_SUCCESS) ? hp : NULL;
561 }
562 
563 struct hostent *
564 getipnodebyname(const char *name, int af, int flags, int *errp)
565 {
566 	struct hostent *hp;
567 	union inx_addr addrbuf;
568 	res_state statp;
569 
570 	switch (af) {
571 	case AF_INET:
572 #ifdef INET6
573 	case AF_INET6:
574 #endif
575 		break;
576 	default:
577 		*errp = NO_RECOVERY;
578 		return NULL;
579 	}
580 
581 #ifdef INET6
582 	/* special case for literal address */
583 	if (inet_pton(AF_INET6, name, &addrbuf) == 1) {
584 		if (af != AF_INET6) {
585 			*errp = HOST_NOT_FOUND;
586 			return NULL;
587 		}
588 		return _hpaddr(af, name, &addrbuf, errp);
589 	}
590 #endif
591 	if (inet_aton(name, (struct in_addr *)&addrbuf) == 1) {
592 		if (af != AF_INET) {
593 			if (MAPADDRENABLED(flags)) {
594 				MAPADDR(&addrbuf, &addrbuf.in_addr);
595 			} else {
596 				*errp = HOST_NOT_FOUND;
597 				return NULL;
598 			}
599 		}
600 		return _hpaddr(af, name, &addrbuf, errp);
601 	}
602 
603 	statp = __res_state();
604 	if ((statp->options & RES_INIT) == 0) {
605 		if (res_ninit(statp) < 0) {
606 			*errp = NETDB_INTERNAL;
607 			return NULL;
608 		}
609 	}
610 
611 	*errp = HOST_NOT_FOUND;
612 	hp = _ghbyname(name, af, flags, errp);
613 
614 #ifdef INET6
615 	if (af == AF_INET6 && ((flags & AI_ALL) || hp == NULL) &&
616 	    MAPADDRENABLED(flags)) {
617 		struct hostent *hp2 = _ghbyname(name, AF_INET, flags, errp);
618 		if (hp == NULL)
619 			hp = _hpmapv6(hp2, errp);
620 		else {
621 			if (hp2 && strcmp(hp->h_name, hp2->h_name) != 0) {
622 				freehostent(hp2);
623 				hp2 = NULL;
624 			}
625 			hp = _hpmerge(hp, hp2, errp);
626 		}
627 	}
628 #endif
629 	return _hpreorder(_hpsort(hp, statp));
630 }
631 
632 struct hostent *
633 getipnodebyaddr(const void *src, size_t len, int af, int *errp)
634 {
635 	struct hostent *hp;
636 	int rval;
637 #ifdef INET6
638 	struct in6_addr addrbuf;
639 #else
640 	struct in_addr addrbuf;
641 #endif
642 
643 #ifdef NS_CACHING
644 	static const nss_cache_info cache_info =
645 	NS_COMMON_CACHE_INFO_INITIALIZER(
646 		hosts, (void *)nss_lt_id,
647 		ipnode_id_func, ipnode_marshal_func, ipnode_unmarshal_func);
648 #endif
649 	static const ns_dtab dtab[] = {
650 		NS_FILES_CB(_files_ghbyaddr, NULL)
651 		{ NSSRC_DNS, _dns_ghbyaddr, NULL },
652 		NS_NIS_CB(_nis_ghbyaddr, NULL)
653 #ifdef ICMPNL
654 		{ NSSRC_ICMP, _icmp_ghbyaddr, NULL },
655 #endif
656 #ifdef NS_CACHING
657 		NS_CACHE_CB(&cache_info)
658 #endif
659 		{ 0 }
660 	};
661 
662 	*errp = HOST_NOT_FOUND;
663 
664 	switch (af) {
665 	case AF_INET:
666 		if (len != sizeof(struct in_addr)) {
667 			*errp = NO_RECOVERY;
668 			return NULL;
669 		}
670 		if ((long)src & ~(sizeof(struct in_addr) - 1)) {
671 			memcpy(&addrbuf, src, len);
672 			src = &addrbuf;
673 		}
674 		if (((struct in_addr *)src)->s_addr == 0)
675 			return NULL;
676 		break;
677 #ifdef INET6
678 	case AF_INET6:
679 		if (len != sizeof(struct in6_addr)) {
680 			*errp = NO_RECOVERY;
681 			return NULL;
682 		}
683 		if ((long)src & ~(sizeof(struct in6_addr) / 2 - 1)) {	/*XXX*/
684 			memcpy(&addrbuf, src, len);
685 			src = &addrbuf;
686 		}
687 		if (IN6_IS_ADDR_UNSPECIFIED((struct in6_addr *)src))
688 			return NULL;
689 		if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)src)
690 		||  IN6_IS_ADDR_V4COMPAT((struct in6_addr *)src)) {
691 			src = (char *)src +
692 			    (sizeof(struct in6_addr) - sizeof(struct in_addr));
693 			af = AF_INET;
694 			len = sizeof(struct in_addr);
695 		}
696 		break;
697 #endif
698 	default:
699 		*errp = NO_RECOVERY;
700 		return NULL;
701 	}
702 
703 	rval = _nsdispatch(&hp, dtab, NSDB_HOSTS, "ghbyaddr", default_src,
704 			  src, len, af, errp);
705 	return (rval == NS_SUCCESS) ? hp : NULL;
706 }
707 
708 void
709 freehostent(struct hostent *ptr)
710 {
711 	free(ptr);
712 }
713 
714 /*
715  * Private utility functions
716  */
717 
718 /*
719  * _hpcopy: allocate and copy hostent structure
720  */
721 static struct hostent *
722 _hpcopy(struct hostent *hp, int *errp)
723 {
724 	struct hostent *nhp;
725 	char *cp, **pp;
726 	int size, addrsize;
727 	int nalias = 0, naddr = 0;
728 	int al_off;
729 	int i;
730 
731 	if (hp == NULL)
732 		return hp;
733 
734 	/* count size to be allocated */
735 	size = sizeof(struct hostent);
736 	if (hp->h_name != NULL)
737 		size += strlen(hp->h_name) + 1;
738 	if ((pp = hp->h_aliases) != NULL) {
739 		for (i = 0; *pp != NULL; i++, pp++) {
740 			if (**pp != '\0') {
741 				size += strlen(*pp) + 1;
742 				nalias++;
743 			}
744 		}
745 	}
746 	/* adjust alignment */
747 	size = ALIGN(size);
748 	al_off = size;
749 	size += sizeof(char *) * (nalias + 1);
750 	addrsize = ALIGN(hp->h_length);
751 	if ((pp = hp->h_addr_list) != NULL) {
752 		while (*pp++ != NULL)
753 			naddr++;
754 	}
755 	size += addrsize * naddr;
756 	size += sizeof(char *) * (naddr + 1);
757 
758 	/* copy */
759 	if ((nhp = (struct hostent *)malloc(size)) == NULL) {
760 		*errp = TRY_AGAIN;
761 		return NULL;
762 	}
763 	cp = (char *)&nhp[1];
764 	if (hp->h_name != NULL) {
765 		nhp->h_name = cp;
766 		strcpy(cp, hp->h_name);
767 		cp += strlen(cp) + 1;
768 	} else
769 		nhp->h_name = NULL;
770 	nhp->h_aliases = (char **)((char *)nhp + al_off);
771 	if ((pp = hp->h_aliases) != NULL) {
772 		for (i = 0; *pp != NULL; pp++) {
773 			if (**pp != '\0') {
774 				nhp->h_aliases[i++] = cp;
775 				strcpy(cp, *pp);
776 				cp += strlen(cp) + 1;
777 			}
778 		}
779 	}
780 	nhp->h_aliases[nalias] = NULL;
781 	cp = (char *)&nhp->h_aliases[nalias + 1];
782 	nhp->h_addrtype = hp->h_addrtype;
783 	nhp->h_length = hp->h_length;
784 	nhp->h_addr_list = (char **)cp;
785 	if ((pp = hp->h_addr_list) != NULL) {
786 		cp = (char *)&nhp->h_addr_list[naddr + 1];
787 		for (i = 0; *pp != NULL; pp++) {
788 			nhp->h_addr_list[i++] = cp;
789 			memcpy(cp, *pp, hp->h_length);
790 			cp += addrsize;
791 		}
792 	}
793 	nhp->h_addr_list[naddr] = NULL;
794 	return nhp;
795 }
796 
797 /*
798  * _hpaddr: construct hostent structure with one address
799  */
800 static struct hostent *
801 _hpaddr(int af, const char *name, void *addr, int *errp)
802 {
803 	struct hostent *hp, hpbuf;
804 	char *addrs[2];
805 
806 	hp = &hpbuf;
807 	hp->h_name = (char *)name;
808 	hp->h_aliases = NULL;
809 	hp->h_addrtype = af;
810 	hp->h_length = ADDRLEN(af);
811 	hp->h_addr_list = addrs;
812 	addrs[0] = (char *)addr;
813 	addrs[1] = NULL;
814 	return _hpcopy(hp, errp);
815 }
816 
817 /*
818  * _hpmerge: merge 2 hostent structure, arguments will be freed
819  */
820 static struct hostent *
821 _hpmerge(struct hostent *hp1, struct hostent *hp2, int *errp)
822 {
823 	int i, j;
824 	int naddr, nalias;
825 	char **pp;
826 	struct hostent *hp, hpbuf;
827 	char *aliases[MAXALIASES + 1], *addrs[MAXADDRS + 1];
828 	union inx_addr addrbuf[MAXADDRS];
829 
830 	if (hp1 == NULL)
831 		return hp2;
832 	if (hp2 == NULL)
833 		return hp1;
834 
835 #define	HP(i)	(i == 1 ? hp1 : hp2)
836 	hp = &hpbuf;
837 	hp->h_name = (hp1->h_name != NULL ? hp1->h_name : hp2->h_name);
838 	hp->h_aliases = aliases;
839 	nalias = 0;
840 	for (i = 1; i <= 2; i++) {
841 		if ((pp = HP(i)->h_aliases) == NULL)
842 			continue;
843 		for (; nalias < MAXALIASES && *pp != NULL; pp++) {
844 			/* check duplicates */
845 			for (j = 0; j < nalias; j++)
846 				if (strcasecmp(*pp, aliases[j]) == 0)
847 					break;
848 			if (j == nalias)
849 				aliases[nalias++] = *pp;
850 		}
851 	}
852 	aliases[nalias] = NULL;
853 #ifdef INET6
854 	if (hp1->h_length != hp2->h_length) {
855 		hp->h_addrtype = AF_INET6;
856 		hp->h_length = sizeof(struct in6_addr);
857 	} else {
858 #endif
859 		hp->h_addrtype = hp1->h_addrtype;
860 		hp->h_length = hp1->h_length;
861 #ifdef INET6
862 	}
863 #endif
864 	hp->h_addr_list = addrs;
865 	naddr = 0;
866 	for (i = 1; i <= 2; i++) {
867 		if ((pp = HP(i)->h_addr_list) == NULL)
868 			continue;
869 		if (HP(i)->h_length == hp->h_length) {
870 			while (naddr < MAXADDRS && *pp != NULL)
871 				addrs[naddr++] = *pp++;
872 		} else {
873 			/* copy IPv4 addr as mapped IPv6 addr */
874 			while (naddr < MAXADDRS && *pp != NULL) {
875 				MAPADDR(&addrbuf[naddr], *pp++);
876 				addrs[naddr] = (char *)&addrbuf[naddr];
877 				naddr++;
878 			}
879 		}
880 	}
881 	addrs[naddr] = NULL;
882 	hp = _hpcopy(hp, errp);
883 	freehostent(hp1);
884 	freehostent(hp2);
885 	return hp;
886 }
887 
888 /*
889  * _hpmapv6: convert IPv4 hostent into IPv4-mapped IPv6 addresses
890  */
891 #ifdef INET6
892 static struct hostent *
893 _hpmapv6(struct hostent *hp, int *errp)
894 {
895 	struct hostent *hp6;
896 
897 	if (hp == NULL)
898 		return NULL;
899 	if (hp->h_addrtype == AF_INET6)
900 		return hp;
901 
902 	/* make dummy hostent to convert IPv6 address */
903 	if ((hp6 = (struct hostent *)malloc(sizeof(struct hostent))) == NULL) {
904 		*errp = TRY_AGAIN;
905 		return NULL;
906 	}
907 	hp6->h_name = NULL;
908 	hp6->h_aliases = NULL;
909 	hp6->h_addrtype = AF_INET6;
910 	hp6->h_length = sizeof(struct in6_addr);
911 	hp6->h_addr_list = NULL;
912 	return _hpmerge(hp6, hp, errp);
913 }
914 #endif
915 
916 /*
917  * _hpsort: sort address by sortlist
918  */
919 static struct hostent *
920 _hpsort(struct hostent *hp, res_state statp)
921 {
922 	int i, j, n;
923 	u_char *ap, *sp, *mp, **pp;
924 	char t;
925 	char order[MAXADDRS];
926 	int nsort = statp->nsort;
927 
928 	if (hp == NULL || hp->h_addr_list[1] == NULL || nsort == 0)
929 		return hp;
930 	for (i = 0; (ap = (u_char *)hp->h_addr_list[i]); i++) {
931 		for (j = 0; j < nsort; j++) {
932 #ifdef INET6
933 			if (statp->_u._ext.ext->sort_list[j].af !=
934 			    hp->h_addrtype)
935 				continue;
936 			sp = (u_char *)&statp->_u._ext.ext->sort_list[j].addr;
937 			mp = (u_char *)&statp->_u._ext.ext->sort_list[j].mask;
938 #else
939 			sp = (u_char *)&statp->sort_list[j].addr;
940 			mp = (u_char *)&statp->sort_list[j].mask;
941 #endif
942 			for (n = 0; n < hp->h_length; n++) {
943 				if ((ap[n] & mp[n]) != sp[n])
944 					break;
945 			}
946 			if (n == hp->h_length)
947 				break;
948 		}
949 		order[i] = j;
950 	}
951 	n = i;
952 	pp = (u_char **)hp->h_addr_list;
953 	for (i = 0; i < n - 1; i++) {
954 		for (j = i + 1; j < n; j++) {
955 			if (order[i] > order[j]) {
956 				ap = pp[i];
957 				pp[i] = pp[j];
958 				pp[j] = ap;
959 				t = order[i];
960 				order[i] = order[j];
961 				order[j] = t;
962 			}
963 		}
964 	}
965 	return hp;
966 }
967 
968 static char *
969 _hgetword(char **pp)
970 {
971 	char c, *p, *ret;
972 	const char *sp;
973 	static const char sep[] = "# \t\n";
974 
975 	ret = NULL;
976 	for (p = *pp; (c = *p) != '\0'; p++) {
977 		for (sp = sep; *sp != '\0'; sp++) {
978 			if (c == *sp)
979 				break;
980 		}
981 		if (c == '#')
982 			p[1] = '\0';	/* ignore rest of line */
983 		if (ret == NULL) {
984 			if (*sp == '\0')
985 				ret = p;
986 		} else {
987 			if (*sp != '\0') {
988 				*p++ = '\0';
989 				break;
990 			}
991 		}
992 	}
993 	*pp = p;
994 	if (ret == NULL || *ret == '\0')
995 		return NULL;
996 	return ret;
997 }
998 
999 /*
1000  * _hpreorder: sort address by default address selection
1001  */
1002 static struct hostent *
1003 _hpreorder(struct hostent *hp)
1004 {
1005 	struct hp_order *aio;
1006 	int i, n;
1007 	char *ap;
1008 	struct sockaddr *sa;
1009 	struct policyhead policyhead;
1010 
1011 	if (hp == NULL)
1012 		return hp;
1013 
1014 	switch (hp->h_addrtype) {
1015 	case AF_INET:
1016 #ifdef INET6
1017 	case AF_INET6:
1018 #endif
1019 		break;
1020 	default:
1021 		free_addrselectpolicy(&policyhead);
1022 		return hp;
1023 	}
1024 
1025 	/* count the number of addrinfo elements for sorting. */
1026 	for (n = 0; hp->h_addr_list[n] != NULL; n++)
1027 		;
1028 
1029 	/*
1030 	 * If the number is small enough, we can skip the reordering process.
1031 	 */
1032 	if (n <= 1)
1033 		return hp;
1034 
1035 	/* allocate a temporary array for sort and initialization of it. */
1036 	if ((aio = malloc(sizeof(*aio) * n)) == NULL)
1037 		return hp;	/* give up reordering */
1038 	memset(aio, 0, sizeof(*aio) * n);
1039 
1040 	/* retrieve address selection policy from the kernel */
1041 	TAILQ_INIT(&policyhead);
1042 	if (!get_addrselectpolicy(&policyhead)) {
1043 		/* no policy is installed into kernel, we don't sort. */
1044 		free(aio);
1045 		return hp;
1046 	}
1047 
1048 	for (i = 0; i < n; i++) {
1049 		ap = hp->h_addr_list[i];
1050 		aio[i].aio_h_addr = ap;
1051 		sa = &aio[i].aio_sa;
1052 		switch (hp->h_addrtype) {
1053 		case AF_INET:
1054 			sa->sa_family = AF_INET;
1055 			sa->sa_len = sizeof(struct sockaddr_in);
1056 			memcpy(&((struct sockaddr_in *)sa)->sin_addr, ap,
1057 			    sizeof(struct in_addr));
1058 			break;
1059 #ifdef INET6
1060 		case AF_INET6:
1061 			if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)ap)) {
1062 				sa->sa_family = AF_INET;
1063 				sa->sa_len = sizeof(struct sockaddr_in);
1064 				memcpy(&((struct sockaddr_in *)sa)->sin_addr,
1065 				    &ap[12], sizeof(struct in_addr));
1066 			} else {
1067 				sa->sa_family = AF_INET6;
1068 				sa->sa_len = sizeof(struct sockaddr_in6);
1069 				memcpy(&((struct sockaddr_in6 *)sa)->sin6_addr,
1070 				    ap, sizeof(struct in6_addr));
1071 			}
1072 			break;
1073 #endif
1074 		}
1075 		aio[i].aio_dstscope = gai_addr2scopetype(sa);
1076 		aio[i].aio_dstpolicy = match_addrselectpolicy(sa, &policyhead);
1077 		set_source(&aio[i], &policyhead);
1078 	}
1079 
1080 	/* perform sorting. */
1081 	qsort(aio, n, sizeof(*aio), comp_dst);
1082 
1083 	/* reorder the h_addr_list. */
1084 	for (i = 0; i < n; i++)
1085 		hp->h_addr_list[i] = aio[i].aio_h_addr;
1086 
1087 	/* cleanup and return */
1088 	free(aio);
1089 	free_addrselectpolicy(&policyhead);
1090 	return hp;
1091 }
1092 
1093 static int
1094 get_addrselectpolicy(struct policyhead *head)
1095 {
1096 #ifdef INET6
1097 	int mib[] = { CTL_NET, PF_INET6, IPPROTO_IPV6, IPV6CTL_ADDRCTLPOLICY };
1098 	size_t l;
1099 	char *buf;
1100 	struct in6_addrpolicy *pol, *ep;
1101 
1102 	if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), NULL, &l, NULL, 0) < 0)
1103 		return (0);
1104 	if ((buf = malloc(l)) == NULL)
1105 		return (0);
1106 	if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), buf, &l, NULL, 0) < 0) {
1107 		free(buf);
1108 		return (0);
1109 	}
1110 
1111 	ep = (struct in6_addrpolicy *)(buf + l);
1112 	for (pol = (struct in6_addrpolicy *)buf; pol + 1 <= ep; pol++) {
1113 		struct policyqueue *new;
1114 
1115 		if ((new = malloc(sizeof(*new))) == NULL) {
1116 			free_addrselectpolicy(head); /* make the list empty */
1117 			break;
1118 		}
1119 		new->pc_policy = *pol;
1120 		TAILQ_INSERT_TAIL(head, new, pc_entry);
1121 	}
1122 
1123 	free(buf);
1124 	return (1);
1125 #else
1126 	return (0);
1127 #endif
1128 }
1129 
1130 static void
1131 free_addrselectpolicy(struct policyhead *head)
1132 {
1133 	struct policyqueue *ent, *nent;
1134 
1135 	for (ent = TAILQ_FIRST(head); ent; ent = nent) {
1136 		nent = TAILQ_NEXT(ent, pc_entry);
1137 		TAILQ_REMOVE(head, ent, pc_entry);
1138 		free(ent);
1139 	}
1140 }
1141 
1142 static struct policyqueue *
1143 match_addrselectpolicy(struct sockaddr *addr, struct policyhead *head)
1144 {
1145 #ifdef INET6
1146 	struct policyqueue *ent, *bestent = NULL;
1147 	struct in6_addrpolicy *pol;
1148 	int matchlen, bestmatchlen = -1;
1149 	u_char *mp, *ep, *k, *p, m;
1150 	struct sockaddr_in6 key;
1151 
1152 	switch(addr->sa_family) {
1153 	case AF_INET6:
1154 		key = *(struct sockaddr_in6 *)addr;
1155 		break;
1156 	case AF_INET:
1157 		/* convert the address into IPv4-mapped IPv6 address. */
1158 		memset(&key, 0, sizeof(key));
1159 		key.sin6_family = AF_INET6;
1160 		key.sin6_len = sizeof(key);
1161 		key.sin6_addr.s6_addr[10] = 0xff;
1162 		key.sin6_addr.s6_addr[11] = 0xff;
1163 		memcpy(&key.sin6_addr.s6_addr[12],
1164 		       &((struct sockaddr_in *)addr)->sin_addr, 4);
1165 		break;
1166 	default:
1167 		return(NULL);
1168 	}
1169 
1170 	for (ent = TAILQ_FIRST(head); ent; ent = TAILQ_NEXT(ent, pc_entry)) {
1171 		pol = &ent->pc_policy;
1172 		matchlen = 0;
1173 
1174 		mp = (u_char *)&pol->addrmask.sin6_addr;
1175 		ep = mp + 16;	/* XXX: scope field? */
1176 		k = (u_char *)&key.sin6_addr;
1177 		p = (u_char *)&pol->addr.sin6_addr;
1178 		for (; mp < ep && *mp; mp++, k++, p++) {
1179 			m = *mp;
1180 			if ((*k & m) != *p)
1181 				goto next; /* not match */
1182 			if (m == 0xff) /* short cut for a typical case */
1183 				matchlen += 8;
1184 			else {
1185 				while (m >= 0x80) {
1186 					matchlen++;
1187 					m <<= 1;
1188 				}
1189 			}
1190 		}
1191 
1192 		/* matched.  check if this is better than the current best. */
1193 		if (matchlen > bestmatchlen) {
1194 			bestent = ent;
1195 			bestmatchlen = matchlen;
1196 		}
1197 
1198 	  next:
1199 		continue;
1200 	}
1201 
1202 	return(bestent);
1203 #else
1204 	return(NULL);
1205 #endif
1206 
1207 }
1208 
1209 static void
1210 set_source(struct hp_order *aio, struct policyhead *ph)
1211 {
1212 	struct sockaddr_storage ss = aio->aio_un.aiou_ss;
1213 	socklen_t srclen;
1214 	int s;
1215 
1216 	/* set unspec ("no source is available"), just in case */
1217 	aio->aio_srcsa.sa_family = AF_UNSPEC;
1218 	aio->aio_srcscope = -1;
1219 
1220 	switch(ss.ss_family) {
1221 	case AF_INET:
1222 		((struct sockaddr_in *)&ss)->sin_port = htons(1);
1223 		break;
1224 #ifdef INET6
1225 	case AF_INET6:
1226 		((struct sockaddr_in6 *)&ss)->sin6_port = htons(1);
1227 		break;
1228 #endif
1229 	default:		/* ignore unsupported AFs explicitly */
1230 		return;
1231 	}
1232 
1233 	/* open a socket to get the source address for the given dst */
1234 	if ((s = _socket(ss.ss_family, SOCK_DGRAM, IPPROTO_UDP)) < 0)
1235 		return;		/* give up */
1236 	if (_connect(s, (struct sockaddr *)&ss, ss.ss_len) < 0)
1237 		goto cleanup;
1238 	srclen = ss.ss_len;
1239 	if (_getsockname(s, &aio->aio_srcsa, &srclen) < 0) {
1240 		aio->aio_srcsa.sa_family = AF_UNSPEC;
1241 		goto cleanup;
1242 	}
1243 	aio->aio_srcscope = gai_addr2scopetype(&aio->aio_srcsa);
1244 	aio->aio_srcpolicy = match_addrselectpolicy(&aio->aio_srcsa, ph);
1245 	aio->aio_matchlen = matchlen(&aio->aio_srcsa, (struct sockaddr *)&ss);
1246 #ifdef INET6
1247 	if (ss.ss_family == AF_INET6) {
1248 		struct in6_ifreq ifr6;
1249 		u_int32_t flags6;
1250 
1251 		/* XXX: interface name should not be hardcoded */
1252 		strncpy(ifr6.ifr_name, "lo0", sizeof(ifr6.ifr_name));
1253 		memset(&ifr6, 0, sizeof(ifr6));
1254 		memcpy(&ifr6.ifr_addr, &ss, ss.ss_len);
1255 		if (_ioctl(s, SIOCGIFAFLAG_IN6, &ifr6) == 0) {
1256 			flags6 = ifr6.ifr_ifru.ifru_flags6;
1257 			if ((flags6 & IN6_IFF_DEPRECATED))
1258 				aio->aio_srcflag |= AIO_SRCFLAG_DEPRECATED;
1259 		}
1260 	}
1261 #endif
1262 
1263   cleanup:
1264 	_close(s);
1265 	return;
1266 }
1267 
1268 static int
1269 matchlen(struct sockaddr *src, struct sockaddr *dst)
1270 {
1271 	int match = 0;
1272 	u_char *s, *d;
1273 	u_char *lim, r;
1274 	int addrlen;
1275 
1276 	switch (src->sa_family) {
1277 #ifdef INET6
1278 	case AF_INET6:
1279 		s = (u_char *)&((struct sockaddr_in6 *)src)->sin6_addr;
1280 		d = (u_char *)&((struct sockaddr_in6 *)dst)->sin6_addr;
1281 		addrlen = sizeof(struct in6_addr);
1282 		lim = s + addrlen;
1283 		break;
1284 #endif
1285 	case AF_INET:
1286 		s = (u_char *)&((struct sockaddr_in *)src)->sin_addr;
1287 		d = (u_char *)&((struct sockaddr_in *)dst)->sin_addr;
1288 		addrlen = sizeof(struct in_addr);
1289 		lim = s + addrlen;
1290 		break;
1291 	default:
1292 		return(0);
1293 	}
1294 
1295 	while (s < lim)
1296 		if ((r = (*d++ ^ *s++)) != 0) {
1297 			while (r < addrlen * 8) {
1298 				match++;
1299 				r <<= 1;
1300 			}
1301 			break;
1302 		} else
1303 			match += 8;
1304 	return(match);
1305 }
1306 
1307 static int
1308 comp_dst(const void *arg1, const void *arg2)
1309 {
1310 	const struct hp_order *dst1 = arg1, *dst2 = arg2;
1311 
1312 	/*
1313 	 * Rule 1: Avoid unusable destinations.
1314 	 * XXX: we currently do not consider if an appropriate route exists.
1315 	 */
1316 	if (dst1->aio_srcsa.sa_family != AF_UNSPEC &&
1317 	    dst2->aio_srcsa.sa_family == AF_UNSPEC) {
1318 		return(-1);
1319 	}
1320 	if (dst1->aio_srcsa.sa_family == AF_UNSPEC &&
1321 	    dst2->aio_srcsa.sa_family != AF_UNSPEC) {
1322 		return(1);
1323 	}
1324 
1325 	/* Rule 2: Prefer matching scope. */
1326 	if (dst1->aio_dstscope == dst1->aio_srcscope &&
1327 	    dst2->aio_dstscope != dst2->aio_srcscope) {
1328 		return(-1);
1329 	}
1330 	if (dst1->aio_dstscope != dst1->aio_srcscope &&
1331 	    dst2->aio_dstscope == dst2->aio_srcscope) {
1332 		return(1);
1333 	}
1334 
1335 	/* Rule 3: Avoid deprecated addresses. */
1336 	if (dst1->aio_srcsa.sa_family != AF_UNSPEC &&
1337 	    dst2->aio_srcsa.sa_family != AF_UNSPEC) {
1338 		if (!(dst1->aio_srcflag & AIO_SRCFLAG_DEPRECATED) &&
1339 		    (dst2->aio_srcflag & AIO_SRCFLAG_DEPRECATED)) {
1340 			return(-1);
1341 		}
1342 		if ((dst1->aio_srcflag & AIO_SRCFLAG_DEPRECATED) &&
1343 		    !(dst2->aio_srcflag & AIO_SRCFLAG_DEPRECATED)) {
1344 			return(1);
1345 		}
1346 	}
1347 
1348 	/* Rule 4: Prefer home addresses. */
1349 	/* XXX: not implemented yet */
1350 
1351 	/* Rule 5: Prefer matching label. */
1352 #ifdef INET6
1353 	if (dst1->aio_srcpolicy && dst1->aio_dstpolicy &&
1354 	    dst1->aio_srcpolicy->pc_policy.label ==
1355 	    dst1->aio_dstpolicy->pc_policy.label &&
1356 	    (dst2->aio_srcpolicy == NULL || dst2->aio_dstpolicy == NULL ||
1357 	     dst2->aio_srcpolicy->pc_policy.label !=
1358 	     dst2->aio_dstpolicy->pc_policy.label)) {
1359 		return(-1);
1360 	}
1361 	if (dst2->aio_srcpolicy && dst2->aio_dstpolicy &&
1362 	    dst2->aio_srcpolicy->pc_policy.label ==
1363 	    dst2->aio_dstpolicy->pc_policy.label &&
1364 	    (dst1->aio_srcpolicy == NULL || dst1->aio_dstpolicy == NULL ||
1365 	     dst1->aio_srcpolicy->pc_policy.label !=
1366 	     dst1->aio_dstpolicy->pc_policy.label)) {
1367 		return(1);
1368 	}
1369 #endif
1370 
1371 	/* Rule 6: Prefer higher precedence. */
1372 #ifdef INET6
1373 	if (dst1->aio_dstpolicy &&
1374 	    (dst2->aio_dstpolicy == NULL ||
1375 	     dst1->aio_dstpolicy->pc_policy.preced >
1376 	     dst2->aio_dstpolicy->pc_policy.preced)) {
1377 		return(-1);
1378 	}
1379 	if (dst2->aio_dstpolicy &&
1380 	    (dst1->aio_dstpolicy == NULL ||
1381 	     dst2->aio_dstpolicy->pc_policy.preced >
1382 	     dst1->aio_dstpolicy->pc_policy.preced)) {
1383 		return(1);
1384 	}
1385 #endif
1386 
1387 	/* Rule 7: Prefer native transport. */
1388 	/* XXX: not implemented yet */
1389 
1390 	/* Rule 8: Prefer smaller scope. */
1391 	if (dst1->aio_dstscope >= 0 &&
1392 	    dst1->aio_dstscope < dst2->aio_dstscope) {
1393 		return(-1);
1394 	}
1395 	if (dst2->aio_dstscope >= 0 &&
1396 	    dst2->aio_dstscope < dst1->aio_dstscope) {
1397 		return(1);
1398 	}
1399 
1400 	/*
1401 	 * Rule 9: Use longest matching prefix.
1402 	 * We compare the match length in a same AF only.
1403 	 */
1404 	if (dst1->aio_sa.sa_family == dst2->aio_sa.sa_family) {
1405 		if (dst1->aio_matchlen > dst2->aio_matchlen) {
1406 			return(-1);
1407 		}
1408 		if (dst1->aio_matchlen < dst2->aio_matchlen) {
1409 			return(1);
1410 		}
1411 	}
1412 
1413 	/* Rule 10: Otherwise, leave the order unchanged. */
1414 	return(-1);
1415 }
1416 
1417 /*
1418  * Copy from scope.c.
1419  * XXX: we should standardize the functions and link them as standard
1420  * library.
1421  */
1422 static int
1423 gai_addr2scopetype(struct sockaddr *sa)
1424 {
1425 #ifdef INET6
1426 	struct sockaddr_in6 *sa6;
1427 #endif
1428 	struct sockaddr_in *sa4;
1429 
1430 	switch(sa->sa_family) {
1431 #ifdef INET6
1432 	case AF_INET6:
1433 		sa6 = (struct sockaddr_in6 *)sa;
1434 		if (IN6_IS_ADDR_MULTICAST(&sa6->sin6_addr)) {
1435 			/* just use the scope field of the multicast address */
1436 			return(sa6->sin6_addr.s6_addr[2] & 0x0f);
1437 		}
1438 		/*
1439 		 * Unicast addresses: map scope type to corresponding scope
1440 		 * value defined for multcast addresses.
1441 		 * XXX: hardcoded scope type values are bad...
1442 		 */
1443 		if (IN6_IS_ADDR_LOOPBACK(&sa6->sin6_addr))
1444 			return(1); /* node local scope */
1445 		if (IN6_IS_ADDR_LINKLOCAL(&sa6->sin6_addr))
1446 			return(2); /* link-local scope */
1447 		if (IN6_IS_ADDR_SITELOCAL(&sa6->sin6_addr))
1448 			return(5); /* site-local scope */
1449 		return(14);	/* global scope */
1450 		break;
1451 #endif
1452 	case AF_INET:
1453 		/*
1454 		 * IPv4 pseudo scoping according to RFC 3484.
1455 		 */
1456 		sa4 = (struct sockaddr_in *)sa;
1457 		/* IPv4 autoconfiguration addresses have link-local scope. */
1458 		if (((u_char *)&sa4->sin_addr)[0] == 169 &&
1459 		    ((u_char *)&sa4->sin_addr)[1] == 254)
1460 			return(2);
1461 		/* Private addresses have site-local scope. */
1462 		if (((u_char *)&sa4->sin_addr)[0] == 10 ||
1463 		    (((u_char *)&sa4->sin_addr)[0] == 172 &&
1464 		     (((u_char *)&sa4->sin_addr)[1] & 0xf0) == 16) ||
1465 		    (((u_char *)&sa4->sin_addr)[0] == 192 &&
1466 		     ((u_char *)&sa4->sin_addr)[1] == 168))
1467 			return(14);	/* XXX: It should be 5 unless NAT */
1468 		/* Loopback addresses have link-local scope. */
1469 		if (((u_char *)&sa4->sin_addr)[0] == 127)
1470 			return(2);
1471 		return(14);
1472 		break;
1473 	default:
1474 		errno = EAFNOSUPPORT; /* is this a good error? */
1475 		return(-1);
1476 	}
1477 }
1478 
1479 /*
1480  * FILES (/etc/hosts)
1481  */
1482 
1483 static FILE *
1484 _files_open(int *errp)
1485 {
1486 	FILE *fp;
1487 	fp = fopen(_PATH_HOSTS, "r");
1488 	if (fp == NULL)
1489 		*errp = NO_RECOVERY;
1490 	return fp;
1491 }
1492 
1493 static int
1494 _files_ghbyname(void *rval, void *cb_data, va_list ap)
1495 {
1496 	const char *name;
1497 	int af;
1498 	int *errp;
1499 	int match, nalias;
1500 	char *p, *line, *addrstr, *cname;
1501 	FILE *fp;
1502 	struct hostent *rethp, *hp, hpbuf;
1503 	char *aliases[MAXALIASES + 1], *addrs[2];
1504 	union inx_addr addrbuf;
1505 	char buf[BUFSIZ];
1506 
1507 	name = va_arg(ap, const char *);
1508 	af = va_arg(ap, int);
1509 	errp = va_arg(ap, int *);
1510 
1511 	*(struct hostent **)rval = NULL;
1512 
1513 	if ((fp = _files_open(errp)) == NULL)
1514 		return NS_UNAVAIL;
1515 	rethp = hp = NULL;
1516 
1517 	while (fgets(buf, sizeof(buf), fp)) {
1518 		line = buf;
1519 		if ((addrstr = _hgetword(&line)) == NULL
1520 		||  (cname = _hgetword(&line)) == NULL)
1521 			continue;
1522 		match = (strcasecmp(cname, name) == 0);
1523 		nalias = 0;
1524 		while ((p = _hgetword(&line)) != NULL) {
1525 			if (!match)
1526 				match = (strcasecmp(p, name) == 0);
1527 			if (nalias < MAXALIASES)
1528 				aliases[nalias++] = p;
1529 		}
1530 		if (!match)
1531 			continue;
1532 		switch (af) {
1533 		case AF_INET:
1534 			if (inet_aton(addrstr, (struct in_addr *)&addrbuf)
1535 			    != 1) {
1536 				*errp = NO_DATA;	/* name found */
1537 				continue;
1538 			}
1539 			break;
1540 #ifdef INET6
1541 		case AF_INET6:
1542 			if (inet_pton(af, addrstr, &addrbuf) != 1) {
1543 				*errp = NO_DATA;	/* name found */
1544 				continue;
1545 			}
1546 			break;
1547 #endif
1548 		}
1549 		hp = &hpbuf;
1550 		hp->h_name = cname;
1551 		hp->h_aliases = aliases;
1552 		aliases[nalias] = NULL;
1553 		hp->h_addrtype = af;
1554 		hp->h_length = ADDRLEN(af);
1555 		hp->h_addr_list = addrs;
1556 		addrs[0] = (char *)&addrbuf;
1557 		addrs[1] = NULL;
1558 		hp = _hpcopy(hp, errp);
1559 		rethp = _hpmerge(rethp, hp, errp);
1560 	}
1561 	fclose(fp);
1562 	*(struct hostent **)rval = rethp;
1563 	return (rethp != NULL) ? NS_SUCCESS : NS_NOTFOUND;
1564 }
1565 
1566 static int
1567 _files_ghbyaddr(void *rval, void *cb_data, va_list ap)
1568 {
1569 	const void *addr;
1570 	int addrlen;
1571 	int af;
1572 	int *errp;
1573 	int nalias;
1574 	char *p, *line;
1575 	FILE *fp;
1576 	struct hostent *hp, hpbuf;
1577 	char *aliases[MAXALIASES + 1], *addrs[2];
1578 	union inx_addr addrbuf;
1579 	char buf[BUFSIZ];
1580 
1581 	addr = va_arg(ap, const void *);
1582 	addrlen = va_arg(ap, int);
1583 	af = va_arg(ap, int);
1584 	errp = va_arg(ap, int *);
1585 
1586 	*(struct hostent**)rval = NULL;
1587 
1588 	if ((fp = _files_open(errp)) == NULL)
1589 		return NS_UNAVAIL;
1590 	hp = NULL;
1591 	while (fgets(buf, sizeof(buf), fp)) {
1592 		line = buf;
1593 		if ((p = _hgetword(&line)) == NULL
1594 		||  (af == AF_INET
1595 		     ? inet_aton(p, (struct in_addr *)&addrbuf)
1596 		     : inet_pton(af, p, &addrbuf)) != 1
1597 		||  memcmp(addr, &addrbuf, addrlen) != 0
1598 		||  (p = _hgetword(&line)) == NULL)
1599 			continue;
1600 		hp = &hpbuf;
1601 		hp->h_name = p;
1602 		hp->h_aliases = aliases;
1603 		nalias = 0;
1604 		while ((p = _hgetword(&line)) != NULL) {
1605 			if (nalias < MAXALIASES)
1606 				aliases[nalias++] = p;
1607 		}
1608 		aliases[nalias] = NULL;
1609 		hp->h_addrtype = af;
1610 		hp->h_length = addrlen;
1611 		hp->h_addr_list = addrs;
1612 		addrs[0] = (char *)&addrbuf;
1613 		addrs[1] = NULL;
1614 		hp = _hpcopy(hp, errp);
1615 		break;
1616 	}
1617 	fclose(fp);
1618 	*(struct hostent **)rval = hp;
1619 	return (hp != NULL) ? NS_SUCCESS : NS_NOTFOUND;
1620 }
1621 
1622 #ifdef YP
1623 /*
1624  * NIS
1625  *
1626  * XXX actually a hack.
1627  */
1628 static int
1629 _nis_ghbyname(void *rval, void *cb_data, va_list ap)
1630 {
1631 	const char *name;
1632 	int af;
1633 	int *errp;
1634 	struct hostent *hp = NULL;
1635 
1636 	name = va_arg(ap, const char *);
1637 	af = va_arg(ap, int);
1638 	errp = va_arg(ap, int *);
1639 
1640 	hp = _gethostbynisname(name, af);
1641 	if (hp != NULL)
1642 		hp = _hpcopy(hp, errp);
1643 
1644 	*(struct hostent **)rval = hp;
1645 	return (hp != NULL) ? NS_SUCCESS : NS_NOTFOUND;
1646 }
1647 
1648 static int
1649 _nis_ghbyaddr(void *rval, void *cb_data, va_list ap)
1650 {
1651 	const void *addr;
1652 	int addrlen;
1653 	int af;
1654 	int *errp;
1655 	struct hostent *hp = NULL;
1656 
1657 	addr = va_arg(ap, const void *);
1658 	addrlen = va_arg(ap, int);
1659 	af = va_arg(ap, int);
1660 
1661 	hp = _gethostbynisaddr(addr, addrlen, af);
1662 	if (hp != NULL)
1663 		hp = _hpcopy(hp, errp);
1664 	*(struct hostent **)rval = hp;
1665 	return (hp != NULL) ? NS_SUCCESS : NS_NOTFOUND;
1666 }
1667 #endif
1668 
1669 #define	MAXPACKET	(64*1024)
1670 
1671 typedef union {
1672 	HEADER hdr;
1673 	u_char buf[MAXPACKET];
1674 } querybuf;
1675 
1676 static struct hostent *getanswer(const querybuf *, int, const char *, int,
1677 	    struct hostent *, int *);
1678 
1679 /*
1680  * we don't need to take care about sorting, nor IPv4 mapped address here.
1681  */
1682 static struct hostent *
1683 getanswer(const querybuf *answer, int anslen, const char *qname, int qtype,
1684     struct hostent *template, int *errp)
1685 {
1686 	const HEADER *hp;
1687 	const u_char *cp;
1688 	int n;
1689 	const u_char *eom, *erdata;
1690 	char *bp, *ep, **ap, **hap;
1691 	int type, class, ancount, qdcount;
1692 	int haveanswer, had_error;
1693 	char tbuf[MAXDNAME];
1694 	const char *tname;
1695 	int (*name_ok)(const char *);
1696 	static char *h_addr_ptrs[MAXADDRS + 1];
1697 	static char *host_aliases[MAXALIASES];
1698 	static char hostbuf[8*1024];
1699 
1700 #define BOUNDED_INCR(x) \
1701 	do { \
1702 		cp += x; \
1703 		if (cp > eom) { \
1704 			*errp = NO_RECOVERY; \
1705 			return (NULL); \
1706 		} \
1707 	} while (0)
1708 
1709 #define BOUNDS_CHECK(ptr, count) \
1710 	do { \
1711 		if ((ptr) + (count) > eom) { \
1712 			*errp = NO_RECOVERY; \
1713 			return (NULL); \
1714 		} \
1715 	} while (0)
1716 
1717 /* XXX do {} while (0) cannot be put here */
1718 #define DNS_ASSERT(x) \
1719 	{				\
1720 		if (!(x)) {		\
1721 			cp += n;	\
1722 			continue;	\
1723 		}			\
1724 	}
1725 
1726 /* XXX do {} while (0) cannot be put here */
1727 #define DNS_FATAL(x) \
1728 	{				\
1729 		if (!(x)) {		\
1730 			had_error++;	\
1731 			continue;	\
1732 		}			\
1733 	}
1734 
1735 	tname = qname;
1736 	template->h_name = NULL;
1737 	eom = answer->buf + anslen;
1738 	switch (qtype) {
1739 	case T_A:
1740 	case T_AAAA:
1741 		name_ok = res_hnok;
1742 		break;
1743 	case T_PTR:
1744 		name_ok = res_dnok;
1745 		break;
1746 	default:
1747 		return (NULL);	/* XXX should be abort(); */
1748 	}
1749 	/*
1750 	 * find first satisfactory answer
1751 	 */
1752 	hp = &answer->hdr;
1753 	ancount = ntohs(hp->ancount);
1754 	qdcount = ntohs(hp->qdcount);
1755 	bp = hostbuf;
1756 	ep = hostbuf + sizeof hostbuf;
1757 	cp = answer->buf;
1758 	BOUNDED_INCR(HFIXEDSZ);
1759 	if (qdcount != 1) {
1760 		*errp = NO_RECOVERY;
1761 		return (NULL);
1762 	}
1763 	n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
1764 	if ((n < 0) || !(*name_ok)(bp)) {
1765 		*errp = NO_RECOVERY;
1766 		return (NULL);
1767 	}
1768 	BOUNDED_INCR(n + QFIXEDSZ);
1769 	if (qtype == T_A || qtype == T_AAAA) {
1770 		/* res_send() has already verified that the query name is the
1771 		 * same as the one we sent; this just gets the expanded name
1772 		 * (i.e., with the succeeding search-domain tacked on).
1773 		 */
1774 		n = strlen(bp) + 1;		/* for the \0 */
1775 		if (n >= MAXHOSTNAMELEN) {
1776 			*errp = NO_RECOVERY;
1777 			return (NULL);
1778 		}
1779 		template->h_name = bp;
1780 		bp += n;
1781 		/* The qname can be abbreviated, but h_name is now absolute. */
1782 		qname = template->h_name;
1783 	}
1784 	ap = host_aliases;
1785 	*ap = NULL;
1786 	template->h_aliases = host_aliases;
1787 	hap = h_addr_ptrs;
1788 	*hap = NULL;
1789 	template->h_addr_list = h_addr_ptrs;
1790 	haveanswer = 0;
1791 	had_error = 0;
1792 	while (ancount-- > 0 && cp < eom && !had_error) {
1793 		n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
1794 		DNS_FATAL(n >= 0);
1795 		DNS_FATAL((*name_ok)(bp));
1796 		cp += n;			/* name */
1797 		BOUNDS_CHECK(cp, 3 * INT16SZ + INT32SZ);
1798 		type = _getshort(cp);
1799  		cp += INT16SZ;			/* type */
1800 		class = _getshort(cp);
1801  		cp += INT16SZ + INT32SZ;	/* class, TTL */
1802 		n = _getshort(cp);
1803 		cp += INT16SZ;			/* len */
1804 		BOUNDS_CHECK(cp, n);
1805 		erdata = cp + n;
1806 		DNS_ASSERT(class == C_IN);
1807 		if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) {
1808 			if (ap >= &host_aliases[MAXALIASES-1])
1809 				continue;
1810 			n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
1811 			DNS_FATAL(n >= 0);
1812 			DNS_FATAL((*name_ok)(tbuf));
1813 			cp += n;
1814 			if (cp != erdata) {
1815 				*errp = NO_RECOVERY;
1816 				return (NULL);
1817 			}
1818 			/* Store alias. */
1819 			*ap++ = bp;
1820 			n = strlen(bp) + 1;	/* for the \0 */
1821 			DNS_FATAL(n < MAXHOSTNAMELEN);
1822 			bp += n;
1823 			/* Get canonical name. */
1824 			n = strlen(tbuf) + 1;	/* for the \0 */
1825 			DNS_FATAL(n <= ep - bp);
1826 			DNS_FATAL(n < MAXHOSTNAMELEN);
1827 			strcpy(bp, tbuf);
1828 			template->h_name = bp;
1829 			bp += n;
1830 			continue;
1831 		}
1832 		if (qtype == T_PTR && type == T_CNAME) {
1833 			n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
1834 			if (n < 0 || !res_dnok(tbuf)) {
1835 				had_error++;
1836 				continue;
1837 			}
1838 			cp += n;
1839 			if (cp != erdata) {
1840 				*errp = NO_RECOVERY;
1841 				return (NULL);
1842 			}
1843 			/* Get canonical name. */
1844 			n = strlen(tbuf) + 1;	/* for the \0 */
1845 			if (n > ep - bp || n >= MAXHOSTNAMELEN) {
1846 				had_error++;
1847 				continue;
1848 			}
1849 			strcpy(bp, tbuf);
1850 			tname = bp;
1851 			bp += n;
1852 			continue;
1853 		}
1854 		DNS_ASSERT(type == qtype);
1855 		switch (type) {
1856 		case T_PTR:
1857 			DNS_ASSERT(strcasecmp(tname, bp) == 0);
1858 			n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
1859 			DNS_FATAL(n >= 0);
1860 			DNS_FATAL(res_hnok(bp));
1861 #if MULTI_PTRS_ARE_ALIASES
1862 			cp += n;
1863 			if (cp != erdata) {
1864 				*errp = NO_RECOVERY;
1865 				return (NULL);
1866 			}
1867 			if (!haveanswer)
1868 				template->h_name = bp;
1869 			else if (ap < &host_aliases[MAXALIASES-1])
1870 				*ap++ = bp;
1871 			else
1872 				n = -1;
1873 			if (n != -1) {
1874 				n = strlen(bp) + 1;	/* for the \0 */
1875 				if (n >= MAXHOSTNAMELEN) {
1876 					had_error++;
1877 					break;
1878 				}
1879 				bp += n;
1880 			}
1881 			break;
1882 #else
1883 			template->h_name = bp;
1884 			*errp = NETDB_SUCCESS;
1885 			return (template);
1886 #endif
1887 		case T_A:
1888 		case T_AAAA:
1889 			DNS_ASSERT(strcasecmp(template->h_name, bp) == 0);
1890 			DNS_ASSERT(n == template->h_length);
1891 			if (!haveanswer) {
1892 				int nn;
1893 
1894 				template->h_name = bp;
1895 				nn = strlen(bp) + 1;	/* for the \0 */
1896 				bp += nn;
1897 			}
1898 			bp = (char *)ALIGN(bp);
1899 
1900 			DNS_FATAL(bp + n < ep);
1901 			DNS_ASSERT(hap < &h_addr_ptrs[MAXADDRS-1]);
1902 #ifdef FILTER_V4MAPPED
1903 			if (type == T_AAAA) {
1904 				struct in6_addr in6;
1905 				memcpy(&in6, cp, sizeof(in6));
1906 				DNS_ASSERT(IN6_IS_ADDR_V4MAPPED(&in6) == 0);
1907 			}
1908 #endif
1909 			bcopy(cp, *hap++ = bp, n);
1910 			bp += n;
1911 			cp += n;
1912 			if (cp != erdata) {
1913 				*errp = NO_RECOVERY;
1914 				return (NULL);
1915 			}
1916 			break;
1917 		default:
1918 			abort();
1919 		}
1920 		if (!had_error)
1921 			haveanswer++;
1922 	}
1923 	if (haveanswer) {
1924 		*ap = NULL;
1925 		*hap = NULL;
1926 		if (!template->h_name) {
1927 			n = strlen(qname) + 1;	/* for the \0 */
1928 			if (n > ep - bp || n >= MAXHOSTNAMELEN)
1929 				goto no_recovery;
1930 			strcpy(bp, qname);
1931 			template->h_name = bp;
1932 			bp += n;
1933 		}
1934 		*errp = NETDB_SUCCESS;
1935 		return (template);
1936 	}
1937  no_recovery:
1938 	*errp = NO_RECOVERY;
1939 	return (NULL);
1940 
1941 #undef BOUNDED_INCR
1942 #undef BOUNDS_CHECK
1943 #undef DNS_ASSERT
1944 #undef DNS_FATAL
1945 }
1946 
1947 static int
1948 _dns_ghbyname(void *rval, void *cb_data, va_list ap)
1949 {
1950 	const char *name;
1951 	int af;
1952 	int *errp;
1953 	int n;
1954 	struct hostent *hp;
1955 	int qtype;
1956 	struct hostent hbuf;
1957 	querybuf *buf;
1958 	res_state statp;
1959 
1960 	name = va_arg(ap, const char *);
1961 	af = va_arg(ap, int);
1962 	errp = va_arg(ap, int *);
1963 
1964 	statp = __res_state();
1965 
1966 	memset(&hbuf, 0, sizeof(hbuf));
1967 	hbuf.h_addrtype = af;
1968 	hbuf.h_length = ADDRLEN(af);
1969 
1970 	switch (af) {
1971 #ifdef INET6
1972 	case AF_INET6:
1973 		qtype = T_AAAA;
1974 		break;
1975 #endif
1976 	case AF_INET:
1977 		qtype = T_A;
1978 		break;
1979 	default:
1980 		*errp = NO_RECOVERY;
1981 		return NS_NOTFOUND;
1982 	}
1983 	buf = malloc(sizeof(*buf));
1984 	if (buf == NULL) {
1985 		*errp = NETDB_INTERNAL;
1986 		return NS_UNAVAIL;
1987 	}
1988 	n = res_nsearch(statp, name, C_IN, qtype, buf->buf, sizeof(buf->buf));
1989 	if (n < 0) {
1990 		free(buf);
1991 		*errp = statp->res_h_errno;
1992 		return NS_UNAVAIL;
1993 	}
1994 	hp = getanswer(buf, n, name, qtype, &hbuf, errp);
1995 	free(buf);
1996 	if (!hp) {
1997 		*errp = NO_RECOVERY;
1998 		return NS_NOTFOUND;
1999 	}
2000 	*(struct hostent **)rval = _hpcopy(&hbuf, errp);
2001 	if (*(struct hostent **)rval != NULL)
2002 		return NS_SUCCESS;
2003 	else if (*errp == TRY_AGAIN)
2004 		return NS_TRYAGAIN;
2005 	else
2006 		return NS_NOTFOUND;
2007 }
2008 
2009 static int
2010 _dns_ghbyaddr(void *rval, void *cb_data, va_list ap)
2011 {
2012 	const void *addr;
2013 	int addrlen;
2014 	int af;
2015 	int *errp;
2016 	int n;
2017 	int err;
2018 	struct hostent *hp;
2019 	u_char c, *cp;
2020 	char *bp;
2021 	struct hostent hbuf;
2022 #ifdef INET6
2023 	static const char hex[] = "0123456789abcdef";
2024 #endif
2025 	querybuf *buf;
2026 	char qbuf[MAXDNAME+1];
2027 	char *hlist[2];
2028 #ifdef INET6
2029 	char *tld6[] = { "ip6.arpa", NULL };
2030 #endif
2031 	char *tld4[] = { "in-addr.arpa", NULL };
2032 	char **tld;
2033 	res_state statp;
2034 
2035 	addr = va_arg(ap, const void *);
2036 	addrlen = va_arg(ap, int);
2037 	af = va_arg(ap, int);
2038 	errp = va_arg(ap, int *);
2039 
2040 	*(struct hostent **)rval = NULL;
2041 
2042 #ifdef INET6
2043 	/* XXX */
2044 	if (af == AF_INET6 && IN6_IS_ADDR_LINKLOCAL((struct in6_addr *)addr))
2045 		return NS_NOTFOUND;
2046 #endif
2047 
2048 	switch (af) {
2049 #ifdef INET6
2050 	case AF_INET6:
2051 		tld = tld6;
2052 		break;
2053 #endif
2054 	case AF_INET:
2055 		tld = tld4;
2056 		break;
2057 	default:
2058 		return NS_NOTFOUND;
2059 	}
2060 
2061 	statp = __res_state();
2062 	if ((statp->options & RES_INIT) == 0) {
2063 		if (res_ninit(statp) < 0) {
2064 			*errp = NETDB_INTERNAL;
2065 			return NS_UNAVAIL;
2066 		}
2067 	}
2068 	memset(&hbuf, 0, sizeof(hbuf));
2069 	hbuf.h_name = NULL;
2070 	hbuf.h_addrtype = af;
2071 	hbuf.h_length = addrlen;
2072 
2073 	buf = malloc(sizeof(*buf));
2074 	if (buf == NULL) {
2075 		*errp = NETDB_INTERNAL;
2076 		return NS_UNAVAIL;
2077 	}
2078 	err = NS_SUCCESS;
2079 	for (/* nothing */; *tld; tld++) {
2080 		/*
2081 		 * XXX assumes that MAXDNAME is big enough - error checks
2082 		 * has been made by callers
2083 		 */
2084 		n = 0;
2085 		bp = qbuf;
2086 		cp = (u_char *)addr+addrlen-1;
2087 		switch (af) {
2088 #ifdef INET6
2089 		case AF_INET6:
2090 			for (; n < addrlen; n++, cp--) {
2091 				c = *cp;
2092 				*bp++ = hex[c & 0xf];
2093 				*bp++ = '.';
2094 				*bp++ = hex[c >> 4];
2095 				*bp++ = '.';
2096 			}
2097 			strcpy(bp, *tld);
2098 			break;
2099 #endif
2100 		case AF_INET:
2101 			for (; n < addrlen; n++, cp--) {
2102 				c = *cp;
2103 				if (c >= 100)
2104 					*bp++ = '0' + c / 100;
2105 				if (c >= 10)
2106 					*bp++ = '0' + (c % 100) / 10;
2107 				*bp++ = '0' + c % 10;
2108 				*bp++ = '.';
2109 			}
2110 			strcpy(bp, *tld);
2111 			break;
2112 		}
2113 
2114 		n = res_nquery(statp, qbuf, C_IN, T_PTR, buf->buf,
2115 		    sizeof buf->buf);
2116 		if (n < 0) {
2117 			*errp = statp->res_h_errno;
2118 			err = NS_UNAVAIL;
2119 			continue;
2120 		} else if (n > sizeof(buf->buf)) {
2121 #if 0
2122 			errno = ERANGE; /* XXX is it OK to set errno here? */
2123 #endif
2124 			*errp = NETDB_INTERNAL;
2125 			err = NS_UNAVAIL;
2126 			continue;
2127 		}
2128 		hp = getanswer(buf, n, qbuf, T_PTR, &hbuf, errp);
2129 		if (!hp) {
2130 			err = NS_NOTFOUND;
2131 			continue;
2132 		}
2133 		free(buf);
2134 		hbuf.h_addrtype = af;
2135 		hbuf.h_length = addrlen;
2136 		hbuf.h_addr_list = hlist;
2137 		hlist[0] = (char *)addr;
2138 		hlist[1] = NULL;
2139 		*(struct hostent **)rval = _hpcopy(&hbuf, errp);
2140 		return NS_SUCCESS;
2141 	}
2142 	free(buf);
2143 	return err;
2144 }
2145 
2146 static void
2147 _dns_shent(int stayopen)
2148 {
2149 	res_state statp;
2150 
2151 	statp = __res_state();
2152 	if ((statp->options & RES_INIT) == 0) {
2153 		if (res_ninit(statp) < 0)
2154 			return;
2155 	}
2156 	if (stayopen)
2157 		statp->options |= RES_STAYOPEN | RES_USEVC;
2158 }
2159 
2160 static void
2161 _dns_ehent(void)
2162 {
2163 	res_state statp;
2164 
2165 	statp = __res_state();
2166 	statp->options &= ~(RES_STAYOPEN | RES_USEVC);
2167 	res_nclose(statp);
2168 }
2169 
2170 #ifdef ICMPNL
2171 
2172 /*
2173  * experimental:
2174  *	draft-ietf-ipngwg-icmp-namelookups-09.txt
2175  *	ifindex is assumed to be encoded in addr.
2176  */
2177 #include <sys/uio.h>
2178 #include <netinet/ip6.h>
2179 #include <netinet/icmp6.h>
2180 #include <ctype.h>
2181 
2182 #ifndef NI_QTYPE_NODENAME
2183 #define NI_QTYPE_NODENAME	NI_QTYPE_DNSNAME
2184 #endif
2185 
2186 static char *
2187 dnsdecode(sp, ep, base, buf, bufsiz)
2188 	const u_char **sp;
2189 	const u_char *ep;
2190 	const u_char *base;	/*base for compressed name*/
2191 	u_char *buf;
2192 	size_t bufsiz;
2193 {
2194 	int i;
2195 	const u_char *cp;
2196 	char cresult[MAXDNAME + 1];
2197 	const u_char *comp;
2198 	int l;
2199 
2200 	cp = *sp;
2201 	*buf = '\0';
2202 
2203 	if (cp >= ep)
2204 		return NULL;
2205 	while (cp < ep) {
2206 		i = *cp;
2207 		if (i == 0 || cp != *sp) {
2208 			if (strlcat(buf, ".", bufsiz) >= bufsiz)
2209 				return NULL;	/* result overrun */
2210 		}
2211 		if (i == 0)
2212 			break;
2213 		cp++;
2214 
2215 		if ((i & 0xc0) == 0xc0 && cp - base > (i & 0x3f)) {
2216 			/* DNS compression */
2217 			if (!base)
2218 				return NULL;
2219 
2220 			comp = base + (i & 0x3f);
2221 			if (dnsdecode(&comp, cp, base, cresult,
2222 			    sizeof(cresult)) == NULL)
2223 				return NULL;
2224 			if (strlcat(buf, cresult, bufsiz) >= bufsiz)
2225 				return NULL;	/* result overrun */
2226 			break;
2227 		} else if ((i & 0x3f) == i) {
2228 			if (i > ep - cp)
2229 				return NULL;	/* source overrun */
2230 			while (i-- > 0 && cp < ep) {
2231 				l = snprintf(cresult, sizeof(cresult),
2232 				    isprint(*cp) ? "%c" : "\\%03o", *cp & 0xff);
2233 				if (l >= sizeof(cresult) || l < 0)
2234 					return NULL;
2235 				if (strlcat(buf, cresult, bufsiz) >= bufsiz)
2236 					return NULL;	/* result overrun */
2237 				cp++;
2238 			}
2239 		} else
2240 			return NULL;	/* invalid label */
2241 	}
2242 	if (i != 0)
2243 		return NULL;	/* not terminated */
2244 	cp++;
2245 	*sp = cp;
2246 	return buf;
2247 }
2248 
2249 static char *
2250 _icmp_nodeinfo_query(const struct in6_addr *addr, int ifindex, char *dnsname)
2251 {
2252 	int s;
2253 	struct icmp6_filter filter;
2254 	struct msghdr msg;
2255 	struct cmsghdr *cmsg;
2256 	struct in6_pktinfo *pkt;
2257 	char cbuf[256], buf[1024], *cp, *end;
2258 	int cc;
2259 	struct icmp6_nodeinfo niq, *nir;
2260 	struct sockaddr_in6 sin6;
2261 	struct iovec iov;
2262 	fd_set s_fds, fds;
2263 	struct timeval tout;
2264 	int len;
2265 	static int pid;
2266 	u_int32_t r1, r2;
2267 
2268 	if (pid == 0)
2269 		pid = getpid();
2270 
2271 	ICMP6_FILTER_SETBLOCKALL(&filter);
2272 	ICMP6_FILTER_SETPASS(ICMP6_NI_REPLY, &filter);
2273 
2274 	FD_ZERO(&s_fds);
2275 	tout.tv_sec = 0;
2276 	tout.tv_usec = 500000;	/* 500ms */
2277 
2278 	memset(&niq, 0, sizeof(niq));
2279 	niq.ni_type = ICMP6_NI_QUERY;
2280 	niq.ni_code = ICMP6_NI_SUBJ_IPV6;
2281 	niq.ni_qtype = htons(NI_QTYPE_NODENAME);
2282 	niq.ni_flags = 0;
2283 	r1 = arc4random();
2284 	r2 = arc4random();
2285 	memcpy(&niq.icmp6_ni_nonce[0], &r1, sizeof(r1));
2286 	memcpy(&niq.icmp6_ni_nonce[4], &r2, sizeof(r2));
2287 
2288 	memset(&sin6, 0, sizeof(sin6));
2289 	sin6.sin6_family = AF_INET6;
2290 	sin6.sin6_addr = *addr;
2291 
2292 	memset(&msg, 0, sizeof(msg));
2293 	msg.msg_name = (caddr_t)&sin6;
2294 	msg.msg_namelen = sizeof(sin6);
2295 	msg.msg_iov = &iov;
2296 	msg.msg_iovlen = 1;
2297 	msg.msg_control = NULL;
2298 	msg.msg_controllen = 0;
2299 	iov.iov_base = (caddr_t)&niq;
2300 	iov.iov_len = sizeof(struct icmp6_nodeinfo);
2301 
2302 	if (ifindex) {
2303 		msg.msg_control = cbuf;
2304 		msg.msg_controllen = sizeof(cbuf);
2305 		cmsg = CMSG_FIRSTHDR(&msg);
2306 		cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
2307 		cmsg->cmsg_level = IPPROTO_IPV6;
2308 		cmsg->cmsg_type = IPV6_PKTINFO;
2309 		pkt = (struct in6_pktinfo *)&cmsg[1];
2310 		memset(&pkt->ipi6_addr, 0, sizeof(struct in6_addr));
2311 		pkt->ipi6_ifindex = ifindex;
2312 		cmsg = CMSG_NXTHDR(&msg, cmsg);
2313 		msg.msg_controllen = (char *)cmsg - cbuf;
2314 	}
2315 
2316 	/* XXX: we need root privilege here */
2317 	if ((s = _socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0)
2318 		return NULL;
2319 	(void)_setsockopt(s, IPPROTO_ICMPV6, ICMP6_FILTER,
2320 			 (char *)&filter, sizeof(filter));
2321 	cc = _sendmsg(s, &msg, 0);
2322 	if (cc < 0) {
2323 		_close(s);
2324 		return (NULL);
2325 	}
2326 	FD_SET(s, &s_fds);
2327 	for (;;) {
2328 		fds = s_fds;
2329 		if (_select(s + 1, &fds, NULL, NULL, &tout) <= 0) {
2330 			_close(s);
2331 			return (NULL);
2332 		}
2333 		len = sizeof(sin6);
2334 		cc = _recvfrom(s, buf, sizeof(buf), 0,
2335 			      (struct sockaddr *)&sin6, &len);
2336 		if (cc <= 0) {
2337 			_close(s);
2338 			return (NULL);
2339 		}
2340 		if (cc < sizeof(struct icmp6_hdr))
2341 			continue;
2342 		nir = (struct icmp6_nodeinfo *)buf;
2343 		if (nir->ni_type != ICMP6_NI_REPLY)
2344 			continue;
2345 		if (nir->ni_qtype != htons(NI_QTYPE_NODENAME))
2346 			continue;
2347 		if (memcmp(nir->icmp6_ni_nonce, niq.icmp6_ni_nonce,
2348 		    sizeof(nir->icmp6_ni_nonce)) != 0) {
2349 			continue;
2350 		}
2351 		if (nir->ni_code != htons(ICMP6_NI_SUCCESS))
2352 			continue; /* or should we fail? */
2353 
2354 		/* this is an expected reply. */
2355 		break;
2356 	}
2357 	_close(s);
2358 
2359 	memset(dnsname, 0, MAXDNAME + 1);
2360 	cp = (char *)(nir + 1);
2361 	end = ((char *)nir) + cc;
2362 	if (end - cp < sizeof(int32_t))	/* for TTL.  we don't use it. */
2363 		return (NULL);
2364 	cp += sizeof(int32_t);
2365 	if (*cp == end - cp - 1) { /* an old version */
2366 		int nlen;
2367 
2368 		cp++;	/* skip length */
2369 		nlen = end - cp;
2370 		if (nlen > MAXDNAME)
2371 			return (NULL); /* XXX: use it anyway? */
2372 		memcpy(dnsname, cp, nlen);
2373 	} else {
2374 		/* XXX: should we use a generic function? */
2375 		if (dnsdecode((const u_char **)(void *)&cp, end,
2376 		    (const u_char *)(nir + 1), dnsname, MAXDNAME + 1)
2377 		    == NULL) {
2378 			return (NULL); /* bogus name */
2379 		}
2380 		/* Name-lookup special handling for truncated name. */
2381 		if (cp + 1 <= end && !*cp && strlen(dnsname) > 0)
2382 			dnsname[strlen(dnsname) - 1] = '\0';
2383 
2384 		/* There may be other names, but we ignore them. */
2385 	}
2386 
2387 	return (dnsname);
2388 }
2389 
2390 static int
2391 _icmp_ghbyaddr(void *rval, void *cb_data, va_list ap)
2392 {
2393 	const void *addr;
2394 	int addrlen;
2395 	int af;
2396 	int *errp;
2397 	char *hname;
2398 	int ifindex = 0;
2399 	struct in6_addr addr6;
2400 	char dnsname[MAXDNAME + 1];
2401 
2402 	addr = va_arg(ap, const void *);
2403 	addrlen = va_arg(ap, int);
2404 	af = va_arg(ap, int);
2405 	errp = va_arg(ap, int *);
2406 
2407 	*(struct hostent **)rval = NULL;
2408 
2409 	if (af != AF_INET6 || addrlen != sizeof(addr6)) {
2410 		/*
2411 		 * Note: rfc1788 defines Who Are You for IPv4,
2412 		 * but no one implements it.
2413 		 */
2414 		return (NS_NOTFOUND);
2415 	}
2416 
2417 	memcpy(&addr6, addr, addrlen);
2418 	if (IN6_IS_ADDR_LINKLOCAL(&addr6)) {
2419 		ifindex = (addr6.s6_addr[2] << 8) | addr6.s6_addr[3];
2420 		addr6.s6_addr[2] = addr6.s6_addr[3] = 0;
2421 	}
2422 
2423 	if ((hname = _icmp_nodeinfo_query(&addr6, ifindex, dnsname)) == NULL)
2424 		return (NS_NOTFOUND);
2425 	*(struct hostent **)rval =_hpaddr(af, hname, &addr6, errp);
2426 	return (NS_SUCCESS);
2427 }
2428 #endif /* ICMPNL */
2429