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
;
664 /* The database contains a negative entry. */
666 else if (__nss_not_use_nscd_hosts
== 0)
668 if (herrno
== NETDB_INTERNAL
&& errno
== ENOMEM
)
670 if (herrno
== TRY_AGAIN
)
677 if (__nss_hosts_database
!= NULL
)
680 nip
= __nss_hosts_database
;
683 no_more
= __nss_database_lookup ("hosts", NULL
,
684 "dns [!UNAVAIL=return] files",
687 /* Initialize configurations. */
688 if (__builtin_expect (!_res_hconf
.initialized
, 0))
690 if (__res_maybe_init (&_res
, 0) == -1)
693 /* If we are looking for both IPv4 and IPv6 address we don't
694 want the lookup functions to automatically promote IPv4
695 addresses to IPv6 addresses. Currently this is decided
696 by setting the RES_USE_INET6 bit in _res.options. */
697 old_res_options
= _res
.options
;
698 _res
.options
&= ~RES_USE_INET6
;
700 size_t tmpbuflen
= 1024;
701 char *tmpbuf
= alloca (tmpbuflen
);
705 nss_gethostbyname4_r fct4
706 = __nss_lookup_function (nip
, "gethostbyname4_r");
714 status
= DL_CALL_FCT (fct4
, (name
, pat
, tmpbuf
,
715 tmpbuflen
, &rc
, &herrno
,
717 if (status
== NSS_STATUS_SUCCESS
)
719 if (status
!= NSS_STATUS_TRYAGAIN
720 || rc
!= ERANGE
|| herrno
!= NETDB_INTERNAL
)
722 if (herrno
== NETDB_INTERNAL
)
724 __set_h_errno (herrno
);
725 _res
.options
= old_res_options
;
728 if (herrno
== TRY_AGAIN
)
731 no_data
= herrno
== NO_DATA
;
734 tmpbuf
= extend_alloca (tmpbuf
,
735 tmpbuflen
, 2 * tmpbuflen
);
738 no_inet6_data
= no_data
;
740 if (status
== NSS_STATUS_SUCCESS
)
742 if ((req
->ai_flags
& AI_CANONNAME
) != 0 && canon
== NULL
)
743 canon
= (*pat
)->name
;
746 pat
= &((*pat
)->next
);
751 nss_gethostbyname3_r fct
= NULL
;
752 if (req
->ai_flags
& AI_CANONNAME
)
753 /* No need to use this function if we do not look for
754 the canonical name. The function does not exist in
755 all NSS modules and therefore the lookup would
757 fct
= __nss_lookup_function (nip
, "gethostbyname3_r");
759 /* We are cheating here. The gethostbyname2_r
760 function does not have the same interface as
761 gethostbyname3_r but the extra arguments the
762 latter takes are added at the end. So the
763 gethostbyname2_r code will just ignore them. */
764 fct
= __nss_lookup_function (nip
, "gethostbyname2_r");
768 if (req
->ai_family
== AF_INET6
769 || req
->ai_family
== AF_UNSPEC
)
771 gethosts (AF_INET6
, struct in6_addr
);
772 no_inet6_data
= no_data
;
773 inet6_status
= status
;
775 if (req
->ai_family
== AF_INET
776 || req
->ai_family
== AF_UNSPEC
777 || (req
->ai_family
== AF_INET6
778 && (req
->ai_flags
& AI_V4MAPPED
)
779 /* Avoid generating the mapped addresses if we
780 know we are not going to need them. */
781 && ((req
->ai_flags
& AI_ALL
) || !got_ipv6
)))
783 gethosts (AF_INET
, struct in_addr
);
785 if (req
->ai_family
== AF_INET
)
787 no_inet6_data
= no_data
;
788 inet6_status
= status
;
792 /* If we found one address for AF_INET or AF_INET6,
793 don't continue the search. */
794 if (inet6_status
== NSS_STATUS_SUCCESS
795 || status
== NSS_STATUS_SUCCESS
)
797 if ((req
->ai_flags
& AI_CANONNAME
) != 0
800 /* If we need the canonical name, get it
801 from the same service as the result. */
802 nss_getcanonname_r cfct
;
805 cfct
= __nss_lookup_function (nip
,
809 const size_t max_fqdn_len
= 256;
810 char *buf
= alloca (max_fqdn_len
);
813 if (DL_CALL_FCT (cfct
, (at
->name
?: name
,
816 == NSS_STATUS_SUCCESS
)
819 /* Set to name now to avoid using
828 /* We can have different states for AF_INET and
829 AF_INET6. Try to find a useful one for both. */
830 if (inet6_status
== NSS_STATUS_TRYAGAIN
)
831 status
= NSS_STATUS_TRYAGAIN
;
832 else if (status
== NSS_STATUS_UNAVAIL
833 && inet6_status
!= NSS_STATUS_UNAVAIL
)
834 status
= inet6_status
;
838 if (nss_next_action (nip
, status
) == NSS_ACTION_RETURN
)
841 if (nip
->next
== NULL
)
847 _res
.options
= old_res_options
;
849 if (no_data
!= 0 && no_inet6_data
!= 0)
851 /* If both requests timed out report this. */
852 if (no_data
== EAI_AGAIN
&& no_inet6_data
== EAI_AGAIN
)
855 /* We made requests but they turned out no data. The name
857 return GAIH_OKIFUNSPEC
| -EAI_NODATA
;
862 if (at
->family
== AF_UNSPEC
)
863 return GAIH_OKIFUNSPEC
| -EAI_NONAME
;
867 struct gaih_addrtuple
*atr
;
868 atr
= at
= __alloca (sizeof (struct gaih_addrtuple
));
869 memset (at
, '\0', sizeof (struct gaih_addrtuple
));
871 if (req
->ai_family
== AF_UNSPEC
)
873 at
->next
= __alloca (sizeof (struct gaih_addrtuple
));
874 memset (at
->next
, '\0', sizeof (struct gaih_addrtuple
));
877 if (req
->ai_family
== AF_UNSPEC
|| req
->ai_family
== AF_INET6
)
879 at
->family
= AF_INET6
;
880 if ((req
->ai_flags
& AI_PASSIVE
) == 0)
881 memcpy (at
->addr
, &in6addr_loopback
, sizeof (struct in6_addr
));
885 if (req
->ai_family
== AF_UNSPEC
|| req
->ai_family
== AF_INET
)
887 atr
->family
= AF_INET
;
888 if ((req
->ai_flags
& AI_PASSIVE
) == 0)
889 atr
->addr
[0] = htonl (INADDR_LOOPBACK
);
894 struct gaih_servtuple
*st2
;
895 struct gaih_addrtuple
*at2
= at
;
900 buffer is the size of an unformatted IPv6 address in printable format.
904 /* Only the first entry gets the canonical name. */
905 if (at2
== at
&& (req
->ai_flags
& AI_CANONNAME
) != 0)
909 struct hostent
*h
= NULL
;
912 size_t tmpbuflen
= 512;
917 tmpbuf
= extend_alloca (tmpbuf
, tmpbuflen
, tmpbuflen
* 2);
918 rc
= __gethostbyaddr_r (at2
->addr
,
919 ((at2
->family
== AF_INET6
)
920 ? sizeof (struct in6_addr
)
921 : sizeof (struct in_addr
)),
922 at2
->family
, &th
, tmpbuf
,
923 tmpbuflen
, &h
, &herrno
);
925 while (rc
== ERANGE
&& herrno
== NETDB_INTERNAL
);
927 if (rc
!= 0 && herrno
== NETDB_INTERNAL
)
929 __set_h_errno (herrno
);
937 assert (orig_name
!= NULL
);
938 /* If the canonical name cannot be determined, use
939 the passed in string. */
945 if (req
->ai_flags
& AI_CANONIDN
)
948 if (req
->ai_flags
& AI_IDN_ALLOW_UNASSIGNED
)
949 idn_flags
|= IDNA_ALLOW_UNASSIGNED
;
950 if (req
->ai_flags
& AI_IDN_USE_STD3_ASCII_RULES
)
951 idn_flags
|= IDNA_USE_STD3_ASCII_RULES
;
954 int rc
= __idna_to_unicode_lzlz (canon
, &out
, idn_flags
);
955 if (rc
!= IDNA_SUCCESS
)
957 if (rc
== IDNA_MALLOC_ERROR
)
959 if (rc
== IDNA_DLOPEN_ERROR
)
961 return -EAI_IDN_ENCODE
;
963 /* In case the output string is the same as the input
964 string no new string has been allocated and we
975 canon
= strdup (canon
);
981 family
= at2
->family
;
982 if (family
== AF_INET6
)
984 socklen
= sizeof (struct sockaddr_in6
);
986 /* If we looked up IPv4 mapped address discard them here if
987 the caller isn't interested in all address and we have
988 found at least one IPv6 address. */
990 && (req
->ai_flags
& (AI_V4MAPPED
|AI_ALL
)) == AI_V4MAPPED
991 && IN6_IS_ADDR_V4MAPPED (at2
->addr
))
995 socklen
= sizeof (struct sockaddr_in
);
997 for (st2
= st
; st2
!= NULL
; st2
= st2
->next
)
1000 ai
= *pai
= malloc (sizeof (struct addrinfo
) + socklen
);
1003 free ((char *) canon
);
1007 ai
->ai_flags
= req
->ai_flags
;
1008 ai
->ai_family
= family
;
1009 ai
->ai_socktype
= st2
->socktype
;
1010 ai
->ai_protocol
= st2
->protocol
;
1011 ai
->ai_addrlen
= socklen
;
1012 ai
->ai_addr
= (void *) (ai
+ 1);
1014 /* We only add the canonical name once. */
1015 ai
->ai_canonname
= (char *) canon
;
1019 ai
->ai_addr
->sa_len
= socklen
;
1020 #endif /* _HAVE_SA_LEN */
1021 ai
->ai_addr
->sa_family
= family
;
1023 /* In case of an allocation error the list must be NULL
1027 if (family
== AF_INET6
)
1029 struct sockaddr_in6
*sin6p
=
1030 (struct sockaddr_in6
*) ai
->ai_addr
;
1032 sin6p
->sin6_port
= st2
->port
;
1033 sin6p
->sin6_flowinfo
= 0;
1034 memcpy (&sin6p
->sin6_addr
,
1035 at2
->addr
, sizeof (struct in6_addr
));
1036 sin6p
->sin6_scope_id
= at2
->scopeid
;
1040 struct sockaddr_in
*sinp
=
1041 (struct sockaddr_in
*) ai
->ai_addr
;
1042 sinp
->sin_port
= st2
->port
;
1043 memcpy (&sinp
->sin_addr
,
1044 at2
->addr
, sizeof (struct in_addr
));
1045 memset (sinp
->sin_zero
, '\0', sizeof (sinp
->sin_zero
));
1048 pai
= &(ai
->ai_next
);
1063 struct addrinfo
*dest_addr
;
1064 /* Using sockaddr_storage is for now overkill. We only support IPv4
1065 and IPv6 so far. If this changes at some point we can adjust the
1067 struct sockaddr_in6 source_addr
;
1068 uint8_t source_addr_len
;
1069 bool got_source_addr
;
1070 uint8_t source_addr_flags
;
1076 struct sort_result_combo
1078 struct sort_result
*results
;
1083 #if __BYTE_ORDER == __BIG_ENDIAN
1084 # define htonl_c(n) n
1086 # define htonl_c(n) __bswap_constant_32 (n)
1089 static const struct scopeentry
1098 } default_scopes
[] =
1100 /* Link-local addresses: scope 2. */
1101 { { { 169, 254, 0, 0 } }, htonl_c (0xffff0000), 2 },
1102 { { { 127, 0, 0, 0 } }, htonl_c (0xff000000), 2 },
1103 /* Site-local addresses: scope 5. */
1104 { { { 10, 0, 0, 0 } }, htonl_c (0xff000000), 5 },
1105 { { { 172, 16, 0, 0 } }, htonl_c (0xfff00000), 5 },
1106 { { { 192, 168, 0, 0 } }, htonl_c (0xffff0000), 5 },
1107 /* Default: scope 14. */
1108 { { { 0, 0, 0, 0 } }, htonl_c (0x00000000), 14 }
1111 /* The label table. */
1112 static const struct scopeentry
*scopes
;
1116 get_scope (const struct sockaddr_in6
*in6
)
1119 if (in6
->sin6_family
== PF_INET6
)
1121 if (! IN6_IS_ADDR_MULTICAST (&in6
->sin6_addr
))
1123 if (IN6_IS_ADDR_LINKLOCAL (&in6
->sin6_addr
)
1124 /* RFC 4291 2.5.3 says that the loopback address is to be
1125 treated like a link-local address. */
1126 || IN6_IS_ADDR_LOOPBACK (&in6
->sin6_addr
))
1128 else if (IN6_IS_ADDR_SITELOCAL (&in6
->sin6_addr
))
1131 /* XXX Is this the correct default behavior? */
1135 scope
= in6
->sin6_addr
.s6_addr
[1] & 0xf;
1137 else if (in6
->sin6_family
== PF_INET
)
1139 const struct sockaddr_in
*in
= (const struct sockaddr_in
*) in6
;
1144 if ((in
->sin_addr
.s_addr
& scopes
[cnt
].netmask
)
1145 == scopes
[cnt
].addr32
)
1146 return scopes
[cnt
].scope
;
1153 /* XXX What is a good default? */
1162 struct in6_addr prefix
;
1168 /* The label table. */
1169 static const struct prefixentry
*labels
;
1171 /* Default labels. */
1172 static const struct prefixentry default_labels
[] =
1174 /* See RFC 3484 for the details. */
1176 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1177 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } }
1180 = { .__u6_addr8
= { 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1181 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1184 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1185 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1188 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1189 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 } }
1191 /* The next two entries differ from RFC 3484. We need to treat
1192 IPv6 site-local addresses special because they are never NATed,
1193 unlike site-locale IPv4 addresses. If this would not happen, on
1194 machines which have only IPv4 and IPv6 site-local addresses, the
1195 sorting would prefer the IPv6 site-local addresses, causing
1196 unnecessary delays when trying to connect to a global IPv6 address
1197 through a site-local IPv6 address. */
1199 = { .__u6_addr8
= { 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1200 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1203 = { .__u6_addr8
= { 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1204 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1206 /* Additional rule for Teredo tunnels. */
1208 = { .__u6_addr8
= { 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1209 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1212 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1213 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1218 /* The precedence table. */
1219 static const struct prefixentry
*precedence
;
1221 /* The default precedences. */
1222 static const struct prefixentry default_precedence
[] =
1224 /* See RFC 3484 for the details. */
1226 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1227 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } }
1230 = { .__u6_addr8
= { 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1231 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1234 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1235 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1238 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1239 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 } }
1242 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1243 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1249 match_prefix (const struct sockaddr_in6
*in6
,
1250 const struct prefixentry
*list
, int default_val
)
1253 struct sockaddr_in6 in6_mem
;
1255 if (in6
->sin6_family
== PF_INET
)
1257 const struct sockaddr_in
*in
= (const struct sockaddr_in
*) in6
;
1259 /* Construct a V4-to-6 mapped address. */
1260 in6_mem
.sin6_family
= PF_INET6
;
1261 in6_mem
.sin6_port
= in
->sin_port
;
1262 in6_mem
.sin6_flowinfo
= 0;
1263 memset (&in6_mem
.sin6_addr
, '\0', sizeof (in6_mem
.sin6_addr
));
1264 in6_mem
.sin6_addr
.s6_addr16
[5] = 0xffff;
1265 in6_mem
.sin6_addr
.s6_addr32
[3] = in
->sin_addr
.s_addr
;
1266 in6_mem
.sin6_scope_id
= 0;
1270 else if (in6
->sin6_family
!= PF_INET6
)
1273 for (idx
= 0; ; ++idx
)
1275 unsigned int bits
= list
[idx
].bits
;
1276 const uint8_t *mask
= list
[idx
].prefix
.s6_addr
;
1277 const uint8_t *val
= in6
->sin6_addr
.s6_addr
;
1291 if ((*mask
& (0xff00 >> bits
)) == (*val
& (0xff00 >> bits
)))
1297 return list
[idx
].val
;
1302 get_label (const struct sockaddr_in6
*in6
)
1304 /* XXX What is a good default value? */
1305 return match_prefix (in6
, labels
, INT_MAX
);
1310 get_precedence (const struct sockaddr_in6
*in6
)
1312 /* XXX What is a good default value? */
1313 return match_prefix (in6
, precedence
, 0);
1317 /* Find last bit set in a word. */
1323 for (n
= 0, mask
= 1 << 31; n
< 32; mask
>>= 1, ++n
)
1324 if ((a
& mask
) != 0)
1331 rfc3484_sort (const void *p1
, const void *p2
, void *arg
)
1333 const size_t idx1
= *(const size_t *) p1
;
1334 const size_t idx2
= *(const size_t *) p2
;
1335 struct sort_result_combo
*src
= (struct sort_result_combo
*) arg
;
1336 struct sort_result
*a1
= &src
->results
[idx1
];
1337 struct sort_result
*a2
= &src
->results
[idx2
];
1339 /* Rule 1: Avoid unusable destinations.
1340 We have the got_source_addr flag set if the destination is reachable. */
1341 if (a1
->got_source_addr
&& ! a2
->got_source_addr
)
1343 if (! a1
->got_source_addr
&& a2
->got_source_addr
)
1347 /* Rule 2: Prefer matching scope. Only interesting if both
1348 destination addresses are IPv6. */
1350 = get_scope ((struct sockaddr_in6
*) a1
->dest_addr
->ai_addr
);
1353 = get_scope ((struct sockaddr_in6
*) a2
->dest_addr
->ai_addr
);
1355 if (a1
->got_source_addr
)
1357 int a1_src_scope
= get_scope (&a1
->source_addr
);
1358 int a2_src_scope
= get_scope (&a2
->source_addr
);
1360 if (a1_dst_scope
== a1_src_scope
&& a2_dst_scope
!= a2_src_scope
)
1362 if (a1_dst_scope
!= a1_src_scope
&& a2_dst_scope
== a2_src_scope
)
1367 /* Rule 3: Avoid deprecated addresses. */
1368 if (a1
->got_source_addr
)
1370 if (!(a1
->source_addr_flags
& in6ai_deprecated
)
1371 && (a2
->source_addr_flags
& in6ai_deprecated
))
1373 if ((a1
->source_addr_flags
& in6ai_deprecated
)
1374 && !(a2
->source_addr_flags
& in6ai_deprecated
))
1378 /* Rule 4: Prefer home addresses. */
1379 if (a1
->got_source_addr
)
1381 if (!(a1
->source_addr_flags
& in6ai_homeaddress
)
1382 && (a2
->source_addr_flags
& in6ai_homeaddress
))
1384 if ((a1
->source_addr_flags
& in6ai_homeaddress
)
1385 && !(a2
->source_addr_flags
& in6ai_homeaddress
))
1389 /* Rule 5: Prefer matching label. */
1390 if (a1
->got_source_addr
)
1393 = get_label ((struct sockaddr_in6
*) a1
->dest_addr
->ai_addr
);
1394 int a1_src_label
= get_label (&a1
->source_addr
);
1397 = get_label ((struct sockaddr_in6
*) a2
->dest_addr
->ai_addr
);
1398 int a2_src_label
= get_label (&a2
->source_addr
);
1400 if (a1_dst_label
== a1_src_label
&& a2_dst_label
!= a2_src_label
)
1402 if (a1_dst_label
!= a1_src_label
&& a2_dst_label
== a2_src_label
)
1407 /* Rule 6: Prefer higher precedence. */
1409 = get_precedence ((struct sockaddr_in6
*) a1
->dest_addr
->ai_addr
);
1411 = get_precedence ((struct sockaddr_in6
*) a2
->dest_addr
->ai_addr
);
1413 if (a1_prec
> a2_prec
)
1415 if (a1_prec
< a2_prec
)
1419 /* Rule 7: Prefer native transport. */
1420 if (a1
->got_source_addr
)
1422 /* The same interface index means the same interface which means
1423 there is no difference in transport. This should catch many
1425 if (a1
->index
!= a2
->index
)
1427 int a1_native
= a1
->native
;
1428 int a2_native
= a2
->native
;
1430 if (a1_native
== -1 || a2_native
== -1)
1433 if (a1_native
== -1)
1435 /* If we do not have the information use 'native' as
1438 a1_index
= a1
->index
;
1441 a1_index
= 0xffffffffu
;
1444 if (a2_native
== -1)
1446 /* If we do not have the information use 'native' as
1449 a2_index
= a2
->index
;
1452 a2_index
= 0xffffffffu
;
1454 __check_native (a1_index
, &a1_native
, a2_index
, &a2_native
);
1456 /* Fill in the results in all the records. */
1457 for (int i
= 0; i
< src
->nresults
; ++i
)
1458 if (src
->results
[i
].index
== a1_index
)
1460 assert (src
->results
[i
].native
== -1
1461 || src
->results
[i
].native
== a1_native
);
1462 src
->results
[i
].native
= a1_native
;
1464 else if (src
->results
[i
].index
== a2_index
)
1466 assert (src
->results
[i
].native
== -1
1467 || src
->results
[i
].native
== a2_native
);
1468 src
->results
[i
].native
= a2_native
;
1472 if (a1_native
&& !a2_native
)
1474 if (!a1_native
&& a2_native
)
1480 /* Rule 8: Prefer smaller scope. */
1481 if (a1_dst_scope
< a2_dst_scope
)
1483 if (a1_dst_scope
> a2_dst_scope
)
1487 /* Rule 9: Use longest matching prefix. */
1488 if (a1
->got_source_addr
1489 && a1
->dest_addr
->ai_family
== a2
->dest_addr
->ai_family
)
1494 if (a1
->dest_addr
->ai_family
== PF_INET
)
1496 assert (a1
->source_addr
.sin6_family
== PF_INET
);
1497 assert (a2
->source_addr
.sin6_family
== PF_INET
);
1499 /* Outside of subnets, as defined by the network masks,
1500 common address prefixes for IPv4 addresses make no sense.
1501 So, define a non-zero value only if source and
1502 destination address are on the same subnet. */
1503 struct sockaddr_in
*in1_dst
1504 = (struct sockaddr_in
*) a1
->dest_addr
->ai_addr
;
1505 in_addr_t in1_dst_addr
= ntohl (in1_dst
->sin_addr
.s_addr
);
1506 struct sockaddr_in
*in1_src
1507 = (struct sockaddr_in
*) &a1
->source_addr
;
1508 in_addr_t in1_src_addr
= ntohl (in1_src
->sin_addr
.s_addr
);
1509 in_addr_t netmask1
= 0xffffffffu
<< (32 - a1
->prefixlen
);
1511 if ((in1_src_addr
& netmask1
) == (in1_dst_addr
& netmask1
))
1512 bit1
= fls (in1_dst_addr
^ in1_src_addr
);
1514 struct sockaddr_in
*in2_dst
1515 = (struct sockaddr_in
*) a2
->dest_addr
->ai_addr
;
1516 in_addr_t in2_dst_addr
= ntohl (in2_dst
->sin_addr
.s_addr
);
1517 struct sockaddr_in
*in2_src
1518 = (struct sockaddr_in
*) &a2
->source_addr
;
1519 in_addr_t in2_src_addr
= ntohl (in2_src
->sin_addr
.s_addr
);
1520 in_addr_t netmask2
= 0xffffffffu
<< (32 - a2
->prefixlen
);
1522 if ((in2_src_addr
& netmask2
) == (in2_dst_addr
& netmask2
))
1523 bit2
= fls (in2_dst_addr
^ in2_src_addr
);
1525 else if (a1
->dest_addr
->ai_family
== PF_INET6
)
1527 assert (a1
->source_addr
.sin6_family
== PF_INET6
);
1528 assert (a2
->source_addr
.sin6_family
== PF_INET6
);
1530 struct sockaddr_in6
*in1_dst
;
1531 struct sockaddr_in6
*in1_src
;
1532 struct sockaddr_in6
*in2_dst
;
1533 struct sockaddr_in6
*in2_src
;
1535 in1_dst
= (struct sockaddr_in6
*) a1
->dest_addr
->ai_addr
;
1536 in1_src
= (struct sockaddr_in6
*) &a1
->source_addr
;
1537 in2_dst
= (struct sockaddr_in6
*) a2
->dest_addr
->ai_addr
;
1538 in2_src
= (struct sockaddr_in6
*) &a2
->source_addr
;
1541 for (i
= 0; i
< 4; ++i
)
1542 if (in1_dst
->sin6_addr
.s6_addr32
[i
]
1543 != in1_src
->sin6_addr
.s6_addr32
[i
]
1544 || (in2_dst
->sin6_addr
.s6_addr32
[i
]
1545 != in2_src
->sin6_addr
.s6_addr32
[i
]))
1550 bit1
= fls (ntohl (in1_dst
->sin6_addr
.s6_addr32
[i
]
1551 ^ in1_src
->sin6_addr
.s6_addr32
[i
]));
1552 bit2
= fls (ntohl (in2_dst
->sin6_addr
.s6_addr32
[i
]
1553 ^ in2_src
->sin6_addr
.s6_addr32
[i
]));
1564 /* Rule 10: Otherwise, leave the order unchanged. To ensure this
1565 compare with the value indicating the order in which the entries
1566 have been received from the services. NB: no two entries can have
1567 the same order so the test will never return zero. */
1568 return idx1
< idx2
? -1 : 1;
1573 in6aicmp (const void *p1
, const void *p2
)
1575 struct in6addrinfo
*a1
= (struct in6addrinfo
*) p1
;
1576 struct in6addrinfo
*a2
= (struct in6addrinfo
*) p2
;
1578 return memcmp (a1
->addr
, a2
->addr
, sizeof (a1
->addr
));
1582 /* Name of the config file for RFC 3484 sorting (for now). */
1583 #define GAICONF_FNAME "/etc/gai.conf"
1586 /* Non-zero if we are supposed to reload the config file automatically
1587 whenever it changed. */
1588 static int gaiconf_reload_flag
;
1590 /* Non-zero if gaiconf_reload_flag was ever set to true. */
1591 static int gaiconf_reload_flag_ever_set
;
1593 /* Last modification time. */
1594 static struct timespec gaiconf_mtime
;
1597 libc_freeres_fn(fini
)
1599 if (labels
!= default_labels
)
1601 const struct prefixentry
*old
= labels
;
1602 labels
= default_labels
;
1603 free ((void *) old
);
1606 if (precedence
!= default_precedence
)
1608 const struct prefixentry
*old
= precedence
;
1609 precedence
= default_precedence
;
1610 free ((void *) old
);
1613 if (scopes
!= default_scopes
)
1615 const struct scopeentry
*old
= scopes
;
1616 scopes
= default_scopes
;
1617 free ((void *) old
);
1624 struct prefixentry entry
;
1625 struct prefixlist
*next
;
1631 struct scopeentry entry
;
1632 struct scopelist
*next
;
1637 free_prefixlist (struct prefixlist
*list
)
1639 while (list
!= NULL
)
1641 struct prefixlist
*oldp
= list
;
1649 free_scopelist (struct scopelist
*list
)
1651 while (list
!= NULL
)
1653 struct scopelist
*oldp
= list
;
1661 prefixcmp (const void *p1
, const void *p2
)
1663 const struct prefixentry
*e1
= (const struct prefixentry
*) p1
;
1664 const struct prefixentry
*e2
= (const struct prefixentry
*) p2
;
1666 if (e1
->bits
< e2
->bits
)
1668 if (e1
->bits
== e2
->bits
)
1675 scopecmp (const void *p1
, const void *p2
)
1677 const struct scopeentry
*e1
= (const struct scopeentry
*) p1
;
1678 const struct scopeentry
*e2
= (const struct scopeentry
*) p2
;
1680 if (e1
->netmask
> e2
->netmask
)
1682 if (e1
->netmask
== e2
->netmask
)
1691 struct prefixlist
*labellist
= NULL
;
1692 size_t nlabellist
= 0;
1693 bool labellist_nullbits
= false;
1694 struct prefixlist
*precedencelist
= NULL
;
1695 size_t nprecedencelist
= 0;
1696 bool precedencelist_nullbits
= false;
1697 struct scopelist
*scopelist
= NULL
;
1698 size_t nscopelist
= 0;
1699 bool scopelist_nullbits
= false;
1701 FILE *fp
= fopen (GAICONF_FNAME
, "rc");
1705 if (__fxstat64 (_STAT_VER
, fileno (fp
), &st
) != 0)
1714 __fsetlocking (fp
, FSETLOCKING_BYCALLER
);
1716 while (!feof_unlocked (fp
))
1718 ssize_t n
= __getline (&line
, &linelen
, fp
);
1722 /* Handle comments. No escaping possible so this is easy. */
1723 char *cp
= strchr (line
, '#');
1728 while (isspace (*cp
))
1732 while (*cp
!= '\0' && !isspace (*cp
))
1734 size_t cmdlen
= cp
- cmd
;
1738 while (isspace (*cp
))
1742 while (*cp
!= '\0' && !isspace (*cp
))
1744 size_t val1len
= cp
- cmd
;
1746 /* We always need at least two values. */
1752 while (isspace (*cp
))
1756 while (*cp
!= '\0' && !isspace (*cp
))
1759 /* Ignore the rest of the line. */
1762 struct prefixlist
**listp
;
1768 if (strcmp (cmd
, "label") == 0)
1770 struct in6_addr prefix
;
1771 unsigned long int bits
;
1772 unsigned long int val
;
1777 nullbitsp
= &labellist_nullbits
;
1782 cp
= strchr (val1
, '/');
1785 if (inet_pton (AF_INET6
, val1
, &prefix
)
1787 || (bits
= strtoul (cp
, &endp
, 10)) != ULONG_MAX
1791 && ((val
= strtoul (val2
, &endp
, 10)) != ULONG_MAX
1796 struct prefixlist
*newp
= malloc (sizeof (*newp
));
1804 memcpy (&newp
->entry
.prefix
, &prefix
, sizeof (prefix
));
1805 newp
->entry
.bits
= bits
;
1806 newp
->entry
.val
= val
;
1807 newp
->next
= *listp
;
1810 *nullbitsp
|= bits
== 0;
1816 if (strcmp (cmd
, "reload") == 0)
1818 gaiconf_reload_flag
= strcmp (val1
, "yes") == 0;
1819 if (gaiconf_reload_flag
)
1820 gaiconf_reload_flag_ever_set
= 1;
1825 if (strcmp (cmd
, "scopev4") == 0)
1827 struct in6_addr prefix
;
1828 unsigned long int bits
;
1829 unsigned long int val
;
1834 cp
= strchr (val1
, '/');
1837 if (inet_pton (AF_INET6
, val1
, &prefix
))
1840 if (IN6_IS_ADDR_V4MAPPED (&prefix
)
1842 || (bits
= strtoul (cp
, &endp
, 10)) != ULONG_MAX
1847 && ((val
= strtoul (val2
, &endp
, 10)) != ULONG_MAX
1852 struct scopelist
*newp
;
1854 newp
= malloc (sizeof (*newp
));
1862 newp
->entry
.netmask
= htonl (bits
!= 96
1866 newp
->entry
.addr32
= (prefix
.s6_addr32
[3]
1867 & newp
->entry
.netmask
);
1868 newp
->entry
.scope
= val
;
1869 newp
->next
= scopelist
;
1872 scopelist_nullbits
|= bits
== 96;
1875 else if (inet_pton (AF_INET
, val1
, &prefix
.s6_addr32
[3])
1877 || (bits
= strtoul (cp
, &endp
, 10)) != ULONG_MAX
1881 && ((val
= strtoul (val2
, &endp
, 10)) != ULONG_MAX
1893 if (strcmp (cmd
, "precedence") == 0)
1895 listp
= &precedencelist
;
1896 lenp
= &nprecedencelist
;
1897 nullbitsp
= &precedencelist_nullbits
;
1908 /* Create the array for the labels. */
1909 struct prefixentry
*new_labels
;
1912 if (!labellist_nullbits
)
1914 new_labels
= malloc (nlabellist
* sizeof (*new_labels
));
1915 if (new_labels
== NULL
)
1919 if (!labellist_nullbits
)
1922 memset (&new_labels
[i
].prefix
, '\0', sizeof (struct in6_addr
));
1923 new_labels
[i
].bits
= 0;
1924 new_labels
[i
].val
= 1;
1927 struct prefixlist
*l
= labellist
;
1930 new_labels
[i
] = l
->entry
;
1933 free_prefixlist (labellist
);
1935 /* Sort the entries so that the most specific ones are at
1937 qsort (new_labels
, nlabellist
, sizeof (*new_labels
), prefixcmp
);
1940 new_labels
= (struct prefixentry
*) default_labels
;
1942 struct prefixentry
*new_precedence
;
1943 if (nprecedencelist
> 0)
1945 if (!precedencelist_nullbits
)
1947 new_precedence
= malloc (nprecedencelist
* sizeof (*new_precedence
));
1948 if (new_precedence
== NULL
)
1950 if (new_labels
!= default_labels
)
1955 int i
= nprecedencelist
;
1956 if (!precedencelist_nullbits
)
1959 memset (&new_precedence
[i
].prefix
, '\0',
1960 sizeof (struct in6_addr
));
1961 new_precedence
[i
].bits
= 0;
1962 new_precedence
[i
].val
= 40;
1965 struct prefixlist
*l
= precedencelist
;
1968 new_precedence
[i
] = l
->entry
;
1971 free_prefixlist (precedencelist
);
1973 /* Sort the entries so that the most specific ones are at
1975 qsort (new_precedence
, nprecedencelist
, sizeof (*new_precedence
),
1979 new_precedence
= (struct prefixentry
*) default_precedence
;
1981 struct scopeentry
*new_scopes
;
1984 if (!scopelist_nullbits
)
1986 new_scopes
= malloc (nscopelist
* sizeof (*new_scopes
));
1987 if (new_scopes
== NULL
)
1989 if (new_labels
!= default_labels
)
1991 if (new_precedence
!= default_precedence
)
1992 free (new_precedence
);
1997 if (!scopelist_nullbits
)
2000 new_scopes
[i
].addr32
= 0;
2001 new_scopes
[i
].netmask
= 0;
2002 new_scopes
[i
].scope
= 14;
2005 struct scopelist
*l
= scopelist
;
2008 new_scopes
[i
] = l
->entry
;
2011 free_scopelist (scopelist
);
2013 /* Sort the entries so that the most specific ones are at
2015 qsort (new_scopes
, nscopelist
, sizeof (*new_scopes
),
2019 new_scopes
= (struct scopeentry
*) default_scopes
;
2021 /* Now we are ready to replace the values. */
2022 const struct prefixentry
*old
= labels
;
2023 labels
= new_labels
;
2024 if (old
!= default_labels
)
2025 free ((void *) old
);
2028 precedence
= new_precedence
;
2029 if (old
!= default_precedence
)
2030 free ((void *) old
);
2032 const struct scopeentry
*oldscope
= scopes
;
2033 scopes
= new_scopes
;
2034 if (oldscope
!= default_scopes
)
2035 free ((void *) oldscope
);
2037 gaiconf_mtime
= st
.st_mtim
;
2042 free_prefixlist (labellist
);
2043 free_prefixlist (precedencelist
);
2044 free_scopelist (scopelist
);
2046 /* If we previously read the file but it is gone now, free the
2047 old data and use the builtin one. Leave the reload flag
2055 gaiconf_reload (void)
2058 if (__xstat64 (_STAT_VER
, GAICONF_FNAME
, &st
) != 0
2059 || memcmp (&st
.st_mtim
, &gaiconf_mtime
, sizeof (gaiconf_mtime
)) != 0)
2065 getaddrinfo (const char *name
, const char *service
,
2066 const struct addrinfo
*hints
, struct addrinfo
**pai
)
2068 int i
= 0, last_i
= 0;
2070 struct addrinfo
*p
= NULL
;
2071 struct gaih_service gaih_service
, *pservice
;
2072 struct addrinfo local_hints
;
2074 if (name
!= NULL
&& name
[0] == '*' && name
[1] == 0)
2077 if (service
!= NULL
&& service
[0] == '*' && service
[1] == 0)
2080 if (name
== NULL
&& service
== NULL
)
2084 hints
= &default_hints
;
2087 & ~(AI_PASSIVE
|AI_CANONNAME
|AI_NUMERICHOST
|AI_ADDRCONFIG
|AI_V4MAPPED
2089 |AI_IDN
|AI_CANONIDN
|AI_IDN_ALLOW_UNASSIGNED
2090 |AI_IDN_USE_STD3_ASCII_RULES
2092 |AI_NUMERICSERV
|AI_ALL
))
2093 return EAI_BADFLAGS
;
2095 if ((hints
->ai_flags
& AI_CANONNAME
) && name
== NULL
)
2096 return EAI_BADFLAGS
;
2098 struct in6addrinfo
*in6ai
= NULL
;
2099 size_t in6ailen
= 0;
2100 bool seen_ipv4
= false;
2101 bool seen_ipv6
= false;
2102 /* We might need information about what interfaces are available.
2103 Also determine whether we have IPv4 or IPv6 interfaces or both. We
2104 cannot cache the results since new interfaces could be added at
2106 __check_pf (&seen_ipv4
, &seen_ipv6
, &in6ai
, &in6ailen
);
2108 if (hints
->ai_flags
& AI_ADDRCONFIG
)
2110 /* Now make a decision on what we return, if anything. */
2111 if (hints
->ai_family
== PF_UNSPEC
&& (seen_ipv4
|| seen_ipv6
))
2113 /* If we haven't seen both IPv4 and IPv6 interfaces we can
2114 narrow down the search. */
2115 if ((! seen_ipv4
|| ! seen_ipv6
) && (seen_ipv4
|| seen_ipv6
))
2117 local_hints
= *hints
;
2118 local_hints
.ai_family
= seen_ipv4
? PF_INET
: PF_INET6
;
2119 hints
= &local_hints
;
2122 else if ((hints
->ai_family
== PF_INET
&& ! seen_ipv4
)
2123 || (hints
->ai_family
== PF_INET6
&& ! seen_ipv6
))
2125 /* We cannot possibly return a valid answer. */
2131 if (service
&& service
[0])
2134 gaih_service
.name
= service
;
2135 gaih_service
.num
= strtoul (gaih_service
.name
, &c
, 10);
2138 if (hints
->ai_flags
& AI_NUMERICSERV
)
2144 gaih_service
.num
= -1;
2147 pservice
= &gaih_service
;
2152 struct addrinfo
**end
= &p
;
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
);
2168 end
= &((*end
)->ai_next
);
2180 /* Read the config file. */
2181 __libc_once_define (static, once
);
2182 __typeof (once
) old_once
= once
;
2183 __libc_once (once
, gaiconf_init
);
2184 /* Sort results according to RFC 3484. */
2185 struct sort_result results
[nresults
];
2186 size_t order
[nresults
];
2188 struct addrinfo
*last
= NULL
;
2189 char *canonname
= NULL
;
2191 /* If we have information about deprecated and temporary addresses
2192 sort the array now. */
2194 qsort (in6ai
, in6ailen
, sizeof (*in6ai
), in6aicmp
);
2199 for (i
= 0, q
= p
; q
!= NULL
; ++i
, last
= q
, q
= q
->ai_next
)
2201 results
[i
].dest_addr
= q
;
2202 results
[i
].native
= -1;
2205 /* If we just looked up the address for a different
2206 protocol, reuse the result. */
2207 if (last
!= NULL
&& last
->ai_addrlen
== q
->ai_addrlen
2208 && memcmp (last
->ai_addr
, q
->ai_addr
, q
->ai_addrlen
) == 0)
2210 memcpy (&results
[i
].source_addr
, &results
[i
- 1].source_addr
,
2211 results
[i
- 1].source_addr_len
);
2212 results
[i
].source_addr_len
= results
[i
- 1].source_addr_len
;
2213 results
[i
].got_source_addr
= results
[i
- 1].got_source_addr
;
2214 results
[i
].source_addr_flags
= results
[i
- 1].source_addr_flags
;
2215 results
[i
].prefixlen
= results
[i
- 1].prefixlen
;
2216 results
[i
].index
= results
[i
- 1].index
;
2220 results
[i
].got_source_addr
= false;
2221 results
[i
].source_addr_flags
= 0;
2222 results
[i
].prefixlen
= 0;
2223 results
[i
].index
= 0xffffffffu
;
2225 /* We overwrite the type with SOCK_DGRAM since we do not
2226 want connect() to connect to the other side. If we
2227 cannot determine the source address remember this
2229 if (fd
== -1 || (af
== AF_INET
&& q
->ai_family
== AF_INET6
))
2233 close_not_cancel_no_status (fd
);
2235 fd
= __socket (af
, SOCK_DGRAM
, IPPROTO_IP
);
2239 /* Reset the connection. */
2240 struct sockaddr sa
= { .sa_family
= AF_UNSPEC
};
2241 __connect (fd
, &sa
, sizeof (sa
));
2244 socklen_t sl
= sizeof (results
[i
].source_addr
);
2246 && __connect (fd
, q
->ai_addr
, q
->ai_addrlen
) == 0
2247 && __getsockname (fd
,
2248 (struct sockaddr
*) &results
[i
].source_addr
,
2251 results
[i
].source_addr_len
= sl
;
2252 results
[i
].got_source_addr
= true;
2256 /* See whether the source address is on the list of
2257 deprecated or temporary addresses. */
2258 struct in6addrinfo tmp
;
2260 if (q
->ai_family
== AF_INET
&& af
== AF_INET
)
2262 struct sockaddr_in
*sinp
2263 = (struct sockaddr_in
*) &results
[i
].source_addr
;
2266 tmp
.addr
[2] = htonl (0xffff);
2267 tmp
.addr
[3] = sinp
->sin_addr
.s_addr
;
2271 struct sockaddr_in6
*sin6p
2272 = (struct sockaddr_in6
*) &results
[i
].source_addr
;
2273 memcpy (tmp
.addr
, &sin6p
->sin6_addr
, IN6ADDRSZ
);
2276 struct in6addrinfo
*found
2277 = bsearch (&tmp
, in6ai
, in6ailen
, sizeof (*in6ai
),
2281 results
[i
].source_addr_flags
= found
->flags
;
2282 results
[i
].prefixlen
= found
->prefixlen
;
2283 results
[i
].index
= found
->index
;
2287 if (q
->ai_family
== AF_INET
&& af
== AF_INET6
)
2289 /* We have to convert the address. The socket is
2290 IPv6 and the request is for IPv4. */
2291 struct sockaddr_in6
*sin6
2292 = (struct sockaddr_in6
*) &results
[i
].source_addr
;
2293 struct sockaddr_in
*sin
2294 = (struct sockaddr_in
*) &results
[i
].source_addr
;
2295 assert (IN6_IS_ADDR_V4MAPPED (sin6
->sin6_addr
.s6_addr32
));
2296 sin
->sin_family
= AF_INET
;
2297 /* We do not have to initialize sin_port since this
2298 fields has the same position and size in the IPv6
2300 assert (offsetof (struct sockaddr_in
, sin_port
)
2301 == offsetof (struct sockaddr_in6
, sin6_port
));
2302 assert (sizeof (sin
->sin_port
)
2303 == sizeof (sin6
->sin6_port
));
2304 memcpy (&sin
->sin_addr
,
2305 &sin6
->sin6_addr
.s6_addr32
[3], INADDRSZ
);
2306 results
[i
].source_addr_len
= sizeof (struct sockaddr_in
);
2309 else if (errno
== EAFNOSUPPORT
&& af
== AF_INET6
2310 && q
->ai_family
== AF_INET
)
2311 /* This could mean IPv6 sockets are IPv6-only. */
2314 /* Just make sure that if we have to process the same
2315 address again we do not copy any memory. */
2316 results
[i
].source_addr_len
= 0;
2319 /* Remember the canonical name. */
2320 if (q
->ai_canonname
!= NULL
)
2322 assert (canonname
== NULL
);
2323 canonname
= q
->ai_canonname
;
2324 q
->ai_canonname
= NULL
;
2329 close_not_cancel_no_status (fd
);
2331 /* We got all the source addresses we can get, now sort using
2333 struct sort_result_combo src
2334 = { .results
= results
, .nresults
= nresults
};
2335 if (__builtin_expect (gaiconf_reload_flag_ever_set
, 0))
2337 __libc_lock_define_initialized (static, lock
);
2339 __libc_lock_lock (lock
);
2340 if (old_once
&& gaiconf_reload_flag
)
2342 qsort_r (order
, nresults
, sizeof (order
[0]), rfc3484_sort
, &src
);
2343 __libc_lock_unlock (lock
);
2346 qsort_r (order
, nresults
, sizeof (order
[0]), rfc3484_sort
, &src
);
2348 /* Queue the results up as they come out of sorting. */
2349 q
= p
= results
[order
[0]].dest_addr
;
2350 for (i
= 1; i
< nresults
; ++i
)
2351 q
= q
->ai_next
= results
[order
[i
]].dest_addr
;
2354 /* Fill in the canonical name into the new first entry. */
2355 p
->ai_canonname
= canonname
;
2366 return last_i
? -(last_i
& GAIH_EAI
) : EAI_NONAME
;
2368 libc_hidden_def (getaddrinfo
)
2370 static_link_warning (getaddrinfo
)
2373 freeaddrinfo (struct addrinfo
*ai
)
2381 free (p
->ai_canonname
);
2385 libc_hidden_def (freeaddrinfo
)