1 /* The Inner Net License, Version 2.00
3 The author(s) grant permission for redistribution and use in source and
4 binary forms, with or without modification, of the software and documentation
5 provided that the following conditions are met:
7 0. If you receive a version of the software that is specifically labelled
8 as not being for redistribution (check the version message and/or README),
9 you are not permitted to redistribute that version of the software in any
11 1. All terms of the all other applicable copyrights and licenses must be
13 2. Redistributions of source code must retain the authors' copyright
14 notice(s), this list of conditions, and the following disclaimer.
15 3. Redistributions in binary form must reproduce the authors' copyright
16 notice(s), this list of conditions, and the following disclaimer in the
17 documentation and/or other materials provided with the distribution.
18 4. [The copyright holder has authorized the removal of this clause.]
19 5. Neither the name(s) of the author(s) nor the names of its contributors
20 may be used to endorse or promote products derived from this software
21 without specific prior written permission.
23 THIS SOFTWARE IS PROVIDED BY ITS AUTHORS AND CONTRIBUTORS ``AS IS'' AND ANY
24 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY
27 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
30 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 If these license terms cause you a real problem, contact the author. */
36 /* This software is Copyright 1996 by Craig Metz, All Rights Reserved. */
47 #include <stdio_ext.h>
50 #include <arpa/inet.h>
52 #include <netinet/in.h>
53 #include <sys/socket.h>
55 #include <sys/types.h>
57 #include <sys/utsname.h>
60 #include <bits/libc-lock.h>
61 #include <not-cancel.h>
62 #include <nscd/nscd-client.h>
63 #include <nscd/nscd_proto.h>
64 #include <resolv/res_hconf.h>
67 extern int __idna_to_ascii_lz (const char *input
, char **output
, int flags
);
68 extern int __idna_to_unicode_lzlz (const char *input
, char **output
,
70 # include <libidn/idna.h>
73 #define GAIH_OKIFUNSPEC 0x0100
74 #define GAIH_EAI ~(GAIH_OKIFUNSPEC)
77 # define UNIX_PATH_MAX 108
88 struct gaih_servtuple
*next
;
94 static const struct gaih_servtuple nullserv
;
106 /* Values for `protoflag'. */
107 #define GAI_PROTO_NOSERVICE 1
108 #define GAI_PROTO_PROTOANY 2
110 static const struct gaih_typeproto gaih_inet_typeproto
[] =
112 { 0, 0, 0, false, "" },
113 { SOCK_STREAM
, IPPROTO_TCP
, 0, true, "tcp" },
114 { SOCK_DGRAM
, IPPROTO_UDP
, 0, true, "udp" },
115 #if defined SOCK_DCCP && defined IPPROTO_DCCP
116 { SOCK_DCCP
, IPPROTO_DCCP
, 0, false, "dccp" },
118 #ifdef IPPROTO_UDPLITE
119 { SOCK_DGRAM
, IPPROTO_UDPLITE
, 0, false, "udplite" },
122 { SOCK_STREAM
, IPPROTO_SCTP
, 0, false, "sctp" },
123 { SOCK_SEQPACKET
, IPPROTO_SCTP
, 0, false, "sctp" },
125 { SOCK_RAW
, 0, GAI_PROTO_PROTOANY
|GAI_PROTO_NOSERVICE
, true, "raw" },
126 { 0, 0, 0, false, "" }
132 int (*gaih
)(const char *name
, const struct gaih_service
*service
,
133 const struct addrinfo
*req
, struct addrinfo
**pai
,
134 unsigned int *naddrs
);
137 static const struct addrinfo default_hints
=
139 .ai_flags
= AI_DEFAULT
,
140 .ai_family
= PF_UNSPEC
,
145 .ai_canonname
= NULL
,
151 gaih_inet_serv (const char *servicename
, const struct gaih_typeproto
*tp
,
152 const struct addrinfo
*req
, struct gaih_servtuple
*st
)
155 size_t tmpbuflen
= 1024;
162 tmpbuf
= __alloca (tmpbuflen
);
164 r
= __getservbyname_r (servicename
, tp
->name
, &ts
, tmpbuf
, tmpbuflen
,
166 if (r
!= 0 || s
== NULL
)
171 return GAIH_OKIFUNSPEC
| -EAI_SERVICE
;
177 st
->socktype
= tp
->socktype
;
178 st
->protocol
= ((tp
->protoflag
& GAI_PROTO_PROTOANY
)
179 ? req
->ai_protocol
: tp
->protocol
);
180 st
->port
= s
->s_port
;
185 #define gethosts(_family, _type) \
191 char *localcanon = NULL; \
195 status = DL_CALL_FCT (fct, (name, _family, &th, tmpbuf, tmpbuflen, \
196 &rc, &herrno, NULL, &localcanon)); \
197 if (rc != ERANGE || herrno != NETDB_INTERNAL) \
199 tmpbuf = extend_alloca (tmpbuf, tmpbuflen, 2 * tmpbuflen); \
201 if (status == NSS_STATUS_SUCCESS && rc == 0) \
207 if (herrno == NETDB_INTERNAL) \
209 __set_h_errno (herrno); \
210 _res.options = old_res_options; \
211 return -EAI_SYSTEM; \
213 if (herrno == TRY_AGAIN) \
214 no_data = EAI_AGAIN; \
216 no_data = herrno == NO_DATA; \
218 else if (h != NULL) \
220 for (i = 0; h->h_addr_list[i]; i++) \
224 *pat = __alloca (sizeof (struct gaih_addrtuple)); \
225 (*pat)->scopeid = 0; \
227 uint32_t *addr = (*pat)->addr; \
228 (*pat)->next = NULL; \
229 (*pat)->name = i == 0 ? strdupa (h->h_name) : NULL; \
230 if (_family == AF_INET && req->ai_family == AF_INET6) \
232 (*pat)->family = AF_INET6; \
233 addr[3] = *(uint32_t *) h->h_addr_list[i]; \
234 addr[2] = htonl (0xffff); \
240 (*pat)->family = _family; \
241 memcpy (addr, h->h_addr_list[i], sizeof(_type)); \
243 pat = &((*pat)->next); \
246 if (localcanon != NULL && canon == NULL) \
247 canon = strdupa (localcanon); \
249 if (_family == AF_INET6 && i > 0) \
255 typedef enum nss_status (*nss_gethostbyname4_r
)
256 (const char *name
, struct gaih_addrtuple
**pat
,
257 char *buffer
, size_t buflen
, int *errnop
,
258 int *h_errnop
, int32_t *ttlp
);
259 typedef enum nss_status (*nss_gethostbyname3_r
)
260 (const char *name
, int af
, struct hostent
*host
,
261 char *buffer
, size_t buflen
, int *errnop
,
262 int *h_errnop
, int32_t *ttlp
, char **canonp
);
263 typedef enum nss_status (*nss_getcanonname_r
)
264 (const char *name
, char *buffer
, size_t buflen
, char **result
,
265 int *errnop
, int *h_errnop
);
266 extern service_user
*__nss_hosts_database attribute_hidden
;
270 gaih_inet (const char *name
, const struct gaih_service
*service
,
271 const struct addrinfo
*req
, struct addrinfo
**pai
,
272 unsigned int *naddrs
)
274 const struct gaih_typeproto
*tp
= gaih_inet_typeproto
;
275 struct gaih_servtuple
*st
= (struct gaih_servtuple
*) &nullserv
;
276 struct gaih_addrtuple
*at
= NULL
;
278 bool got_ipv6
= false;
279 const char *canon
= NULL
;
280 const char *orig_name
= name
;
282 if (req
->ai_protocol
|| req
->ai_socktype
)
287 && ((req
->ai_socktype
!= 0 && req
->ai_socktype
!= tp
->socktype
)
288 || (req
->ai_protocol
!= 0
289 && !(tp
->protoflag
& GAI_PROTO_PROTOANY
)
290 && req
->ai_protocol
!= tp
->protocol
)))
295 if (req
->ai_socktype
)
296 return GAIH_OKIFUNSPEC
| -EAI_SOCKTYPE
;
298 return GAIH_OKIFUNSPEC
| -EAI_SERVICE
;
305 if ((tp
->protoflag
& GAI_PROTO_NOSERVICE
) != 0)
306 return GAIH_OKIFUNSPEC
| -EAI_SERVICE
;
308 if (service
->num
< 0)
312 st
= (struct gaih_servtuple
*)
313 __alloca (sizeof (struct gaih_servtuple
));
315 if ((rc
= gaih_inet_serv (service
->name
, tp
, req
, st
)))
320 struct gaih_servtuple
**pst
= &st
;
321 for (tp
++; tp
->name
[0]; tp
++)
323 struct gaih_servtuple
*newp
;
325 if ((tp
->protoflag
& GAI_PROTO_NOSERVICE
) != 0)
328 if (req
->ai_socktype
!= 0
329 && req
->ai_socktype
!= tp
->socktype
)
331 if (req
->ai_protocol
!= 0
332 && !(tp
->protoflag
& GAI_PROTO_PROTOANY
)
333 && req
->ai_protocol
!= tp
->protocol
)
336 newp
= (struct gaih_servtuple
*)
337 __alloca (sizeof (struct gaih_servtuple
));
339 if ((rc
= gaih_inet_serv (service
->name
, tp
, req
, newp
)))
341 if (rc
& GAIH_OKIFUNSPEC
)
349 if (st
== (struct gaih_servtuple
*) &nullserv
)
350 return GAIH_OKIFUNSPEC
| -EAI_SERVICE
;
355 port
= htons (service
->num
);
363 if (req
->ai_socktype
|| req
->ai_protocol
)
365 st
= __alloca (sizeof (struct gaih_servtuple
));
367 st
->socktype
= tp
->socktype
;
368 st
->protocol
= ((tp
->protoflag
& GAI_PROTO_PROTOANY
)
369 ? req
->ai_protocol
: tp
->protocol
);
374 /* Neither socket type nor protocol is set. Return all socket types
376 struct gaih_servtuple
**lastp
= &st
;
377 for (++tp
; tp
->name
[0]; ++tp
)
380 struct gaih_servtuple
*newp
;
382 newp
= __alloca (sizeof (struct gaih_servtuple
));
384 newp
->socktype
= tp
->socktype
;
385 newp
->protocol
= tp
->protocol
;
396 at
= __alloca (sizeof (struct gaih_addrtuple
));
398 at
->family
= AF_UNSPEC
;
403 if (req
->ai_flags
& AI_IDN
)
406 if (req
->ai_flags
& AI_IDN_ALLOW_UNASSIGNED
)
407 idn_flags
|= IDNA_ALLOW_UNASSIGNED
;
408 if (req
->ai_flags
& AI_IDN_USE_STD3_ASCII_RULES
)
409 idn_flags
|= IDNA_USE_STD3_ASCII_RULES
;
412 rc
= __idna_to_ascii_lz (name
, &p
, idn_flags
);
413 if (rc
!= IDNA_SUCCESS
)
415 if (rc
== IDNA_MALLOC_ERROR
)
417 if (rc
== IDNA_DLOPEN_ERROR
)
419 return -EAI_IDN_ENCODE
;
421 /* In case the output string is the same as the input string
422 no new string has been allocated. */
431 if (__inet_aton (name
, (struct in_addr
*) at
->addr
) != 0)
433 if (req
->ai_family
== AF_UNSPEC
|| req
->ai_family
== AF_INET
)
434 at
->family
= AF_INET
;
435 else if (req
->ai_family
== AF_INET6
&& (req
->ai_flags
& AI_V4MAPPED
))
437 at
->addr
[3] = at
->addr
[0];
438 at
->addr
[2] = htonl (0xffff);
441 at
->family
= AF_INET6
;
444 return -EAI_ADDRFAMILY
;
446 if (req
->ai_flags
& AI_CANONNAME
)
449 else if (at
->family
== AF_UNSPEC
)
451 char *namebuf
= (char *) name
;
452 char *scope_delim
= strchr (name
, SCOPE_DELIMITER
);
454 if (__builtin_expect (scope_delim
!= NULL
, 0))
456 namebuf
= alloca (scope_delim
- name
+ 1);
457 *((char *) __mempcpy (namebuf
, name
, scope_delim
- name
)) = '\0';
460 if (inet_pton (AF_INET6
, namebuf
, at
->addr
) > 0)
462 if (req
->ai_family
== AF_UNSPEC
|| req
->ai_family
== AF_INET6
)
463 at
->family
= AF_INET6
;
464 else if (req
->ai_family
== AF_INET
465 && IN6_IS_ADDR_V4MAPPED (at
->addr
))
467 at
->addr
[0] = at
->addr
[3];
468 at
->family
= AF_INET
;
471 return -EAI_ADDRFAMILY
;
473 if (scope_delim
!= NULL
)
475 int try_numericscope
= 0;
476 if (IN6_IS_ADDR_LINKLOCAL (at
->addr
)
477 || IN6_IS_ADDR_MC_LINKLOCAL (at
->addr
))
479 at
->scopeid
= if_nametoindex (scope_delim
+ 1);
480 if (at
->scopeid
== 0)
481 try_numericscope
= 1;
484 try_numericscope
= 1;
486 if (try_numericscope
!= 0)
489 assert (sizeof (uint32_t) <= sizeof (unsigned long));
490 at
->scopeid
= (uint32_t) strtoul (scope_delim
+ 1, &end
,
493 return GAIH_OKIFUNSPEC
| -EAI_NONAME
;
497 if (req
->ai_flags
& AI_CANONNAME
)
502 if (at
->family
== AF_UNSPEC
&& (req
->ai_flags
& AI_NUMERICHOST
) == 0)
504 struct gaih_addrtuple
**pat
= &at
;
506 int no_inet6_data
= 0;
507 service_user
*nip
= NULL
;
508 enum nss_status inet6_status
= NSS_STATUS_UNAVAIL
;
509 enum nss_status status
= NSS_STATUS_UNAVAIL
;
513 /* If we do not have to look for IPv4 and IPv6 together, use
514 the simple, old functions. */
515 if (req
->ai_family
== AF_INET
516 || (req
->ai_family
== AF_INET6
517 && ((req
->ai_flags
& AI_V4MAPPED
) == 0
518 || (req
->ai_flags
& AI_ALL
) == 0)))
520 int family
= req
->ai_family
;
521 size_t tmpbuflen
= 512;
522 char *tmpbuf
= alloca (tmpbuflen
);
531 rc
= __gethostbyname2_r (name
, family
, &th
, tmpbuf
,
532 tmpbuflen
, &h
, &herrno
);
533 if (rc
!= ERANGE
|| herrno
!= NETDB_INTERNAL
)
535 tmpbuf
= extend_alloca (tmpbuf
, tmpbuflen
, 2 * tmpbuflen
);
542 if (req
->ai_family
== AF_INET6
543 && (req
->ai_flags
& AI_V4MAPPED
)
544 && family
== AF_INET6
)
546 /* Try again, this time looking for IPv4
554 /* We found data, now convert it into the list. */
555 for (int i
= 0; h
->h_addr_list
[i
]; ++i
)
559 *pat
= __alloca (sizeof (struct gaih_addrtuple
));
563 (*pat
)->family
= req
->ai_family
;
564 if (family
== req
->ai_family
)
565 memcpy ((*pat
)->addr
, h
->h_addr_list
[i
],
569 uint32_t *addr
= (uint32_t *) (*pat
)->addr
;
570 addr
[3] = *(uint32_t *) h
->h_addr_list
[i
];
571 addr
[2] = htonl (0xffff);
575 pat
= &((*pat
)->next
);
581 if (herrno
== NETDB_INTERNAL
)
583 __set_h_errno (herrno
);
586 if (herrno
== TRY_AGAIN
)
590 /* We made requests but they turned out no data.
591 The name is known, though. */
592 return GAIH_OKIFUNSPEC
| -EAI_NODATA
;
599 if (__nss_not_use_nscd_hosts
> 0
600 && ++__nss_not_use_nscd_hosts
> NSS_NSCD_RETRY
)
601 __nss_not_use_nscd_hosts
= 0;
603 if (!__nss_not_use_nscd_hosts
)
605 /* Try to use nscd. */
606 struct nscd_ai_result
*air
= NULL
;
608 int err
= __nscd_getai (name
, &air
, &herrno
);
611 /* Transform into gaih_addrtuple list. */
612 bool added_canon
= (req
->ai_flags
& AI_CANONNAME
) == 0;
613 char *addrs
= air
->addrs
;
615 for (int i
= 0; i
< air
->naddrs
; ++i
)
617 socklen_t size
= (air
->family
[i
] == AF_INET
618 ? INADDRSZ
: IN6ADDRSZ
);
621 *pat
= __alloca (sizeof (struct gaih_addrtuple
));
624 uint32_t *pataddr
= (*pat
)->addr
;
626 if (added_canon
|| air
->canon
== NULL
)
629 canon
= (*pat
)->name
= strdupa (air
->canon
);
631 if (air
->family
[i
] == AF_INET
632 && req
->ai_family
== AF_INET6
633 && (req
->ai_flags
& AI_V4MAPPED
))
635 (*pat
)->family
= AF_INET6
;
636 pataddr
[3] = *(uint32_t *) addrs
;
637 pataddr
[2] = htonl (0xffff);
640 pat
= &((*pat
)->next
);
643 else if (req
->ai_family
== AF_UNSPEC
644 || air
->family
[i
] == req
->ai_family
)
646 (*pat
)->family
= air
->family
[i
];
647 memcpy (pataddr
, addrs
, size
);
648 pat
= &((*pat
)->next
);
650 if (air
->family
[i
] == AF_INET6
)
658 if (at
->family
== AF_UNSPEC
)
659 return GAIH_OKIFUNSPEC
| -EAI_NONAME
;
663 else if (err
!= 0 && __nss_not_use_nscd_hosts
== 0)
665 if (herrno
== NETDB_INTERNAL
&& errno
== ENOMEM
)
667 if (herrno
== TRY_AGAIN
)
674 if (__nss_hosts_database
!= NULL
)
677 nip
= __nss_hosts_database
;
680 no_more
= __nss_database_lookup ("hosts", NULL
,
681 "dns [!UNAVAIL=return] files",
684 if (__res_maybe_init (&_res
, 0) == -1)
687 /* If we are looking for both IPv4 and IPv6 address we don't
688 want the lookup functions to automatically promote IPv4
689 addresses to IPv6 addresses. Currently this is decided
690 by setting the RES_USE_INET6 bit in _res.options. */
691 old_res_options
= _res
.options
;
692 _res
.options
&= ~RES_USE_INET6
;
694 size_t tmpbuflen
= 512;
695 char *tmpbuf
= alloca (tmpbuflen
);
699 nss_gethostbyname4_r fct4
700 = __nss_lookup_function (nip
, "gethostbyname4_r");
708 status
= DL_CALL_FCT (fct4
, (name
, pat
, tmpbuf
,
709 tmpbuflen
, &rc
, &herrno
,
711 if (status
!= NSS_STATUS_TRYAGAIN
712 || rc
!= ERANGE
|| herrno
!= NETDB_INTERNAL
)
714 if (herrno
== NETDB_INTERNAL
)
716 __set_h_errno (herrno
);
717 _res
.options
= old_res_options
;
720 if (herrno
== TRY_AGAIN
)
723 no_data
= herrno
== NO_DATA
;
726 tmpbuf
= extend_alloca (tmpbuf
,
727 tmpbuflen
, 2 * tmpbuflen
);
730 if (status
== NSS_STATUS_SUCCESS
)
732 canon
= (*pat
)->name
;
735 pat
= &((*pat
)->next
);
740 nss_gethostbyname3_r fct
= NULL
;
741 if (req
->ai_flags
& AI_CANONNAME
)
742 /* No need to use this function if we do not look for
743 the canonical name. The function does not exist in
744 all NSS modules and therefore the lookup would
746 fct
= __nss_lookup_function (nip
, "gethostbyname3_r");
748 /* We are cheating here. The gethostbyname2_r
749 function does not have the same interface as
750 gethostbyname3_r but the extra arguments the
751 latter takes are added at the end. So the
752 gethostbyname2_r code will just ignore them. */
753 fct
= __nss_lookup_function (nip
, "gethostbyname2_r");
757 if (req
->ai_family
== AF_INET6
758 || req
->ai_family
== AF_UNSPEC
)
760 gethosts (AF_INET6
, struct in6_addr
);
761 no_inet6_data
= no_data
;
762 inet6_status
= status
;
764 if (req
->ai_family
== AF_INET
765 || req
->ai_family
== AF_UNSPEC
766 || (req
->ai_family
== AF_INET6
767 && (req
->ai_flags
& AI_V4MAPPED
)
768 /* Avoid generating the mapped addresses if we
769 know we are not going to need them. */
770 && ((req
->ai_flags
& AI_ALL
) || !got_ipv6
)))
772 gethosts (AF_INET
, struct in_addr
);
774 if (req
->ai_family
== AF_INET
)
776 no_inet6_data
= no_data
;
777 inet6_status
= status
;
781 /* If we found one address for AF_INET or AF_INET6,
782 don't continue the search. */
783 if (inet6_status
== NSS_STATUS_SUCCESS
784 || status
== NSS_STATUS_SUCCESS
)
786 if ((req
->ai_flags
& AI_CANONNAME
) != 0
789 /* If we need the canonical name, get it
790 from the same service as the result. */
791 nss_getcanonname_r cfct
;
794 cfct
= __nss_lookup_function (nip
,
798 const size_t max_fqdn_len
= 256;
799 char *buf
= alloca (max_fqdn_len
);
802 if (DL_CALL_FCT (cfct
, (at
->name
?: name
,
805 == NSS_STATUS_SUCCESS
)
808 /* Set to name now to avoid using
817 /* We can have different states for AF_INET and
818 AF_INET6. Try to find a useful one for both. */
819 if (inet6_status
== NSS_STATUS_TRYAGAIN
)
820 status
= NSS_STATUS_TRYAGAIN
;
821 else if (status
== NSS_STATUS_UNAVAIL
822 && inet6_status
!= NSS_STATUS_UNAVAIL
)
823 status
= inet6_status
;
827 if (nss_next_action (nip
, status
) == NSS_ACTION_RETURN
)
830 if (nip
->next
== NULL
)
836 _res
.options
= old_res_options
;
838 if (no_data
!= 0 && no_inet6_data
!= 0)
840 /* If both requests timed out report this. */
841 if (no_data
== EAI_AGAIN
&& no_inet6_data
== EAI_AGAIN
)
844 /* We made requests but they turned out no data. The name
846 return GAIH_OKIFUNSPEC
| -EAI_NODATA
;
851 if (at
->family
== AF_UNSPEC
)
852 return GAIH_OKIFUNSPEC
| -EAI_NONAME
;
856 struct gaih_addrtuple
*atr
;
857 atr
= at
= __alloca (sizeof (struct gaih_addrtuple
));
858 memset (at
, '\0', sizeof (struct gaih_addrtuple
));
860 if (req
->ai_family
== AF_UNSPEC
)
862 at
->next
= __alloca (sizeof (struct gaih_addrtuple
));
863 memset (at
->next
, '\0', sizeof (struct gaih_addrtuple
));
866 if (req
->ai_family
== AF_UNSPEC
|| req
->ai_family
== AF_INET6
)
868 at
->family
= AF_INET6
;
869 if ((req
->ai_flags
& AI_PASSIVE
) == 0)
870 memcpy (at
->addr
, &in6addr_loopback
, sizeof (struct in6_addr
));
874 if (req
->ai_family
== AF_UNSPEC
|| req
->ai_family
== AF_INET
)
876 atr
->family
= AF_INET
;
877 if ((req
->ai_flags
& AI_PASSIVE
) == 0)
878 atr
->addr
[0] = htonl (INADDR_LOOPBACK
);
886 struct gaih_servtuple
*st2
;
887 struct gaih_addrtuple
*at2
= at
;
892 buffer is the size of an unformatted IPv6 address in printable format.
896 /* Only the first entry gets the canonical name. */
897 if (at2
== at
&& (req
->ai_flags
& AI_CANONNAME
) != 0)
901 struct hostent
*h
= NULL
;
904 size_t tmpbuflen
= 512;
909 tmpbuf
= extend_alloca (tmpbuf
, tmpbuflen
, tmpbuflen
* 2);
910 rc
= __gethostbyaddr_r (at2
->addr
,
911 ((at2
->family
== AF_INET6
)
912 ? sizeof (struct in6_addr
)
913 : sizeof (struct in_addr
)),
914 at2
->family
, &th
, tmpbuf
,
915 tmpbuflen
, &h
, &herrno
);
917 while (rc
== ERANGE
&& herrno
== NETDB_INTERNAL
);
919 if (rc
!= 0 && herrno
== NETDB_INTERNAL
)
921 __set_h_errno (herrno
);
929 assert (orig_name
!= NULL
);
930 /* If the canonical name cannot be determined, use
931 the passed in string. */
937 if (req
->ai_flags
& AI_CANONIDN
)
940 if (req
->ai_flags
& AI_IDN_ALLOW_UNASSIGNED
)
941 idn_flags
|= IDNA_ALLOW_UNASSIGNED
;
942 if (req
->ai_flags
& AI_IDN_USE_STD3_ASCII_RULES
)
943 idn_flags
|= IDNA_USE_STD3_ASCII_RULES
;
946 int rc
= __idna_to_unicode_lzlz (canon
, &out
, idn_flags
);
947 if (rc
!= IDNA_SUCCESS
)
949 if (rc
== IDNA_MALLOC_ERROR
)
951 if (rc
== IDNA_DLOPEN_ERROR
)
953 return -EAI_IDN_ENCODE
;
955 /* In case the output string is the same as the input
956 string no new string has been allocated. Otherwise
967 canon
= strdup (canon
);
973 family
= at2
->family
;
974 if (family
== AF_INET6
)
976 socklen
= sizeof (struct sockaddr_in6
);
978 /* If we looked up IPv4 mapped address discard them here if
979 the caller isn't interested in all address and we have
980 found at least one IPv6 address. */
982 && (req
->ai_flags
& (AI_V4MAPPED
|AI_ALL
)) == AI_V4MAPPED
983 && IN6_IS_ADDR_V4MAPPED (at2
->addr
))
987 socklen
= sizeof (struct sockaddr_in
);
989 for (st2
= st
; st2
!= NULL
; st2
= st2
->next
)
992 ai
= *pai
= malloc (sizeof (struct addrinfo
) + socklen
);
995 free ((char *) canon
);
999 ai
->ai_flags
= req
->ai_flags
;
1000 ai
->ai_family
= family
;
1001 ai
->ai_socktype
= st2
->socktype
;
1002 ai
->ai_protocol
= st2
->protocol
;
1003 ai
->ai_addrlen
= socklen
;
1004 ai
->ai_addr
= (void *) (ai
+ 1);
1006 /* We only add the canonical name once. */
1007 ai
->ai_canonname
= (char *) canon
;
1011 ai
->ai_addr
->sa_len
= socklen
;
1012 #endif /* _HAVE_SA_LEN */
1013 ai
->ai_addr
->sa_family
= family
;
1015 /* In case of an allocation error the list must be NULL
1019 if (family
== AF_INET6
)
1021 struct sockaddr_in6
*sin6p
=
1022 (struct sockaddr_in6
*) ai
->ai_addr
;
1024 sin6p
->sin6_port
= st2
->port
;
1025 sin6p
->sin6_flowinfo
= 0;
1026 memcpy (&sin6p
->sin6_addr
,
1027 at2
->addr
, sizeof (struct in6_addr
));
1028 sin6p
->sin6_scope_id
= at2
->scopeid
;
1032 struct sockaddr_in
*sinp
=
1033 (struct sockaddr_in
*) ai
->ai_addr
;
1034 sinp
->sin_port
= st2
->port
;
1035 memcpy (&sinp
->sin_addr
,
1036 at2
->addr
, sizeof (struct in_addr
));
1037 memset (sinp
->sin_zero
, '\0', sizeof (sinp
->sin_zero
));
1040 pai
= &(ai
->ai_next
);
1055 struct addrinfo
*dest_addr
;
1056 /* Using sockaddr_storage is for now overkill. We only support IPv4
1057 and IPv6 so far. If this changes at some point we can adjust the
1059 struct sockaddr_in6 source_addr
;
1060 uint8_t source_addr_len
;
1061 bool got_source_addr
;
1062 uint8_t source_addr_flags
;
1068 struct sort_result_combo
1070 struct sort_result
*results
;
1075 #if __BYTE_ORDER == __BIG_ENDIAN
1076 # define htonl_c(n) n
1078 # define htonl_c(n) __bswap_constant_32 (n)
1081 static const struct scopeentry
1090 } default_scopes
[] =
1092 /* Link-local addresses: scope 2. */
1093 { { { 169, 254, 0, 0 } }, htonl_c (0xffff0000), 2 },
1094 { { { 127, 0, 0, 0 } }, htonl_c (0xff000000), 2 },
1095 /* Site-local addresses: scope 5. */
1096 { { { 10, 0, 0, 0 } }, htonl_c (0xff000000), 5 },
1097 { { { 172, 16, 0, 0 } }, htonl_c (0xfff00000), 5 },
1098 { { { 192, 168, 0, 0 } }, htonl_c (0xffff0000), 5 },
1099 /* Default: scope 14. */
1100 { { { 0, 0, 0, 0 } }, htonl_c (0x00000000), 14 }
1103 /* The label table. */
1104 static const struct scopeentry
*scopes
;
1108 get_scope (const struct sockaddr_in6
*in6
)
1111 if (in6
->sin6_family
== PF_INET6
)
1113 if (! IN6_IS_ADDR_MULTICAST (&in6
->sin6_addr
))
1115 if (IN6_IS_ADDR_LINKLOCAL (&in6
->sin6_addr
)
1116 /* RFC 4291 2.5.3 says that the loopback address is to be
1117 treated like a link-local address. */
1118 || IN6_IS_ADDR_LOOPBACK (&in6
->sin6_addr
))
1120 else if (IN6_IS_ADDR_SITELOCAL (&in6
->sin6_addr
))
1123 /* XXX Is this the correct default behavior? */
1127 scope
= in6
->sin6_addr
.s6_addr
[1] & 0xf;
1129 else if (in6
->sin6_family
== PF_INET
)
1131 const struct sockaddr_in
*in
= (const struct sockaddr_in
*) in6
;
1136 if ((in
->sin_addr
.s_addr
& scopes
[cnt
].netmask
)
1137 == scopes
[cnt
].addr32
)
1138 return scopes
[cnt
].scope
;
1145 /* XXX What is a good default? */
1154 struct in6_addr prefix
;
1160 /* The label table. */
1161 static const struct prefixentry
*labels
;
1163 /* Default labels. */
1164 static const struct prefixentry default_labels
[] =
1166 /* See RFC 3484 for the details. */
1168 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1169 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } }
1172 = { .__u6_addr8
= { 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1173 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1176 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1177 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1180 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1181 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 } }
1183 /* The next two entries differ from RFC 3484. We need to treat
1184 IPv6 site-local addresses special because they are never NATed,
1185 unlike site-locale IPv4 addresses. If this would not happen, on
1186 machines which have only IPv4 and IPv6 site-local addresses, the
1187 sorting would prefer the IPv6 site-local addresses, causing
1188 unnecessary delays when trying to connect to a global IPv6 address
1189 through a site-local IPv6 address. */
1191 = { .__u6_addr8
= { 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1192 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1195 = { .__u6_addr8
= { 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1196 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1198 /* Additional rule for Teredo tunnels. */
1200 = { .__u6_addr8
= { 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1201 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1204 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1205 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1210 /* The precedence table. */
1211 static const struct prefixentry
*precedence
;
1213 /* The default precedences. */
1214 static const struct prefixentry default_precedence
[] =
1216 /* See RFC 3484 for the details. */
1218 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1219 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } }
1222 = { .__u6_addr8
= { 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1223 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1226 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1227 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1230 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1231 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 } }
1234 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1235 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1241 match_prefix (const struct sockaddr_in6
*in6
,
1242 const struct prefixentry
*list
, int default_val
)
1245 struct sockaddr_in6 in6_mem
;
1247 if (in6
->sin6_family
== PF_INET
)
1249 const struct sockaddr_in
*in
= (const struct sockaddr_in
*) in6
;
1251 /* Construct a V4-to-6 mapped address. */
1252 in6_mem
.sin6_family
= PF_INET6
;
1253 in6_mem
.sin6_port
= in
->sin_port
;
1254 in6_mem
.sin6_flowinfo
= 0;
1255 memset (&in6_mem
.sin6_addr
, '\0', sizeof (in6_mem
.sin6_addr
));
1256 in6_mem
.sin6_addr
.s6_addr16
[5] = 0xffff;
1257 in6_mem
.sin6_addr
.s6_addr32
[3] = in
->sin_addr
.s_addr
;
1258 in6_mem
.sin6_scope_id
= 0;
1262 else if (in6
->sin6_family
!= PF_INET6
)
1265 for (idx
= 0; ; ++idx
)
1267 unsigned int bits
= list
[idx
].bits
;
1268 const uint8_t *mask
= list
[idx
].prefix
.s6_addr
;
1269 const uint8_t *val
= in6
->sin6_addr
.s6_addr
;
1283 if ((*mask
& (0xff00 >> bits
)) == (*val
& (0xff00 >> bits
)))
1289 return list
[idx
].val
;
1294 get_label (const struct sockaddr_in6
*in6
)
1296 /* XXX What is a good default value? */
1297 return match_prefix (in6
, labels
, INT_MAX
);
1302 get_precedence (const struct sockaddr_in6
*in6
)
1304 /* XXX What is a good default value? */
1305 return match_prefix (in6
, precedence
, 0);
1309 /* Find last bit set in a word. */
1315 for (n
= 0, mask
= 1 << 31; n
< 32; mask
>>= 1, ++n
)
1316 if ((a
& mask
) != 0)
1323 rfc3484_sort (const void *p1
, const void *p2
, void *arg
)
1325 const size_t idx1
= *(const size_t *) p1
;
1326 const size_t idx2
= *(const size_t *) p2
;
1327 struct sort_result_combo
*src
= (struct sort_result_combo
*) arg
;
1328 struct sort_result
*a1
= &src
->results
[idx1
];
1329 struct sort_result
*a2
= &src
->results
[idx2
];
1331 /* Rule 1: Avoid unusable destinations.
1332 We have the got_source_addr flag set if the destination is reachable. */
1333 if (a1
->got_source_addr
&& ! a2
->got_source_addr
)
1335 if (! a1
->got_source_addr
&& a2
->got_source_addr
)
1339 /* Rule 2: Prefer matching scope. Only interesting if both
1340 destination addresses are IPv6. */
1342 = get_scope ((struct sockaddr_in6
*) a1
->dest_addr
->ai_addr
);
1345 = get_scope ((struct sockaddr_in6
*) a2
->dest_addr
->ai_addr
);
1347 if (a1
->got_source_addr
)
1349 int a1_src_scope
= get_scope (&a1
->source_addr
);
1350 int a2_src_scope
= get_scope (&a2
->source_addr
);
1352 if (a1_dst_scope
== a1_src_scope
&& a2_dst_scope
!= a2_src_scope
)
1354 if (a1_dst_scope
!= a1_src_scope
&& a2_dst_scope
== a2_src_scope
)
1359 /* Rule 3: Avoid deprecated addresses. */
1360 if (a1
->got_source_addr
)
1362 if (!(a1
->source_addr_flags
& in6ai_deprecated
)
1363 && (a2
->source_addr_flags
& in6ai_deprecated
))
1365 if ((a1
->source_addr_flags
& in6ai_deprecated
)
1366 && !(a2
->source_addr_flags
& in6ai_deprecated
))
1370 /* Rule 4: Prefer home addresses. */
1371 if (a1
->got_source_addr
)
1373 if (!(a1
->source_addr_flags
& in6ai_homeaddress
)
1374 && (a2
->source_addr_flags
& in6ai_homeaddress
))
1376 if ((a1
->source_addr_flags
& in6ai_homeaddress
)
1377 && !(a2
->source_addr_flags
& in6ai_homeaddress
))
1381 /* Rule 5: Prefer matching label. */
1382 if (a1
->got_source_addr
)
1385 = get_label ((struct sockaddr_in6
*) a1
->dest_addr
->ai_addr
);
1386 int a1_src_label
= get_label (&a1
->source_addr
);
1389 = get_label ((struct sockaddr_in6
*) a2
->dest_addr
->ai_addr
);
1390 int a2_src_label
= get_label (&a2
->source_addr
);
1392 if (a1_dst_label
== a1_src_label
&& a2_dst_label
!= a2_src_label
)
1394 if (a1_dst_label
!= a1_src_label
&& a2_dst_label
== a2_src_label
)
1399 /* Rule 6: Prefer higher precedence. */
1401 = get_precedence ((struct sockaddr_in6
*) a1
->dest_addr
->ai_addr
);
1403 = get_precedence ((struct sockaddr_in6
*) a2
->dest_addr
->ai_addr
);
1405 if (a1_prec
> a2_prec
)
1407 if (a1_prec
< a2_prec
)
1411 /* Rule 7: Prefer native transport. */
1412 if (a1
->got_source_addr
)
1414 /* The same interface index means the same interface which means
1415 there is no difference in transport. This should catch many
1417 if (a1
->index
!= a2
->index
)
1419 int a1_native
= a1
->native
;
1420 int a2_native
= a2
->native
;
1422 if (a1_native
== -1 || a2_native
== -1)
1425 if (a1_native
== -1)
1427 /* If we do not have the information use 'native' as
1430 a1_index
= a1
->index
;
1433 a1_index
= 0xffffffffu
;
1436 if (a2_native
== -1)
1438 /* If we do not have the information use 'native' as
1441 a2_index
= a2
->index
;
1444 a2_index
= 0xffffffffu
;
1446 __check_native (a1_index
, &a1_native
, a2_index
, &a2_native
);
1448 /* Fill in the results in all the records. */
1449 for (int i
= 0; i
< src
->nresults
; ++i
)
1450 if (src
->results
[i
].index
== a1_index
)
1452 assert (src
->results
[i
].native
== -1
1453 || src
->results
[i
].native
== a1_native
);
1454 src
->results
[i
].native
= a1_native
;
1456 else if (src
->results
[i
].index
== a2_index
)
1458 assert (src
->results
[i
].native
== -1
1459 || src
->results
[i
].native
== a2_native
);
1460 src
->results
[i
].native
= a2_native
;
1464 if (a1_native
&& !a2_native
)
1466 if (!a1_native
&& a2_native
)
1472 /* Rule 8: Prefer smaller scope. */
1473 if (a1_dst_scope
< a2_dst_scope
)
1475 if (a1_dst_scope
> a2_dst_scope
)
1479 /* Rule 9: Use longest matching prefix. */
1480 if (a1
->got_source_addr
1481 && a1
->dest_addr
->ai_family
== a2
->dest_addr
->ai_family
)
1486 if (a1
->dest_addr
->ai_family
== PF_INET
)
1488 assert (a1
->source_addr
.sin6_family
== PF_INET
);
1489 assert (a2
->source_addr
.sin6_family
== PF_INET
);
1491 /* Outside of subnets, as defined by the network masks,
1492 common address prefixes for IPv4 addresses make no sense.
1493 So, define a non-zero value only if source and
1494 destination address are on the same subnet. */
1495 struct sockaddr_in
*in1_dst
1496 = (struct sockaddr_in
*) a1
->dest_addr
->ai_addr
;
1497 in_addr_t in1_dst_addr
= ntohl (in1_dst
->sin_addr
.s_addr
);
1498 struct sockaddr_in
*in1_src
1499 = (struct sockaddr_in
*) &a1
->source_addr
;
1500 in_addr_t in1_src_addr
= ntohl (in1_src
->sin_addr
.s_addr
);
1501 in_addr_t netmask1
= 0xffffffffu
<< (32 - a1
->prefixlen
);
1503 if ((in1_src_addr
& netmask1
) == (in1_dst_addr
& netmask1
))
1504 bit1
= fls (in1_dst_addr
^ in1_src_addr
);
1506 struct sockaddr_in
*in2_dst
1507 = (struct sockaddr_in
*) a2
->dest_addr
->ai_addr
;
1508 in_addr_t in2_dst_addr
= ntohl (in2_dst
->sin_addr
.s_addr
);
1509 struct sockaddr_in
*in2_src
1510 = (struct sockaddr_in
*) &a2
->source_addr
;
1511 in_addr_t in2_src_addr
= ntohl (in2_src
->sin_addr
.s_addr
);
1512 in_addr_t netmask2
= 0xffffffffu
<< (32 - a2
->prefixlen
);
1514 if ((in2_src_addr
& netmask2
) == (in2_dst_addr
& netmask2
))
1515 bit2
= fls (in2_dst_addr
^ in2_src_addr
);
1517 else if (a1
->dest_addr
->ai_family
== PF_INET6
)
1519 assert (a1
->source_addr
.sin6_family
== PF_INET6
);
1520 assert (a2
->source_addr
.sin6_family
== PF_INET6
);
1522 struct sockaddr_in6
*in1_dst
;
1523 struct sockaddr_in6
*in1_src
;
1524 struct sockaddr_in6
*in2_dst
;
1525 struct sockaddr_in6
*in2_src
;
1527 in1_dst
= (struct sockaddr_in6
*) a1
->dest_addr
->ai_addr
;
1528 in1_src
= (struct sockaddr_in6
*) &a1
->source_addr
;
1529 in2_dst
= (struct sockaddr_in6
*) a2
->dest_addr
->ai_addr
;
1530 in2_src
= (struct sockaddr_in6
*) &a2
->source_addr
;
1533 for (i
= 0; i
< 4; ++i
)
1534 if (in1_dst
->sin6_addr
.s6_addr32
[i
]
1535 != in1_src
->sin6_addr
.s6_addr32
[i
]
1536 || (in2_dst
->sin6_addr
.s6_addr32
[i
]
1537 != in2_src
->sin6_addr
.s6_addr32
[i
]))
1542 bit1
= fls (ntohl (in1_dst
->sin6_addr
.s6_addr32
[i
]
1543 ^ in1_src
->sin6_addr
.s6_addr32
[i
]));
1544 bit2
= fls (ntohl (in2_dst
->sin6_addr
.s6_addr32
[i
]
1545 ^ in2_src
->sin6_addr
.s6_addr32
[i
]));
1556 /* Rule 10: Otherwise, leave the order unchanged. To ensure this
1557 compare with the value indicating the order in which the entries
1558 have been received from the services. NB: no two entries can have
1559 the same order so the test will never return zero. */
1560 return idx1
< idx2
? -1 : 1;
1565 in6aicmp (const void *p1
, const void *p2
)
1567 struct in6addrinfo
*a1
= (struct in6addrinfo
*) p1
;
1568 struct in6addrinfo
*a2
= (struct in6addrinfo
*) p2
;
1570 return memcmp (a1
->addr
, a2
->addr
, sizeof (a1
->addr
));
1574 /* Name of the config file for RFC 3484 sorting (for now). */
1575 #define GAICONF_FNAME "/etc/gai.conf"
1578 /* Non-zero if we are supposed to reload the config file automatically
1579 whenever it changed. */
1580 static int gaiconf_reload_flag
;
1582 /* Non-zero if gaiconf_reload_flag was ever set to true. */
1583 static int gaiconf_reload_flag_ever_set
;
1585 /* Last modification time. */
1586 static struct timespec gaiconf_mtime
;
1589 libc_freeres_fn(fini
)
1591 if (labels
!= default_labels
)
1593 const struct prefixentry
*old
= labels
;
1594 labels
= default_labels
;
1595 free ((void *) old
);
1598 if (precedence
!= default_precedence
)
1600 const struct prefixentry
*old
= precedence
;
1601 precedence
= default_precedence
;
1602 free ((void *) old
);
1605 if (scopes
!= default_scopes
)
1607 const struct scopeentry
*old
= scopes
;
1608 scopes
= default_scopes
;
1609 free ((void *) old
);
1616 struct prefixentry entry
;
1617 struct prefixlist
*next
;
1623 struct scopeentry entry
;
1624 struct scopelist
*next
;
1629 free_prefixlist (struct prefixlist
*list
)
1631 while (list
!= NULL
)
1633 struct prefixlist
*oldp
= list
;
1641 free_scopelist (struct scopelist
*list
)
1643 while (list
!= NULL
)
1645 struct scopelist
*oldp
= list
;
1653 prefixcmp (const void *p1
, const void *p2
)
1655 const struct prefixentry
*e1
= (const struct prefixentry
*) p1
;
1656 const struct prefixentry
*e2
= (const struct prefixentry
*) p2
;
1658 if (e1
->bits
< e2
->bits
)
1660 if (e1
->bits
== e2
->bits
)
1667 scopecmp (const void *p1
, const void *p2
)
1669 const struct scopeentry
*e1
= (const struct scopeentry
*) p1
;
1670 const struct scopeentry
*e2
= (const struct scopeentry
*) p2
;
1672 if (e1
->netmask
> e2
->netmask
)
1674 if (e1
->netmask
== e2
->netmask
)
1683 struct prefixlist
*labellist
= NULL
;
1684 size_t nlabellist
= 0;
1685 bool labellist_nullbits
= false;
1686 struct prefixlist
*precedencelist
= NULL
;
1687 size_t nprecedencelist
= 0;
1688 bool precedencelist_nullbits
= false;
1689 struct scopelist
*scopelist
= NULL
;
1690 size_t nscopelist
= 0;
1691 bool scopelist_nullbits
= false;
1693 FILE *fp
= fopen (GAICONF_FNAME
, "rc");
1697 if (__fxstat64 (_STAT_VER
, fileno (fp
), &st
) != 0)
1706 __fsetlocking (fp
, FSETLOCKING_BYCALLER
);
1708 while (!feof_unlocked (fp
))
1710 ssize_t n
= __getline (&line
, &linelen
, fp
);
1714 /* Handle comments. No escaping possible so this is easy. */
1715 char *cp
= strchr (line
, '#');
1720 while (isspace (*cp
))
1724 while (*cp
!= '\0' && !isspace (*cp
))
1726 size_t cmdlen
= cp
- cmd
;
1730 while (isspace (*cp
))
1734 while (*cp
!= '\0' && !isspace (*cp
))
1736 size_t val1len
= cp
- cmd
;
1738 /* We always need at least two values. */
1744 while (isspace (*cp
))
1748 while (*cp
!= '\0' && !isspace (*cp
))
1751 /* Ignore the rest of the line. */
1754 struct prefixlist
**listp
;
1760 if (strcmp (cmd
, "label") == 0)
1762 struct in6_addr prefix
;
1763 unsigned long int bits
;
1764 unsigned long int val
;
1769 nullbitsp
= &labellist_nullbits
;
1774 cp
= strchr (val1
, '/');
1777 if (inet_pton (AF_INET6
, val1
, &prefix
)
1779 || (bits
= strtoul (cp
, &endp
, 10)) != ULONG_MAX
1783 && ((val
= strtoul (val2
, &endp
, 10)) != ULONG_MAX
1788 struct prefixlist
*newp
= malloc (sizeof (*newp
));
1796 memcpy (&newp
->entry
.prefix
, &prefix
, sizeof (prefix
));
1797 newp
->entry
.bits
= bits
;
1798 newp
->entry
.val
= val
;
1799 newp
->next
= *listp
;
1802 *nullbitsp
|= bits
== 0;
1808 if (strcmp (cmd
, "reload") == 0)
1810 gaiconf_reload_flag
= strcmp (val1
, "yes") == 0;
1811 if (gaiconf_reload_flag
)
1812 gaiconf_reload_flag_ever_set
= 1;
1817 if (strcmp (cmd
, "scopev4") == 0)
1819 struct in6_addr prefix
;
1820 unsigned long int bits
;
1821 unsigned long int val
;
1826 cp
= strchr (val1
, '/');
1829 if (inet_pton (AF_INET6
, val1
, &prefix
))
1832 if (IN6_IS_ADDR_V4MAPPED (&prefix
)
1834 || (bits
= strtoul (cp
, &endp
, 10)) != ULONG_MAX
1839 && ((val
= strtoul (val2
, &endp
, 10)) != ULONG_MAX
1844 struct scopelist
*newp
;
1846 newp
= malloc (sizeof (*newp
));
1854 newp
->entry
.netmask
= htonl (bits
!= 96
1858 newp
->entry
.addr32
= (prefix
.s6_addr32
[3]
1859 & newp
->entry
.netmask
);
1860 newp
->entry
.scope
= val
;
1861 newp
->next
= scopelist
;
1864 scopelist_nullbits
|= bits
== 96;
1867 else if (inet_pton (AF_INET
, val1
, &prefix
.s6_addr32
[3])
1869 || (bits
= strtoul (cp
, &endp
, 10)) != ULONG_MAX
1873 && ((val
= strtoul (val2
, &endp
, 10)) != ULONG_MAX
1885 if (strcmp (cmd
, "precedence") == 0)
1887 listp
= &precedencelist
;
1888 lenp
= &nprecedencelist
;
1889 nullbitsp
= &precedencelist_nullbits
;
1900 /* Create the array for the labels. */
1901 struct prefixentry
*new_labels
;
1904 if (!labellist_nullbits
)
1906 new_labels
= malloc (nlabellist
* sizeof (*new_labels
));
1907 if (new_labels
== NULL
)
1911 if (!labellist_nullbits
)
1914 memset (&new_labels
[i
].prefix
, '\0', sizeof (struct in6_addr
));
1915 new_labels
[i
].bits
= 0;
1916 new_labels
[i
].val
= 1;
1919 struct prefixlist
*l
= labellist
;
1922 new_labels
[i
] = l
->entry
;
1925 free_prefixlist (labellist
);
1927 /* Sort the entries so that the most specific ones are at
1929 qsort (new_labels
, nlabellist
, sizeof (*new_labels
), prefixcmp
);
1932 new_labels
= (struct prefixentry
*) default_labels
;
1934 struct prefixentry
*new_precedence
;
1935 if (nprecedencelist
> 0)
1937 if (!precedencelist_nullbits
)
1939 new_precedence
= malloc (nprecedencelist
* sizeof (*new_precedence
));
1940 if (new_precedence
== NULL
)
1942 if (new_labels
!= default_labels
)
1947 int i
= nprecedencelist
;
1948 if (!precedencelist_nullbits
)
1951 memset (&new_precedence
[i
].prefix
, '\0',
1952 sizeof (struct in6_addr
));
1953 new_precedence
[i
].bits
= 0;
1954 new_precedence
[i
].val
= 40;
1957 struct prefixlist
*l
= precedencelist
;
1960 new_precedence
[i
] = l
->entry
;
1963 free_prefixlist (precedencelist
);
1965 /* Sort the entries so that the most specific ones are at
1967 qsort (new_precedence
, nprecedencelist
, sizeof (*new_precedence
),
1971 new_precedence
= (struct prefixentry
*) default_precedence
;
1973 struct scopeentry
*new_scopes
;
1976 if (!scopelist_nullbits
)
1978 new_scopes
= malloc (nscopelist
* sizeof (*new_scopes
));
1979 if (new_scopes
== NULL
)
1981 if (new_labels
!= default_labels
)
1983 if (new_precedence
!= default_precedence
)
1984 free (new_precedence
);
1989 if (!scopelist_nullbits
)
1992 new_scopes
[i
].addr32
= 0;
1993 new_scopes
[i
].netmask
= 0;
1994 new_scopes
[i
].scope
= 14;
1997 struct scopelist
*l
= scopelist
;
2000 new_scopes
[i
] = l
->entry
;
2003 free_scopelist (scopelist
);
2005 /* Sort the entries so that the most specific ones are at
2007 qsort (new_scopes
, nscopelist
, sizeof (*new_scopes
),
2011 new_scopes
= (struct scopeentry
*) default_scopes
;
2013 /* Now we are ready to replace the values. */
2014 const struct prefixentry
*old
= labels
;
2015 labels
= new_labels
;
2016 if (old
!= default_labels
)
2017 free ((void *) old
);
2020 precedence
= new_precedence
;
2021 if (old
!= default_precedence
)
2022 free ((void *) old
);
2024 const struct scopeentry
*oldscope
= scopes
;
2025 scopes
= new_scopes
;
2026 if (oldscope
!= default_scopes
)
2027 free ((void *) oldscope
);
2029 gaiconf_mtime
= st
.st_mtim
;
2034 free_prefixlist (labellist
);
2035 free_prefixlist (precedencelist
);
2036 free_scopelist (scopelist
);
2038 /* If we previously read the file but it is gone now, free the
2039 old data and use the builtin one. Leave the reload flag
2047 gaiconf_reload (void)
2050 if (__xstat64 (_STAT_VER
, GAICONF_FNAME
, &st
) != 0
2051 || memcmp (&st
.st_mtim
, &gaiconf_mtime
, sizeof (gaiconf_mtime
)) != 0)
2057 getaddrinfo (const char *name
, const char *service
,
2058 const struct addrinfo
*hints
, struct addrinfo
**pai
)
2060 int i
= 0, last_i
= 0;
2062 struct addrinfo
*p
= NULL
;
2063 struct gaih_service gaih_service
, *pservice
;
2064 struct addrinfo local_hints
;
2066 if (name
!= NULL
&& name
[0] == '*' && name
[1] == 0)
2069 if (service
!= NULL
&& service
[0] == '*' && service
[1] == 0)
2072 if (name
== NULL
&& service
== NULL
)
2076 hints
= &default_hints
;
2079 & ~(AI_PASSIVE
|AI_CANONNAME
|AI_NUMERICHOST
|AI_ADDRCONFIG
|AI_V4MAPPED
2081 |AI_IDN
|AI_CANONIDN
|AI_IDN_ALLOW_UNASSIGNED
2082 |AI_IDN_USE_STD3_ASCII_RULES
2084 |AI_NUMERICSERV
|AI_ALL
))
2085 return EAI_BADFLAGS
;
2087 if ((hints
->ai_flags
& AI_CANONNAME
) && name
== NULL
)
2088 return EAI_BADFLAGS
;
2090 /* Initialize configurations. */
2091 if (__builtin_expect (!_res_hconf
.initialized
, 0))
2094 struct in6addrinfo
*in6ai
= NULL
;
2095 size_t in6ailen
= 0;
2096 bool seen_ipv4
= false;
2097 bool seen_ipv6
= false;
2098 /* We might need information about what interfaces are available.
2099 Also determine whether we have IPv4 or IPv6 interfaces or both. We
2100 cannot cache the results since new interfaces could be added at
2102 __check_pf (&seen_ipv4
, &seen_ipv6
, &in6ai
, &in6ailen
);
2104 if (hints
->ai_flags
& AI_ADDRCONFIG
)
2106 /* Now make a decision on what we return, if anything. */
2107 if (hints
->ai_family
== PF_UNSPEC
&& (seen_ipv4
|| seen_ipv6
))
2109 /* If we haven't seen both IPv4 and IPv6 interfaces we can
2110 narrow down the search. */
2111 if (! seen_ipv4
|| ! seen_ipv6
)
2113 local_hints
= *hints
;
2114 local_hints
.ai_family
= seen_ipv4
? PF_INET
: PF_INET6
;
2115 hints
= &local_hints
;
2118 else if ((hints
->ai_family
== PF_INET
&& ! seen_ipv4
)
2119 || (hints
->ai_family
== PF_INET6
&& ! seen_ipv6
))
2121 /* We cannot possibly return a valid answer. */
2127 if (service
&& service
[0])
2130 gaih_service
.name
= service
;
2131 gaih_service
.num
= strtoul (gaih_service
.name
, &c
, 10);
2134 if (hints
->ai_flags
& AI_NUMERICSERV
)
2140 gaih_service
.num
= -1;
2143 pservice
= &gaih_service
;
2148 struct addrinfo
**end
;
2154 unsigned int naddrs
= 0;
2155 if (hints
->ai_family
== AF_UNSPEC
|| hints
->ai_family
== AF_INET
2156 || hints
->ai_family
== AF_INET6
)
2158 last_i
= gaih_inet (name
, pservice
, hints
, end
, &naddrs
);
2164 return -(last_i
& GAIH_EAI
);
2169 end
= &((*end
)->ai_next
);
2181 /* Read the config file. */
2182 __libc_once_define (static, once
);
2183 __typeof (once
) old_once
= once
;
2184 __libc_once (once
, gaiconf_init
);
2185 /* Sort results according to RFC 3484. */
2186 struct sort_result results
[nresults
];
2187 size_t order
[nresults
];
2189 struct addrinfo
*last
= NULL
;
2190 char *canonname
= NULL
;
2192 /* If we have information about deprecated and temporary addresses
2193 sort the array now. */
2195 qsort (in6ai
, in6ailen
, sizeof (*in6ai
), in6aicmp
);
2200 for (i
= 0, q
= p
; q
!= NULL
; ++i
, last
= q
, q
= q
->ai_next
)
2202 results
[i
].dest_addr
= q
;
2203 results
[i
].native
= -1;
2206 /* If we just looked up the address for a different
2207 protocol, reuse the result. */
2208 if (last
!= NULL
&& last
->ai_addrlen
== q
->ai_addrlen
2209 && memcmp (last
->ai_addr
, q
->ai_addr
, q
->ai_addrlen
) == 0)
2211 memcpy (&results
[i
].source_addr
, &results
[i
- 1].source_addr
,
2212 results
[i
- 1].source_addr_len
);
2213 results
[i
].source_addr_len
= results
[i
- 1].source_addr_len
;
2214 results
[i
].got_source_addr
= results
[i
- 1].got_source_addr
;
2215 results
[i
].source_addr_flags
= results
[i
- 1].source_addr_flags
;
2216 results
[i
].prefixlen
= results
[i
- 1].prefixlen
;
2217 results
[i
].index
= results
[i
- 1].index
;
2221 results
[i
].got_source_addr
= false;
2222 results
[i
].source_addr_flags
= 0;
2223 results
[i
].prefixlen
= 0;
2224 results
[i
].index
= 0xffffffffu
;
2226 /* We overwrite the type with SOCK_DGRAM since we do not
2227 want connect() to connect to the other side. If we
2228 cannot determine the source address remember this
2230 if (fd
== -1 || (af
== AF_INET
&& q
->ai_family
== AF_INET6
))
2234 close_not_cancel_no_status (fd
);
2236 fd
= __socket (af
, SOCK_DGRAM
, IPPROTO_IP
);
2240 /* Reset the connection. */
2241 struct sockaddr sa
= { .sa_family
= AF_UNSPEC
};
2242 __connect (fd
, &sa
, sizeof (sa
));
2245 socklen_t sl
= sizeof (results
[i
].source_addr
);
2247 && __connect (fd
, q
->ai_addr
, q
->ai_addrlen
) == 0
2248 && __getsockname (fd
,
2249 (struct sockaddr
*) &results
[i
].source_addr
,
2252 results
[i
].source_addr_len
= sl
;
2253 results
[i
].got_source_addr
= true;
2257 /* See whether the source address is on the list of
2258 deprecated or temporary addresses. */
2259 struct in6addrinfo tmp
;
2261 if (q
->ai_family
== AF_INET
&& af
== AF_INET
)
2263 struct sockaddr_in
*sinp
2264 = (struct sockaddr_in
*) &results
[i
].source_addr
;
2267 tmp
.addr
[2] = htonl (0xffff);
2268 tmp
.addr
[3] = sinp
->sin_addr
.s_addr
;
2272 struct sockaddr_in6
*sin6p
2273 = (struct sockaddr_in6
*) &results
[i
].source_addr
;
2274 memcpy (tmp
.addr
, &sin6p
->sin6_addr
, IN6ADDRSZ
);
2277 struct in6addrinfo
*found
2278 = bsearch (&tmp
, in6ai
, in6ailen
, sizeof (*in6ai
),
2282 results
[i
].source_addr_flags
= found
->flags
;
2283 results
[i
].prefixlen
= found
->prefixlen
;
2284 results
[i
].index
= found
->index
;
2288 if (q
->ai_family
== AF_INET
&& af
== AF_INET6
)
2290 /* We have to convert the address. The socket is
2291 IPv6 and the request is for IPv4. */
2292 struct sockaddr_in6
*sin6
2293 = (struct sockaddr_in6
*) &results
[i
].source_addr
;
2294 struct sockaddr_in
*sin
2295 = (struct sockaddr_in
*) &results
[i
].source_addr
;
2296 assert (IN6_IS_ADDR_V4MAPPED (sin6
->sin6_addr
.s6_addr32
));
2297 sin
->sin_family
= AF_INET
;
2298 /* We do not have to initialize sin_port since this
2299 fields has the same position and size in the IPv6
2301 assert (offsetof (struct sockaddr_in
, sin_port
)
2302 == offsetof (struct sockaddr_in6
, sin6_port
));
2303 assert (sizeof (sin
->sin_port
)
2304 == sizeof (sin6
->sin6_port
));
2305 memcpy (&sin
->sin_addr
,
2306 &sin6
->sin6_addr
.s6_addr32
[3], INADDRSZ
);
2307 results
[i
].source_addr_len
= sizeof (struct sockaddr_in
);
2310 else if (errno
== EAFNOSUPPORT
&& af
== AF_INET6
2311 && q
->ai_family
== AF_INET
)
2312 /* This could mean IPv6 sockets are IPv6-only. */
2315 /* Just make sure that if we have to process the same
2316 address again we do not copy any memory. */
2317 results
[i
].source_addr_len
= 0;
2320 /* Remember the canonical name. */
2321 if (q
->ai_canonname
!= NULL
)
2323 assert (canonname
== NULL
);
2324 canonname
= q
->ai_canonname
;
2325 q
->ai_canonname
= NULL
;
2330 close_not_cancel_no_status (fd
);
2332 /* We got all the source addresses we can get, now sort using
2334 struct sort_result_combo src
2335 = { .results
= results
, .nresults
= nresults
};
2336 if (__builtin_expect (gaiconf_reload_flag_ever_set
, 0))
2338 __libc_lock_define_initialized (static, lock
);
2340 __libc_lock_lock (lock
);
2341 if (old_once
&& gaiconf_reload_flag
)
2343 qsort_r (order
, nresults
, sizeof (order
[0]), rfc3484_sort
, &src
);
2344 __libc_lock_unlock (lock
);
2347 qsort_r (order
, nresults
, sizeof (order
[0]), rfc3484_sort
, &src
);
2349 /* Queue the results up as they come out of sorting. */
2350 q
= p
= results
[order
[0]].dest_addr
;
2351 for (i
= 1; i
< nresults
; ++i
)
2352 q
= q
->ai_next
= results
[order
[i
]].dest_addr
;
2355 /* Fill in the canonical name into the new first entry. */
2356 p
->ai_canonname
= canonname
;
2367 if (pai
== NULL
&& last_i
== 0)
2370 return last_i
? -(last_i
& GAIH_EAI
) : EAI_NONAME
;
2372 libc_hidden_def (getaddrinfo
)
2374 static_link_warning (getaddrinfo
)
2377 freeaddrinfo (struct addrinfo
*ai
)
2385 free (p
->ai_canonname
);
2389 libc_hidden_def (freeaddrinfo
)