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
;
837 status
= NSS_STATUS_UNAVAIL
;
840 if (nss_next_action (nip
, status
) == NSS_ACTION_RETURN
)
843 if (nip
->next
== NULL
)
849 _res
.options
= old_res_options
;
851 if (no_data
!= 0 && no_inet6_data
!= 0)
853 /* If both requests timed out report this. */
854 if (no_data
== EAI_AGAIN
&& no_inet6_data
== EAI_AGAIN
)
857 /* We made requests but they turned out no data. The name
859 return GAIH_OKIFUNSPEC
| -EAI_NODATA
;
864 if (at
->family
== AF_UNSPEC
)
865 return GAIH_OKIFUNSPEC
| -EAI_NONAME
;
869 struct gaih_addrtuple
*atr
;
870 atr
= at
= __alloca (sizeof (struct gaih_addrtuple
));
871 memset (at
, '\0', sizeof (struct gaih_addrtuple
));
873 if (req
->ai_family
== AF_UNSPEC
)
875 at
->next
= __alloca (sizeof (struct gaih_addrtuple
));
876 memset (at
->next
, '\0', sizeof (struct gaih_addrtuple
));
879 if (req
->ai_family
== AF_UNSPEC
|| req
->ai_family
== AF_INET6
)
881 at
->family
= AF_INET6
;
882 if ((req
->ai_flags
& AI_PASSIVE
) == 0)
883 memcpy (at
->addr
, &in6addr_loopback
, sizeof (struct in6_addr
));
887 if (req
->ai_family
== AF_UNSPEC
|| req
->ai_family
== AF_INET
)
889 atr
->family
= AF_INET
;
890 if ((req
->ai_flags
& AI_PASSIVE
) == 0)
891 atr
->addr
[0] = htonl (INADDR_LOOPBACK
);
896 struct gaih_servtuple
*st2
;
897 struct gaih_addrtuple
*at2
= at
;
902 buffer is the size of an unformatted IPv6 address in printable format.
906 /* Only the first entry gets the canonical name. */
907 if (at2
== at
&& (req
->ai_flags
& AI_CANONNAME
) != 0)
911 struct hostent
*h
= NULL
;
914 size_t tmpbuflen
= 512;
919 tmpbuf
= extend_alloca (tmpbuf
, tmpbuflen
, tmpbuflen
* 2);
920 rc
= __gethostbyaddr_r (at2
->addr
,
921 ((at2
->family
== AF_INET6
)
922 ? sizeof (struct in6_addr
)
923 : sizeof (struct in_addr
)),
924 at2
->family
, &th
, tmpbuf
,
925 tmpbuflen
, &h
, &herrno
);
927 while (rc
== ERANGE
&& herrno
== NETDB_INTERNAL
);
929 if (rc
!= 0 && herrno
== NETDB_INTERNAL
)
931 __set_h_errno (herrno
);
939 assert (orig_name
!= NULL
);
940 /* If the canonical name cannot be determined, use
941 the passed in string. */
947 if (req
->ai_flags
& AI_CANONIDN
)
950 if (req
->ai_flags
& AI_IDN_ALLOW_UNASSIGNED
)
951 idn_flags
|= IDNA_ALLOW_UNASSIGNED
;
952 if (req
->ai_flags
& AI_IDN_USE_STD3_ASCII_RULES
)
953 idn_flags
|= IDNA_USE_STD3_ASCII_RULES
;
956 int rc
= __idna_to_unicode_lzlz (canon
, &out
, idn_flags
);
957 if (rc
!= IDNA_SUCCESS
)
959 if (rc
== IDNA_MALLOC_ERROR
)
961 if (rc
== IDNA_DLOPEN_ERROR
)
963 return -EAI_IDN_ENCODE
;
965 /* In case the output string is the same as the input
966 string no new string has been allocated and we
977 canon
= strdup (canon
);
983 family
= at2
->family
;
984 if (family
== AF_INET6
)
986 socklen
= sizeof (struct sockaddr_in6
);
988 /* If we looked up IPv4 mapped address discard them here if
989 the caller isn't interested in all address and we have
990 found at least one IPv6 address. */
992 && (req
->ai_flags
& (AI_V4MAPPED
|AI_ALL
)) == AI_V4MAPPED
993 && IN6_IS_ADDR_V4MAPPED (at2
->addr
))
997 socklen
= sizeof (struct sockaddr_in
);
999 for (st2
= st
; st2
!= NULL
; st2
= st2
->next
)
1001 struct addrinfo
*ai
;
1002 ai
= *pai
= malloc (sizeof (struct addrinfo
) + socklen
);
1005 free ((char *) canon
);
1009 ai
->ai_flags
= req
->ai_flags
;
1010 ai
->ai_family
= family
;
1011 ai
->ai_socktype
= st2
->socktype
;
1012 ai
->ai_protocol
= st2
->protocol
;
1013 ai
->ai_addrlen
= socklen
;
1014 ai
->ai_addr
= (void *) (ai
+ 1);
1016 /* We only add the canonical name once. */
1017 ai
->ai_canonname
= (char *) canon
;
1021 ai
->ai_addr
->sa_len
= socklen
;
1022 #endif /* _HAVE_SA_LEN */
1023 ai
->ai_addr
->sa_family
= family
;
1025 /* In case of an allocation error the list must be NULL
1029 if (family
== AF_INET6
)
1031 struct sockaddr_in6
*sin6p
=
1032 (struct sockaddr_in6
*) ai
->ai_addr
;
1034 sin6p
->sin6_port
= st2
->port
;
1035 sin6p
->sin6_flowinfo
= 0;
1036 memcpy (&sin6p
->sin6_addr
,
1037 at2
->addr
, sizeof (struct in6_addr
));
1038 sin6p
->sin6_scope_id
= at2
->scopeid
;
1042 struct sockaddr_in
*sinp
=
1043 (struct sockaddr_in
*) ai
->ai_addr
;
1044 sinp
->sin_port
= st2
->port
;
1045 memcpy (&sinp
->sin_addr
,
1046 at2
->addr
, sizeof (struct in_addr
));
1047 memset (sinp
->sin_zero
, '\0', sizeof (sinp
->sin_zero
));
1050 pai
= &(ai
->ai_next
);
1065 struct addrinfo
*dest_addr
;
1066 /* Using sockaddr_storage is for now overkill. We only support IPv4
1067 and IPv6 so far. If this changes at some point we can adjust the
1069 struct sockaddr_in6 source_addr
;
1070 uint8_t source_addr_len
;
1071 bool got_source_addr
;
1072 uint8_t source_addr_flags
;
1078 struct sort_result_combo
1080 struct sort_result
*results
;
1085 #if __BYTE_ORDER == __BIG_ENDIAN
1086 # define htonl_c(n) n
1088 # define htonl_c(n) __bswap_constant_32 (n)
1091 static const struct scopeentry
1100 } default_scopes
[] =
1102 /* Link-local addresses: scope 2. */
1103 { { { 169, 254, 0, 0 } }, htonl_c (0xffff0000), 2 },
1104 { { { 127, 0, 0, 0 } }, htonl_c (0xff000000), 2 },
1105 /* Site-local addresses: scope 5. */
1106 { { { 10, 0, 0, 0 } }, htonl_c (0xff000000), 5 },
1107 { { { 172, 16, 0, 0 } }, htonl_c (0xfff00000), 5 },
1108 { { { 192, 168, 0, 0 } }, htonl_c (0xffff0000), 5 },
1109 /* Default: scope 14. */
1110 { { { 0, 0, 0, 0 } }, htonl_c (0x00000000), 14 }
1113 /* The label table. */
1114 static const struct scopeentry
*scopes
;
1118 get_scope (const struct sockaddr_in6
*in6
)
1121 if (in6
->sin6_family
== PF_INET6
)
1123 if (! IN6_IS_ADDR_MULTICAST (&in6
->sin6_addr
))
1125 if (IN6_IS_ADDR_LINKLOCAL (&in6
->sin6_addr
)
1126 /* RFC 4291 2.5.3 says that the loopback address is to be
1127 treated like a link-local address. */
1128 || IN6_IS_ADDR_LOOPBACK (&in6
->sin6_addr
))
1130 else if (IN6_IS_ADDR_SITELOCAL (&in6
->sin6_addr
))
1133 /* XXX Is this the correct default behavior? */
1137 scope
= in6
->sin6_addr
.s6_addr
[1] & 0xf;
1139 else if (in6
->sin6_family
== PF_INET
)
1141 const struct sockaddr_in
*in
= (const struct sockaddr_in
*) in6
;
1146 if ((in
->sin_addr
.s_addr
& scopes
[cnt
].netmask
)
1147 == scopes
[cnt
].addr32
)
1148 return scopes
[cnt
].scope
;
1155 /* XXX What is a good default? */
1164 struct in6_addr prefix
;
1170 /* The label table. */
1171 static const struct prefixentry
*labels
;
1173 /* Default labels. */
1174 static const struct prefixentry default_labels
[] =
1176 /* See RFC 3484 for the details. */
1178 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1179 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } }
1182 = { .__u6_addr8
= { 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1183 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1186 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1187 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1190 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1191 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 } }
1193 /* The next two entries differ from RFC 3484. We need to treat
1194 IPv6 site-local addresses special because they are never NATed,
1195 unlike site-locale IPv4 addresses. If this would not happen, on
1196 machines which have only IPv4 and IPv6 site-local addresses, the
1197 sorting would prefer the IPv6 site-local addresses, causing
1198 unnecessary delays when trying to connect to a global IPv6 address
1199 through a site-local IPv6 address. */
1201 = { .__u6_addr8
= { 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1202 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1205 = { .__u6_addr8
= { 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1206 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1208 /* Additional rule for Teredo tunnels. */
1210 = { .__u6_addr8
= { 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1211 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1214 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1215 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1220 /* The precedence table. */
1221 static const struct prefixentry
*precedence
;
1223 /* The default precedences. */
1224 static const struct prefixentry default_precedence
[] =
1226 /* See RFC 3484 for the details. */
1228 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1229 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } }
1232 = { .__u6_addr8
= { 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1233 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1236 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1237 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1240 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1241 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 } }
1244 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1245 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1251 match_prefix (const struct sockaddr_in6
*in6
,
1252 const struct prefixentry
*list
, int default_val
)
1255 struct sockaddr_in6 in6_mem
;
1257 if (in6
->sin6_family
== PF_INET
)
1259 const struct sockaddr_in
*in
= (const struct sockaddr_in
*) in6
;
1261 /* Construct a V4-to-6 mapped address. */
1262 in6_mem
.sin6_family
= PF_INET6
;
1263 in6_mem
.sin6_port
= in
->sin_port
;
1264 in6_mem
.sin6_flowinfo
= 0;
1265 memset (&in6_mem
.sin6_addr
, '\0', sizeof (in6_mem
.sin6_addr
));
1266 in6_mem
.sin6_addr
.s6_addr16
[5] = 0xffff;
1267 in6_mem
.sin6_addr
.s6_addr32
[3] = in
->sin_addr
.s_addr
;
1268 in6_mem
.sin6_scope_id
= 0;
1272 else if (in6
->sin6_family
!= PF_INET6
)
1275 for (idx
= 0; ; ++idx
)
1277 unsigned int bits
= list
[idx
].bits
;
1278 const uint8_t *mask
= list
[idx
].prefix
.s6_addr
;
1279 const uint8_t *val
= in6
->sin6_addr
.s6_addr
;
1293 if ((*mask
& (0xff00 >> bits
)) == (*val
& (0xff00 >> bits
)))
1299 return list
[idx
].val
;
1304 get_label (const struct sockaddr_in6
*in6
)
1306 /* XXX What is a good default value? */
1307 return match_prefix (in6
, labels
, INT_MAX
);
1312 get_precedence (const struct sockaddr_in6
*in6
)
1314 /* XXX What is a good default value? */
1315 return match_prefix (in6
, precedence
, 0);
1319 /* Find last bit set in a word. */
1325 for (n
= 0, mask
= 1 << 31; n
< 32; mask
>>= 1, ++n
)
1326 if ((a
& mask
) != 0)
1333 rfc3484_sort (const void *p1
, const void *p2
, void *arg
)
1335 const size_t idx1
= *(const size_t *) p1
;
1336 const size_t idx2
= *(const size_t *) p2
;
1337 struct sort_result_combo
*src
= (struct sort_result_combo
*) arg
;
1338 struct sort_result
*a1
= &src
->results
[idx1
];
1339 struct sort_result
*a2
= &src
->results
[idx2
];
1341 /* Rule 1: Avoid unusable destinations.
1342 We have the got_source_addr flag set if the destination is reachable. */
1343 if (a1
->got_source_addr
&& ! a2
->got_source_addr
)
1345 if (! a1
->got_source_addr
&& a2
->got_source_addr
)
1349 /* Rule 2: Prefer matching scope. Only interesting if both
1350 destination addresses are IPv6. */
1352 = get_scope ((struct sockaddr_in6
*) a1
->dest_addr
->ai_addr
);
1355 = get_scope ((struct sockaddr_in6
*) a2
->dest_addr
->ai_addr
);
1357 if (a1
->got_source_addr
)
1359 int a1_src_scope
= get_scope (&a1
->source_addr
);
1360 int a2_src_scope
= get_scope (&a2
->source_addr
);
1362 if (a1_dst_scope
== a1_src_scope
&& a2_dst_scope
!= a2_src_scope
)
1364 if (a1_dst_scope
!= a1_src_scope
&& a2_dst_scope
== a2_src_scope
)
1369 /* Rule 3: Avoid deprecated addresses. */
1370 if (a1
->got_source_addr
)
1372 if (!(a1
->source_addr_flags
& in6ai_deprecated
)
1373 && (a2
->source_addr_flags
& in6ai_deprecated
))
1375 if ((a1
->source_addr_flags
& in6ai_deprecated
)
1376 && !(a2
->source_addr_flags
& in6ai_deprecated
))
1380 /* Rule 4: Prefer home addresses. */
1381 if (a1
->got_source_addr
)
1383 if (!(a1
->source_addr_flags
& in6ai_homeaddress
)
1384 && (a2
->source_addr_flags
& in6ai_homeaddress
))
1386 if ((a1
->source_addr_flags
& in6ai_homeaddress
)
1387 && !(a2
->source_addr_flags
& in6ai_homeaddress
))
1391 /* Rule 5: Prefer matching label. */
1392 if (a1
->got_source_addr
)
1395 = get_label ((struct sockaddr_in6
*) a1
->dest_addr
->ai_addr
);
1396 int a1_src_label
= get_label (&a1
->source_addr
);
1399 = get_label ((struct sockaddr_in6
*) a2
->dest_addr
->ai_addr
);
1400 int a2_src_label
= get_label (&a2
->source_addr
);
1402 if (a1_dst_label
== a1_src_label
&& a2_dst_label
!= a2_src_label
)
1404 if (a1_dst_label
!= a1_src_label
&& a2_dst_label
== a2_src_label
)
1409 /* Rule 6: Prefer higher precedence. */
1411 = get_precedence ((struct sockaddr_in6
*) a1
->dest_addr
->ai_addr
);
1413 = get_precedence ((struct sockaddr_in6
*) a2
->dest_addr
->ai_addr
);
1415 if (a1_prec
> a2_prec
)
1417 if (a1_prec
< a2_prec
)
1421 /* Rule 7: Prefer native transport. */
1422 if (a1
->got_source_addr
)
1424 /* The same interface index means the same interface which means
1425 there is no difference in transport. This should catch many
1427 if (a1
->index
!= a2
->index
)
1429 int a1_native
= a1
->native
;
1430 int a2_native
= a2
->native
;
1432 if (a1_native
== -1 || a2_native
== -1)
1435 if (a1_native
== -1)
1437 /* If we do not have the information use 'native' as
1440 a1_index
= a1
->index
;
1443 a1_index
= 0xffffffffu
;
1446 if (a2_native
== -1)
1448 /* If we do not have the information use 'native' as
1451 a2_index
= a2
->index
;
1454 a2_index
= 0xffffffffu
;
1456 __check_native (a1_index
, &a1_native
, a2_index
, &a2_native
);
1458 /* Fill in the results in all the records. */
1459 for (int i
= 0; i
< src
->nresults
; ++i
)
1460 if (src
->results
[i
].index
== a1_index
)
1462 assert (src
->results
[i
].native
== -1
1463 || src
->results
[i
].native
== a1_native
);
1464 src
->results
[i
].native
= a1_native
;
1466 else if (src
->results
[i
].index
== a2_index
)
1468 assert (src
->results
[i
].native
== -1
1469 || src
->results
[i
].native
== a2_native
);
1470 src
->results
[i
].native
= a2_native
;
1474 if (a1_native
&& !a2_native
)
1476 if (!a1_native
&& a2_native
)
1482 /* Rule 8: Prefer smaller scope. */
1483 if (a1_dst_scope
< a2_dst_scope
)
1485 if (a1_dst_scope
> a2_dst_scope
)
1489 /* Rule 9: Use longest matching prefix. */
1490 if (a1
->got_source_addr
1491 && a1
->dest_addr
->ai_family
== a2
->dest_addr
->ai_family
)
1496 if (a1
->dest_addr
->ai_family
== PF_INET
)
1498 assert (a1
->source_addr
.sin6_family
== PF_INET
);
1499 assert (a2
->source_addr
.sin6_family
== PF_INET
);
1501 /* Outside of subnets, as defined by the network masks,
1502 common address prefixes for IPv4 addresses make no sense.
1503 So, define a non-zero value only if source and
1504 destination address are on the same subnet. */
1505 struct sockaddr_in
*in1_dst
1506 = (struct sockaddr_in
*) a1
->dest_addr
->ai_addr
;
1507 in_addr_t in1_dst_addr
= ntohl (in1_dst
->sin_addr
.s_addr
);
1508 struct sockaddr_in
*in1_src
1509 = (struct sockaddr_in
*) &a1
->source_addr
;
1510 in_addr_t in1_src_addr
= ntohl (in1_src
->sin_addr
.s_addr
);
1511 in_addr_t netmask1
= 0xffffffffu
<< (32 - a1
->prefixlen
);
1513 if ((in1_src_addr
& netmask1
) == (in1_dst_addr
& netmask1
))
1514 bit1
= fls (in1_dst_addr
^ in1_src_addr
);
1516 struct sockaddr_in
*in2_dst
1517 = (struct sockaddr_in
*) a2
->dest_addr
->ai_addr
;
1518 in_addr_t in2_dst_addr
= ntohl (in2_dst
->sin_addr
.s_addr
);
1519 struct sockaddr_in
*in2_src
1520 = (struct sockaddr_in
*) &a2
->source_addr
;
1521 in_addr_t in2_src_addr
= ntohl (in2_src
->sin_addr
.s_addr
);
1522 in_addr_t netmask2
= 0xffffffffu
<< (32 - a2
->prefixlen
);
1524 if ((in2_src_addr
& netmask2
) == (in2_dst_addr
& netmask2
))
1525 bit2
= fls (in2_dst_addr
^ in2_src_addr
);
1527 else if (a1
->dest_addr
->ai_family
== PF_INET6
)
1529 assert (a1
->source_addr
.sin6_family
== PF_INET6
);
1530 assert (a2
->source_addr
.sin6_family
== PF_INET6
);
1532 struct sockaddr_in6
*in1_dst
;
1533 struct sockaddr_in6
*in1_src
;
1534 struct sockaddr_in6
*in2_dst
;
1535 struct sockaddr_in6
*in2_src
;
1537 in1_dst
= (struct sockaddr_in6
*) a1
->dest_addr
->ai_addr
;
1538 in1_src
= (struct sockaddr_in6
*) &a1
->source_addr
;
1539 in2_dst
= (struct sockaddr_in6
*) a2
->dest_addr
->ai_addr
;
1540 in2_src
= (struct sockaddr_in6
*) &a2
->source_addr
;
1543 for (i
= 0; i
< 4; ++i
)
1544 if (in1_dst
->sin6_addr
.s6_addr32
[i
]
1545 != in1_src
->sin6_addr
.s6_addr32
[i
]
1546 || (in2_dst
->sin6_addr
.s6_addr32
[i
]
1547 != in2_src
->sin6_addr
.s6_addr32
[i
]))
1552 bit1
= fls (ntohl (in1_dst
->sin6_addr
.s6_addr32
[i
]
1553 ^ in1_src
->sin6_addr
.s6_addr32
[i
]));
1554 bit2
= fls (ntohl (in2_dst
->sin6_addr
.s6_addr32
[i
]
1555 ^ in2_src
->sin6_addr
.s6_addr32
[i
]));
1566 /* Rule 10: Otherwise, leave the order unchanged. To ensure this
1567 compare with the value indicating the order in which the entries
1568 have been received from the services. NB: no two entries can have
1569 the same order so the test will never return zero. */
1570 return idx1
< idx2
? -1 : 1;
1575 in6aicmp (const void *p1
, const void *p2
)
1577 struct in6addrinfo
*a1
= (struct in6addrinfo
*) p1
;
1578 struct in6addrinfo
*a2
= (struct in6addrinfo
*) p2
;
1580 return memcmp (a1
->addr
, a2
->addr
, sizeof (a1
->addr
));
1584 /* Name of the config file for RFC 3484 sorting (for now). */
1585 #define GAICONF_FNAME "/etc/gai.conf"
1588 /* Non-zero if we are supposed to reload the config file automatically
1589 whenever it changed. */
1590 static int gaiconf_reload_flag
;
1592 /* Non-zero if gaiconf_reload_flag was ever set to true. */
1593 static int gaiconf_reload_flag_ever_set
;
1595 /* Last modification time. */
1596 static struct timespec gaiconf_mtime
;
1599 libc_freeres_fn(fini
)
1601 if (labels
!= default_labels
)
1603 const struct prefixentry
*old
= labels
;
1604 labels
= default_labels
;
1605 free ((void *) old
);
1608 if (precedence
!= default_precedence
)
1610 const struct prefixentry
*old
= precedence
;
1611 precedence
= default_precedence
;
1612 free ((void *) old
);
1615 if (scopes
!= default_scopes
)
1617 const struct scopeentry
*old
= scopes
;
1618 scopes
= default_scopes
;
1619 free ((void *) old
);
1626 struct prefixentry entry
;
1627 struct prefixlist
*next
;
1633 struct scopeentry entry
;
1634 struct scopelist
*next
;
1639 free_prefixlist (struct prefixlist
*list
)
1641 while (list
!= NULL
)
1643 struct prefixlist
*oldp
= list
;
1651 free_scopelist (struct scopelist
*list
)
1653 while (list
!= NULL
)
1655 struct scopelist
*oldp
= list
;
1663 prefixcmp (const void *p1
, const void *p2
)
1665 const struct prefixentry
*e1
= (const struct prefixentry
*) p1
;
1666 const struct prefixentry
*e2
= (const struct prefixentry
*) p2
;
1668 if (e1
->bits
< e2
->bits
)
1670 if (e1
->bits
== e2
->bits
)
1677 scopecmp (const void *p1
, const void *p2
)
1679 const struct scopeentry
*e1
= (const struct scopeentry
*) p1
;
1680 const struct scopeentry
*e2
= (const struct scopeentry
*) p2
;
1682 if (e1
->netmask
> e2
->netmask
)
1684 if (e1
->netmask
== e2
->netmask
)
1693 struct prefixlist
*labellist
= NULL
;
1694 size_t nlabellist
= 0;
1695 bool labellist_nullbits
= false;
1696 struct prefixlist
*precedencelist
= NULL
;
1697 size_t nprecedencelist
= 0;
1698 bool precedencelist_nullbits
= false;
1699 struct scopelist
*scopelist
= NULL
;
1700 size_t nscopelist
= 0;
1701 bool scopelist_nullbits
= false;
1703 FILE *fp
= fopen (GAICONF_FNAME
, "rc");
1707 if (__fxstat64 (_STAT_VER
, fileno (fp
), &st
) != 0)
1716 __fsetlocking (fp
, FSETLOCKING_BYCALLER
);
1718 while (!feof_unlocked (fp
))
1720 ssize_t n
= __getline (&line
, &linelen
, fp
);
1724 /* Handle comments. No escaping possible so this is easy. */
1725 char *cp
= strchr (line
, '#');
1730 while (isspace (*cp
))
1734 while (*cp
!= '\0' && !isspace (*cp
))
1736 size_t cmdlen
= cp
- cmd
;
1740 while (isspace (*cp
))
1744 while (*cp
!= '\0' && !isspace (*cp
))
1746 size_t val1len
= cp
- cmd
;
1748 /* We always need at least two values. */
1754 while (isspace (*cp
))
1758 while (*cp
!= '\0' && !isspace (*cp
))
1761 /* Ignore the rest of the line. */
1764 struct prefixlist
**listp
;
1770 if (strcmp (cmd
, "label") == 0)
1772 struct in6_addr prefix
;
1773 unsigned long int bits
;
1774 unsigned long int val
;
1779 nullbitsp
= &labellist_nullbits
;
1784 cp
= strchr (val1
, '/');
1787 if (inet_pton (AF_INET6
, val1
, &prefix
)
1789 || (bits
= strtoul (cp
, &endp
, 10)) != ULONG_MAX
1793 && ((val
= strtoul (val2
, &endp
, 10)) != ULONG_MAX
1798 struct prefixlist
*newp
= malloc (sizeof (*newp
));
1806 memcpy (&newp
->entry
.prefix
, &prefix
, sizeof (prefix
));
1807 newp
->entry
.bits
= bits
;
1808 newp
->entry
.val
= val
;
1809 newp
->next
= *listp
;
1812 *nullbitsp
|= bits
== 0;
1818 if (strcmp (cmd
, "reload") == 0)
1820 gaiconf_reload_flag
= strcmp (val1
, "yes") == 0;
1821 if (gaiconf_reload_flag
)
1822 gaiconf_reload_flag_ever_set
= 1;
1827 if (strcmp (cmd
, "scopev4") == 0)
1829 struct in6_addr prefix
;
1830 unsigned long int bits
;
1831 unsigned long int val
;
1836 cp
= strchr (val1
, '/');
1839 if (inet_pton (AF_INET6
, val1
, &prefix
))
1842 if (IN6_IS_ADDR_V4MAPPED (&prefix
)
1844 || (bits
= strtoul (cp
, &endp
, 10)) != ULONG_MAX
1849 && ((val
= strtoul (val2
, &endp
, 10)) != ULONG_MAX
1854 struct scopelist
*newp
;
1856 newp
= malloc (sizeof (*newp
));
1864 newp
->entry
.netmask
= htonl (bits
!= 96
1868 newp
->entry
.addr32
= (prefix
.s6_addr32
[3]
1869 & newp
->entry
.netmask
);
1870 newp
->entry
.scope
= val
;
1871 newp
->next
= scopelist
;
1874 scopelist_nullbits
|= bits
== 96;
1877 else if (inet_pton (AF_INET
, val1
, &prefix
.s6_addr32
[3])
1879 || (bits
= strtoul (cp
, &endp
, 10)) != ULONG_MAX
1883 && ((val
= strtoul (val2
, &endp
, 10)) != ULONG_MAX
1895 if (strcmp (cmd
, "precedence") == 0)
1897 listp
= &precedencelist
;
1898 lenp
= &nprecedencelist
;
1899 nullbitsp
= &precedencelist_nullbits
;
1910 /* Create the array for the labels. */
1911 struct prefixentry
*new_labels
;
1914 if (!labellist_nullbits
)
1916 new_labels
= malloc (nlabellist
* sizeof (*new_labels
));
1917 if (new_labels
== NULL
)
1921 if (!labellist_nullbits
)
1924 memset (&new_labels
[i
].prefix
, '\0', sizeof (struct in6_addr
));
1925 new_labels
[i
].bits
= 0;
1926 new_labels
[i
].val
= 1;
1929 struct prefixlist
*l
= labellist
;
1932 new_labels
[i
] = l
->entry
;
1935 free_prefixlist (labellist
);
1937 /* Sort the entries so that the most specific ones are at
1939 qsort (new_labels
, nlabellist
, sizeof (*new_labels
), prefixcmp
);
1942 new_labels
= (struct prefixentry
*) default_labels
;
1944 struct prefixentry
*new_precedence
;
1945 if (nprecedencelist
> 0)
1947 if (!precedencelist_nullbits
)
1949 new_precedence
= malloc (nprecedencelist
* sizeof (*new_precedence
));
1950 if (new_precedence
== NULL
)
1952 if (new_labels
!= default_labels
)
1957 int i
= nprecedencelist
;
1958 if (!precedencelist_nullbits
)
1961 memset (&new_precedence
[i
].prefix
, '\0',
1962 sizeof (struct in6_addr
));
1963 new_precedence
[i
].bits
= 0;
1964 new_precedence
[i
].val
= 40;
1967 struct prefixlist
*l
= precedencelist
;
1970 new_precedence
[i
] = l
->entry
;
1973 free_prefixlist (precedencelist
);
1975 /* Sort the entries so that the most specific ones are at
1977 qsort (new_precedence
, nprecedencelist
, sizeof (*new_precedence
),
1981 new_precedence
= (struct prefixentry
*) default_precedence
;
1983 struct scopeentry
*new_scopes
;
1986 if (!scopelist_nullbits
)
1988 new_scopes
= malloc (nscopelist
* sizeof (*new_scopes
));
1989 if (new_scopes
== NULL
)
1991 if (new_labels
!= default_labels
)
1993 if (new_precedence
!= default_precedence
)
1994 free (new_precedence
);
1999 if (!scopelist_nullbits
)
2002 new_scopes
[i
].addr32
= 0;
2003 new_scopes
[i
].netmask
= 0;
2004 new_scopes
[i
].scope
= 14;
2007 struct scopelist
*l
= scopelist
;
2010 new_scopes
[i
] = l
->entry
;
2013 free_scopelist (scopelist
);
2015 /* Sort the entries so that the most specific ones are at
2017 qsort (new_scopes
, nscopelist
, sizeof (*new_scopes
),
2021 new_scopes
= (struct scopeentry
*) default_scopes
;
2023 /* Now we are ready to replace the values. */
2024 const struct prefixentry
*old
= labels
;
2025 labels
= new_labels
;
2026 if (old
!= default_labels
)
2027 free ((void *) old
);
2030 precedence
= new_precedence
;
2031 if (old
!= default_precedence
)
2032 free ((void *) old
);
2034 const struct scopeentry
*oldscope
= scopes
;
2035 scopes
= new_scopes
;
2036 if (oldscope
!= default_scopes
)
2037 free ((void *) oldscope
);
2039 gaiconf_mtime
= st
.st_mtim
;
2044 free_prefixlist (labellist
);
2045 free_prefixlist (precedencelist
);
2046 free_scopelist (scopelist
);
2048 /* If we previously read the file but it is gone now, free the
2049 old data and use the builtin one. Leave the reload flag
2057 gaiconf_reload (void)
2060 if (__xstat64 (_STAT_VER
, GAICONF_FNAME
, &st
) != 0
2061 || memcmp (&st
.st_mtim
, &gaiconf_mtime
, sizeof (gaiconf_mtime
)) != 0)
2067 getaddrinfo (const char *name
, const char *service
,
2068 const struct addrinfo
*hints
, struct addrinfo
**pai
)
2070 int i
= 0, last_i
= 0;
2072 struct addrinfo
*p
= NULL
;
2073 struct gaih_service gaih_service
, *pservice
;
2074 struct addrinfo local_hints
;
2076 if (name
!= NULL
&& name
[0] == '*' && name
[1] == 0)
2079 if (service
!= NULL
&& service
[0] == '*' && service
[1] == 0)
2082 if (name
== NULL
&& service
== NULL
)
2086 hints
= &default_hints
;
2089 & ~(AI_PASSIVE
|AI_CANONNAME
|AI_NUMERICHOST
|AI_ADDRCONFIG
|AI_V4MAPPED
2091 |AI_IDN
|AI_CANONIDN
|AI_IDN_ALLOW_UNASSIGNED
2092 |AI_IDN_USE_STD3_ASCII_RULES
2094 |AI_NUMERICSERV
|AI_ALL
))
2095 return EAI_BADFLAGS
;
2097 if ((hints
->ai_flags
& AI_CANONNAME
) && name
== NULL
)
2098 return EAI_BADFLAGS
;
2100 struct in6addrinfo
*in6ai
= NULL
;
2101 size_t in6ailen
= 0;
2102 bool seen_ipv4
= false;
2103 bool seen_ipv6
= false;
2104 /* We might need information about what interfaces are available.
2105 Also determine whether we have IPv4 or IPv6 interfaces or both. We
2106 cannot cache the results since new interfaces could be added at
2108 __check_pf (&seen_ipv4
, &seen_ipv6
, &in6ai
, &in6ailen
);
2110 if (hints
->ai_flags
& AI_ADDRCONFIG
)
2112 /* Now make a decision on what we return, if anything. */
2113 if (hints
->ai_family
== PF_UNSPEC
&& (seen_ipv4
|| seen_ipv6
))
2115 /* If we haven't seen both IPv4 and IPv6 interfaces we can
2116 narrow down the search. */
2117 if ((! seen_ipv4
|| ! seen_ipv6
) && (seen_ipv4
|| seen_ipv6
))
2119 local_hints
= *hints
;
2120 local_hints
.ai_family
= seen_ipv4
? PF_INET
: PF_INET6
;
2121 hints
= &local_hints
;
2124 else if ((hints
->ai_family
== PF_INET
&& ! seen_ipv4
)
2125 || (hints
->ai_family
== PF_INET6
&& ! seen_ipv6
))
2127 /* We cannot possibly return a valid answer. */
2133 if (service
&& service
[0])
2136 gaih_service
.name
= service
;
2137 gaih_service
.num
= strtoul (gaih_service
.name
, &c
, 10);
2140 if (hints
->ai_flags
& AI_NUMERICSERV
)
2146 gaih_service
.num
= -1;
2149 pservice
= &gaih_service
;
2154 struct addrinfo
**end
= &p
;
2156 unsigned int naddrs
= 0;
2157 if (hints
->ai_family
== AF_UNSPEC
|| hints
->ai_family
== AF_INET
2158 || hints
->ai_family
== AF_INET6
)
2160 last_i
= gaih_inet (name
, pservice
, hints
, end
, &naddrs
);
2166 return -(last_i
& GAIH_EAI
);
2170 end
= &((*end
)->ai_next
);
2182 /* Read the config file. */
2183 __libc_once_define (static, once
);
2184 __typeof (once
) old_once
= once
;
2185 __libc_once (once
, gaiconf_init
);
2186 /* Sort results according to RFC 3484. */
2187 struct sort_result results
[nresults
];
2188 size_t order
[nresults
];
2190 struct addrinfo
*last
= NULL
;
2191 char *canonname
= NULL
;
2193 /* If we have information about deprecated and temporary addresses
2194 sort the array now. */
2196 qsort (in6ai
, in6ailen
, sizeof (*in6ai
), in6aicmp
);
2201 for (i
= 0, q
= p
; q
!= NULL
; ++i
, last
= q
, q
= q
->ai_next
)
2203 results
[i
].dest_addr
= q
;
2204 results
[i
].native
= -1;
2207 /* If we just looked up the address for a different
2208 protocol, reuse the result. */
2209 if (last
!= NULL
&& last
->ai_addrlen
== q
->ai_addrlen
2210 && memcmp (last
->ai_addr
, q
->ai_addr
, q
->ai_addrlen
) == 0)
2212 memcpy (&results
[i
].source_addr
, &results
[i
- 1].source_addr
,
2213 results
[i
- 1].source_addr_len
);
2214 results
[i
].source_addr_len
= results
[i
- 1].source_addr_len
;
2215 results
[i
].got_source_addr
= results
[i
- 1].got_source_addr
;
2216 results
[i
].source_addr_flags
= results
[i
- 1].source_addr_flags
;
2217 results
[i
].prefixlen
= results
[i
- 1].prefixlen
;
2218 results
[i
].index
= results
[i
- 1].index
;
2222 results
[i
].got_source_addr
= false;
2223 results
[i
].source_addr_flags
= 0;
2224 results
[i
].prefixlen
= 0;
2225 results
[i
].index
= 0xffffffffu
;
2227 /* We overwrite the type with SOCK_DGRAM since we do not
2228 want connect() to connect to the other side. If we
2229 cannot determine the source address remember this
2231 if (fd
== -1 || (af
== AF_INET
&& q
->ai_family
== AF_INET6
))
2235 close_not_cancel_no_status (fd
);
2237 fd
= __socket (af
, SOCK_DGRAM
, IPPROTO_IP
);
2241 /* Reset the connection. */
2242 struct sockaddr sa
= { .sa_family
= AF_UNSPEC
};
2243 __connect (fd
, &sa
, sizeof (sa
));
2246 socklen_t sl
= sizeof (results
[i
].source_addr
);
2248 && __connect (fd
, q
->ai_addr
, q
->ai_addrlen
) == 0
2249 && __getsockname (fd
,
2250 (struct sockaddr
*) &results
[i
].source_addr
,
2253 results
[i
].source_addr_len
= sl
;
2254 results
[i
].got_source_addr
= true;
2258 /* See whether the source address is on the list of
2259 deprecated or temporary addresses. */
2260 struct in6addrinfo tmp
;
2262 if (q
->ai_family
== AF_INET
&& af
== AF_INET
)
2264 struct sockaddr_in
*sinp
2265 = (struct sockaddr_in
*) &results
[i
].source_addr
;
2268 tmp
.addr
[2] = htonl (0xffff);
2269 tmp
.addr
[3] = sinp
->sin_addr
.s_addr
;
2273 struct sockaddr_in6
*sin6p
2274 = (struct sockaddr_in6
*) &results
[i
].source_addr
;
2275 memcpy (tmp
.addr
, &sin6p
->sin6_addr
, IN6ADDRSZ
);
2278 struct in6addrinfo
*found
2279 = bsearch (&tmp
, in6ai
, in6ailen
, sizeof (*in6ai
),
2283 results
[i
].source_addr_flags
= found
->flags
;
2284 results
[i
].prefixlen
= found
->prefixlen
;
2285 results
[i
].index
= found
->index
;
2289 if (q
->ai_family
== AF_INET
&& af
== AF_INET6
)
2291 /* We have to convert the address. The socket is
2292 IPv6 and the request is for IPv4. */
2293 struct sockaddr_in6
*sin6
2294 = (struct sockaddr_in6
*) &results
[i
].source_addr
;
2295 struct sockaddr_in
*sin
2296 = (struct sockaddr_in
*) &results
[i
].source_addr
;
2297 assert (IN6_IS_ADDR_V4MAPPED (sin6
->sin6_addr
.s6_addr32
));
2298 sin
->sin_family
= AF_INET
;
2299 /* We do not have to initialize sin_port since this
2300 fields has the same position and size in the IPv6
2302 assert (offsetof (struct sockaddr_in
, sin_port
)
2303 == offsetof (struct sockaddr_in6
, sin6_port
));
2304 assert (sizeof (sin
->sin_port
)
2305 == sizeof (sin6
->sin6_port
));
2306 memcpy (&sin
->sin_addr
,
2307 &sin6
->sin6_addr
.s6_addr32
[3], INADDRSZ
);
2308 results
[i
].source_addr_len
= sizeof (struct sockaddr_in
);
2311 else if (errno
== EAFNOSUPPORT
&& af
== AF_INET6
2312 && q
->ai_family
== AF_INET
)
2313 /* This could mean IPv6 sockets are IPv6-only. */
2316 /* Just make sure that if we have to process the same
2317 address again we do not copy any memory. */
2318 results
[i
].source_addr_len
= 0;
2321 /* Remember the canonical name. */
2322 if (q
->ai_canonname
!= NULL
)
2324 assert (canonname
== NULL
);
2325 canonname
= q
->ai_canonname
;
2326 q
->ai_canonname
= NULL
;
2331 close_not_cancel_no_status (fd
);
2333 /* We got all the source addresses we can get, now sort using
2335 struct sort_result_combo src
2336 = { .results
= results
, .nresults
= nresults
};
2337 if (__builtin_expect (gaiconf_reload_flag_ever_set
, 0))
2339 __libc_lock_define_initialized (static, lock
);
2341 __libc_lock_lock (lock
);
2342 if (old_once
&& gaiconf_reload_flag
)
2344 qsort_r (order
, nresults
, sizeof (order
[0]), rfc3484_sort
, &src
);
2345 __libc_lock_unlock (lock
);
2348 qsort_r (order
, nresults
, sizeof (order
[0]), rfc3484_sort
, &src
);
2350 /* Queue the results up as they come out of sorting. */
2351 q
= p
= results
[order
[0]].dest_addr
;
2352 for (i
= 1; i
< nresults
; ++i
)
2353 q
= q
->ai_next
= results
[order
[i
]].dest_addr
;
2356 /* Fill in the canonical name into the new first entry. */
2357 p
->ai_canonname
= canonname
;
2368 return last_i
? -(last_i
& GAIH_EAI
) : EAI_NONAME
;
2370 libc_hidden_def (getaddrinfo
)
2372 static_link_warning (getaddrinfo
)
2375 freeaddrinfo (struct addrinfo
*ai
)
2383 free (p
->ai_canonname
);
2387 libc_hidden_def (freeaddrinfo
)