]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/libc/net/name6.c
Update the resolver in libc to BIND9's one.
[FreeBSD/FreeBSD.git] / lib / libc / net / name6.c
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 #ifdef ICMPNL
95 #include "reentrant.h"
96 #endif
97 #include <sys/param.h>
98 #include <sys/socket.h>
99 #include <sys/time.h>
100 #include <sys/queue.h>
101 #include <netinet/in.h>
102 #ifdef INET6
103 #include <net/if.h>
104 #include <net/if_var.h>
105 #include <sys/sysctl.h>
106 #include <sys/ioctl.h>
107 #include <netinet6/in6_var.h>   /* XXX */
108 #endif
109
110 #include <arpa/inet.h>
111 #include <arpa/nameser.h>
112
113 #include <errno.h>
114 #include <netdb.h>
115 #include <resolv.h>
116 #include <stdio.h>
117 #include <stdlib.h>
118 #include <string.h>
119 #include <stdarg.h>
120 #include <nsswitch.h>
121 #include <unistd.h>
122 #include "un-namespace.h"
123 #include "netdb_private.h"
124 #include "res_config.h"
125 #include "res_private.h"
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
239 #ifdef ICMPNL
240 static mutex_t _getipnodeby_thread_lock = MUTEX_INITIALIZER;
241 #define THREAD_LOCK()   mutex_lock(&_getipnodeby_thread_lock);
242 #define THREAD_UNLOCK() mutex_unlock(&_getipnodeby_thread_lock);
243 #endif
244
245 /* Host lookup order if nsswitch.conf is broken or nonexistant */
246 static const ns_src default_src[] = { 
247         { NSSRC_FILES, NS_SUCCESS },
248         { NSSRC_DNS, NS_SUCCESS },
249 #ifdef ICMPNL
250 #define NSSRC_ICMP "icmp"
251         { NSSRC_ICMP, NS_SUCCESS },
252 #endif
253         { 0 }
254 };
255
256 /*
257  * Check if kernel supports mapped address.
258  *      implementation dependent
259  */
260 #ifdef __KAME__
261 #include <sys/sysctl.h>
262 #endif /* __KAME__ */
263
264 static int
265 _mapped_addr_enabled(void)
266 {
267         /* implementation dependent check */
268 #if defined(__KAME__) && defined(IPV6CTL_MAPPED_ADDR)
269         int mib[4];
270         size_t len;
271         int val;
272
273         mib[0] = CTL_NET;
274         mib[1] = PF_INET6;
275         mib[2] = IPPROTO_IPV6;
276         mib[3] = IPV6CTL_MAPPED_ADDR;
277         len = sizeof(val);
278         if (sysctl(mib, 4, &val, &len, 0, 0) == 0 && val != 0)
279                 return 1;
280 #endif /* __KAME__ && IPV6CTL_MAPPED_ADDR */
281         return 0;
282 }
283
284 /*
285  * Functions defined in RFC2553
286  *      getipnodebyname, getipnodebyaddr, freehostent
287  */
288
289 static struct hostent *
290 _ghbyname(const char *name, int af, int flags, int *errp)
291 {
292         struct hostent *hp;
293         int rval;
294
295         static const ns_dtab dtab[] = {
296                 NS_FILES_CB(_files_ghbyname, NULL)
297                 { NSSRC_DNS, _dns_ghbyname, NULL },
298                 NS_NIS_CB(_nis_ghbyname, NULL)
299                 { 0 }
300         };
301
302         if (flags & AI_ADDRCONFIG) {
303                 int s;
304
305                 if ((s = _socket(af, SOCK_DGRAM, 0)) < 0)
306                         return NULL;
307                 /*
308                  * TODO:
309                  * Note that implementation dependent test for address
310                  * configuration should be done everytime called
311                  * (or apropriate interval),
312                  * because addresses will be dynamically assigned or deleted.
313                  */
314                 _close(s);
315         }
316
317         rval = _nsdispatch(&hp, dtab, NSDB_HOSTS, "ghbyname", default_src,
318                           name, af, errp);
319         return (rval == NS_SUCCESS) ? hp : NULL;
320 }
321
322 struct hostent *
323 getipnodebyname(const char *name, int af, int flags, int *errp)
324 {
325         struct hostent *hp;
326         union inx_addr addrbuf;
327         res_state statp;
328
329         switch (af) {
330         case AF_INET:
331 #ifdef INET6
332         case AF_INET6:
333 #endif
334                 break;
335         default:
336                 *errp = NO_RECOVERY;
337                 return NULL;
338         }
339
340 #ifdef INET6
341         /* special case for literal address */
342         if (inet_pton(AF_INET6, name, &addrbuf) == 1) {
343                 if (af != AF_INET6) {
344                         *errp = HOST_NOT_FOUND;
345                         return NULL;
346                 }
347                 return _hpaddr(af, name, &addrbuf, errp);
348         }
349 #endif
350         if (inet_aton(name, (struct in_addr *)&addrbuf) == 1) {
351                 if (af != AF_INET) {
352                         if (MAPADDRENABLED(flags)) {
353                                 MAPADDR(&addrbuf, &addrbuf.in_addr);
354                         } else {
355                                 *errp = HOST_NOT_FOUND;
356                                 return NULL;
357                         }
358                 }
359                 return _hpaddr(af, name, &addrbuf, errp);
360         }
361
362         statp = __res_state();
363         if ((statp->options & RES_INIT) == 0) {
364                 if (res_ninit(statp) < 0) {
365                         *errp = NETDB_INTERNAL;
366                         return NULL;
367                 }
368         }
369
370         *errp = HOST_NOT_FOUND;
371         hp = _ghbyname(name, af, flags, errp);
372
373 #ifdef INET6
374         if (af == AF_INET6 && ((flags & AI_ALL) || hp == NULL) &&
375             MAPADDRENABLED(flags)) {
376                 struct hostent *hp2 = _ghbyname(name, AF_INET, flags, errp);
377                 if (hp == NULL)
378                         hp = _hpmapv6(hp2, errp);
379                 else {
380                         if (hp2 && strcmp(hp->h_name, hp2->h_name) != 0) {
381                                 freehostent(hp2);
382                                 hp2 = NULL;
383                         }
384                         hp = _hpmerge(hp, hp2, errp);
385                 }
386         }
387 #endif
388         return _hpreorder(_hpsort(hp, statp));
389 }
390
391 struct hostent *
392 getipnodebyaddr(const void *src, size_t len, int af, int *errp)
393 {
394         struct hostent *hp;
395         int rval;
396 #ifdef INET6
397         struct in6_addr addrbuf;
398 #else
399         struct in_addr addrbuf;
400 #endif
401
402         static const ns_dtab dtab[] = {
403                 NS_FILES_CB(_files_ghbyaddr, NULL)
404                 { NSSRC_DNS, _dns_ghbyaddr, NULL },
405                 NS_NIS_CB(_nis_ghbyaddr, NULL)
406 #ifdef ICMPNL
407                 { NSSRC_ICMP, _icmp_ghbyaddr, NULL },
408 #endif
409                 { 0 }
410         };
411
412         *errp = HOST_NOT_FOUND;
413
414         switch (af) {
415         case AF_INET:
416                 if (len != sizeof(struct in_addr)) {
417                         *errp = NO_RECOVERY;
418                         return NULL;
419                 }
420                 if ((long)src & ~(sizeof(struct in_addr) - 1)) {
421                         memcpy(&addrbuf, src, len);
422                         src = &addrbuf;
423                 }
424                 if (((struct in_addr *)src)->s_addr == 0)
425                         return NULL;
426                 break;
427 #ifdef INET6
428         case AF_INET6:
429                 if (len != sizeof(struct in6_addr)) {
430                         *errp = NO_RECOVERY;
431                         return NULL;
432                 }
433                 if ((long)src & ~(sizeof(struct in6_addr) / 2 - 1)) {   /*XXX*/
434                         memcpy(&addrbuf, src, len);
435                         src = &addrbuf;
436                 }
437                 if (IN6_IS_ADDR_UNSPECIFIED((struct in6_addr *)src))
438                         return NULL;
439                 if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)src)
440                 ||  IN6_IS_ADDR_V4COMPAT((struct in6_addr *)src)) {
441                         src = (char *)src +
442                             (sizeof(struct in6_addr) - sizeof(struct in_addr));
443                         af = AF_INET;
444                         len = sizeof(struct in_addr);
445                 }
446                 break;
447 #endif
448         default:
449                 *errp = NO_RECOVERY;
450                 return NULL;
451         }
452
453         rval = _nsdispatch(&hp, dtab, NSDB_HOSTS, "ghbyaddr", default_src,
454                           src, len, af, errp);
455         return (rval == NS_SUCCESS) ? hp : NULL;
456 }
457
458 void
459 freehostent(struct hostent *ptr)
460 {
461         free(ptr);
462 }
463
464 /*
465  * Private utility functions
466  */
467
468 /*
469  * _hpcopy: allocate and copy hostent structure
470  */
471 static struct hostent *
472 _hpcopy(struct hostent *hp, int *errp)
473 {
474         struct hostent *nhp;
475         char *cp, **pp;
476         int size, addrsize;
477         int nalias = 0, naddr = 0;
478         int al_off;
479         int i;
480
481         if (hp == NULL)
482                 return hp;
483
484         /* count size to be allocated */
485         size = sizeof(struct hostent);
486         if (hp->h_name != NULL)
487                 size += strlen(hp->h_name) + 1;
488         if ((pp = hp->h_aliases) != NULL) {
489                 for (i = 0; *pp != NULL; i++, pp++) {
490                         if (**pp != '\0') {
491                                 size += strlen(*pp) + 1;
492                                 nalias++;
493                         }
494                 }
495         }
496         /* adjust alignment */
497         size = ALIGN(size);
498         al_off = size;
499         size += sizeof(char *) * (nalias + 1);
500         addrsize = ALIGN(hp->h_length);
501         if ((pp = hp->h_addr_list) != NULL) {
502                 while (*pp++ != NULL)
503                         naddr++;
504         }
505         size += addrsize * naddr;
506         size += sizeof(char *) * (naddr + 1);
507
508         /* copy */
509         if ((nhp = (struct hostent *)malloc(size)) == NULL) {
510                 *errp = TRY_AGAIN;
511                 return NULL;
512         }
513         cp = (char *)&nhp[1];
514         if (hp->h_name != NULL) {
515                 nhp->h_name = cp;
516                 strcpy(cp, hp->h_name);
517                 cp += strlen(cp) + 1;
518         } else
519                 nhp->h_name = NULL;
520         nhp->h_aliases = (char **)((char *)nhp + al_off);
521         if ((pp = hp->h_aliases) != NULL) {
522                 for (i = 0; *pp != NULL; pp++) {
523                         if (**pp != '\0') {
524                                 nhp->h_aliases[i++] = cp;
525                                 strcpy(cp, *pp);
526                                 cp += strlen(cp) + 1;
527                         }
528                 }
529         }
530         nhp->h_aliases[nalias] = NULL;
531         cp = (char *)&nhp->h_aliases[nalias + 1];
532         nhp->h_addrtype = hp->h_addrtype;
533         nhp->h_length = hp->h_length;
534         nhp->h_addr_list = (char **)cp;
535         if ((pp = hp->h_addr_list) != NULL) {
536                 cp = (char *)&nhp->h_addr_list[naddr + 1];
537                 for (i = 0; *pp != NULL; pp++) {
538                         nhp->h_addr_list[i++] = cp;
539                         memcpy(cp, *pp, hp->h_length);
540                         cp += addrsize;
541                 }
542         }
543         nhp->h_addr_list[naddr] = NULL;
544         return nhp;
545 }
546
547 /*
548  * _hpaddr: construct hostent structure with one address
549  */
550 static struct hostent *
551 _hpaddr(int af, const char *name, void *addr, int *errp)
552 {
553         struct hostent *hp, hpbuf;
554         char *addrs[2];
555
556         hp = &hpbuf;
557         hp->h_name = (char *)name;
558         hp->h_aliases = NULL;
559         hp->h_addrtype = af;
560         hp->h_length = ADDRLEN(af);
561         hp->h_addr_list = addrs;
562         addrs[0] = (char *)addr;
563         addrs[1] = NULL;
564         return _hpcopy(hp, errp);
565 }
566
567 /*
568  * _hpmerge: merge 2 hostent structure, arguments will be freed
569  */
570 static struct hostent *
571 _hpmerge(struct hostent *hp1, struct hostent *hp2, int *errp)
572 {
573         int i, j;
574         int naddr, nalias;
575         char **pp;
576         struct hostent *hp, hpbuf;
577         char *aliases[MAXALIASES + 1], *addrs[MAXADDRS + 1];
578         union inx_addr addrbuf[MAXADDRS];
579
580         if (hp1 == NULL)
581                 return hp2;
582         if (hp2 == NULL)
583                 return hp1;
584
585 #define HP(i)   (i == 1 ? hp1 : hp2)
586         hp = &hpbuf;
587         hp->h_name = (hp1->h_name != NULL ? hp1->h_name : hp2->h_name);
588         hp->h_aliases = aliases;
589         nalias = 0;
590         for (i = 1; i <= 2; i++) {
591                 if ((pp = HP(i)->h_aliases) == NULL)
592                         continue;
593                 for (; nalias < MAXALIASES && *pp != NULL; pp++) {
594                         /* check duplicates */
595                         for (j = 0; j < nalias; j++)
596                                 if (strcasecmp(*pp, aliases[j]) == 0)
597                                         break;
598                         if (j == nalias)
599                                 aliases[nalias++] = *pp;
600                 }
601         }
602         aliases[nalias] = NULL;
603 #ifdef INET6
604         if (hp1->h_length != hp2->h_length) {
605                 hp->h_addrtype = AF_INET6;
606                 hp->h_length = sizeof(struct in6_addr);
607         } else {
608 #endif
609                 hp->h_addrtype = hp1->h_addrtype;
610                 hp->h_length = hp1->h_length;
611 #ifdef INET6
612         }
613 #endif
614         hp->h_addr_list = addrs;
615         naddr = 0;
616         for (i = 1; i <= 2; i++) {
617                 if ((pp = HP(i)->h_addr_list) == NULL)
618                         continue;
619                 if (HP(i)->h_length == hp->h_length) {
620                         while (naddr < MAXADDRS && *pp != NULL)
621                                 addrs[naddr++] = *pp++;
622                 } else {
623                         /* copy IPv4 addr as mapped IPv6 addr */
624                         while (naddr < MAXADDRS && *pp != NULL) {
625                                 MAPADDR(&addrbuf[naddr], *pp++);
626                                 addrs[naddr] = (char *)&addrbuf[naddr];
627                                 naddr++;
628                         }
629                 }
630         }
631         addrs[naddr] = NULL;
632         hp = _hpcopy(hp, errp);
633         freehostent(hp1);
634         freehostent(hp2);
635         return hp;
636 }
637
638 /*
639  * _hpmapv6: convert IPv4 hostent into IPv4-mapped IPv6 addresses
640  */
641 #ifdef INET6
642 static struct hostent *
643 _hpmapv6(struct hostent *hp, int *errp)
644 {
645         struct hostent *hp6;
646
647         if (hp == NULL)
648                 return NULL;
649         if (hp->h_addrtype == AF_INET6)
650                 return hp;
651
652         /* make dummy hostent to convert IPv6 address */
653         if ((hp6 = (struct hostent *)malloc(sizeof(struct hostent))) == NULL) {
654                 *errp = TRY_AGAIN;
655                 return NULL;
656         }
657         hp6->h_name = NULL;
658         hp6->h_aliases = NULL;
659         hp6->h_addrtype = AF_INET6;
660         hp6->h_length = sizeof(struct in6_addr);
661         hp6->h_addr_list = NULL;
662         return _hpmerge(hp6, hp, errp);
663 }
664 #endif
665
666 /*
667  * _hpsort: sort address by sortlist
668  */
669 static struct hostent *
670 _hpsort(struct hostent *hp, res_state statp)
671 {
672         int i, j, n;
673         u_char *ap, *sp, *mp, **pp;
674         char t;
675         char order[MAXADDRS];
676         int nsort = statp->nsort;
677
678         if (hp == NULL || hp->h_addr_list[1] == NULL || nsort == 0)
679                 return hp;
680         for (i = 0; (ap = (u_char *)hp->h_addr_list[i]); i++) {
681                 for (j = 0; j < nsort; j++) {
682 #ifdef INET6
683                         if (statp->_u._ext.ext->sort_list[j].af !=
684                             hp->h_addrtype)
685                                 continue;
686                         sp = (u_char *)&statp->_u._ext.ext->sort_list[j].addr;
687                         mp = (u_char *)&statp->_u._ext.ext->sort_list[j].mask;
688 #else
689                         sp = (u_char *)&statp->sort_list[j].addr;
690                         mp = (u_char *)&statp->sort_list[j].mask;
691 #endif
692                         for (n = 0; n < hp->h_length; n++) {
693                                 if ((ap[n] & mp[n]) != sp[n])
694                                         break;
695                         }
696                         if (n == hp->h_length)
697                                 break;
698                 }
699                 order[i] = j;
700         }
701         n = i;
702         pp = (u_char **)hp->h_addr_list;
703         for (i = 0; i < n - 1; i++) {
704                 for (j = i + 1; j < n; j++) {
705                         if (order[i] > order[j]) {
706                                 ap = pp[i];
707                                 pp[i] = pp[j];
708                                 pp[j] = ap;
709                                 t = order[i];
710                                 order[i] = order[j];
711                                 order[j] = t;
712                         }
713                 }
714         }
715         return hp;
716 }
717
718 static char *
719 _hgetword(char **pp)
720 {
721         char c, *p, *ret;
722         const char *sp;
723         static const char sep[] = "# \t\n";
724
725         ret = NULL;
726         for (p = *pp; (c = *p) != '\0'; p++) {
727                 for (sp = sep; *sp != '\0'; sp++) {
728                         if (c == *sp)
729                                 break;
730                 }
731                 if (c == '#')
732                         p[1] = '\0';    /* ignore rest of line */
733                 if (ret == NULL) {
734                         if (*sp == '\0')
735                                 ret = p;
736                 } else {
737                         if (*sp != '\0') {
738                                 *p++ = '\0';
739                                 break;
740                         }
741                 }
742         }
743         *pp = p;
744         if (ret == NULL || *ret == '\0')
745                 return NULL;
746         return ret;
747 }
748
749 /*
750  * _hpreorder: sort address by default address selection
751  */
752 static struct hostent *
753 _hpreorder(struct hostent *hp)
754 {
755         struct hp_order *aio;
756         int i, n;
757         char *ap;
758         struct sockaddr *sa;
759         struct policyhead policyhead;
760
761         if (hp == NULL)
762                 return hp;
763
764         switch (hp->h_addrtype) {
765         case AF_INET:
766 #ifdef INET6
767         case AF_INET6:
768 #endif
769                 break;
770         default:
771                 free_addrselectpolicy(&policyhead);
772                 return hp;
773         }
774
775         /* count the number of addrinfo elements for sorting. */
776         for (n = 0; hp->h_addr_list[n] != NULL; n++)
777                 ;
778
779         /*
780          * If the number is small enough, we can skip the reordering process.
781          */
782         if (n <= 1)
783                 return hp;
784
785         /* allocate a temporary array for sort and initialization of it. */
786         if ((aio = malloc(sizeof(*aio) * n)) == NULL)
787                 return hp;      /* give up reordering */
788         memset(aio, 0, sizeof(*aio) * n);
789
790         /* retrieve address selection policy from the kernel */
791         TAILQ_INIT(&policyhead);
792         if (!get_addrselectpolicy(&policyhead)) {
793                 /* no policy is installed into kernel, we don't sort. */
794                 free(aio);
795                 return hp;
796         }
797
798         for (i = 0; i < n; i++) {
799                 ap = hp->h_addr_list[i];
800                 aio[i].aio_h_addr = ap;
801                 sa = &aio[i].aio_sa;
802                 switch (hp->h_addrtype) {
803                 case AF_INET:
804                         sa->sa_family = AF_INET;
805                         sa->sa_len = sizeof(struct sockaddr_in);
806                         memcpy(&((struct sockaddr_in *)sa)->sin_addr, ap,
807                             sizeof(struct in_addr));
808                         break;
809 #ifdef INET6
810                 case AF_INET6:
811                         if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)ap)) {
812                                 sa->sa_family = AF_INET;
813                                 sa->sa_len = sizeof(struct sockaddr_in);
814                                 memcpy(&((struct sockaddr_in *)sa)->sin_addr,
815                                     &ap[12], sizeof(struct in_addr));
816                         } else {
817                                 sa->sa_family = AF_INET6;
818                                 sa->sa_len = sizeof(struct sockaddr_in6);
819                                 memcpy(&((struct sockaddr_in6 *)sa)->sin6_addr,
820                                     ap, sizeof(struct in6_addr));
821                         }
822                         break;
823 #endif
824                 }
825                 aio[i].aio_dstscope = gai_addr2scopetype(sa);
826                 aio[i].aio_dstpolicy = match_addrselectpolicy(sa, &policyhead);
827                 set_source(&aio[i], &policyhead);
828         }
829
830         /* perform sorting. */
831         qsort(aio, n, sizeof(*aio), comp_dst);
832
833         /* reorder the h_addr_list. */
834         for (i = 0; i < n; i++)
835                 hp->h_addr_list[i] = aio[i].aio_h_addr;
836
837         /* cleanup and return */
838         free(aio);
839         free_addrselectpolicy(&policyhead);
840         return hp;
841 }
842
843 static int
844 get_addrselectpolicy(head)
845         struct policyhead *head;
846 {
847 #ifdef INET6
848         int mib[] = { CTL_NET, PF_INET6, IPPROTO_IPV6, IPV6CTL_ADDRCTLPOLICY };
849         size_t l;
850         char *buf;
851         struct in6_addrpolicy *pol, *ep;
852
853         if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), NULL, &l, NULL, 0) < 0)
854                 return (0);
855         if ((buf = malloc(l)) == NULL)
856                 return (0);
857         if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), buf, &l, NULL, 0) < 0) {
858                 free(buf);
859                 return (0);
860         }
861
862         ep = (struct in6_addrpolicy *)(buf + l);
863         for (pol = (struct in6_addrpolicy *)buf; pol + 1 <= ep; pol++) {
864                 struct policyqueue *new;
865
866                 if ((new = malloc(sizeof(*new))) == NULL) {
867                         free_addrselectpolicy(head); /* make the list empty */
868                         break;
869                 }
870                 new->pc_policy = *pol;
871                 TAILQ_INSERT_TAIL(head, new, pc_entry);
872         }
873
874         free(buf);
875         return (1);
876 #else
877         return (0);
878 #endif
879 }
880
881 static void
882 free_addrselectpolicy(head)
883         struct policyhead *head;
884 {
885         struct policyqueue *ent, *nent;
886
887         for (ent = TAILQ_FIRST(head); ent; ent = nent) {
888                 nent = TAILQ_NEXT(ent, pc_entry);
889                 TAILQ_REMOVE(head, ent, pc_entry);
890                 free(ent);
891         }
892 }
893
894 static struct policyqueue *
895 match_addrselectpolicy(addr, head)
896         struct sockaddr *addr;
897         struct policyhead *head;
898 {
899 #ifdef INET6
900         struct policyqueue *ent, *bestent = NULL;
901         struct in6_addrpolicy *pol;
902         int matchlen, bestmatchlen = -1;
903         u_char *mp, *ep, *k, *p, m;
904         struct sockaddr_in6 key;
905
906         switch(addr->sa_family) {
907         case AF_INET6:
908                 key = *(struct sockaddr_in6 *)addr;
909                 break;
910         case AF_INET:
911                 /* convert the address into IPv4-mapped IPv6 address. */
912                 memset(&key, 0, sizeof(key));
913                 key.sin6_family = AF_INET6;
914                 key.sin6_len = sizeof(key);
915                 key.sin6_addr.s6_addr[10] = 0xff;
916                 key.sin6_addr.s6_addr[11] = 0xff;
917                 memcpy(&key.sin6_addr.s6_addr[12],
918                        &((struct sockaddr_in *)addr)->sin_addr, 4);
919                 break;
920         default:
921                 return(NULL);
922         }
923
924         for (ent = TAILQ_FIRST(head); ent; ent = TAILQ_NEXT(ent, pc_entry)) {
925                 pol = &ent->pc_policy;
926                 matchlen = 0;
927
928                 mp = (u_char *)&pol->addrmask.sin6_addr;
929                 ep = mp + 16;   /* XXX: scope field? */
930                 k = (u_char *)&key.sin6_addr;
931                 p = (u_char *)&pol->addr.sin6_addr;
932                 for (; mp < ep && *mp; mp++, k++, p++) {
933                         m = *mp;
934                         if ((*k & m) != *p)
935                                 goto next; /* not match */
936                         if (m == 0xff) /* short cut for a typical case */
937                                 matchlen += 8;
938                         else {
939                                 while (m >= 0x80) {
940                                         matchlen++;
941                                         m <<= 1;
942                                 }
943                         }
944                 }
945
946                 /* matched.  check if this is better than the current best. */
947                 if (matchlen > bestmatchlen) {
948                         bestent = ent;
949                         bestmatchlen = matchlen;
950                 }
951
952           next:
953                 continue;
954         }
955
956         return(bestent);
957 #else
958         return(NULL);
959 #endif
960
961 }
962
963 static void
964 set_source(aio, ph)
965         struct hp_order *aio;
966         struct policyhead *ph;
967 {
968         struct sockaddr_storage ss = aio->aio_un.aiou_ss;
969         socklen_t srclen;
970         int s;
971
972         /* set unspec ("no source is available"), just in case */
973         aio->aio_srcsa.sa_family = AF_UNSPEC;
974         aio->aio_srcscope = -1;
975
976         switch(ss.ss_family) {
977         case AF_INET:
978                 ((struct sockaddr_in *)&ss)->sin_port = htons(1);
979                 break;
980 #ifdef INET6
981         case AF_INET6:
982                 ((struct sockaddr_in6 *)&ss)->sin6_port = htons(1);
983                 break;
984 #endif
985         default:                /* ignore unsupported AFs explicitly */
986                 return;
987         }
988
989         /* open a socket to get the source address for the given dst */
990         if ((s = _socket(ss.ss_family, SOCK_DGRAM, IPPROTO_UDP)) < 0)
991                 return;         /* give up */
992         if (_connect(s, (struct sockaddr *)&ss, ss.ss_len) < 0)
993                 goto cleanup;
994         srclen = ss.ss_len;
995         if (_getsockname(s, &aio->aio_srcsa, &srclen) < 0) {
996                 aio->aio_srcsa.sa_family = AF_UNSPEC;
997                 goto cleanup;
998         }
999         aio->aio_srcscope = gai_addr2scopetype(&aio->aio_srcsa);
1000         aio->aio_srcpolicy = match_addrselectpolicy(&aio->aio_srcsa, ph);
1001         aio->aio_matchlen = matchlen(&aio->aio_srcsa, (struct sockaddr *)&ss);
1002 #ifdef INET6
1003         if (ss.ss_family == AF_INET6) {
1004                 struct in6_ifreq ifr6;
1005                 u_int32_t flags6;
1006
1007                 /* XXX: interface name should not be hardcoded */
1008                 strncpy(ifr6.ifr_name, "lo0", sizeof(ifr6.ifr_name));
1009                 memset(&ifr6, 0, sizeof(ifr6));
1010                 memcpy(&ifr6.ifr_addr, &ss, ss.ss_len);
1011                 if (_ioctl(s, SIOCGIFAFLAG_IN6, &ifr6) == 0) {
1012                         flags6 = ifr6.ifr_ifru.ifru_flags6;
1013                         if ((flags6 & IN6_IFF_DEPRECATED))
1014                                 aio->aio_srcflag |= AIO_SRCFLAG_DEPRECATED;
1015                 }
1016         }
1017 #endif
1018
1019   cleanup:
1020         _close(s);
1021         return;
1022 }
1023
1024 static int
1025 matchlen(src, dst)
1026         struct sockaddr *src, *dst;
1027 {
1028         int match = 0;
1029         u_char *s, *d;
1030         u_char *lim, r;
1031         int addrlen;
1032
1033         switch (src->sa_family) {
1034 #ifdef INET6
1035         case AF_INET6:
1036                 s = (u_char *)&((struct sockaddr_in6 *)src)->sin6_addr;
1037                 d = (u_char *)&((struct sockaddr_in6 *)dst)->sin6_addr;
1038                 addrlen = sizeof(struct in6_addr);
1039                 lim = s + addrlen;
1040                 break;
1041 #endif
1042         case AF_INET:
1043                 s = (u_char *)&((struct sockaddr_in *)src)->sin_addr;
1044                 d = (u_char *)&((struct sockaddr_in *)dst)->sin_addr;
1045                 addrlen = sizeof(struct in_addr);
1046                 lim = s + addrlen;
1047                 break;
1048         default:
1049                 return(0);
1050         }
1051
1052         while (s < lim)
1053                 if ((r = (*d++ ^ *s++)) != 0) {
1054                         while (r < addrlen * 8) {
1055                                 match++;
1056                                 r <<= 1;
1057                         }
1058                         break;
1059                 } else
1060                         match += 8;
1061         return(match);
1062 }
1063
1064 static int
1065 comp_dst(arg1, arg2)
1066         const void *arg1, *arg2;
1067 {
1068         const struct hp_order *dst1 = arg1, *dst2 = arg2;
1069
1070         /*
1071          * Rule 1: Avoid unusable destinations.
1072          * XXX: we currently do not consider if an appropriate route exists.
1073          */
1074         if (dst1->aio_srcsa.sa_family != AF_UNSPEC &&
1075             dst2->aio_srcsa.sa_family == AF_UNSPEC) {
1076                 return(-1);
1077         }
1078         if (dst1->aio_srcsa.sa_family == AF_UNSPEC &&
1079             dst2->aio_srcsa.sa_family != AF_UNSPEC) {
1080                 return(1);
1081         }
1082
1083         /* Rule 2: Prefer matching scope. */
1084         if (dst1->aio_dstscope == dst1->aio_srcscope &&
1085             dst2->aio_dstscope != dst2->aio_srcscope) {
1086                 return(-1);
1087         }
1088         if (dst1->aio_dstscope != dst1->aio_srcscope &&
1089             dst2->aio_dstscope == dst2->aio_srcscope) {
1090                 return(1);
1091         }
1092
1093         /* Rule 3: Avoid deprecated addresses. */
1094         if (dst1->aio_srcsa.sa_family != AF_UNSPEC &&
1095             dst2->aio_srcsa.sa_family != AF_UNSPEC) {
1096                 if (!(dst1->aio_srcflag & AIO_SRCFLAG_DEPRECATED) &&
1097                     (dst2->aio_srcflag & AIO_SRCFLAG_DEPRECATED)) {
1098                         return(-1);
1099                 }
1100                 if ((dst1->aio_srcflag & AIO_SRCFLAG_DEPRECATED) &&
1101                     !(dst2->aio_srcflag & AIO_SRCFLAG_DEPRECATED)) {
1102                         return(1);
1103                 }
1104         }
1105
1106         /* Rule 4: Prefer home addresses. */
1107         /* XXX: not implemented yet */
1108
1109         /* Rule 5: Prefer matching label. */
1110 #ifdef INET6
1111         if (dst1->aio_srcpolicy && dst1->aio_dstpolicy &&
1112             dst1->aio_srcpolicy->pc_policy.label ==
1113             dst1->aio_dstpolicy->pc_policy.label &&
1114             (dst2->aio_srcpolicy == NULL || dst2->aio_dstpolicy == NULL ||
1115              dst2->aio_srcpolicy->pc_policy.label !=
1116              dst2->aio_dstpolicy->pc_policy.label)) {
1117                 return(-1);
1118         }
1119         if (dst2->aio_srcpolicy && dst2->aio_dstpolicy &&
1120             dst2->aio_srcpolicy->pc_policy.label ==
1121             dst2->aio_dstpolicy->pc_policy.label &&
1122             (dst1->aio_srcpolicy == NULL || dst1->aio_dstpolicy == NULL ||
1123              dst1->aio_srcpolicy->pc_policy.label !=
1124              dst1->aio_dstpolicy->pc_policy.label)) {
1125                 return(1);
1126         }
1127 #endif
1128
1129         /* Rule 6: Prefer higher precedence. */
1130 #ifdef INET6
1131         if (dst1->aio_dstpolicy &&
1132             (dst2->aio_dstpolicy == NULL ||
1133              dst1->aio_dstpolicy->pc_policy.preced >
1134              dst2->aio_dstpolicy->pc_policy.preced)) {
1135                 return(-1);
1136         }
1137         if (dst2->aio_dstpolicy &&
1138             (dst1->aio_dstpolicy == NULL ||
1139              dst2->aio_dstpolicy->pc_policy.preced >
1140              dst1->aio_dstpolicy->pc_policy.preced)) {
1141                 return(1);
1142         }
1143 #endif
1144
1145         /* Rule 7: Prefer native transport. */
1146         /* XXX: not implemented yet */
1147
1148         /* Rule 8: Prefer smaller scope. */
1149         if (dst1->aio_dstscope >= 0 &&
1150             dst1->aio_dstscope < dst2->aio_dstscope) {
1151                 return(-1);
1152         }
1153         if (dst2->aio_dstscope >= 0 &&
1154             dst2->aio_dstscope < dst1->aio_dstscope) {
1155                 return(1);
1156         }
1157
1158         /*
1159          * Rule 9: Use longest matching prefix.
1160          * We compare the match length in a same AF only.
1161          */
1162         if (dst1->aio_sa.sa_family == dst2->aio_sa.sa_family) {
1163                 if (dst1->aio_matchlen > dst2->aio_matchlen) {
1164                         return(-1);
1165                 }
1166                 if (dst1->aio_matchlen < dst2->aio_matchlen) {
1167                         return(1);
1168                 }
1169         }
1170
1171         /* Rule 10: Otherwise, leave the order unchanged. */
1172         return(-1);
1173 }
1174
1175 /*
1176  * Copy from scope.c.
1177  * XXX: we should standardize the functions and link them as standard
1178  * library.
1179  */
1180 static int
1181 gai_addr2scopetype(sa)
1182         struct sockaddr *sa;
1183 {
1184 #ifdef INET6
1185         struct sockaddr_in6 *sa6;
1186 #endif
1187         struct sockaddr_in *sa4;
1188
1189         switch(sa->sa_family) {
1190 #ifdef INET6
1191         case AF_INET6:
1192                 sa6 = (struct sockaddr_in6 *)sa;
1193                 if (IN6_IS_ADDR_MULTICAST(&sa6->sin6_addr)) {
1194                         /* just use the scope field of the multicast address */
1195                         return(sa6->sin6_addr.s6_addr[2] & 0x0f);
1196                 }
1197                 /*
1198                  * Unicast addresses: map scope type to corresponding scope
1199                  * value defined for multcast addresses.
1200                  * XXX: hardcoded scope type values are bad...
1201                  */
1202                 if (IN6_IS_ADDR_LOOPBACK(&sa6->sin6_addr))
1203                         return(1); /* node local scope */
1204                 if (IN6_IS_ADDR_LINKLOCAL(&sa6->sin6_addr))
1205                         return(2); /* link-local scope */
1206                 if (IN6_IS_ADDR_SITELOCAL(&sa6->sin6_addr))
1207                         return(5); /* site-local scope */
1208                 return(14);     /* global scope */
1209                 break;
1210 #endif
1211         case AF_INET:
1212                 /*
1213                  * IPv4 pseudo scoping according to RFC 3484.
1214                  */
1215                 sa4 = (struct sockaddr_in *)sa;
1216                 /* IPv4 autoconfiguration addresses have link-local scope. */
1217                 if (((u_char *)&sa4->sin_addr)[0] == 169 &&
1218                     ((u_char *)&sa4->sin_addr)[1] == 254)
1219                         return(2);
1220                 /* Private addresses have site-local scope. */
1221                 if (((u_char *)&sa4->sin_addr)[0] == 10 ||
1222                     (((u_char *)&sa4->sin_addr)[0] == 172 &&
1223                      (((u_char *)&sa4->sin_addr)[1] & 0xf0) == 16) ||
1224                     (((u_char *)&sa4->sin_addr)[0] == 192 &&
1225                      ((u_char *)&sa4->sin_addr)[1] == 168))
1226                         return(14);     /* XXX: It should be 5 unless NAT */
1227                 /* Loopback addresses have link-local scope. */
1228                 if (((u_char *)&sa4->sin_addr)[0] == 127)
1229                         return(2);
1230                 return(14);
1231                 break;
1232         default:
1233                 errno = EAFNOSUPPORT; /* is this a good error? */
1234                 return(-1);
1235         }
1236 }
1237
1238 /*
1239  * FILES (/etc/hosts)
1240  */
1241
1242 static FILE *
1243 _files_open(int *errp)
1244 {
1245         FILE *fp;
1246         fp = fopen(_PATH_HOSTS, "r");
1247         if (fp == NULL)
1248                 *errp = NO_RECOVERY;
1249         return fp;
1250 }
1251
1252 static int
1253 _files_ghbyname(void *rval, void *cb_data, va_list ap)
1254 {
1255         const char *name;
1256         int af; 
1257         int *errp;
1258         int match, nalias;
1259         char *p, *line, *addrstr, *cname;
1260         FILE *fp;
1261         struct hostent *rethp, *hp, hpbuf;
1262         char *aliases[MAXALIASES + 1], *addrs[2];
1263         union inx_addr addrbuf;
1264         char buf[BUFSIZ];
1265
1266         name = va_arg(ap, const char *);
1267         af = va_arg(ap, int);
1268         errp = va_arg(ap, int *);
1269
1270         *(struct hostent **)rval = NULL;
1271
1272         if ((fp = _files_open(errp)) == NULL)
1273                 return NS_UNAVAIL;
1274         rethp = hp = NULL;
1275
1276         while (fgets(buf, sizeof(buf), fp)) {
1277                 line = buf;
1278                 if ((addrstr = _hgetword(&line)) == NULL
1279                 ||  (cname = _hgetword(&line)) == NULL)
1280                         continue;
1281                 match = (strcasecmp(cname, name) == 0);
1282                 nalias = 0;
1283                 while ((p = _hgetword(&line)) != NULL) {
1284                         if (!match)
1285                                 match = (strcasecmp(p, name) == 0);
1286                         if (nalias < MAXALIASES)
1287                                 aliases[nalias++] = p;
1288                 }
1289                 if (!match)
1290                         continue;
1291                 switch (af) {
1292                 case AF_INET:
1293                         if (inet_aton(addrstr, (struct in_addr *)&addrbuf)
1294                             != 1) {
1295                                 *errp = NO_DATA;        /* name found */
1296                                 continue;
1297                         }
1298                         break;
1299 #ifdef INET6
1300                 case AF_INET6:
1301                         if (inet_pton(af, addrstr, &addrbuf) != 1) {
1302                                 *errp = NO_DATA;        /* name found */
1303                                 continue;
1304                         }
1305                         break;
1306 #endif
1307                 }
1308                 hp = &hpbuf;
1309                 hp->h_name = cname;
1310                 hp->h_aliases = aliases;
1311                 aliases[nalias] = NULL;
1312                 hp->h_addrtype = af;
1313                 hp->h_length = ADDRLEN(af);
1314                 hp->h_addr_list = addrs;
1315                 addrs[0] = (char *)&addrbuf;
1316                 addrs[1] = NULL;
1317                 hp = _hpcopy(hp, errp);
1318                 rethp = _hpmerge(rethp, hp, errp);
1319         }
1320         fclose(fp);
1321         *(struct hostent **)rval = rethp;
1322         return (rethp != NULL) ? NS_SUCCESS : NS_NOTFOUND;
1323 }
1324
1325 static int
1326 _files_ghbyaddr(void *rval, void *cb_data, va_list ap)
1327 {
1328         const void *addr; 
1329         int addrlen; 
1330         int af; 
1331         int *errp;
1332         int nalias;
1333         char *p, *line;
1334         FILE *fp;
1335         struct hostent *hp, hpbuf;
1336         char *aliases[MAXALIASES + 1], *addrs[2];
1337         union inx_addr addrbuf;
1338         char buf[BUFSIZ];
1339
1340         addr = va_arg(ap, const void *);
1341         addrlen = va_arg(ap, int);
1342         af = va_arg(ap, int);
1343         errp = va_arg(ap, int *);
1344
1345         *(struct hostent**)rval = NULL;
1346
1347         if ((fp = _files_open(errp)) == NULL)
1348                 return NS_UNAVAIL;
1349         hp = NULL;
1350         while (fgets(buf, sizeof(buf), fp)) {
1351                 line = buf;
1352                 if ((p = _hgetword(&line)) == NULL
1353                 ||  (af == AF_INET
1354                      ? inet_aton(p, (struct in_addr *)&addrbuf)
1355                      : inet_pton(af, p, &addrbuf)) != 1
1356                 ||  memcmp(addr, &addrbuf, addrlen) != 0
1357                 ||  (p = _hgetword(&line)) == NULL)
1358                         continue;
1359                 hp = &hpbuf;
1360                 hp->h_name = p;
1361                 hp->h_aliases = aliases;
1362                 nalias = 0;
1363                 while ((p = _hgetword(&line)) != NULL) {
1364                         if (nalias < MAXALIASES)
1365                                 aliases[nalias++] = p;
1366                 }
1367                 aliases[nalias] = NULL;
1368                 hp->h_addrtype = af;
1369                 hp->h_length = addrlen;
1370                 hp->h_addr_list = addrs;
1371                 addrs[0] = (char *)&addrbuf;
1372                 addrs[1] = NULL;
1373                 hp = _hpcopy(hp, errp);
1374                 break;
1375         }
1376         fclose(fp);
1377         *(struct hostent **)rval = hp;
1378         return (hp != NULL) ? NS_SUCCESS : NS_NOTFOUND;
1379 }
1380
1381 #ifdef YP
1382 /*
1383  * NIS
1384  *
1385  * XXX actually a hack.
1386  */
1387 static int
1388 _nis_ghbyname(void *rval, void *cb_data, va_list ap)
1389 {
1390         const char *name;
1391         int af;
1392         int *errp;
1393         struct hostent *hp = NULL;
1394
1395         name = va_arg(ap, const char *);
1396         af = va_arg(ap, int);
1397         errp = va_arg(ap, int *);
1398
1399         hp = _gethostbynisname(name, af);
1400         if (hp != NULL)
1401                 hp = _hpcopy(hp, errp);
1402
1403         *(struct hostent **)rval = hp;
1404         return (hp != NULL) ? NS_SUCCESS : NS_NOTFOUND;
1405 }
1406
1407 static int
1408 _nis_ghbyaddr(void *rval, void *cb_data, va_list ap)
1409 {
1410         const void *addr;
1411         int addrlen;
1412         int af;
1413         int *errp;
1414         struct hostent *hp = NULL;
1415
1416         addr = va_arg(ap, const void *);
1417         addrlen = va_arg(ap, int);
1418         af = va_arg(ap, int);
1419
1420         hp = _gethostbynisaddr(addr, addrlen, af);
1421         if (hp != NULL)
1422                 hp = _hpcopy(hp, errp);
1423         *(struct hostent **)rval = hp;
1424         return (hp != NULL) ? NS_SUCCESS : NS_NOTFOUND;
1425 }
1426 #endif
1427
1428 #define MAXPACKET       (64*1024)
1429
1430 typedef union {
1431         HEADER hdr;
1432         u_char buf[MAXPACKET];
1433 } querybuf;
1434
1435 static struct hostent *getanswer(const querybuf *, int, const char *, int,
1436             struct hostent *, int *);
1437
1438 /*
1439  * we don't need to take care about sorting, nor IPv4 mapped address here.
1440  */
1441 static struct hostent *
1442 getanswer(answer, anslen, qname, qtype, template, errp)
1443         const querybuf *answer;
1444         int anslen;
1445         const char *qname;
1446         int qtype;
1447         struct hostent *template;
1448         int *errp;
1449 {
1450         const HEADER *hp;
1451         const u_char *cp;
1452         int n;
1453         const u_char *eom, *erdata;
1454         char *bp, *ep, **ap, **hap;
1455         int type, class, ancount, qdcount;
1456         int haveanswer, had_error;
1457         char tbuf[MAXDNAME];
1458         const char *tname;
1459         int (*name_ok)(const char *);
1460         static char *h_addr_ptrs[MAXADDRS + 1];
1461         static char *host_aliases[MAXALIASES];
1462         static char hostbuf[8*1024];
1463
1464 #define BOUNDED_INCR(x) \
1465         do { \
1466                 cp += x; \
1467                 if (cp > eom) { \
1468                         *errp = NO_RECOVERY; \
1469                         return (NULL); \
1470                 } \
1471         } while (0)
1472
1473 #define BOUNDS_CHECK(ptr, count) \
1474         do { \
1475                 if ((ptr) + (count) > eom) { \
1476                         *errp = NO_RECOVERY; \
1477                         return (NULL); \
1478                 } \
1479         } while (0)
1480
1481 /* XXX do {} while (0) cannot be put here */
1482 #define DNS_ASSERT(x) \
1483         {                               \
1484                 if (!(x)) {             \
1485                         cp += n;        \
1486                         continue;       \
1487                 }                       \
1488         }
1489
1490 /* XXX do {} while (0) cannot be put here */
1491 #define DNS_FATAL(x) \
1492         {                               \
1493                 if (!(x)) {             \
1494                         had_error++;    \
1495                         continue;       \
1496                 }                       \
1497         }
1498
1499         tname = qname;
1500         template->h_name = NULL;
1501         eom = answer->buf + anslen;
1502         switch (qtype) {
1503         case T_A:
1504         case T_AAAA:
1505                 name_ok = res_hnok;
1506                 break;
1507         case T_PTR:
1508                 name_ok = res_dnok;
1509                 break;
1510         default:
1511                 return (NULL);  /* XXX should be abort(); */
1512         }
1513         /*
1514          * find first satisfactory answer
1515          */
1516         hp = &answer->hdr;
1517         ancount = ntohs(hp->ancount);
1518         qdcount = ntohs(hp->qdcount);
1519         bp = hostbuf;
1520         ep = hostbuf + sizeof hostbuf;
1521         cp = answer->buf;
1522         BOUNDED_INCR(HFIXEDSZ);
1523         if (qdcount != 1) {
1524                 *errp = NO_RECOVERY;
1525                 return (NULL);
1526         }
1527         n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
1528         if ((n < 0) || !(*name_ok)(bp)) {
1529                 *errp = NO_RECOVERY;
1530                 return (NULL);
1531         }
1532         BOUNDED_INCR(n + QFIXEDSZ);
1533         if (qtype == T_A || qtype == T_AAAA) {
1534                 /* res_send() has already verified that the query name is the
1535                  * same as the one we sent; this just gets the expanded name
1536                  * (i.e., with the succeeding search-domain tacked on).
1537                  */
1538                 n = strlen(bp) + 1;             /* for the \0 */
1539                 if (n >= MAXHOSTNAMELEN) {
1540                         *errp = NO_RECOVERY;
1541                         return (NULL);
1542                 }
1543                 template->h_name = bp;
1544                 bp += n;
1545                 /* The qname can be abbreviated, but h_name is now absolute. */
1546                 qname = template->h_name;
1547         }
1548         ap = host_aliases;
1549         *ap = NULL;
1550         template->h_aliases = host_aliases;
1551         hap = h_addr_ptrs;
1552         *hap = NULL;
1553         template->h_addr_list = h_addr_ptrs;
1554         haveanswer = 0;
1555         had_error = 0;
1556         while (ancount-- > 0 && cp < eom && !had_error) {
1557                 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
1558                 DNS_FATAL(n >= 0);
1559                 DNS_FATAL((*name_ok)(bp));
1560                 cp += n;                        /* name */
1561                 BOUNDS_CHECK(cp, 3 * INT16SZ + INT32SZ);
1562                 type = _getshort(cp);
1563                 cp += INT16SZ;                  /* type */
1564                 class = _getshort(cp);
1565                 cp += INT16SZ + INT32SZ;        /* class, TTL */
1566                 n = _getshort(cp);
1567                 cp += INT16SZ;                  /* len */
1568                 BOUNDS_CHECK(cp, n);
1569                 erdata = cp + n;
1570                 DNS_ASSERT(class == C_IN);
1571                 if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) {
1572                         if (ap >= &host_aliases[MAXALIASES-1])
1573                                 continue;
1574                         n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
1575                         DNS_FATAL(n >= 0);
1576                         DNS_FATAL((*name_ok)(tbuf));
1577                         cp += n;
1578                         if (cp != erdata) {
1579                                 *errp = NO_RECOVERY;
1580                                 return (NULL);
1581                         }
1582                         /* Store alias. */
1583                         *ap++ = bp;
1584                         n = strlen(bp) + 1;     /* for the \0 */
1585                         DNS_FATAL(n < MAXHOSTNAMELEN);
1586                         bp += n;
1587                         /* Get canonical name. */
1588                         n = strlen(tbuf) + 1;   /* for the \0 */
1589                         DNS_FATAL(n <= ep - bp);
1590                         DNS_FATAL(n < MAXHOSTNAMELEN);
1591                         strcpy(bp, tbuf);
1592                         template->h_name = bp;
1593                         bp += n;
1594                         continue;
1595                 }
1596                 if (qtype == T_PTR && type == T_CNAME) {
1597                         n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
1598                         if (n < 0 || !res_dnok(tbuf)) {
1599                                 had_error++;
1600                                 continue;
1601                         }
1602                         cp += n;
1603                         if (cp != erdata) {
1604                                 *errp = NO_RECOVERY;
1605                                 return (NULL);
1606                         }
1607                         /* Get canonical name. */
1608                         n = strlen(tbuf) + 1;   /* for the \0 */
1609                         if (n > ep - bp || n >= MAXHOSTNAMELEN) {
1610                                 had_error++;
1611                                 continue;
1612                         }
1613                         strcpy(bp, tbuf);
1614                         tname = bp;
1615                         bp += n;
1616                         continue;
1617                 }
1618                 DNS_ASSERT(type == qtype);
1619                 switch (type) {
1620                 case T_PTR:
1621                         DNS_ASSERT(strcasecmp(tname, bp) == 0);
1622                         n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
1623                         DNS_FATAL(n >= 0);
1624                         DNS_FATAL(res_hnok(bp));
1625 #if MULTI_PTRS_ARE_ALIASES
1626                         cp += n;
1627                         if (cp != erdata) {
1628                                 *errp = NO_RECOVERY;
1629                                 return (NULL);
1630                         }
1631                         if (!haveanswer)
1632                                 template->h_name = bp;
1633                         else if (ap < &host_aliases[MAXALIASES-1])
1634                                 *ap++ = bp;
1635                         else
1636                                 n = -1;
1637                         if (n != -1) {
1638                                 n = strlen(bp) + 1;     /* for the \0 */
1639                                 if (n >= MAXHOSTNAMELEN) {
1640                                         had_error++;
1641                                         break;
1642                                 }
1643                                 bp += n;
1644                         }
1645                         break;
1646 #else
1647                         template->h_name = bp;
1648                         *errp = NETDB_SUCCESS;
1649                         return (template);
1650 #endif
1651                 case T_A:
1652                 case T_AAAA:
1653                         DNS_ASSERT(strcasecmp(template->h_name, bp) == 0);
1654                         DNS_ASSERT(n == template->h_length);
1655                         if (!haveanswer) {
1656                                 int nn;
1657
1658                                 template->h_name = bp;
1659                                 nn = strlen(bp) + 1;    /* for the \0 */
1660                                 bp += nn;
1661                         }
1662                         bp = (char *)ALIGN(bp);
1663
1664                         DNS_FATAL(bp + n < ep);
1665                         DNS_ASSERT(hap < &h_addr_ptrs[MAXADDRS-1]);
1666 #ifdef FILTER_V4MAPPED
1667                         if (type == T_AAAA) {
1668                                 struct in6_addr in6;
1669                                 memcpy(&in6, cp, sizeof(in6));
1670                                 DNS_ASSERT(IN6_IS_ADDR_V4MAPPED(&in6) == 0);
1671                         }
1672 #endif
1673                         bcopy(cp, *hap++ = bp, n);
1674                         bp += n;
1675                         cp += n;
1676                         if (cp != erdata) {
1677                                 *errp = NO_RECOVERY;
1678                                 return (NULL);
1679                         }
1680                         break;
1681                 default:
1682                         abort();
1683                 }
1684                 if (!had_error)
1685                         haveanswer++;
1686         }
1687         if (haveanswer) {
1688                 *ap = NULL;
1689                 *hap = NULL;
1690                 if (!template->h_name) {
1691                         n = strlen(qname) + 1;  /* for the \0 */
1692                         if (n > ep - bp || n >= MAXHOSTNAMELEN)
1693                                 goto no_recovery;
1694                         strcpy(bp, qname);
1695                         template->h_name = bp;
1696                         bp += n;
1697                 }
1698                 *errp = NETDB_SUCCESS;
1699                 return (template);
1700         }
1701  no_recovery:
1702         *errp = NO_RECOVERY;
1703         return (NULL);
1704
1705 #undef BOUNDED_INCR
1706 #undef BOUNDS_CHECK
1707 #undef DNS_ASSERT
1708 #undef DNS_FATAL
1709 }
1710
1711 static int
1712 _dns_ghbyname(void *rval, void *cb_data, va_list ap)
1713 {
1714         const char *name;
1715         int af;
1716         int *errp;
1717         int n;
1718         struct hostent *hp;
1719         int qtype;
1720         struct hostent hbuf;
1721         querybuf *buf;
1722         res_state statp;
1723
1724         name = va_arg(ap, const char *);
1725         af = va_arg(ap, int);
1726         errp = va_arg(ap, int *);
1727
1728         statp = __res_state();
1729
1730         memset(&hbuf, 0, sizeof(hbuf));
1731         hbuf.h_addrtype = af;
1732         hbuf.h_length = ADDRLEN(af);
1733
1734         switch (af) {
1735 #ifdef INET6
1736         case AF_INET6:
1737                 qtype = T_AAAA;
1738                 break;
1739 #endif
1740         case AF_INET:
1741                 qtype = T_A;
1742                 break;
1743         default:
1744                 *errp = NO_RECOVERY;
1745                 return NS_NOTFOUND;
1746         }
1747         buf = malloc(sizeof(*buf));
1748         if (buf == NULL) {
1749                 *errp = NETDB_INTERNAL;
1750                 return NS_UNAVAIL;
1751         }
1752         n = res_nsearch(statp, name, C_IN, qtype, buf->buf, sizeof(buf->buf));
1753         if (n < 0) {
1754                 free(buf);
1755                 *errp = statp->res_h_errno;
1756                 return NS_UNAVAIL;
1757         }
1758         hp = getanswer(buf, n, name, qtype, &hbuf, errp);
1759         free(buf);
1760         if (!hp) {
1761                 *errp = NO_RECOVERY;
1762                 return NS_NOTFOUND;
1763         }
1764         *(struct hostent **)rval = _hpcopy(&hbuf, errp);
1765         if (*(struct hostent **)rval != NULL)
1766                 return NS_SUCCESS;
1767         else if (*errp == TRY_AGAIN)
1768                 return NS_TRYAGAIN;
1769         else
1770                 return NS_NOTFOUND;
1771 }
1772
1773 static int
1774 _dns_ghbyaddr(void *rval, void *cb_data, va_list ap)
1775 {
1776         const void *addr;
1777         int addrlen;
1778         int af;
1779         int *errp;
1780         int n;
1781         int err;
1782         struct hostent *hp;
1783         u_char c, *cp;
1784         char *bp;
1785         struct hostent hbuf;
1786 #ifdef INET6
1787         static const char hex[] = "0123456789abcdef";
1788 #endif
1789         querybuf *buf;
1790         char qbuf[MAXDNAME+1];
1791         char *hlist[2];
1792         char *tld6[] = { "ip6.arpa", NULL };
1793         char *tld4[] = { "in-addr.arpa", NULL };
1794         char **tld;
1795         res_state statp;
1796
1797         addr = va_arg(ap, const void *);
1798         addrlen = va_arg(ap, int);
1799         af = va_arg(ap, int);
1800         errp = va_arg(ap, int *);
1801
1802         *(struct hostent **)rval = NULL;
1803
1804 #ifdef INET6
1805         /* XXX */
1806         if (af == AF_INET6 && IN6_IS_ADDR_LINKLOCAL((struct in6_addr *)addr))
1807                 return NS_NOTFOUND;
1808 #endif
1809
1810         switch (af) {
1811 #ifdef INET6
1812         case AF_INET6:
1813                 tld = tld6;
1814                 break;
1815 #endif
1816         case AF_INET:
1817                 tld = tld4;
1818                 break;
1819         default:
1820                 return NS_NOTFOUND;
1821         }
1822
1823         statp = __res_state();
1824         if ((statp->options & RES_INIT) == 0) {
1825                 if (res_ninit(statp) < 0) {
1826                         *errp = NETDB_INTERNAL;
1827                         return NS_UNAVAIL;
1828                 }
1829         }
1830         memset(&hbuf, 0, sizeof(hbuf));
1831         hbuf.h_name = NULL;
1832         hbuf.h_addrtype = af;
1833         hbuf.h_length = addrlen;
1834
1835         buf = malloc(sizeof(*buf));
1836         if (buf == NULL) {
1837                 *errp = NETDB_INTERNAL;
1838                 return NS_UNAVAIL;
1839         }
1840         err = NS_SUCCESS;
1841         for (/* nothing */; *tld; tld++) {
1842                 /*
1843                  * XXX assumes that MAXDNAME is big enough - error checks
1844                  * has been made by callers
1845                  */
1846                 n = 0;
1847                 bp = qbuf;
1848                 cp = (u_char *)addr+addrlen-1;
1849                 switch (af) {
1850 #ifdef INET6
1851                 case AF_INET6:
1852                         for (; n < addrlen; n++, cp--) {
1853                                 c = *cp;
1854                                 *bp++ = hex[c & 0xf];
1855                                 *bp++ = '.';
1856                                 *bp++ = hex[c >> 4];
1857                                 *bp++ = '.';
1858                         }
1859                         strcpy(bp, *tld);
1860                         break;
1861 #endif
1862                 case AF_INET:
1863                         for (; n < addrlen; n++, cp--) {
1864                                 c = *cp;
1865                                 if (c >= 100)
1866                                         *bp++ = '0' + c / 100;
1867                                 if (c >= 10)
1868                                         *bp++ = '0' + (c % 100) / 10;
1869                                 *bp++ = '0' + c % 10;
1870                                 *bp++ = '.';
1871                         }
1872                         strcpy(bp, *tld);
1873                         break;
1874                 }
1875
1876                 n = res_nquery(statp, qbuf, C_IN, T_PTR, buf->buf,
1877                     sizeof buf->buf);
1878                 if (n < 0) {
1879                         *errp = statp->res_h_errno;
1880                         err = NS_UNAVAIL;
1881                         continue;
1882                 } else if (n > sizeof(buf->buf)) {
1883 #if 0
1884                         errno = ERANGE; /* XXX is it OK to set errno here? */
1885 #endif
1886                         *errp = NETDB_INTERNAL;
1887                         err = NS_UNAVAIL;
1888                         continue;
1889                 }
1890                 hp = getanswer(buf, n, qbuf, T_PTR, &hbuf, errp);
1891                 if (!hp) {
1892                         err = NS_NOTFOUND;
1893                         continue;
1894                 }
1895                 free(buf);
1896                 hbuf.h_addrtype = af;
1897                 hbuf.h_length = addrlen;
1898                 hbuf.h_addr_list = hlist;
1899                 hlist[0] = (char *)addr;
1900                 hlist[1] = NULL;
1901                 *(struct hostent **)rval = _hpcopy(&hbuf, errp);
1902                 return NS_SUCCESS;
1903         }
1904         free(buf);
1905         return err;
1906 }
1907
1908 static void
1909 _dns_shent(int stayopen)
1910 {
1911         res_state statp;
1912
1913         statp = __res_state();
1914         if ((statp->options & RES_INIT) == 0) {
1915                 if (res_ninit(statp) < 0)
1916                         return;
1917         }
1918         if (stayopen)
1919                 statp->options |= RES_STAYOPEN | RES_USEVC;
1920 }
1921
1922 static void
1923 _dns_ehent(void)
1924 {
1925         res_state statp;
1926
1927         statp = __res_state();
1928         statp->options &= ~(RES_STAYOPEN | RES_USEVC);
1929         res_nclose(statp);
1930 }
1931
1932 #ifdef ICMPNL
1933
1934 /*
1935  * experimental:
1936  *      draft-ietf-ipngwg-icmp-namelookups-02.txt
1937  *      ifindex is assumed to be encoded in addr.
1938  */
1939 #include <sys/uio.h>
1940 #include <netinet/ip6.h>
1941 #include <netinet/icmp6.h>
1942
1943 struct _icmp_host_cache {
1944         struct _icmp_host_cache *hc_next;
1945         int hc_ifindex;
1946         struct in6_addr hc_addr;
1947         char *hc_name;
1948 };
1949
1950 static char *
1951 _icmp_fqdn_query(const struct in6_addr *addr, int ifindex)
1952 {
1953         int s;
1954         struct icmp6_filter filter;
1955         struct msghdr msg;
1956         struct cmsghdr *cmsg;
1957         struct in6_pktinfo *pkt;
1958         char cbuf[256];
1959         char buf[1024];
1960         int cc;
1961         struct icmp6_fqdn_query *fq;
1962         struct icmp6_fqdn_reply *fr;
1963         struct _icmp_host_cache *hc;
1964         struct sockaddr_in6 sin6;
1965         struct iovec iov;
1966         fd_set s_fds, fds;
1967         struct timeval tout;
1968         int len;
1969         char *name;
1970         static struct _icmp_host_cache *hc_head;
1971
1972         THREAD_LOCK();
1973         for (hc = hc_head; hc; hc = hc->hc_next) {
1974                 if (hc->hc_ifindex == ifindex
1975                 &&  IN6_ARE_ADDR_EQUAL(&hc->hc_addr, addr)) {
1976                         THREAD_UNLOCK();
1977                         return hc->hc_name;     /* XXX: never freed */
1978                 }
1979         }
1980         THREAD_UNLOCK();
1981
1982         ICMP6_FILTER_SETBLOCKALL(&filter);
1983         ICMP6_FILTER_SETPASS(ICMP6_FQDN_REPLY, &filter);
1984
1985         FD_ZERO(&s_fds);
1986         tout.tv_sec = 0;
1987         tout.tv_usec = 200000;  /*XXX: 200ms*/
1988
1989         fq = (struct icmp6_fqdn_query *)buf;
1990         fq->icmp6_fqdn_type = ICMP6_FQDN_QUERY;
1991         fq->icmp6_fqdn_code = 0;
1992         fq->icmp6_fqdn_cksum = 0;
1993         fq->icmp6_fqdn_id = (u_short)getpid();
1994         fq->icmp6_fqdn_unused = 0;
1995         fq->icmp6_fqdn_cookie[0] = 0;
1996         fq->icmp6_fqdn_cookie[1] = 0;
1997
1998         memset(&sin6, 0, sizeof(sin6));
1999         sin6.sin6_family = AF_INET6;
2000         sin6.sin6_addr = *addr;
2001
2002         memset(&msg, 0, sizeof(msg));
2003         msg.msg_name = (caddr_t)&sin6;
2004         msg.msg_namelen = sizeof(sin6);
2005         msg.msg_iov = &iov;
2006         msg.msg_iovlen = 1;
2007         msg.msg_control = NULL;
2008         msg.msg_controllen = 0;
2009         iov.iov_base = (caddr_t)buf;
2010         iov.iov_len = sizeof(struct icmp6_fqdn_query);
2011
2012         if (ifindex) {
2013                 msg.msg_control = cbuf;
2014                 msg.msg_controllen = sizeof(cbuf);
2015                 cmsg = CMSG_FIRSTHDR(&msg);
2016                 cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
2017                 cmsg->cmsg_level = IPPROTO_IPV6;
2018                 cmsg->cmsg_type = IPV6_PKTINFO;
2019                 pkt = (struct in6_pktinfo *)&cmsg[1];
2020                 memset(&pkt->ipi6_addr, 0, sizeof(struct in6_addr));
2021                 pkt->ipi6_ifindex = ifindex;
2022                 cmsg = CMSG_NXTHDR(&msg, cmsg);
2023                 msg.msg_controllen = (char *)cmsg - cbuf;
2024         }
2025
2026         if ((s = _socket(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0)
2027                 return NULL;
2028         (void)_setsockopt(s, IPPROTO_ICMPV6, ICMP6_FILTER,
2029                          (char *)&filter, sizeof(filter));
2030         cc = _sendmsg(s, &msg, 0);
2031         if (cc < 0) {
2032                 _close(s);
2033                 return NULL;
2034         }
2035         FD_SET(s, &s_fds);
2036         for (;;) {
2037                 fds = s_fds;
2038                 if (_select(s + 1, &fds, NULL, NULL, &tout) <= 0) {
2039                         _close(s);
2040                         return NULL;
2041                 }
2042                 len = sizeof(sin6);
2043                 cc = _recvfrom(s, buf, sizeof(buf), 0,
2044                               (struct sockaddr *)&sin6, &len);
2045                 if (cc <= 0) {
2046                         _close(s);
2047                         return NULL;
2048                 }
2049                 if (cc < sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr))
2050                         continue;
2051                 if (!IN6_ARE_ADDR_EQUAL(addr, &sin6.sin6_addr))
2052                         continue;
2053                 fr = (struct icmp6_fqdn_reply *)(buf + sizeof(struct ip6_hdr));
2054                 if (fr->icmp6_fqdn_type == ICMP6_FQDN_REPLY)
2055                         break;
2056         }
2057         _close(s);
2058         if (fr->icmp6_fqdn_cookie[1] != 0) {
2059                 /* rfc1788 type */
2060                 name = buf + sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr) + 4;
2061                 len = (buf + cc) - name;
2062         } else {
2063                 len = fr->icmp6_fqdn_namelen;
2064                 name = fr->icmp6_fqdn_name;
2065         }
2066         if (len <= 0)
2067                 return NULL;
2068         name[len] = 0;
2069
2070         if ((hc = (struct _icmp_host_cache *)malloc(sizeof(*hc))) == NULL)
2071                 return NULL;
2072         /* XXX: limit number of cached entries */
2073         hc->hc_ifindex = ifindex;
2074         hc->hc_addr = *addr;
2075         hc->hc_name = strdup(name);
2076         THREAD_LOCK();
2077         hc->hc_next = hc_head;
2078         hc_head = hc;
2079         THREAD_UNLOCK();
2080         return hc->hc_name;
2081 }
2082
2083 static struct hostent *
2084 _icmp_ghbyaddr(const void *addr, int addrlen, int af, int *errp)
2085 {
2086         char *hname;
2087         int ifindex;
2088         struct in6_addr addr6;
2089
2090         if (af != AF_INET6) {
2091                 /*
2092                  * Note: rfc1788 defines Who Are You for IPv4,
2093                  * but no one implements it.
2094                  */
2095                 return NULL;
2096         }
2097
2098         memcpy(&addr6, addr, addrlen);
2099         ifindex = (addr6.s6_addr[2] << 8) | addr6.s6_addr[3];
2100         addr6.s6_addr[2] = addr6.s6_addr[3] = 0;
2101
2102         if (!IN6_IS_ADDR_LINKLOCAL(&addr6))
2103                 return NULL;    /*XXX*/
2104
2105         if ((hname = _icmp_fqdn_query(&addr6, ifindex)) == NULL)
2106                 return NULL;
2107         return _hpaddr(af, hname, &addr6, errp);
2108 }
2109 #endif /* ICMPNL */