name6.c revision 160699
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: head/lib/libc/net/name6.c 160699 2006-07-26 08:35:46Z yar $");
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) \
149do {									\
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
158union 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
173struct policyqueue {
174	TAILQ_ENTRY(policyqueue) pc_entry;
175#ifdef INET6
176	struct in6_addrpolicy pc_policy;
177#endif
178};
179TAILQ_HEAD(policyhead, policyqueue);
180
181#define AIO_SRCFLAG_DEPRECATED	0x1
182
183struct 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
203static struct	 hostent *_hpcopy(struct hostent *, int *);
204static struct	 hostent *_hpaddr(int, const char *, void *, int *);
205static struct	 hostent *_hpmerge(struct hostent *, struct hostent *, int *);
206#ifdef INET6
207static struct	 hostent *_hpmapv6(struct hostent *, int *);
208#endif
209static struct	 hostent *_hpsort(struct hostent *, res_state);
210static struct	 hostent *_ghbyname(const char *, int, int, int *);
211static char	*_hgetword(char **);
212static int	 _mapped_addr_enabled(void);
213
214static struct	 hostent *_hpreorder(struct hostent *);
215static int	 get_addrselectpolicy(struct policyhead *);
216static void	 free_addrselectpolicy(struct policyhead *);
217static struct	 policyqueue *match_addrselectpolicy(struct sockaddr *,
218	struct policyhead *);
219static void	 set_source(struct hp_order *, struct policyhead *);
220static int	 matchlen(struct sockaddr *, struct sockaddr *);
221static int	 comp_dst(const void *, const void *);
222static int	 gai_addr2scopetype(struct sockaddr *);
223
224static FILE	*_files_open(int *);
225static int	 _files_ghbyname(void *, void *, va_list);
226static int	 _files_ghbyaddr(void *, void *, va_list);
227#ifdef YP
228static int	 _nis_ghbyname(void *, void *, va_list);
229static int	 _nis_ghbyaddr(void *, void *, va_list);
230#endif
231static int	 _dns_ghbyname(void *, void *, va_list);
232static int	 _dns_ghbyaddr(void *, void *, va_list);
233static void	 _dns_shent(int) __unused;
234static void	 _dns_ehent(void) __unused;
235#ifdef ICMPNL
236static int	 _icmp_ghbyaddr(void *, void *, va_list);
237#endif /* ICMPNL */
238#ifdef NS_CACHING
239static int ipnode_id_func(char *, size_t *, va_list, void *);
240static int ipnode_marshal_func(char *, size_t *, void *, va_list, void *);
241static 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 */
245static 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
263static 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
284static int
285ipnode_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
377fin:
378	*buffer_size = desired_size;
379	return (res);
380}
381
382static int
383ipnode_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
470static int
471ipnode_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
521static 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
563struct hostent *
564getipnodebyname(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
632struct hostent *
633getipnodebyaddr(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
708void
709freehostent(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 */
721static 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 */
800static 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 */
820static 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
892static 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 */
919static 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
968static 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 */
1002static 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
1093static int
1094get_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
1130static void
1131free_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
1142static struct policyqueue *
1143match_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
1209static void
1210set_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
1268static int
1269matchlen(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
1307static int
1308comp_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 */
1422static int
1423gai_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
1483static 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
1493static 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
1566static 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 */
1628static 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
1648static 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
1671typedef union {
1672	HEADER hdr;
1673	u_char buf[MAXPACKET];
1674} querybuf;
1675
1676static 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 */
1682static struct hostent *
1683getanswer(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
1947static 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
2009static 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
2146static 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
2160static 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
2186static char *
2187dnsdecode(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
2249static 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
2390static 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