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. */
46 #include <stdio_ext.h>
49 #include <arpa/inet.h>
51 #include <netinet/in.h>
52 #include <sys/socket.h>
54 #include <sys/types.h>
56 #include <sys/utsname.h>
59 #include <bits/libc-lock.h>
60 #include <not-cancel.h>
61 #include <nscd/nscd-client.h>
62 #include <nscd/nscd_proto.h>
64 #ifdef HAVE_NETLINK_ROUTE
65 # include <kernel-features.h>
69 extern int __idna_to_ascii_lz (const char *input
, char **output
, int flags
);
70 extern int __idna_to_unicode_lzlz (const char *input
, char **output
,
72 # include <libidn/idna.h>
75 #define GAIH_OKIFUNSPEC 0x0100
76 #define GAIH_EAI ~(GAIH_OKIFUNSPEC)
79 # define UNIX_PATH_MAX 108
90 struct gaih_servtuple
*next
;
96 static const struct gaih_servtuple nullserv
;
100 struct gaih_addrtuple
*next
;
107 struct gaih_typeproto
115 /* Values for `protoflag'. */
116 #define GAI_PROTO_NOSERVICE 1
117 #define GAI_PROTO_PROTOANY 2
119 static const struct gaih_typeproto gaih_inet_typeproto
[] =
122 { SOCK_STREAM
, IPPROTO_TCP
, "tcp", 0 },
123 { SOCK_DGRAM
, IPPROTO_UDP
, "udp", 0 },
124 { SOCK_RAW
, 0, "raw", GAI_PROTO_PROTOANY
|GAI_PROTO_NOSERVICE
},
131 int (*gaih
)(const char *name
, const struct gaih_service
*service
,
132 const struct addrinfo
*req
, struct addrinfo
**pai
,
133 unsigned int *naddrs
);
136 static const struct addrinfo default_hints
=
138 .ai_flags
= AI_DEFAULT
,
139 .ai_family
= PF_UNSPEC
,
144 .ai_canonname
= NULL
,
150 gaih_inet_serv (const char *servicename
, const struct gaih_typeproto
*tp
,
151 const struct addrinfo
*req
, struct gaih_servtuple
*st
)
154 size_t tmpbuflen
= 1024;
161 tmpbuf
= __alloca (tmpbuflen
);
163 r
= __getservbyname_r (servicename
, tp
->name
, &ts
, tmpbuf
, tmpbuflen
,
165 if (r
!= 0 || s
== NULL
)
170 return GAIH_OKIFUNSPEC
| -EAI_SERVICE
;
176 st
->socktype
= tp
->socktype
;
177 st
->protocol
= ((tp
->protoflag
& GAI_PROTO_PROTOANY
)
178 ? req
->ai_protocol
: tp
->protocol
);
179 st
->port
= s
->s_port
;
184 #define gethosts(_family, _type) \
190 char *localcanon = NULL; \
194 status = DL_CALL_FCT (fct, (name, _family, &th, tmpbuf, tmpbuflen, \
195 &rc, &herrno, NULL, &localcanon)); \
196 if (rc != ERANGE || herrno != NETDB_INTERNAL) \
198 tmpbuf = extend_alloca (tmpbuf, tmpbuflen, 2 * tmpbuflen); \
200 if (status == NSS_STATUS_SUCCESS && rc == 0) \
206 if (herrno == NETDB_INTERNAL) \
208 __set_h_errno (herrno); \
209 return -EAI_SYSTEM; \
211 if (herrno == TRY_AGAIN) \
212 no_data = EAI_AGAIN; \
214 no_data = herrno == NO_DATA; \
216 else if (h != NULL) \
218 for (i = 0; h->h_addr_list[i]; i++) \
222 *pat = __alloca (sizeof (struct gaih_addrtuple)); \
223 (*pat)->scopeid = 0; \
225 uint32_t *addr = (*pat)->addr; \
226 (*pat)->next = NULL; \
227 (*pat)->name = i == 0 ? strdupa (h->h_name) : NULL; \
228 if (_family == AF_INET && req->ai_family == AF_INET6) \
230 (*pat)->family = AF_INET6; \
231 addr[3] = *(uint32_t *) h->h_addr_list[i]; \
232 addr[2] = htonl (0xffff); \
238 (*pat)->family = _family; \
239 memcpy (addr, h->h_addr_list[i], sizeof(_type)); \
241 pat = &((*pat)->next); \
244 if (localcanon != NULL && canon == NULL) \
245 canon = strdupa (localcanon); \
247 if (_family == AF_INET6 && i > 0) \
253 typedef enum nss_status (*nss_gethostbyname3_r
)
254 (const char *name
, int af
, struct hostent
*host
,
255 char *buffer
, size_t buflen
, int *errnop
,
256 int *h_errnop
, int32_t *ttlp
, char **canonp
);
257 typedef enum nss_status (*nss_getcanonname_r
)
258 (const char *name
, char *buffer
, size_t buflen
, char **result
,
259 int *errnop
, int *h_errnop
);
260 extern service_user
*__nss_hosts_database attribute_hidden
;
264 gaih_inet (const char *name
, const struct gaih_service
*service
,
265 const struct addrinfo
*req
, struct addrinfo
**pai
,
266 unsigned int *naddrs
)
268 const struct gaih_typeproto
*tp
= gaih_inet_typeproto
;
269 struct gaih_servtuple
*st
= (struct gaih_servtuple
*) &nullserv
;
270 struct gaih_addrtuple
*at
= NULL
;
272 bool got_ipv6
= false;
273 const char *canon
= NULL
;
274 const char *orig_name
= name
;
276 if (req
->ai_protocol
|| req
->ai_socktype
)
281 && ((req
->ai_socktype
!= 0 && req
->ai_socktype
!= tp
->socktype
)
282 || (req
->ai_protocol
!= 0
283 && !(tp
->protoflag
& GAI_PROTO_PROTOANY
)
284 && req
->ai_protocol
!= tp
->protocol
)))
289 if (req
->ai_socktype
)
290 return GAIH_OKIFUNSPEC
| -EAI_SOCKTYPE
;
292 return GAIH_OKIFUNSPEC
| -EAI_SERVICE
;
299 if ((tp
->protoflag
& GAI_PROTO_NOSERVICE
) != 0)
300 return GAIH_OKIFUNSPEC
| -EAI_SERVICE
;
302 if (service
->num
< 0)
306 st
= (struct gaih_servtuple
*)
307 __alloca (sizeof (struct gaih_servtuple
));
309 if ((rc
= gaih_inet_serv (service
->name
, tp
, req
, st
)))
314 struct gaih_servtuple
**pst
= &st
;
315 for (tp
++; tp
->name
[0]; tp
++)
317 struct gaih_servtuple
*newp
;
319 if ((tp
->protoflag
& GAI_PROTO_NOSERVICE
) != 0)
322 if (req
->ai_socktype
!= 0
323 && req
->ai_socktype
!= tp
->socktype
)
325 if (req
->ai_protocol
!= 0
326 && !(tp
->protoflag
& GAI_PROTO_PROTOANY
)
327 && req
->ai_protocol
!= tp
->protocol
)
330 newp
= (struct gaih_servtuple
*)
331 __alloca (sizeof (struct gaih_servtuple
));
333 if ((rc
= gaih_inet_serv (service
->name
, tp
, req
, newp
)))
335 if (rc
& GAIH_OKIFUNSPEC
)
343 if (st
== (struct gaih_servtuple
*) &nullserv
)
344 return GAIH_OKIFUNSPEC
| -EAI_SERVICE
;
349 port
= htons (service
->num
);
357 if (req
->ai_socktype
|| req
->ai_protocol
)
359 st
= __alloca (sizeof (struct gaih_servtuple
));
361 st
->socktype
= tp
->socktype
;
362 st
->protocol
= ((tp
->protoflag
& GAI_PROTO_PROTOANY
)
363 ? req
->ai_protocol
: tp
->protocol
);
368 /* Neither socket type nor protocol is set. Return all socket types
370 struct gaih_servtuple
**lastp
= &st
;
371 for (++tp
; tp
->name
[0]; ++tp
)
373 struct gaih_servtuple
*newp
;
375 newp
= __alloca (sizeof (struct gaih_servtuple
));
377 newp
->socktype
= tp
->socktype
;
378 newp
->protocol
= tp
->protocol
;
389 at
= __alloca (sizeof (struct gaih_addrtuple
));
391 at
->family
= AF_UNSPEC
;
396 if (req
->ai_flags
& AI_IDN
)
399 if (req
->ai_flags
& AI_IDN_ALLOW_UNASSIGNED
)
400 idn_flags
|= IDNA_ALLOW_UNASSIGNED
;
401 if (req
->ai_flags
& AI_IDN_USE_STD3_ASCII_RULES
)
402 idn_flags
|= IDNA_USE_STD3_ASCII_RULES
;
405 rc
= __idna_to_ascii_lz (name
, &p
, idn_flags
);
406 if (rc
!= IDNA_SUCCESS
)
408 if (rc
== IDNA_MALLOC_ERROR
)
410 if (rc
== IDNA_DLOPEN_ERROR
)
412 return -EAI_IDN_ENCODE
;
414 /* In case the output string is the same as the input string
415 no new string has been allocated. */
424 if (__inet_aton (name
, (struct in_addr
*) at
->addr
) != 0)
426 if (req
->ai_family
== AF_UNSPEC
|| req
->ai_family
== AF_INET
)
427 at
->family
= AF_INET
;
428 else if (req
->ai_family
== AF_INET6
&& (req
->ai_flags
& AI_V4MAPPED
))
430 at
->addr
[3] = at
->addr
[0];
431 at
->addr
[2] = htonl (0xffff);
434 at
->family
= AF_INET6
;
437 return -EAI_ADDRFAMILY
;
439 if (req
->ai_flags
& AI_CANONNAME
)
442 else if (at
->family
== AF_UNSPEC
)
444 char *namebuf
= (char *) name
;
445 char *scope_delim
= strchr (name
, SCOPE_DELIMITER
);
447 if (__builtin_expect (scope_delim
!= NULL
, 0))
449 namebuf
= alloca (scope_delim
- name
+ 1);
450 *((char *) __mempcpy (namebuf
, name
, scope_delim
- name
)) = '\0';
453 if (inet_pton (AF_INET6
, namebuf
, at
->addr
) > 0)
455 if (req
->ai_family
== AF_UNSPEC
|| req
->ai_family
== AF_INET6
)
456 at
->family
= AF_INET6
;
457 else if (req
->ai_family
== AF_INET
458 && IN6_IS_ADDR_V4MAPPED (at
->addr
))
460 at
->addr
[0] = at
->addr
[3];
461 at
->family
= AF_INET
;
464 return -EAI_ADDRFAMILY
;
466 if (scope_delim
!= NULL
)
468 int try_numericscope
= 0;
469 if (IN6_IS_ADDR_LINKLOCAL (at
->addr
)
470 || IN6_IS_ADDR_MC_LINKLOCAL (at
->addr
))
472 at
->scopeid
= if_nametoindex (scope_delim
+ 1);
473 if (at
->scopeid
== 0)
474 try_numericscope
= 1;
477 try_numericscope
= 1;
479 if (try_numericscope
!= 0)
482 assert (sizeof (uint32_t) <= sizeof (unsigned long));
483 at
->scopeid
= (uint32_t) strtoul (scope_delim
+ 1, &end
,
486 return GAIH_OKIFUNSPEC
| -EAI_NONAME
;
490 if (req
->ai_flags
& AI_CANONNAME
)
495 if (at
->family
== AF_UNSPEC
&& (req
->ai_flags
& AI_NUMERICHOST
) == 0)
497 struct gaih_addrtuple
**pat
= &at
;
499 int no_inet6_data
= 0;
500 service_user
*nip
= NULL
;
501 enum nss_status inet6_status
= NSS_STATUS_UNAVAIL
;
502 enum nss_status status
= NSS_STATUS_UNAVAIL
;
506 /* If we do not have to look for IPv4 and IPv6 together, use
507 the simple, old functions. */
508 if (req
->ai_family
== AF_INET
509 || (req
->ai_family
== AF_INET6
510 && ((req
->ai_flags
& AI_V4MAPPED
) == 0
511 || (req
->ai_flags
& AI_ALL
) == 0)))
513 int family
= req
->ai_family
;
514 size_t tmpbuflen
= 512;
515 char *tmpbuf
= alloca (tmpbuflen
);
524 rc
= __gethostbyname2_r (name
, family
, &th
, tmpbuf
,
525 tmpbuflen
, &h
, &herrno
);
526 if (rc
!= ERANGE
|| herrno
!= NETDB_INTERNAL
)
528 tmpbuf
= extend_alloca (tmpbuf
, tmpbuflen
, 2 * tmpbuflen
);
535 if (req
->ai_family
== AF_INET6
536 && (req
->ai_flags
& AI_V4MAPPED
)
537 && family
== AF_INET6
)
539 /* Try again, this time looking for IPv4
547 /* We found data, now convert it into the list. */
548 for (int i
= 0; h
->h_addr_list
[i
]; ++i
)
552 *pat
= __alloca (sizeof (struct gaih_addrtuple
));
556 (*pat
)->family
= req
->ai_family
;
557 if (family
== req
->ai_family
)
558 memcpy ((*pat
)->addr
, h
->h_addr_list
[i
],
562 uint32_t *addr
= (uint32_t *) (*pat
)->addr
;
563 addr
[3] = *(uint32_t *) h
->h_addr_list
[i
];
564 addr
[2] = htonl (0xffff);
568 pat
= &((*pat
)->next
);
574 if (herrno
== NETDB_INTERNAL
)
576 __set_h_errno (herrno
);
579 if (herrno
== TRY_AGAIN
)
583 /* We made requests but they turned out no data.
584 The name is known, though. */
585 return GAIH_OKIFUNSPEC
| -EAI_NODATA
;
592 if (__nss_not_use_nscd_hosts
> 0
593 && ++__nss_not_use_nscd_hosts
> NSS_NSCD_RETRY
)
594 __nss_not_use_nscd_hosts
= 0;
596 if (!__nss_not_use_nscd_hosts
)
598 /* Try to use nscd. */
599 struct nscd_ai_result
*air
= NULL
;
601 int err
= __nscd_getai (name
, &air
, &herrno
);
604 /* Transform into gaih_addrtuple list. */
605 bool added_canon
= (req
->ai_flags
& AI_CANONNAME
) == 0;
606 char *addrs
= air
->addrs
;
608 for (int i
= 0; i
< air
->naddrs
; ++i
)
610 socklen_t size
= (air
->family
[i
] == AF_INET
611 ? INADDRSZ
: IN6ADDRSZ
);
614 *pat
= __alloca (sizeof (struct gaih_addrtuple
));
617 uint32_t *pataddr
= (*pat
)->addr
;
619 if (added_canon
|| air
->canon
== NULL
)
622 canon
= (*pat
)->name
= strdupa (air
->canon
);
624 if (air
->family
[i
] == AF_INET
625 && req
->ai_family
== AF_INET6
626 && (req
->ai_flags
& AI_V4MAPPED
))
628 (*pat
)->family
= AF_INET6
;
629 pataddr
[3] = *(uint32_t *) addrs
;
630 pataddr
[2] = htonl (0xffff);
633 pat
= &((*pat
)->next
);
636 else if (req
->ai_family
== AF_UNSPEC
637 || air
->family
[i
] == req
->ai_family
)
639 (*pat
)->family
= air
->family
[i
];
640 memcpy (pataddr
, addrs
, size
);
641 pat
= &((*pat
)->next
);
643 if (air
->family
[i
] == AF_INET6
)
651 if (at
->family
== AF_UNSPEC
)
652 return GAIH_OKIFUNSPEC
| -EAI_NONAME
;
656 else if (err
!= 0 && __nss_not_use_nscd_hosts
== 0)
658 if (herrno
== NETDB_INTERNAL
&& errno
== ENOMEM
)
660 if (herrno
== TRY_AGAIN
)
667 if (__nss_hosts_database
!= NULL
)
670 nip
= __nss_hosts_database
;
673 no_more
= __nss_database_lookup ("hosts", NULL
,
674 "dns [!UNAVAIL=return] files",
677 if (__res_maybe_init (&_res
, 0) == -1)
680 /* If we are looking for both IPv4 and IPv6 address we don't
681 want the lookup functions to automatically promote IPv4
682 addresses to IPv6 addresses. Currently this is decided
683 by setting the RES_USE_INET6 bit in _res.options. */
684 old_res_options
= _res
.options
;
685 _res
.options
&= ~RES_USE_INET6
;
687 size_t tmpbuflen
= 512;
688 char *tmpbuf
= alloca (tmpbuflen
);
692 nss_gethostbyname3_r fct
= NULL
;
693 if (req
->ai_flags
& AI_CANONNAME
)
694 /* No need to use this function if we do not look for
695 the canonical name. The function does not exist in
696 all NSS modules and therefore the lookup would
698 fct
= __nss_lookup_function (nip
, "gethostbyname3_r");
700 /* We are cheating here. The gethostbyname2_r function does
701 not have the same interface as gethostbyname3_r but the
702 extra arguments the latter takes are added at the end.
703 So the gethostbyname2_r code will just ignore them. */
704 fct
= __nss_lookup_function (nip
, "gethostbyname2_r");
708 if (req
->ai_family
== AF_INET6
709 || req
->ai_family
== AF_UNSPEC
)
711 gethosts (AF_INET6
, struct in6_addr
);
712 no_inet6_data
= no_data
;
713 inet6_status
= status
;
715 if (req
->ai_family
== AF_INET
716 || req
->ai_family
== AF_UNSPEC
717 || (req
->ai_family
== AF_INET6
718 && (req
->ai_flags
& AI_V4MAPPED
)
719 /* Avoid generating the mapped addresses if we
720 know we are not going to need them. */
721 && ((req
->ai_flags
& AI_ALL
) || !got_ipv6
)))
723 gethosts (AF_INET
, struct in_addr
);
725 if (req
->ai_family
== AF_INET
)
727 no_inet6_data
= no_data
;
728 inet6_status
= status
;
732 /* If we found one address for AF_INET or AF_INET6,
733 don't continue the search. */
734 if (inet6_status
== NSS_STATUS_SUCCESS
735 || status
== NSS_STATUS_SUCCESS
)
737 if ((req
->ai_flags
& AI_CANONNAME
) != 0 && canon
== NULL
)
739 /* If we need the canonical name, get it
740 from the same service as the result. */
741 nss_getcanonname_r cfct
;
744 cfct
= __nss_lookup_function (nip
, "getcanonname_r");
747 const size_t max_fqdn_len
= 256;
748 char *buf
= alloca (max_fqdn_len
);
751 if (DL_CALL_FCT (cfct
, (at
->name
?: name
, buf
,
752 max_fqdn_len
, &s
, &rc
,
754 == NSS_STATUS_SUCCESS
)
757 /* Set to name now to avoid using
766 /* We can have different states for AF_INET and
767 AF_INET6. Try to find a useful one for both. */
768 if (inet6_status
== NSS_STATUS_TRYAGAIN
)
769 status
= NSS_STATUS_TRYAGAIN
;
770 else if (status
== NSS_STATUS_UNAVAIL
771 && inet6_status
!= NSS_STATUS_UNAVAIL
)
772 status
= inet6_status
;
775 if (nss_next_action (nip
, status
) == NSS_ACTION_RETURN
)
778 if (nip
->next
== NULL
)
784 _res
.options
= old_res_options
;
786 if (no_data
!= 0 && no_inet6_data
!= 0)
788 /* If both requests timed out report this. */
789 if (no_data
== EAI_AGAIN
&& no_inet6_data
== EAI_AGAIN
)
792 /* We made requests but they turned out no data. The name
794 return GAIH_OKIFUNSPEC
| -EAI_NODATA
;
799 if (at
->family
== AF_UNSPEC
)
800 return GAIH_OKIFUNSPEC
| -EAI_NONAME
;
804 struct gaih_addrtuple
*atr
;
805 atr
= at
= __alloca (sizeof (struct gaih_addrtuple
));
806 memset (at
, '\0', sizeof (struct gaih_addrtuple
));
808 if (req
->ai_family
== AF_UNSPEC
)
810 at
->next
= __alloca (sizeof (struct gaih_addrtuple
));
811 memset (at
->next
, '\0', sizeof (struct gaih_addrtuple
));
814 if (req
->ai_family
== AF_UNSPEC
|| req
->ai_family
== AF_INET6
)
816 at
->family
= AF_INET6
;
817 if ((req
->ai_flags
& AI_PASSIVE
) == 0)
818 memcpy (at
->addr
, &in6addr_loopback
, sizeof (struct in6_addr
));
822 if (req
->ai_family
== AF_UNSPEC
|| req
->ai_family
== AF_INET
)
824 atr
->family
= AF_INET
;
825 if ((req
->ai_flags
& AI_PASSIVE
) == 0)
826 atr
->addr
[0] = htonl (INADDR_LOOPBACK
);
834 struct gaih_servtuple
*st2
;
835 struct gaih_addrtuple
*at2
= at
;
840 buffer is the size of an unformatted IPv6 address in printable format.
844 /* Only the first entry gets the canonical name. */
845 if (at2
== at
&& (req
->ai_flags
& AI_CANONNAME
) != 0)
849 struct hostent
*h
= NULL
;
852 size_t tmpbuflen
= 512;
857 tmpbuf
= extend_alloca (tmpbuf
, tmpbuflen
, tmpbuflen
* 2);
858 rc
= __gethostbyaddr_r (at2
->addr
,
859 ((at2
->family
== AF_INET6
)
860 ? sizeof (struct in6_addr
)
861 : sizeof (struct in_addr
)),
862 at2
->family
, &th
, tmpbuf
,
863 tmpbuflen
, &h
, &herrno
);
865 while (rc
== ERANGE
&& herrno
== NETDB_INTERNAL
);
867 if (rc
!= 0 && herrno
== NETDB_INTERNAL
)
869 __set_h_errno (herrno
);
877 assert (orig_name
!= NULL
);
878 /* If the canonical name cannot be determined, use
879 the passed in string. */
885 if (req
->ai_flags
& AI_CANONIDN
)
888 if (req
->ai_flags
& AI_IDN_ALLOW_UNASSIGNED
)
889 idn_flags
|= IDNA_ALLOW_UNASSIGNED
;
890 if (req
->ai_flags
& AI_IDN_USE_STD3_ASCII_RULES
)
891 idn_flags
|= IDNA_USE_STD3_ASCII_RULES
;
894 int rc
= __idna_to_unicode_lzlz (canon
, &out
, idn_flags
);
895 if (rc
!= IDNA_SUCCESS
)
897 if (rc
== IDNA_MALLOC_ERROR
)
899 if (rc
== IDNA_DLOPEN_ERROR
)
901 return -EAI_IDN_ENCODE
;
903 /* In case the output string is the same as the input
904 string no new string has been allocated. Otherwise
915 canon
= strdup (canon
);
921 family
= at2
->family
;
922 if (family
== AF_INET6
)
924 socklen
= sizeof (struct sockaddr_in6
);
926 /* If we looked up IPv4 mapped address discard them here if
927 the caller isn't interested in all address and we have
928 found at least one IPv6 address. */
930 && (req
->ai_flags
& (AI_V4MAPPED
|AI_ALL
)) == AI_V4MAPPED
931 && IN6_IS_ADDR_V4MAPPED (at2
->addr
))
935 socklen
= sizeof (struct sockaddr_in
);
937 for (st2
= st
; st2
!= NULL
; st2
= st2
->next
)
940 ai
= *pai
= malloc (sizeof (struct addrinfo
) + socklen
);
943 free ((char *) canon
);
947 ai
->ai_flags
= req
->ai_flags
;
948 ai
->ai_family
= family
;
949 ai
->ai_socktype
= st2
->socktype
;
950 ai
->ai_protocol
= st2
->protocol
;
951 ai
->ai_addrlen
= socklen
;
952 ai
->ai_addr
= (void *) (ai
+ 1);
954 /* We only add the canonical name once. */
955 ai
->ai_canonname
= (char *) canon
;
959 ai
->ai_addr
->sa_len
= socklen
;
960 #endif /* _HAVE_SA_LEN */
961 ai
->ai_addr
->sa_family
= family
;
963 /* In case of an allocation error the list must be NULL
967 if (family
== AF_INET6
)
969 struct sockaddr_in6
*sin6p
=
970 (struct sockaddr_in6
*) ai
->ai_addr
;
972 sin6p
->sin6_port
= st2
->port
;
973 sin6p
->sin6_flowinfo
= 0;
974 memcpy (&sin6p
->sin6_addr
,
975 at2
->addr
, sizeof (struct in6_addr
));
976 sin6p
->sin6_scope_id
= at2
->scopeid
;
980 struct sockaddr_in
*sinp
=
981 (struct sockaddr_in
*) ai
->ai_addr
;
982 sinp
->sin_port
= st2
->port
;
983 memcpy (&sinp
->sin_addr
,
984 at2
->addr
, sizeof (struct in_addr
));
985 memset (sinp
->sin_zero
, '\0', sizeof (sinp
->sin_zero
));
988 pai
= &(ai
->ai_next
);
1003 struct addrinfo
*dest_addr
;
1004 struct sockaddr_storage source_addr
;
1005 size_t service_order
;
1006 uint8_t source_addr_len
;
1007 bool got_source_addr
;
1008 uint8_t source_addr_flags
;
1013 get_scope (const struct sockaddr_storage
*ss
)
1016 if (ss
->ss_family
== PF_INET6
)
1018 const struct sockaddr_in6
*in6
= (const struct sockaddr_in6
*) ss
;
1020 if (! IN6_IS_ADDR_MULTICAST (&in6
->sin6_addr
))
1022 if (IN6_IS_ADDR_LINKLOCAL (&in6
->sin6_addr
))
1024 else if (IN6_IS_ADDR_SITELOCAL (&in6
->sin6_addr
))
1027 /* XXX Is this the correct default behavior? */
1031 scope
= in6
->sin6_addr
.s6_addr
[1] & 0xf;
1033 else if (ss
->ss_family
== PF_INET
)
1035 const struct sockaddr_in
*in
= (const struct sockaddr_in
*) ss
;
1036 const uint8_t *addr
= (const uint8_t *) &in
->sin_addr
;
1038 /* RFC 3484 specifies how to map IPv6 addresses to scopes.
1039 169.254/16 and 127/8 are link-local. */
1040 if ((addr
[0] == 169 && addr
[1] == 254) || addr
[0] == 127)
1042 else if (addr
[0] == 10 || (addr
[0] == 172 && (addr
[1] & 0xf0) == 16)
1043 || (addr
[0] == 192 && addr
[1] == 168))
1049 /* XXX What is a good default? */
1058 struct in6_addr prefix
;
1064 /* The label table. */
1065 static const struct prefixentry
*labels
;
1067 /* Default labels. */
1068 static const struct prefixentry default_labels
[] =
1070 /* See RFC 3484 for the details. */
1072 = { .u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1073 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } } },
1076 = { .u6_addr8
= { 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1077 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
1080 = { .u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1081 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
1084 = { .u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1085 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 } } },
1087 /* The next two entries differ from RFC 3484. We need to treat
1088 IPv6 site-local addresses special because they are never NATed,
1089 unlike site-locale IPv4 addresses. If this would not happen, on
1090 machines which have only IPv4 and IPv6 site-local addresses, the
1091 sorting would prefer the IPv6 site-local addresses, causing
1092 unnecessary delays when trying to connect to a global IPv6 address
1093 through a site-local IPv6 address. */
1095 = { .u6_addr8
= { 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1096 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
1099 = { .u6_addr8
= { 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1100 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
1103 = { .u6_addr8
= { 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1104 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
1107 = { .u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1108 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
1113 /* The precedence table. */
1114 static const struct prefixentry
*precedence
;
1116 /* The default precedences. */
1117 static const struct prefixentry default_precedence
[] =
1119 /* See RFC 3484 for the details. */
1121 = { .u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1122 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } } },
1125 = { .u6_addr8
= { 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1126 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
1129 = { .u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1130 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
1133 = { .u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1134 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 } } },
1137 = { .u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1138 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
1144 match_prefix (const struct sockaddr_storage
*ss
,
1145 const struct prefixentry
*list
, int default_val
)
1148 struct sockaddr_in6 in6_mem
;
1149 const struct sockaddr_in6
*in6
;
1151 if (ss
->ss_family
== PF_INET6
)
1152 in6
= (const struct sockaddr_in6
*) ss
;
1153 else if (ss
->ss_family
== PF_INET
)
1155 const struct sockaddr_in
*in
= (const struct sockaddr_in
*) ss
;
1157 /* Convert to IPv6 address. */
1158 in6_mem
.sin6_family
= PF_INET6
;
1159 in6_mem
.sin6_port
= in
->sin_port
;
1160 in6_mem
.sin6_flowinfo
= 0;
1161 if (in
->sin_addr
.s_addr
== htonl (0x7f000001))
1162 in6_mem
.sin6_addr
= (struct in6_addr
) IN6ADDR_LOOPBACK_INIT
;
1165 /* Construct a V4-to-6 mapped address. */
1166 memset (&in6_mem
.sin6_addr
, '\0', sizeof (in6_mem
.sin6_addr
));
1167 in6_mem
.sin6_addr
.s6_addr16
[5] = 0xffff;
1168 in6_mem
.sin6_addr
.s6_addr32
[3] = in
->sin_addr
.s_addr
;
1169 in6_mem
.sin6_scope_id
= 0;
1177 for (idx
= 0; ; ++idx
)
1179 unsigned int bits
= list
[idx
].bits
;
1180 const uint8_t *mask
= list
[idx
].prefix
.s6_addr
;
1181 const uint8_t *val
= in6
->sin6_addr
.s6_addr
;
1195 if ((*mask
& (0xff00 >> bits
)) == (*val
& (0xff00 >> bits
)))
1201 return list
[idx
].val
;
1206 get_label (const struct sockaddr_storage
*ss
)
1208 /* XXX What is a good default value? */
1209 return match_prefix (ss
, labels
, INT_MAX
);
1214 get_precedence (const struct sockaddr_storage
*ss
)
1216 /* XXX What is a good default value? */
1217 return match_prefix (ss
, precedence
, 0);
1221 /* Find last bit set in a word. */
1227 for (n
= 0, mask
= 1 << 31; n
< 32; mask
>>= 1, ++n
)
1228 if ((a
& mask
) != 0)
1235 rfc3484_sort (const void *p1
, const void *p2
)
1237 const struct sort_result
*a1
= (const struct sort_result
*) p1
;
1238 const struct sort_result
*a2
= (const struct sort_result
*) p2
;
1240 /* Rule 1: Avoid unusable destinations.
1241 We have the got_source_addr flag set if the destination is reachable. */
1242 if (a1
->got_source_addr
&& ! a2
->got_source_addr
)
1244 if (! a1
->got_source_addr
&& a2
->got_source_addr
)
1248 /* Rule 2: Prefer matching scope. Only interesting if both
1249 destination addresses are IPv6. */
1251 = get_scope ((struct sockaddr_storage
*) a1
->dest_addr
->ai_addr
);
1254 = get_scope ((struct sockaddr_storage
*) a2
->dest_addr
->ai_addr
);
1256 if (a1
->got_source_addr
)
1258 int a1_src_scope
= get_scope (&a1
->source_addr
);
1259 int a2_src_scope
= get_scope (&a2
->source_addr
);
1261 if (a1_dst_scope
== a1_src_scope
&& a2_dst_scope
!= a2_src_scope
)
1263 if (a1_dst_scope
!= a1_src_scope
&& a2_dst_scope
== a2_src_scope
)
1268 /* Rule 3: Avoid deprecated addresses. */
1269 if (a1
->got_source_addr
)
1271 if (!(a1
->source_addr_flags
& in6ai_deprecated
)
1272 && (a2
->source_addr_flags
& in6ai_deprecated
))
1274 if ((a1
->source_addr_flags
& in6ai_deprecated
)
1275 && !(a2
->source_addr_flags
& in6ai_deprecated
))
1279 /* Rule 4: Prefer home addresses. */
1280 if (a1
->got_source_addr
)
1282 if (!(a1
->source_addr_flags
& in6ai_homeaddress
)
1283 && (a2
->source_addr_flags
& in6ai_homeaddress
))
1285 if ((a1
->source_addr_flags
& in6ai_homeaddress
)
1286 && !(a2
->source_addr_flags
& in6ai_homeaddress
))
1290 /* Rule 5: Prefer matching label. */
1291 if (a1
->got_source_addr
)
1294 = get_label ((struct sockaddr_storage
*) a1
->dest_addr
->ai_addr
);
1295 int a1_src_label
= get_label (&a1
->source_addr
);
1298 = get_label ((struct sockaddr_storage
*) a2
->dest_addr
->ai_addr
);
1299 int a2_src_label
= get_label (&a2
->source_addr
);
1301 if (a1_dst_label
== a1_src_label
&& a2_dst_label
!= a2_src_label
)
1303 if (a1_dst_label
!= a1_src_label
&& a2_dst_label
== a2_src_label
)
1308 /* Rule 6: Prefer higher precedence. */
1310 = get_precedence ((struct sockaddr_storage
*) a1
->dest_addr
->ai_addr
);
1312 = get_precedence ((struct sockaddr_storage
*) a2
->dest_addr
->ai_addr
);
1314 if (a1_prec
> a2_prec
)
1316 if (a1_prec
< a2_prec
)
1320 /* Rule 7: Prefer native transport. */
1321 if (a1
->got_source_addr
)
1323 if (!(a1
->source_addr_flags
& in6ai_temporary
)
1324 && (a2
->source_addr_flags
& in6ai_temporary
))
1326 if ((a1
->source_addr_flags
& in6ai_temporary
)
1327 && !(a2
->source_addr_flags
& in6ai_temporary
))
1330 /* XXX Do we need to check anything beside temporary addresses? */
1334 /* Rule 8: Prefer smaller scope. */
1335 if (a1_dst_scope
< a2_dst_scope
)
1337 if (a1_dst_scope
> a2_dst_scope
)
1341 /* Rule 9: Use longest matching prefix. */
1342 if (a1
->got_source_addr
1343 && a1
->dest_addr
->ai_family
== a2
->dest_addr
->ai_family
)
1348 if (a1
->dest_addr
->ai_family
== PF_INET
)
1350 assert (a1
->source_addr
.ss_family
== PF_INET
);
1351 assert (a2
->source_addr
.ss_family
== PF_INET
);
1353 struct sockaddr_in
*in1_dst
;
1354 struct sockaddr_in
*in1_src
;
1355 struct sockaddr_in
*in2_dst
;
1356 struct sockaddr_in
*in2_src
;
1358 in1_dst
= (struct sockaddr_in
*) a1
->dest_addr
->ai_addr
;
1359 in1_src
= (struct sockaddr_in
*) &a1
->source_addr
;
1360 in2_dst
= (struct sockaddr_in
*) a2
->dest_addr
->ai_addr
;
1361 in2_src
= (struct sockaddr_in
*) &a2
->source_addr
;
1363 bit1
= fls (ntohl (in1_dst
->sin_addr
.s_addr
1364 ^ in1_src
->sin_addr
.s_addr
));
1365 bit2
= fls (ntohl (in2_dst
->sin_addr
.s_addr
1366 ^ in2_src
->sin_addr
.s_addr
));
1368 else if (a1
->dest_addr
->ai_family
== PF_INET6
)
1370 assert (a1
->source_addr
.ss_family
== PF_INET6
);
1371 assert (a2
->source_addr
.ss_family
== PF_INET6
);
1373 struct sockaddr_in6
*in1_dst
;
1374 struct sockaddr_in6
*in1_src
;
1375 struct sockaddr_in6
*in2_dst
;
1376 struct sockaddr_in6
*in2_src
;
1378 in1_dst
= (struct sockaddr_in6
*) a1
->dest_addr
->ai_addr
;
1379 in1_src
= (struct sockaddr_in6
*) &a1
->source_addr
;
1380 in2_dst
= (struct sockaddr_in6
*) a2
->dest_addr
->ai_addr
;
1381 in2_src
= (struct sockaddr_in6
*) &a2
->source_addr
;
1384 for (i
= 0; i
< 4; ++i
)
1385 if (in1_dst
->sin6_addr
.s6_addr32
[i
]
1386 != in1_src
->sin6_addr
.s6_addr32
[i
]
1387 || (in2_dst
->sin6_addr
.s6_addr32
[i
]
1388 != in2_src
->sin6_addr
.s6_addr32
[i
]))
1393 bit1
= fls (ntohl (in1_dst
->sin6_addr
.s6_addr32
[i
]
1394 ^ in1_src
->sin6_addr
.s6_addr32
[i
]));
1395 bit2
= fls (ntohl (in2_dst
->sin6_addr
.s6_addr32
[i
]
1396 ^ in2_src
->sin6_addr
.s6_addr32
[i
]));
1407 /* Rule 10: Otherwise, leave the order unchanged. To ensure this
1408 compare with the value indicating the order in which the entries
1409 have been received from the services. NB: no two entries can have
1410 the same order so the test will never return zero. */
1411 return a1
->service_order
< a2
->service_order
? -1 : 1;
1416 in6aicmp (const void *p1
, const void *p2
)
1418 struct in6addrinfo
*a1
= (struct in6addrinfo
*) p1
;
1419 struct in6addrinfo
*a2
= (struct in6addrinfo
*) p2
;
1421 return memcmp (a1
->addr
, a2
->addr
, sizeof (a1
->addr
));
1425 /* Name of the config file for RFC 3484 sorting (for now). */
1426 #define GAICONF_FNAME "/etc/gai.conf"
1429 /* Nozero if we are supposed to reload the config file automatically
1430 whenever it changed. */
1431 static int gaiconf_reload_flag
;
1433 /* Last modification time. */
1434 static struct timespec gaiconf_mtime
;
1437 libc_freeres_fn(fini
)
1439 if (labels
!= default_labels
)
1441 const struct prefixentry
*old
= labels
;
1442 labels
= default_labels
;
1443 free ((void *) old
);
1446 if (precedence
!= default_precedence
)
1448 const struct prefixentry
*old
= precedence
;
1449 precedence
= default_precedence
;
1450 free ((void *) old
);
1457 struct prefixentry entry
;
1458 struct prefixlist
*next
;
1463 free_prefixlist (struct prefixlist
*list
)
1465 while (list
!= NULL
)
1467 struct prefixlist
*oldp
= list
;
1475 prefixcmp (const void *p1
, const void *p2
)
1477 const struct prefixentry
*e1
= (const struct prefixentry
*) p1
;
1478 const struct prefixentry
*e2
= (const struct prefixentry
*) p2
;
1480 if (e1
->bits
< e2
->bits
)
1482 if (e1
->bits
== e2
->bits
)
1491 struct prefixlist
*labellist
= NULL
;
1492 size_t nlabellist
= 0;
1493 bool labellist_nullbits
= false;
1494 struct prefixlist
*precedencelist
= NULL
;
1495 size_t nprecedencelist
= 0;
1496 bool precedencelist_nullbits
= false;
1498 FILE *fp
= fopen (GAICONF_FNAME
, "rc");
1502 if (__fxstat64 (_STAT_VER
, fileno (fp
), &st
) != 0)
1511 __fsetlocking (fp
, FSETLOCKING_BYCALLER
);
1513 while (!feof_unlocked (fp
))
1515 ssize_t n
= __getline (&line
, &linelen
, fp
);
1519 /* Handle comments. No escaping possible so this is easy. */
1520 char *cp
= strchr (line
, '#');
1525 while (isspace (*cp
))
1529 while (*cp
!= '\0' && !isspace (*cp
))
1531 size_t cmdlen
= cp
- cmd
;
1535 while (isspace (*cp
))
1539 while (*cp
!= '\0' && !isspace (*cp
))
1541 size_t val1len
= cp
- cmd
;
1543 /* We always need at least two values. */
1549 while (isspace (*cp
))
1553 while (*cp
!= '\0' && !isspace (*cp
))
1556 /* Ignore the rest of the line. */
1559 struct prefixlist
**listp
;
1565 if (strcmp (cmd
, "label") == 0)
1567 struct in6_addr prefix
;
1568 unsigned long int bits
;
1569 unsigned long int val
;
1574 nullbitsp
= &labellist_nullbits
;
1579 cp
= strchr (val1
, '/');
1582 if (inet_pton (AF_INET6
, val1
, &prefix
)
1584 || (bits
= strtoul (cp
, &endp
, 10)) != ULONG_MAX
1588 && ((val
= strtoul (val2
, &endp
, 10)) != ULONG_MAX
1593 struct prefixlist
*newp
= malloc (sizeof (*newp
));
1601 memcpy (&newp
->entry
.prefix
, &prefix
, sizeof (prefix
));
1602 newp
->entry
.bits
= bits
;
1603 newp
->entry
.val
= val
;
1604 newp
->next
= *listp
;
1607 *nullbitsp
|= bits
== 0;
1613 if (strcmp (cmd
, "reload") == 0)
1614 gaiconf_reload_flag
= strcmp (val1
, "yes") == 0;
1618 if (strcmp (cmd
, "precedence") == 0)
1620 listp
= &precedencelist
;
1621 lenp
= &nprecedencelist
;
1622 nullbitsp
= &precedencelist_nullbits
;
1633 /* Create the array for the labels. */
1634 struct prefixentry
*new_labels
;
1637 if (!labellist_nullbits
)
1639 new_labels
= malloc (nlabellist
* sizeof (*new_labels
));
1640 if (new_labels
== NULL
)
1644 if (!labellist_nullbits
)
1647 memset (&new_labels
[i
].prefix
, '\0', sizeof (struct in6_addr
));
1648 new_labels
[i
].bits
= 0;
1649 new_labels
[i
].val
= 1;
1652 struct prefixlist
*l
= labellist
;
1655 new_labels
[i
] = l
->entry
;
1658 free_prefixlist (labellist
);
1660 /* Sort the entries so that the most specific ones are at
1662 qsort (new_labels
, nlabellist
, sizeof (*new_labels
), prefixcmp
);
1665 new_labels
= (struct prefixentry
*) default_labels
;
1667 struct prefixentry
*new_precedence
;
1668 if (nprecedencelist
> 0)
1670 if (!precedencelist_nullbits
)
1672 new_precedence
= malloc (nprecedencelist
* sizeof (*new_precedence
));
1673 if (new_precedence
== NULL
)
1675 if (new_labels
!= default_labels
)
1680 int i
= nprecedencelist
;
1681 if (!precedencelist_nullbits
)
1684 memset (&new_precedence
[i
].prefix
, '\0',
1685 sizeof (struct in6_addr
));
1686 new_precedence
[i
].bits
= 0;
1687 new_precedence
[i
].val
= 40;
1690 struct prefixlist
*l
= precedencelist
;
1693 new_precedence
[i
] = l
->entry
;
1696 free_prefixlist (precedencelist
);
1698 /* Sort the entries so that the most specific ones are at
1700 qsort (new_precedence
, nprecedencelist
, sizeof (*new_labels
),
1704 new_precedence
= (struct prefixentry
*) default_precedence
;
1706 /* Now we are ready to replace the values. */
1707 const struct prefixentry
*old
= labels
;
1708 labels
= new_labels
;
1709 if (old
!= default_labels
)
1710 free ((void *) old
);
1713 precedence
= new_precedence
;
1714 if (old
!= default_precedence
)
1715 free ((void *) old
);
1717 gaiconf_mtime
= st
.st_mtim
;
1722 free_prefixlist (labellist
);
1723 free_prefixlist (precedencelist
);
1725 /* If we previously read the file but it is gone now, free the
1726 old data and use the builtin one. Leave the reload flag
1734 gaiconf_reload (void)
1737 if (__xstat64 (_STAT_VER
, GAICONF_FNAME
, &st
) != 0
1738 || memcmp (&st
.st_mtim
, &gaiconf_mtime
, sizeof (gaiconf_mtime
)) != 0)
1743 #if HAVE_NETLINK_ROUTE
1744 # if __ASSUME_NETLINK_SUPPORT == 0
1745 /* Defined in ifaddrs.c. */
1746 extern int __no_netlink_support attribute_hidden
;
1748 # define __no_netlink_support 0
1754 getaddrinfo (const char *name
, const char *service
,
1755 const struct addrinfo
*hints
, struct addrinfo
**pai
)
1757 int i
= 0, last_i
= 0;
1759 struct addrinfo
*p
= NULL
;
1760 struct gaih_service gaih_service
, *pservice
;
1761 struct addrinfo local_hints
;
1763 if (name
!= NULL
&& name
[0] == '*' && name
[1] == 0)
1766 if (service
!= NULL
&& service
[0] == '*' && service
[1] == 0)
1769 if (name
== NULL
&& service
== NULL
)
1773 hints
= &default_hints
;
1776 & ~(AI_PASSIVE
|AI_CANONNAME
|AI_NUMERICHOST
|AI_ADDRCONFIG
|AI_V4MAPPED
1778 |AI_IDN
|AI_CANONIDN
|AI_IDN_ALLOW_UNASSIGNED
1779 |AI_IDN_USE_STD3_ASCII_RULES
1781 |AI_NUMERICSERV
|AI_ALL
))
1782 return EAI_BADFLAGS
;
1784 if ((hints
->ai_flags
& AI_CANONNAME
) && name
== NULL
)
1785 return EAI_BADFLAGS
;
1787 struct in6addrinfo
*in6ai
= NULL
;
1788 size_t in6ailen
= 0;
1789 bool seen_ipv4
= false;
1790 bool seen_ipv6
= false;
1791 #ifdef HAVE_NETLINK_ROUTE
1795 /* We might need information about what kind of interfaces are available.
1796 But even if AI_ADDRCONFIG is not used, if the user requested IPv6
1797 addresses we have to know whether an address is deprecated or
1799 if ((hints
->ai_flags
& AI_ADDRCONFIG
) || hints
->ai_family
== PF_UNSPEC
1800 || hints
->ai_family
== PF_INET6
)
1802 /* Determine whether we have IPv4 or IPv6 interfaces or both. We
1803 cannot cache the results since new interfaces could be added at
1805 __check_pf (&seen_ipv4
, &seen_ipv6
, &in6ai
, &in6ailen
);
1806 #ifdef HAVE_NETLINK_ROUTE
1807 if (! __no_netlink_support
)
1809 sockfd
= __socket (PF_NETLINK
, SOCK_RAW
, NETLINK_ROUTE
);
1811 struct sockaddr_nl nladdr
;
1812 memset (&nladdr
, '\0', sizeof (nladdr
));
1813 nladdr
.nl_family
= AF_NETLINK
;
1815 socklen_t addr_len
= sizeof (nladdr
);
1818 && __bind (fd
, (struct sockaddr
*) &nladdr
, sizeof (nladdr
)) == 0
1819 && __getsockname (sockfd
, (struct sockaddr
*) &nladdr
,
1821 && make_request (sockfd
, nladdr
.nl_pid
, &seen_ipv4
, &seen_ipv6
,
1822 in6ai
, in6ailen
) == 0)
1825 nl_pid
= nladdr
.nl_pid
;
1826 goto got_netlink_socket
;
1830 close_not_cancel_no_status (sockfd
);
1832 #if __ASSUME_NETLINK_SUPPORT == 0
1833 /* Remember that there is no netlink support. */
1834 if (errno
!= EMFILE
&& errno
!= ENFILE
)
1835 __no_netlink_support
= 1;
1839 if (errno
!= EMFILE
&& errno
!= ENFILE
)
1842 /* We cannot determine what interfaces are available. Be
1853 #ifdef HAVE_NETLINK_ROUTE
1856 if (hints
->ai_flags
& AI_ADDRCONFIG
)
1858 /* Now make a decision on what we return, if anything. */
1859 if (hints
->ai_family
== PF_UNSPEC
&& (seen_ipv4
|| seen_ipv6
))
1861 /* If we haven't seen both IPv4 and IPv6 interfaces we can
1862 narrow down the search. */
1863 if (! seen_ipv4
|| ! seen_ipv6
)
1865 local_hints
= *hints
;
1866 local_hints
.ai_family
= seen_ipv4
? PF_INET
: PF_INET6
;
1867 hints
= &local_hints
;
1870 else if ((hints
->ai_family
== PF_INET
&& ! seen_ipv4
)
1871 || (hints
->ai_family
== PF_INET6
&& ! seen_ipv6
))
1873 /* We cannot possibly return a valid answer. */
1879 if (service
&& service
[0])
1882 gaih_service
.name
= service
;
1883 gaih_service
.num
= strtoul (gaih_service
.name
, &c
, 10);
1886 if (hints
->ai_flags
& AI_NUMERICSERV
)
1892 gaih_service
.num
= -1;
1895 pservice
= &gaih_service
;
1900 struct addrinfo
**end
;
1906 unsigned int naddrs
= 0;
1907 if (hints
->ai_family
== AF_UNSPEC
|| hints
->ai_family
== AF_INET
1908 || hints
->ai_family
== AF_INET6
)
1910 last_i
= gaih_inet (name
, pservice
, hints
, end
, &naddrs
);
1916 return -(last_i
& GAIH_EAI
);
1921 end
= &((*end
)->ai_next
);
1933 /* Read the config file. */
1934 __libc_once_define (static, once
);
1935 __typeof (once
) old_once
= once
;
1936 __libc_once (once
, gaiconf_init
);
1937 if (old_once
&& gaiconf_reload_flag
)
1940 /* Sort results according to RFC 3484. */
1941 struct sort_result results
[nresults
];
1943 struct addrinfo
*last
= NULL
;
1944 char *canonname
= NULL
;
1946 /* If we have information about deprecated and temporary address
1947 sort the array now. */
1949 qsort (in6ai
, in6ailen
, sizeof (*in6ai
), in6aicmp
);
1954 for (i
= 0, q
= p
; q
!= NULL
; ++i
, last
= q
, q
= q
->ai_next
)
1956 results
[i
].dest_addr
= q
;
1957 results
[i
].got_source_addr
= false;
1958 results
[i
].service_order
= i
;
1960 /* If we just looked up the address for a different
1961 protocol, reuse the result. */
1962 if (last
!= NULL
&& last
->ai_addrlen
== q
->ai_addrlen
1963 && memcmp (last
->ai_addr
, q
->ai_addr
, q
->ai_addrlen
) == 0)
1965 memcpy (&results
[i
].source_addr
, &results
[i
- 1].source_addr
,
1966 results
[i
- 1].source_addr_len
);
1967 results
[i
].source_addr_len
= results
[i
- 1].source_addr_len
;
1968 results
[i
].got_source_addr
= results
[i
- 1].got_source_addr
;
1969 results
[i
].source_addr_flags
= results
[i
- 1].source_addr_flags
;
1973 results
[i
].source_addr_flags
= 0;
1975 /* We overwrite the type with SOCK_DGRAM since we do not
1976 want connect() to connect to the other side. If we
1977 cannot determine the source address remember this
1979 if (fd
== -1 || (af
== AF_INET
&& q
->ai_family
== AF_INET6
))
1983 close_not_cancel_no_status (fd
);
1985 fd
= __socket (af
, SOCK_DGRAM
, IPPROTO_IP
);
1989 /* Reset the connection. */
1990 struct sockaddr sa
= { .sa_family
= AF_UNSPEC
};
1991 __connect (fd
, &sa
, sizeof (sa
));
1994 socklen_t sl
= sizeof (results
[i
].source_addr
);
1996 && __connect (fd
, q
->ai_addr
, q
->ai_addrlen
) == 0
1997 && __getsockname (fd
,
1998 (struct sockaddr
*) &results
[i
].source_addr
,
2001 results
[i
].source_addr_len
= sl
;
2002 results
[i
].got_source_addr
= true;
2004 if (q
->ai_family
== AF_INET6
&& in6ai
!= NULL
)
2006 /* See whether the source address is on the list of
2007 deprecated or temporary addresses. */
2008 struct in6addrinfo tmp
;
2009 struct sockaddr_in6
*sin6p
2010 = (struct sockaddr_in6
*) &results
[i
].source_addr
;
2011 memcpy (tmp
.addr
, &sin6p
->sin6_addr
, IN6ADDRSZ
);
2013 struct in6addrinfo
*found
2014 = bsearch (&tmp
, in6ai
, in6ailen
, sizeof (*in6ai
),
2017 results
[i
].source_addr_flags
= found
->flags
;
2019 else if (q
->ai_family
== AF_INET
&& af
== AF_INET6
)
2021 /* We have to convert the address. The socket is
2022 IPv6 and the request is for IPv4. */
2023 struct sockaddr_in6
*sin6
2024 = (struct sockaddr_in6
*) &results
[i
].source_addr
;
2025 struct sockaddr_in
*sin
2026 = (struct sockaddr_in
*) &results
[i
].source_addr
;
2027 assert (IN6_IS_ADDR_V4MAPPED (sin6
->sin6_addr
.s6_addr32
));
2028 memcpy (&sin
->sin_addr
,
2029 &sin6
->sin6_addr
.s6_addr32
[3], INADDRSZ
);
2030 results
[i
].source_addr_len
= INADDRSZ
;
2031 sin
->sin_family
= AF_INET
;
2034 else if (errno
== EAFNOSUPPORT
&& af
== AF_INET6
2035 && q
->ai_family
== AF_INET
)
2036 /* This could mean IPv6 sockets are IPv6-only. */
2039 /* Just make sure that if we have to process the same
2040 address again we do not copy any memory. */
2041 results
[i
].source_addr_len
= 0;
2044 /* Remember the canonical name. */
2045 if (q
->ai_canonname
!= NULL
)
2047 assert (canonname
== NULL
);
2048 canonname
= q
->ai_canonname
;
2049 q
->ai_canonname
= NULL
;
2054 close_not_cancel_no_status (fd
);
2056 /* We got all the source addresses we can get, now sort using
2058 qsort (results
, nresults
, sizeof (results
[0]), rfc3484_sort
);
2060 /* Queue the results up as they come out of sorting. */
2061 q
= p
= results
[0].dest_addr
;
2062 for (i
= 1; i
< nresults
; ++i
)
2063 q
= q
->ai_next
= results
[i
].dest_addr
;
2066 /* Fill in the canonical name into the new first entry. */
2067 p
->ai_canonname
= canonname
;
2078 if (pai
== NULL
&& last_i
== 0)
2081 return last_i
? -(last_i
& GAIH_EAI
) : EAI_NONAME
;
2083 libc_hidden_def (getaddrinfo
)
2085 static_link_warning (getaddrinfo
)
2088 freeaddrinfo (struct addrinfo
*ai
)
2096 free (p
->ai_canonname
);
2100 libc_hidden_def (freeaddrinfo
)