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>
65 extern int __idna_to_ascii_lz (const char *input
, char **output
, int flags
);
66 extern int __idna_to_unicode_lzlz (const char *input
, char **output
,
68 # include <libidn/idna.h>
71 #define GAIH_OKIFUNSPEC 0x0100
72 #define GAIH_EAI ~(GAIH_OKIFUNSPEC)
75 # define UNIX_PATH_MAX 108
86 struct gaih_servtuple
*next
;
92 static const struct gaih_servtuple nullserv
;
96 struct gaih_addrtuple
*next
;
103 struct gaih_typeproto
111 /* Values for `protoflag'. */
112 #define GAI_PROTO_NOSERVICE 1
113 #define GAI_PROTO_PROTOANY 2
115 static const struct gaih_typeproto gaih_inet_typeproto
[] =
118 { SOCK_STREAM
, IPPROTO_TCP
, "tcp", 0 },
119 { SOCK_DGRAM
, IPPROTO_UDP
, "udp", 0 },
120 { SOCK_RAW
, 0, "raw", GAI_PROTO_PROTOANY
|GAI_PROTO_NOSERVICE
},
127 int (*gaih
)(const char *name
, const struct gaih_service
*service
,
128 const struct addrinfo
*req
, struct addrinfo
**pai
,
129 unsigned int *naddrs
);
132 static const struct addrinfo default_hints
=
134 .ai_flags
= AI_DEFAULT
,
135 .ai_family
= PF_UNSPEC
,
140 .ai_canonname
= NULL
,
146 gaih_inet_serv (const char *servicename
, const struct gaih_typeproto
*tp
,
147 const struct addrinfo
*req
, struct gaih_servtuple
*st
)
150 size_t tmpbuflen
= 1024;
157 tmpbuf
= __alloca (tmpbuflen
);
159 r
= __getservbyname_r (servicename
, tp
->name
, &ts
, tmpbuf
, tmpbuflen
,
161 if (r
!= 0 || s
== NULL
)
166 return GAIH_OKIFUNSPEC
| -EAI_SERVICE
;
172 st
->socktype
= tp
->socktype
;
173 st
->protocol
= ((tp
->protoflag
& GAI_PROTO_PROTOANY
)
174 ? req
->ai_protocol
: tp
->protocol
);
175 st
->port
= s
->s_port
;
180 #define gethosts(_family, _type) \
186 char *localcanon = NULL; \
190 status = DL_CALL_FCT (fct, (name, _family, &th, tmpbuf, tmpbuflen, \
191 &rc, &herrno, NULL, &localcanon)); \
192 if (rc != ERANGE || herrno != NETDB_INTERNAL) \
194 tmpbuf = extend_alloca (tmpbuf, tmpbuflen, 2 * tmpbuflen); \
196 if (status == NSS_STATUS_SUCCESS && rc == 0) \
202 if (herrno == NETDB_INTERNAL) \
204 __set_h_errno (herrno); \
205 return -EAI_SYSTEM; \
207 if (herrno == TRY_AGAIN) \
208 no_data = EAI_AGAIN; \
210 no_data = herrno == NO_DATA; \
212 else if (h != NULL) \
214 for (i = 0; h->h_addr_list[i]; i++) \
218 *pat = __alloca (sizeof (struct gaih_addrtuple)); \
219 (*pat)->scopeid = 0; \
221 uint32_t *addr = (*pat)->addr; \
222 (*pat)->next = NULL; \
223 (*pat)->name = i == 0 ? strdupa (h->h_name) : NULL; \
224 if (_family == AF_INET && req->ai_family == AF_INET6) \
226 (*pat)->family = AF_INET6; \
227 addr[3] = *(uint32_t *) h->h_addr_list[i]; \
228 addr[2] = htonl (0xffff); \
234 (*pat)->family = _family; \
235 memcpy (addr, h->h_addr_list[i], sizeof(_type)); \
237 pat = &((*pat)->next); \
240 if (localcanon != NULL && canon == NULL) \
241 canon = strdupa (localcanon); \
243 if (_family == AF_INET6 && i > 0) \
249 typedef enum nss_status (*nss_gethostbyname3_r
)
250 (const char *name
, int af
, struct hostent
*host
,
251 char *buffer
, size_t buflen
, int *errnop
,
252 int *h_errnop
, int32_t *ttlp
, char **canonp
);
253 typedef enum nss_status (*nss_getcanonname_r
)
254 (const char *name
, char *buffer
, size_t buflen
, char **result
,
255 int *errnop
, int *h_errnop
);
256 extern service_user
*__nss_hosts_database attribute_hidden
;
260 gaih_inet (const char *name
, const struct gaih_service
*service
,
261 const struct addrinfo
*req
, struct addrinfo
**pai
,
262 unsigned int *naddrs
)
264 const struct gaih_typeproto
*tp
= gaih_inet_typeproto
;
265 struct gaih_servtuple
*st
= (struct gaih_servtuple
*) &nullserv
;
266 struct gaih_addrtuple
*at
= NULL
;
268 bool got_ipv6
= false;
269 const char *canon
= NULL
;
270 const char *orig_name
= name
;
272 if (req
->ai_protocol
|| req
->ai_socktype
)
277 && ((req
->ai_socktype
!= 0 && req
->ai_socktype
!= tp
->socktype
)
278 || (req
->ai_protocol
!= 0
279 && !(tp
->protoflag
& GAI_PROTO_PROTOANY
)
280 && req
->ai_protocol
!= tp
->protocol
)))
285 if (req
->ai_socktype
)
286 return GAIH_OKIFUNSPEC
| -EAI_SOCKTYPE
;
288 return GAIH_OKIFUNSPEC
| -EAI_SERVICE
;
295 if ((tp
->protoflag
& GAI_PROTO_NOSERVICE
) != 0)
296 return GAIH_OKIFUNSPEC
| -EAI_SERVICE
;
298 if (service
->num
< 0)
302 st
= (struct gaih_servtuple
*)
303 __alloca (sizeof (struct gaih_servtuple
));
305 if ((rc
= gaih_inet_serv (service
->name
, tp
, req
, st
)))
310 struct gaih_servtuple
**pst
= &st
;
311 for (tp
++; tp
->name
[0]; tp
++)
313 struct gaih_servtuple
*newp
;
315 if ((tp
->protoflag
& GAI_PROTO_NOSERVICE
) != 0)
318 if (req
->ai_socktype
!= 0
319 && req
->ai_socktype
!= tp
->socktype
)
321 if (req
->ai_protocol
!= 0
322 && !(tp
->protoflag
& GAI_PROTO_PROTOANY
)
323 && req
->ai_protocol
!= tp
->protocol
)
326 newp
= (struct gaih_servtuple
*)
327 __alloca (sizeof (struct gaih_servtuple
));
329 if ((rc
= gaih_inet_serv (service
->name
, tp
, req
, newp
)))
331 if (rc
& GAIH_OKIFUNSPEC
)
339 if (st
== (struct gaih_servtuple
*) &nullserv
)
340 return GAIH_OKIFUNSPEC
| -EAI_SERVICE
;
345 port
= htons (service
->num
);
353 if (req
->ai_socktype
|| req
->ai_protocol
)
355 st
= __alloca (sizeof (struct gaih_servtuple
));
357 st
->socktype
= tp
->socktype
;
358 st
->protocol
= ((tp
->protoflag
& GAI_PROTO_PROTOANY
)
359 ? req
->ai_protocol
: tp
->protocol
);
364 /* Neither socket type nor protocol is set. Return all socket types
366 struct gaih_servtuple
**lastp
= &st
;
367 for (++tp
; tp
->name
[0]; ++tp
)
369 struct gaih_servtuple
*newp
;
371 newp
= __alloca (sizeof (struct gaih_servtuple
));
373 newp
->socktype
= tp
->socktype
;
374 newp
->protocol
= tp
->protocol
;
385 at
= __alloca (sizeof (struct gaih_addrtuple
));
387 at
->family
= AF_UNSPEC
;
392 if (req
->ai_flags
& AI_IDN
)
395 if (req
->ai_flags
& AI_IDN_ALLOW_UNASSIGNED
)
396 idn_flags
|= IDNA_ALLOW_UNASSIGNED
;
397 if (req
->ai_flags
& AI_IDN_USE_STD3_ASCII_RULES
)
398 idn_flags
|= IDNA_USE_STD3_ASCII_RULES
;
401 rc
= __idna_to_ascii_lz (name
, &p
, idn_flags
);
402 if (rc
!= IDNA_SUCCESS
)
404 if (rc
== IDNA_MALLOC_ERROR
)
406 if (rc
== IDNA_DLOPEN_ERROR
)
408 return -EAI_IDN_ENCODE
;
410 /* In case the output string is the same as the input string
411 no new string has been allocated. */
420 if (__inet_aton (name
, (struct in_addr
*) at
->addr
) != 0)
422 if (req
->ai_family
== AF_UNSPEC
|| req
->ai_family
== AF_INET
)
423 at
->family
= AF_INET
;
424 else if (req
->ai_family
== AF_INET6
&& (req
->ai_flags
& AI_V4MAPPED
))
426 at
->addr
[3] = at
->addr
[0];
427 at
->addr
[2] = htonl (0xffff);
430 at
->family
= AF_INET6
;
433 return -EAI_ADDRFAMILY
;
435 if (req
->ai_flags
& AI_CANONNAME
)
438 else if (at
->family
== AF_UNSPEC
)
440 char *namebuf
= (char *) name
;
441 char *scope_delim
= strchr (name
, SCOPE_DELIMITER
);
443 if (__builtin_expect (scope_delim
!= NULL
, 0))
445 namebuf
= alloca (scope_delim
- name
+ 1);
446 *((char *) __mempcpy (namebuf
, name
, scope_delim
- name
)) = '\0';
449 if (inet_pton (AF_INET6
, namebuf
, at
->addr
) > 0)
451 if (req
->ai_family
== AF_UNSPEC
|| req
->ai_family
== AF_INET6
)
452 at
->family
= AF_INET6
;
453 else if (req
->ai_family
== AF_INET
454 && IN6_IS_ADDR_V4MAPPED (at
->addr
))
456 at
->addr
[0] = at
->addr
[3];
457 at
->family
= AF_INET
;
460 return -EAI_ADDRFAMILY
;
462 if (scope_delim
!= NULL
)
464 int try_numericscope
= 0;
465 if (IN6_IS_ADDR_LINKLOCAL (at
->addr
)
466 || IN6_IS_ADDR_MC_LINKLOCAL (at
->addr
))
468 at
->scopeid
= if_nametoindex (scope_delim
+ 1);
469 if (at
->scopeid
== 0)
470 try_numericscope
= 1;
473 try_numericscope
= 1;
475 if (try_numericscope
!= 0)
478 assert (sizeof (uint32_t) <= sizeof (unsigned long));
479 at
->scopeid
= (uint32_t) strtoul (scope_delim
+ 1, &end
,
482 return GAIH_OKIFUNSPEC
| -EAI_NONAME
;
486 if (req
->ai_flags
& AI_CANONNAME
)
491 if (at
->family
== AF_UNSPEC
&& (req
->ai_flags
& AI_NUMERICHOST
) == 0)
493 struct gaih_addrtuple
**pat
= &at
;
495 int no_inet6_data
= 0;
496 service_user
*nip
= NULL
;
497 enum nss_status inet6_status
= NSS_STATUS_UNAVAIL
;
498 enum nss_status status
= NSS_STATUS_UNAVAIL
;
502 /* If we do not have to look for IPv4 and IPv6 together, use
503 the simple, old functions. */
504 if (req
->ai_family
== AF_INET
505 || (req
->ai_family
== AF_INET6
506 && ((req
->ai_flags
& AI_V4MAPPED
) == 0
507 || (req
->ai_flags
& AI_ALL
) == 0)))
509 int family
= req
->ai_family
;
510 size_t tmpbuflen
= 512;
511 char *tmpbuf
= alloca (tmpbuflen
);
520 rc
= __gethostbyname2_r (name
, family
, &th
, tmpbuf
,
521 tmpbuflen
, &h
, &herrno
);
522 if (rc
!= ERANGE
|| herrno
!= NETDB_INTERNAL
)
524 tmpbuf
= extend_alloca (tmpbuf
, tmpbuflen
, 2 * tmpbuflen
);
531 if (req
->ai_family
== AF_INET6
532 && (req
->ai_flags
& AI_V4MAPPED
)
533 && family
== AF_INET6
)
535 /* Try again, this time looking for IPv4
543 /* We found data, now convert it into the list. */
544 for (int i
= 0; h
->h_addr_list
[i
]; ++i
)
548 *pat
= __alloca (sizeof (struct gaih_addrtuple
));
552 (*pat
)->family
= req
->ai_family
;
553 if (family
== req
->ai_family
)
554 memcpy ((*pat
)->addr
, h
->h_addr_list
[i
],
558 uint32_t *addr
= (uint32_t *) (*pat
)->addr
;
559 addr
[3] = *(uint32_t *) h
->h_addr_list
[i
];
560 addr
[2] = htonl (0xffff);
564 pat
= &((*pat
)->next
);
570 if (herrno
== NETDB_INTERNAL
)
572 __set_h_errno (herrno
);
575 if (herrno
== TRY_AGAIN
)
579 /* We made requests but they turned out no data.
580 The name is known, though. */
581 return GAIH_OKIFUNSPEC
| -EAI_NODATA
;
588 if (__nss_not_use_nscd_hosts
> 0
589 && ++__nss_not_use_nscd_hosts
> NSS_NSCD_RETRY
)
590 __nss_not_use_nscd_hosts
= 0;
592 if (!__nss_not_use_nscd_hosts
)
594 /* Try to use nscd. */
595 struct nscd_ai_result
*air
= NULL
;
597 int err
= __nscd_getai (name
, &air
, &herrno
);
600 /* Transform into gaih_addrtuple list. */
601 bool added_canon
= (req
->ai_flags
& AI_CANONNAME
) == 0;
602 char *addrs
= air
->addrs
;
604 for (int i
= 0; i
< air
->naddrs
; ++i
)
606 socklen_t size
= (air
->family
[i
] == AF_INET
607 ? INADDRSZ
: IN6ADDRSZ
);
610 *pat
= __alloca (sizeof (struct gaih_addrtuple
));
613 uint32_t *pataddr
= (*pat
)->addr
;
615 if (added_canon
|| air
->canon
== NULL
)
618 canon
= (*pat
)->name
= strdupa (air
->canon
);
620 if (air
->family
[i
] == AF_INET
621 && req
->ai_family
== AF_INET6
622 && (req
->ai_flags
& AI_V4MAPPED
))
624 (*pat
)->family
= AF_INET6
;
625 pataddr
[3] = *(uint32_t *) addrs
;
626 pataddr
[2] = htonl (0xffff);
629 pat
= &((*pat
)->next
);
632 else if (req
->ai_family
== AF_UNSPEC
633 || air
->family
[i
] == req
->ai_family
)
635 (*pat
)->family
= air
->family
[i
];
636 memcpy (pataddr
, addrs
, size
);
637 pat
= &((*pat
)->next
);
639 if (air
->family
[i
] == AF_INET6
)
647 if (at
->family
== AF_UNSPEC
)
648 return GAIH_OKIFUNSPEC
| -EAI_NONAME
;
652 else if (err
!= 0 && __nss_not_use_nscd_hosts
== 0)
654 if (herrno
== NETDB_INTERNAL
&& errno
== ENOMEM
)
656 if (herrno
== TRY_AGAIN
)
663 if (__nss_hosts_database
!= NULL
)
666 nip
= __nss_hosts_database
;
669 no_more
= __nss_database_lookup ("hosts", NULL
,
670 "dns [!UNAVAIL=return] files",
673 if (__res_maybe_init (&_res
, 0) == -1)
676 /* If we are looking for both IPv4 and IPv6 address we don't
677 want the lookup functions to automatically promote IPv4
678 addresses to IPv6 addresses. Currently this is decided
679 by setting the RES_USE_INET6 bit in _res.options. */
680 old_res_options
= _res
.options
;
681 _res
.options
&= ~RES_USE_INET6
;
683 size_t tmpbuflen
= 512;
684 char *tmpbuf
= alloca (tmpbuflen
);
688 nss_gethostbyname3_r fct
= NULL
;
689 if (req
->ai_flags
& AI_CANONNAME
)
690 /* No need to use this function if we do not look for
691 the canonical name. The function does not exist in
692 all NSS modules and therefore the lookup would
694 fct
= __nss_lookup_function (nip
, "gethostbyname3_r");
696 /* We are cheating here. The gethostbyname2_r function does
697 not have the same interface as gethostbyname3_r but the
698 extra arguments the latter takes are added at the end.
699 So the gethostbyname2_r code will just ignore them. */
700 fct
= __nss_lookup_function (nip
, "gethostbyname2_r");
704 if (req
->ai_family
== AF_INET6
705 || req
->ai_family
== AF_UNSPEC
)
707 gethosts (AF_INET6
, struct in6_addr
);
708 no_inet6_data
= no_data
;
709 inet6_status
= status
;
711 if (req
->ai_family
== AF_INET
712 || req
->ai_family
== AF_UNSPEC
713 || (req
->ai_family
== AF_INET6
714 && (req
->ai_flags
& AI_V4MAPPED
)
715 /* Avoid generating the mapped addresses if we
716 know we are not going to need them. */
717 && ((req
->ai_flags
& AI_ALL
) || !got_ipv6
)))
719 gethosts (AF_INET
, struct in_addr
);
721 if (req
->ai_family
== AF_INET
)
723 no_inet6_data
= no_data
;
724 inet6_status
= status
;
728 /* If we found one address for AF_INET or AF_INET6,
729 don't continue the search. */
730 if (inet6_status
== NSS_STATUS_SUCCESS
731 || status
== NSS_STATUS_SUCCESS
)
733 if ((req
->ai_flags
& AI_CANONNAME
) != 0 && canon
== NULL
)
735 /* If we need the canonical name, get it
736 from the same service as the result. */
737 nss_getcanonname_r cfct
;
740 cfct
= __nss_lookup_function (nip
, "getcanonname_r");
743 const size_t max_fqdn_len
= 256;
744 char *buf
= alloca (max_fqdn_len
);
747 if (DL_CALL_FCT (cfct
, (at
->name
?: name
, buf
,
748 max_fqdn_len
, &s
, &rc
,
750 == NSS_STATUS_SUCCESS
)
753 /* Set to name now to avoid using
762 /* We can have different states for AF_INET and
763 AF_INET6. Try to find a useful one for both. */
764 if (inet6_status
== NSS_STATUS_TRYAGAIN
)
765 status
= NSS_STATUS_TRYAGAIN
;
766 else if (status
== NSS_STATUS_UNAVAIL
767 && inet6_status
!= NSS_STATUS_UNAVAIL
)
768 status
= inet6_status
;
771 if (nss_next_action (nip
, status
) == NSS_ACTION_RETURN
)
774 if (nip
->next
== NULL
)
780 _res
.options
= old_res_options
;
782 if (no_data
!= 0 && no_inet6_data
!= 0)
784 /* If both requests timed out report this. */
785 if (no_data
== EAI_AGAIN
&& no_inet6_data
== EAI_AGAIN
)
788 /* We made requests but they turned out no data. The name
790 return GAIH_OKIFUNSPEC
| -EAI_NODATA
;
795 if (at
->family
== AF_UNSPEC
)
796 return GAIH_OKIFUNSPEC
| -EAI_NONAME
;
800 struct gaih_addrtuple
*atr
;
801 atr
= at
= __alloca (sizeof (struct gaih_addrtuple
));
802 memset (at
, '\0', sizeof (struct gaih_addrtuple
));
804 if (req
->ai_family
== AF_UNSPEC
)
806 at
->next
= __alloca (sizeof (struct gaih_addrtuple
));
807 memset (at
->next
, '\0', sizeof (struct gaih_addrtuple
));
810 if (req
->ai_family
== AF_UNSPEC
|| req
->ai_family
== AF_INET6
)
812 at
->family
= AF_INET6
;
813 if ((req
->ai_flags
& AI_PASSIVE
) == 0)
814 memcpy (at
->addr
, &in6addr_loopback
, sizeof (struct in6_addr
));
818 if (req
->ai_family
== AF_UNSPEC
|| req
->ai_family
== AF_INET
)
820 atr
->family
= AF_INET
;
821 if ((req
->ai_flags
& AI_PASSIVE
) == 0)
822 atr
->addr
[0] = htonl (INADDR_LOOPBACK
);
830 struct gaih_servtuple
*st2
;
831 struct gaih_addrtuple
*at2
= at
;
836 buffer is the size of an unformatted IPv6 address in printable format.
840 /* Only the first entry gets the canonical name. */
841 if (at2
== at
&& (req
->ai_flags
& AI_CANONNAME
) != 0)
845 struct hostent
*h
= NULL
;
848 size_t tmpbuflen
= 512;
853 tmpbuf
= extend_alloca (tmpbuf
, tmpbuflen
, tmpbuflen
* 2);
854 rc
= __gethostbyaddr_r (at2
->addr
,
855 ((at2
->family
== AF_INET6
)
856 ? sizeof (struct in6_addr
)
857 : sizeof (struct in_addr
)),
858 at2
->family
, &th
, tmpbuf
,
859 tmpbuflen
, &h
, &herrno
);
861 while (rc
== ERANGE
&& herrno
== NETDB_INTERNAL
);
863 if (rc
!= 0 && herrno
== NETDB_INTERNAL
)
865 __set_h_errno (herrno
);
873 assert (orig_name
!= NULL
);
874 /* If the canonical name cannot be determined, use
875 the passed in string. */
881 if (req
->ai_flags
& AI_CANONIDN
)
884 if (req
->ai_flags
& AI_IDN_ALLOW_UNASSIGNED
)
885 idn_flags
|= IDNA_ALLOW_UNASSIGNED
;
886 if (req
->ai_flags
& AI_IDN_USE_STD3_ASCII_RULES
)
887 idn_flags
|= IDNA_USE_STD3_ASCII_RULES
;
890 int rc
= __idna_to_unicode_lzlz (canon
, &out
, idn_flags
);
891 if (rc
!= IDNA_SUCCESS
)
893 if (rc
== IDNA_MALLOC_ERROR
)
895 if (rc
== IDNA_DLOPEN_ERROR
)
897 return -EAI_IDN_ENCODE
;
899 /* In case the output string is the same as the input
900 string no new string has been allocated. Otherwise
911 canon
= strdup (canon
);
917 family
= at2
->family
;
918 if (family
== AF_INET6
)
920 socklen
= sizeof (struct sockaddr_in6
);
922 /* If we looked up IPv4 mapped address discard them here if
923 the caller isn't interested in all address and we have
924 found at least one IPv6 address. */
926 && (req
->ai_flags
& (AI_V4MAPPED
|AI_ALL
)) == AI_V4MAPPED
927 && IN6_IS_ADDR_V4MAPPED (at2
->addr
))
931 socklen
= sizeof (struct sockaddr_in
);
933 for (st2
= st
; st2
!= NULL
; st2
= st2
->next
)
936 ai
= *pai
= malloc (sizeof (struct addrinfo
) + socklen
);
939 free ((char *) canon
);
943 ai
->ai_flags
= req
->ai_flags
;
944 ai
->ai_family
= family
;
945 ai
->ai_socktype
= st2
->socktype
;
946 ai
->ai_protocol
= st2
->protocol
;
947 ai
->ai_addrlen
= socklen
;
948 ai
->ai_addr
= (void *) (ai
+ 1);
950 /* We only add the canonical name once. */
951 ai
->ai_canonname
= (char *) canon
;
955 ai
->ai_addr
->sa_len
= socklen
;
956 #endif /* _HAVE_SA_LEN */
957 ai
->ai_addr
->sa_family
= family
;
959 /* In case of an allocation error the list must be NULL
963 if (family
== AF_INET6
)
965 struct sockaddr_in6
*sin6p
=
966 (struct sockaddr_in6
*) ai
->ai_addr
;
968 sin6p
->sin6_port
= st2
->port
;
969 sin6p
->sin6_flowinfo
= 0;
970 memcpy (&sin6p
->sin6_addr
,
971 at2
->addr
, sizeof (struct in6_addr
));
972 sin6p
->sin6_scope_id
= at2
->scopeid
;
976 struct sockaddr_in
*sinp
=
977 (struct sockaddr_in
*) ai
->ai_addr
;
978 sinp
->sin_port
= st2
->port
;
979 memcpy (&sinp
->sin_addr
,
980 at2
->addr
, sizeof (struct in_addr
));
981 memset (sinp
->sin_zero
, '\0', sizeof (sinp
->sin_zero
));
984 pai
= &(ai
->ai_next
);
999 struct addrinfo
*dest_addr
;
1000 /* Using sockaddr_storage is for now overkill. We only support IPv4
1001 and IPv6 so far. If this changes at some point we can adjust the
1003 struct sockaddr_in6 source_addr
;
1004 uint8_t source_addr_len
;
1005 bool got_source_addr
;
1006 uint8_t source_addr_flags
;
1012 struct sort_result_combo
1014 struct sort_result
*results
;
1019 #if __BYTE_ORDER == __BIG_ENDIAN
1020 # define htonl_c(n) n
1022 # define htonl_c(n) __bswap_constant_32 (n)
1025 static const struct scopeentry
1034 } default_scopes
[] =
1036 /* Link-local addresses: scope 2. */
1037 { { { 169, 254, 0, 0 } }, htonl_c (0xffff0000), 2 },
1038 { { { 127, 0, 0, 0 } }, htonl_c (0xff000000), 2 },
1039 /* Site-local addresses: scope 5. */
1040 { { { 10, 0, 0, 0 } }, htonl_c (0xff000000), 5 },
1041 { { { 172, 16, 0, 0 } }, htonl_c (0xfff00000), 5 },
1042 { { { 192, 168, 0, 0 } }, htonl_c (0xffff0000), 5 },
1043 /* Default: scope 14. */
1044 { { { 0, 0, 0, 0 } }, htonl_c (0x00000000), 14 }
1047 /* The label table. */
1048 static const struct scopeentry
*scopes
;
1052 get_scope (const struct sockaddr_in6
*in6
)
1055 if (in6
->sin6_family
== PF_INET6
)
1057 if (! IN6_IS_ADDR_MULTICAST (&in6
->sin6_addr
))
1059 if (IN6_IS_ADDR_LINKLOCAL (&in6
->sin6_addr
))
1061 else if (IN6_IS_ADDR_SITELOCAL (&in6
->sin6_addr
))
1064 /* XXX Is this the correct default behavior? */
1068 scope
= in6
->sin6_addr
.s6_addr
[1] & 0xf;
1070 else if (in6
->sin6_family
== PF_INET
)
1072 const struct sockaddr_in
*in
= (const struct sockaddr_in
*) in6
;
1077 if ((in
->sin_addr
.s_addr
& scopes
[cnt
].netmask
)
1078 == scopes
[cnt
].addr32
)
1079 return scopes
[cnt
].scope
;
1086 /* XXX What is a good default? */
1095 struct in6_addr prefix
;
1101 /* The label table. */
1102 static const struct prefixentry
*labels
;
1104 /* Default labels. */
1105 static const struct prefixentry default_labels
[] =
1107 /* See RFC 3484 for the details. */
1109 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1110 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } }
1113 = { .__u6_addr8
= { 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1114 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1117 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1118 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1121 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1122 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 } }
1124 /* The next two entries differ from RFC 3484. We need to treat
1125 IPv6 site-local addresses special because they are never NATed,
1126 unlike site-locale IPv4 addresses. If this would not happen, on
1127 machines which have only IPv4 and IPv6 site-local addresses, the
1128 sorting would prefer the IPv6 site-local addresses, causing
1129 unnecessary delays when trying to connect to a global IPv6 address
1130 through a site-local IPv6 address. */
1132 = { .__u6_addr8
= { 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1133 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1136 = { .__u6_addr8
= { 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1137 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1139 /* Additional rule for Teredo tunnels. */
1141 = { .__u6_addr8
= { 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1142 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1145 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1146 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1151 /* The precedence table. */
1152 static const struct prefixentry
*precedence
;
1154 /* The default precedences. */
1155 static const struct prefixentry default_precedence
[] =
1157 /* See RFC 3484 for the details. */
1159 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1160 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } }
1163 = { .__u6_addr8
= { 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1164 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1167 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1168 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1171 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1172 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 } }
1175 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1176 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1182 match_prefix (const struct sockaddr_in6
*in6
,
1183 const struct prefixentry
*list
, int default_val
)
1186 struct sockaddr_in6 in6_mem
;
1188 if (in6
->sin6_family
== PF_INET
)
1190 const struct sockaddr_in
*in
= (const struct sockaddr_in
*) in6
;
1192 /* Convert to IPv6 address. */
1193 in6_mem
.sin6_family
= PF_INET6
;
1194 in6_mem
.sin6_port
= in
->sin_port
;
1195 in6_mem
.sin6_flowinfo
= 0;
1196 if (in
->sin_addr
.s_addr
== htonl (0x7f000001))
1197 in6_mem
.sin6_addr
= (struct in6_addr
) IN6ADDR_LOOPBACK_INIT
;
1200 /* Construct a V4-to-6 mapped address. */
1201 memset (&in6_mem
.sin6_addr
, '\0', sizeof (in6_mem
.sin6_addr
));
1202 in6_mem
.sin6_addr
.s6_addr16
[5] = 0xffff;
1203 in6_mem
.sin6_addr
.s6_addr32
[3] = in
->sin_addr
.s_addr
;
1204 in6_mem
.sin6_scope_id
= 0;
1209 else if (in6
->sin6_family
!= PF_INET6
)
1212 for (idx
= 0; ; ++idx
)
1214 unsigned int bits
= list
[idx
].bits
;
1215 const uint8_t *mask
= list
[idx
].prefix
.s6_addr
;
1216 const uint8_t *val
= in6
->sin6_addr
.s6_addr
;
1230 if ((*mask
& (0xff00 >> bits
)) == (*val
& (0xff00 >> bits
)))
1236 return list
[idx
].val
;
1241 get_label (const struct sockaddr_in6
*in6
)
1243 /* XXX What is a good default value? */
1244 return match_prefix (in6
, labels
, INT_MAX
);
1249 get_precedence (const struct sockaddr_in6
*in6
)
1251 /* XXX What is a good default value? */
1252 return match_prefix (in6
, precedence
, 0);
1256 /* Find last bit set in a word. */
1262 for (n
= 0, mask
= 1 << 31; n
< 32; mask
>>= 1, ++n
)
1263 if ((a
& mask
) != 0)
1270 rfc3484_sort (const void *p1
, const void *p2
, void *arg
)
1272 const size_t idx1
= *(const size_t *) p1
;
1273 const size_t idx2
= *(const size_t *) p2
;
1274 struct sort_result_combo
*src
= (struct sort_result_combo
*) arg
;
1275 struct sort_result
*a1
= &src
->results
[idx1
];
1276 struct sort_result
*a2
= &src
->results
[idx2
];
1278 /* Rule 1: Avoid unusable destinations.
1279 We have the got_source_addr flag set if the destination is reachable. */
1280 if (a1
->got_source_addr
&& ! a2
->got_source_addr
)
1282 if (! a1
->got_source_addr
&& a2
->got_source_addr
)
1286 /* Rule 2: Prefer matching scope. Only interesting if both
1287 destination addresses are IPv6. */
1289 = get_scope ((struct sockaddr_in6
*) a1
->dest_addr
->ai_addr
);
1292 = get_scope ((struct sockaddr_in6
*) a2
->dest_addr
->ai_addr
);
1294 if (a1
->got_source_addr
)
1296 int a1_src_scope
= get_scope (&a1
->source_addr
);
1297 int a2_src_scope
= get_scope (&a2
->source_addr
);
1299 if (a1_dst_scope
== a1_src_scope
&& a2_dst_scope
!= a2_src_scope
)
1301 if (a1_dst_scope
!= a1_src_scope
&& a2_dst_scope
== a2_src_scope
)
1306 /* Rule 3: Avoid deprecated addresses. */
1307 if (a1
->got_source_addr
)
1309 if (!(a1
->source_addr_flags
& in6ai_deprecated
)
1310 && (a2
->source_addr_flags
& in6ai_deprecated
))
1312 if ((a1
->source_addr_flags
& in6ai_deprecated
)
1313 && !(a2
->source_addr_flags
& in6ai_deprecated
))
1317 /* Rule 4: Prefer home addresses. */
1318 if (a1
->got_source_addr
)
1320 if (!(a1
->source_addr_flags
& in6ai_homeaddress
)
1321 && (a2
->source_addr_flags
& in6ai_homeaddress
))
1323 if ((a1
->source_addr_flags
& in6ai_homeaddress
)
1324 && !(a2
->source_addr_flags
& in6ai_homeaddress
))
1328 /* Rule 5: Prefer matching label. */
1329 if (a1
->got_source_addr
)
1332 = get_label ((struct sockaddr_in6
*) a1
->dest_addr
->ai_addr
);
1333 int a1_src_label
= get_label (&a1
->source_addr
);
1336 = get_label ((struct sockaddr_in6
*) a2
->dest_addr
->ai_addr
);
1337 int a2_src_label
= get_label (&a2
->source_addr
);
1339 if (a1_dst_label
== a1_src_label
&& a2_dst_label
!= a2_src_label
)
1341 if (a1_dst_label
!= a1_src_label
&& a2_dst_label
== a2_src_label
)
1346 /* Rule 6: Prefer higher precedence. */
1348 = get_precedence ((struct sockaddr_in6
*) a1
->dest_addr
->ai_addr
);
1350 = get_precedence ((struct sockaddr_in6
*) a2
->dest_addr
->ai_addr
);
1352 if (a1_prec
> a2_prec
)
1354 if (a1_prec
< a2_prec
)
1358 /* Rule 7: Prefer native transport. */
1359 if (a1
->got_source_addr
)
1361 /* The same interface index means the same interface which means
1362 there is no difference in transport. This should catch many
1364 if (a1
->index
!= a2
->index
)
1366 int a1_native
= a1
->native
;
1367 int a2_native
= a2
->native
;
1369 if (a1_native
== -1 || a2_native
== -1)
1372 if (a1_native
== -1)
1374 /* If we do not have the information use 'native' as
1377 a1_index
= a1
->index
;
1380 a1_index
= 0xffffffffu
;
1383 if (a2_native
== -1)
1385 /* If we do not have the information use 'native' as
1388 a2_index
= a2
->index
;
1391 a2_index
= 0xffffffffu
;
1393 __check_native (a1_index
, &a1_native
, a2_index
, &a2_native
);
1395 /* Fill in the results in all the records. */
1396 for (int i
= 0; i
< src
->nresults
; ++i
)
1397 if (src
->results
[i
].index
== a1_index
)
1399 assert (src
->results
[i
].native
== -1
1400 || src
->results
[i
].native
== a1_native
);
1401 src
->results
[i
].native
= a1_native
;
1403 else if (src
->results
[i
].index
== a2_index
)
1405 assert (src
->results
[i
].native
== -1
1406 || src
->results
[i
].native
== a2_native
);
1407 src
->results
[i
].native
= a2_native
;
1411 if (a1_native
&& !a2_native
)
1413 if (!a1_native
&& a2_native
)
1419 /* Rule 8: Prefer smaller scope. */
1420 if (a1_dst_scope
< a2_dst_scope
)
1422 if (a1_dst_scope
> a2_dst_scope
)
1426 /* Rule 9: Use longest matching prefix. */
1427 if (a1
->got_source_addr
1428 && a1
->dest_addr
->ai_family
== a2
->dest_addr
->ai_family
)
1433 if (a1
->dest_addr
->ai_family
== PF_INET
)
1435 assert (a1
->source_addr
.sin6_family
== PF_INET
);
1436 assert (a2
->source_addr
.sin6_family
== PF_INET
);
1438 /* Outside of subnets, as defined by the network masks,
1439 common address prefixes for IPv4 addresses make no sense.
1440 So, define a non-zero value only if source and
1441 destination address are on the same subnet. */
1442 struct sockaddr_in
*in1_dst
1443 = (struct sockaddr_in
*) a1
->dest_addr
->ai_addr
;
1444 in_addr_t in1_dst_addr
= ntohl (in1_dst
->sin_addr
.s_addr
);
1445 struct sockaddr_in
*in1_src
1446 = (struct sockaddr_in
*) &a1
->source_addr
;
1447 in_addr_t in1_src_addr
= ntohl (in1_src
->sin_addr
.s_addr
);
1448 in_addr_t netmask1
= 0xffffffffu
<< (32 - a1
->prefixlen
);
1450 if ((in1_src_addr
& netmask1
) == (in1_dst_addr
& netmask1
))
1451 bit1
= fls (in1_dst_addr
^ in1_src_addr
);
1453 struct sockaddr_in
*in2_dst
1454 = (struct sockaddr_in
*) a2
->dest_addr
->ai_addr
;
1455 in_addr_t in2_dst_addr
= ntohl (in2_dst
->sin_addr
.s_addr
);
1456 struct sockaddr_in
*in2_src
1457 = (struct sockaddr_in
*) &a2
->source_addr
;
1458 in_addr_t in2_src_addr
= ntohl (in2_src
->sin_addr
.s_addr
);
1459 in_addr_t netmask2
= 0xffffffffu
<< (32 - a2
->prefixlen
);
1461 if ((in2_src_addr
& netmask2
) == (in2_dst_addr
& netmask2
))
1462 bit2
= fls (in2_dst_addr
^ in2_src_addr
);
1464 else if (a1
->dest_addr
->ai_family
== PF_INET6
)
1466 assert (a1
->source_addr
.sin6_family
== PF_INET6
);
1467 assert (a2
->source_addr
.sin6_family
== PF_INET6
);
1469 struct sockaddr_in6
*in1_dst
;
1470 struct sockaddr_in6
*in1_src
;
1471 struct sockaddr_in6
*in2_dst
;
1472 struct sockaddr_in6
*in2_src
;
1474 in1_dst
= (struct sockaddr_in6
*) a1
->dest_addr
->ai_addr
;
1475 in1_src
= (struct sockaddr_in6
*) &a1
->source_addr
;
1476 in2_dst
= (struct sockaddr_in6
*) a2
->dest_addr
->ai_addr
;
1477 in2_src
= (struct sockaddr_in6
*) &a2
->source_addr
;
1480 for (i
= 0; i
< 4; ++i
)
1481 if (in1_dst
->sin6_addr
.s6_addr32
[i
]
1482 != in1_src
->sin6_addr
.s6_addr32
[i
]
1483 || (in2_dst
->sin6_addr
.s6_addr32
[i
]
1484 != in2_src
->sin6_addr
.s6_addr32
[i
]))
1489 bit1
= fls (ntohl (in1_dst
->sin6_addr
.s6_addr32
[i
]
1490 ^ in1_src
->sin6_addr
.s6_addr32
[i
]));
1491 bit2
= fls (ntohl (in2_dst
->sin6_addr
.s6_addr32
[i
]
1492 ^ in2_src
->sin6_addr
.s6_addr32
[i
]));
1503 /* Rule 10: Otherwise, leave the order unchanged. To ensure this
1504 compare with the value indicating the order in which the entries
1505 have been received from the services. NB: no two entries can have
1506 the same order so the test will never return zero. */
1507 return idx1
< idx2
? -1 : 1;
1512 in6aicmp (const void *p1
, const void *p2
)
1514 struct in6addrinfo
*a1
= (struct in6addrinfo
*) p1
;
1515 struct in6addrinfo
*a2
= (struct in6addrinfo
*) p2
;
1517 return memcmp (a1
->addr
, a2
->addr
, sizeof (a1
->addr
));
1521 /* Name of the config file for RFC 3484 sorting (for now). */
1522 #define GAICONF_FNAME "/etc/gai.conf"
1525 /* Non-zero if we are supposed to reload the config file automatically
1526 whenever it changed. */
1527 static int gaiconf_reload_flag
;
1529 /* Non-zero if gaiconf_reload_flag was ever set to true. */
1530 static int gaiconf_reload_flag_ever_set
;
1532 /* Last modification time. */
1533 static struct timespec gaiconf_mtime
;
1536 libc_freeres_fn(fini
)
1538 if (labels
!= default_labels
)
1540 const struct prefixentry
*old
= labels
;
1541 labels
= default_labels
;
1542 free ((void *) old
);
1545 if (precedence
!= default_precedence
)
1547 const struct prefixentry
*old
= precedence
;
1548 precedence
= default_precedence
;
1549 free ((void *) old
);
1552 if (scopes
!= default_scopes
)
1554 const struct scopeentry
*old
= scopes
;
1555 scopes
= default_scopes
;
1556 free ((void *) old
);
1563 struct prefixentry entry
;
1564 struct prefixlist
*next
;
1570 struct scopeentry entry
;
1571 struct scopelist
*next
;
1576 free_prefixlist (struct prefixlist
*list
)
1578 while (list
!= NULL
)
1580 struct prefixlist
*oldp
= list
;
1588 free_scopelist (struct scopelist
*list
)
1590 while (list
!= NULL
)
1592 struct scopelist
*oldp
= list
;
1600 prefixcmp (const void *p1
, const void *p2
)
1602 const struct prefixentry
*e1
= (const struct prefixentry
*) p1
;
1603 const struct prefixentry
*e2
= (const struct prefixentry
*) p2
;
1605 if (e1
->bits
< e2
->bits
)
1607 if (e1
->bits
== e2
->bits
)
1614 scopecmp (const void *p1
, const void *p2
)
1616 const struct scopeentry
*e1
= (const struct scopeentry
*) p1
;
1617 const struct scopeentry
*e2
= (const struct scopeentry
*) p2
;
1619 if (e1
->netmask
> e2
->netmask
)
1621 if (e1
->netmask
== e2
->netmask
)
1630 struct prefixlist
*labellist
= NULL
;
1631 size_t nlabellist
= 0;
1632 bool labellist_nullbits
= false;
1633 struct prefixlist
*precedencelist
= NULL
;
1634 size_t nprecedencelist
= 0;
1635 bool precedencelist_nullbits
= false;
1636 struct scopelist
*scopelist
= NULL
;
1637 size_t nscopelist
= 0;
1638 bool scopelist_nullbits
= false;
1640 FILE *fp
= fopen (GAICONF_FNAME
, "rc");
1644 if (__fxstat64 (_STAT_VER
, fileno (fp
), &st
) != 0)
1653 __fsetlocking (fp
, FSETLOCKING_BYCALLER
);
1655 while (!feof_unlocked (fp
))
1657 ssize_t n
= __getline (&line
, &linelen
, fp
);
1661 /* Handle comments. No escaping possible so this is easy. */
1662 char *cp
= strchr (line
, '#');
1667 while (isspace (*cp
))
1671 while (*cp
!= '\0' && !isspace (*cp
))
1673 size_t cmdlen
= cp
- cmd
;
1677 while (isspace (*cp
))
1681 while (*cp
!= '\0' && !isspace (*cp
))
1683 size_t val1len
= cp
- cmd
;
1685 /* We always need at least two values. */
1691 while (isspace (*cp
))
1695 while (*cp
!= '\0' && !isspace (*cp
))
1698 /* Ignore the rest of the line. */
1701 struct prefixlist
**listp
;
1707 if (strcmp (cmd
, "label") == 0)
1709 struct in6_addr prefix
;
1710 unsigned long int bits
;
1711 unsigned long int val
;
1716 nullbitsp
= &labellist_nullbits
;
1721 cp
= strchr (val1
, '/');
1724 if (inet_pton (AF_INET6
, val1
, &prefix
)
1726 || (bits
= strtoul (cp
, &endp
, 10)) != ULONG_MAX
1730 && ((val
= strtoul (val2
, &endp
, 10)) != ULONG_MAX
1735 struct prefixlist
*newp
= malloc (sizeof (*newp
));
1743 memcpy (&newp
->entry
.prefix
, &prefix
, sizeof (prefix
));
1744 newp
->entry
.bits
= bits
;
1745 newp
->entry
.val
= val
;
1746 newp
->next
= *listp
;
1749 *nullbitsp
|= bits
== 0;
1755 if (strcmp (cmd
, "reload") == 0)
1757 gaiconf_reload_flag
= strcmp (val1
, "yes") == 0;
1758 if (gaiconf_reload_flag
)
1759 gaiconf_reload_flag_ever_set
= 1;
1764 if (strcmp (cmd
, "scopev4") == 0)
1766 struct in6_addr prefix
;
1767 unsigned long int bits
;
1768 unsigned long int val
;
1773 cp
= strchr (val1
, '/');
1776 if (inet_pton (AF_INET6
, val1
, &prefix
))
1779 if (IN6_IS_ADDR_V4MAPPED (&prefix
)
1781 || (bits
= strtoul (cp
, &endp
, 10)) != ULONG_MAX
1786 && ((val
= strtoul (val2
, &endp
, 10)) != ULONG_MAX
1791 struct scopelist
*newp
;
1793 newp
= malloc (sizeof (*newp
));
1801 newp
->entry
.netmask
= htonl (bits
!= 96
1805 newp
->entry
.addr32
= (prefix
.s6_addr32
[3]
1806 & newp
->entry
.netmask
);
1807 newp
->entry
.scope
= val
;
1808 newp
->next
= scopelist
;
1811 scopelist_nullbits
|= bits
== 96;
1814 else if (inet_pton (AF_INET
, val1
, &prefix
.s6_addr32
[3])
1816 || (bits
= strtoul (cp
, &endp
, 10)) != ULONG_MAX
1820 && ((val
= strtoul (val2
, &endp
, 10)) != ULONG_MAX
1832 if (strcmp (cmd
, "precedence") == 0)
1834 listp
= &precedencelist
;
1835 lenp
= &nprecedencelist
;
1836 nullbitsp
= &precedencelist_nullbits
;
1847 /* Create the array for the labels. */
1848 struct prefixentry
*new_labels
;
1851 if (!labellist_nullbits
)
1853 new_labels
= malloc (nlabellist
* sizeof (*new_labels
));
1854 if (new_labels
== NULL
)
1858 if (!labellist_nullbits
)
1861 memset (&new_labels
[i
].prefix
, '\0', sizeof (struct in6_addr
));
1862 new_labels
[i
].bits
= 0;
1863 new_labels
[i
].val
= 1;
1866 struct prefixlist
*l
= labellist
;
1869 new_labels
[i
] = l
->entry
;
1872 free_prefixlist (labellist
);
1874 /* Sort the entries so that the most specific ones are at
1876 qsort (new_labels
, nlabellist
, sizeof (*new_labels
), prefixcmp
);
1879 new_labels
= (struct prefixentry
*) default_labels
;
1881 struct prefixentry
*new_precedence
;
1882 if (nprecedencelist
> 0)
1884 if (!precedencelist_nullbits
)
1886 new_precedence
= malloc (nprecedencelist
* sizeof (*new_precedence
));
1887 if (new_precedence
== NULL
)
1889 if (new_labels
!= default_labels
)
1894 int i
= nprecedencelist
;
1895 if (!precedencelist_nullbits
)
1898 memset (&new_precedence
[i
].prefix
, '\0',
1899 sizeof (struct in6_addr
));
1900 new_precedence
[i
].bits
= 0;
1901 new_precedence
[i
].val
= 40;
1904 struct prefixlist
*l
= precedencelist
;
1907 new_precedence
[i
] = l
->entry
;
1910 free_prefixlist (precedencelist
);
1912 /* Sort the entries so that the most specific ones are at
1914 qsort (new_precedence
, nprecedencelist
, sizeof (*new_precedence
),
1918 new_precedence
= (struct prefixentry
*) default_precedence
;
1920 struct scopeentry
*new_scopes
;
1923 if (!scopelist_nullbits
)
1925 new_scopes
= malloc (nscopelist
* sizeof (*new_scopes
));
1926 if (new_scopes
== NULL
)
1928 if (new_labels
!= default_labels
)
1930 if (new_precedence
!= default_precedence
)
1931 free (new_precedence
);
1936 if (!scopelist_nullbits
)
1939 new_scopes
[i
].addr32
= 0;
1940 new_scopes
[i
].netmask
= 0;
1941 new_scopes
[i
].scope
= 14;
1944 struct scopelist
*l
= scopelist
;
1947 new_scopes
[i
] = l
->entry
;
1950 free_scopelist (scopelist
);
1952 /* Sort the entries so that the most specific ones are at
1954 qsort (new_scopes
, nscopelist
, sizeof (*new_scopes
),
1958 new_scopes
= (struct scopeentry
*) default_scopes
;
1960 /* Now we are ready to replace the values. */
1961 const struct prefixentry
*old
= labels
;
1962 labels
= new_labels
;
1963 if (old
!= default_labels
)
1964 free ((void *) old
);
1967 precedence
= new_precedence
;
1968 if (old
!= default_precedence
)
1969 free ((void *) old
);
1971 const struct scopeentry
*oldscope
= scopes
;
1972 scopes
= new_scopes
;
1973 if (oldscope
!= default_scopes
)
1974 free ((void *) oldscope
);
1976 gaiconf_mtime
= st
.st_mtim
;
1981 free_prefixlist (labellist
);
1982 free_prefixlist (precedencelist
);
1983 free_scopelist (scopelist
);
1985 /* If we previously read the file but it is gone now, free the
1986 old data and use the builtin one. Leave the reload flag
1994 gaiconf_reload (void)
1997 if (__xstat64 (_STAT_VER
, GAICONF_FNAME
, &st
) != 0
1998 || memcmp (&st
.st_mtim
, &gaiconf_mtime
, sizeof (gaiconf_mtime
)) != 0)
2004 getaddrinfo (const char *name
, const char *service
,
2005 const struct addrinfo
*hints
, struct addrinfo
**pai
)
2007 int i
= 0, last_i
= 0;
2009 struct addrinfo
*p
= NULL
;
2010 struct gaih_service gaih_service
, *pservice
;
2011 struct addrinfo local_hints
;
2013 if (name
!= NULL
&& name
[0] == '*' && name
[1] == 0)
2016 if (service
!= NULL
&& service
[0] == '*' && service
[1] == 0)
2019 if (name
== NULL
&& service
== NULL
)
2023 hints
= &default_hints
;
2026 & ~(AI_PASSIVE
|AI_CANONNAME
|AI_NUMERICHOST
|AI_ADDRCONFIG
|AI_V4MAPPED
2028 |AI_IDN
|AI_CANONIDN
|AI_IDN_ALLOW_UNASSIGNED
2029 |AI_IDN_USE_STD3_ASCII_RULES
2031 |AI_NUMERICSERV
|AI_ALL
))
2032 return EAI_BADFLAGS
;
2034 if ((hints
->ai_flags
& AI_CANONNAME
) && name
== NULL
)
2035 return EAI_BADFLAGS
;
2037 struct in6addrinfo
*in6ai
= NULL
;
2038 size_t in6ailen
= 0;
2039 bool seen_ipv4
= false;
2040 bool seen_ipv6
= false;
2041 /* We might need information about what interfaces are available.
2042 Also determine whether we have IPv4 or IPv6 interfaces or both. We
2043 cannot cache the results since new interfaces could be added at
2045 __check_pf (&seen_ipv4
, &seen_ipv6
, &in6ai
, &in6ailen
);
2047 if (hints
->ai_flags
& AI_ADDRCONFIG
)
2049 /* Now make a decision on what we return, if anything. */
2050 if (hints
->ai_family
== PF_UNSPEC
&& (seen_ipv4
|| seen_ipv6
))
2052 /* If we haven't seen both IPv4 and IPv6 interfaces we can
2053 narrow down the search. */
2054 if (! seen_ipv4
|| ! seen_ipv6
)
2056 local_hints
= *hints
;
2057 local_hints
.ai_family
= seen_ipv4
? PF_INET
: PF_INET6
;
2058 hints
= &local_hints
;
2061 else if ((hints
->ai_family
== PF_INET
&& ! seen_ipv4
)
2062 || (hints
->ai_family
== PF_INET6
&& ! seen_ipv6
))
2064 /* We cannot possibly return a valid answer. */
2070 if (service
&& service
[0])
2073 gaih_service
.name
= service
;
2074 gaih_service
.num
= strtoul (gaih_service
.name
, &c
, 10);
2077 if (hints
->ai_flags
& AI_NUMERICSERV
)
2083 gaih_service
.num
= -1;
2086 pservice
= &gaih_service
;
2091 struct addrinfo
**end
;
2097 unsigned int naddrs
= 0;
2098 if (hints
->ai_family
== AF_UNSPEC
|| hints
->ai_family
== AF_INET
2099 || hints
->ai_family
== AF_INET6
)
2101 last_i
= gaih_inet (name
, pservice
, hints
, end
, &naddrs
);
2107 return -(last_i
& GAIH_EAI
);
2112 end
= &((*end
)->ai_next
);
2124 /* Read the config file. */
2125 __libc_once_define (static, once
);
2126 __typeof (once
) old_once
= once
;
2127 __libc_once (once
, gaiconf_init
);
2128 /* Sort results according to RFC 3484. */
2129 struct sort_result results
[nresults
];
2130 size_t order
[nresults
];
2132 struct addrinfo
*last
= NULL
;
2133 char *canonname
= NULL
;
2135 /* If we have information about deprecated and temporary addresses
2136 sort the array now. */
2138 qsort (in6ai
, in6ailen
, sizeof (*in6ai
), in6aicmp
);
2143 for (i
= 0, q
= p
; q
!= NULL
; ++i
, last
= q
, q
= q
->ai_next
)
2145 results
[i
].dest_addr
= q
;
2146 results
[i
].native
= -1;
2149 /* If we just looked up the address for a different
2150 protocol, reuse the result. */
2151 if (last
!= NULL
&& last
->ai_addrlen
== q
->ai_addrlen
2152 && memcmp (last
->ai_addr
, q
->ai_addr
, q
->ai_addrlen
) == 0)
2154 memcpy (&results
[i
].source_addr
, &results
[i
- 1].source_addr
,
2155 results
[i
- 1].source_addr_len
);
2156 results
[i
].source_addr_len
= results
[i
- 1].source_addr_len
;
2157 results
[i
].got_source_addr
= results
[i
- 1].got_source_addr
;
2158 results
[i
].source_addr_flags
= results
[i
- 1].source_addr_flags
;
2159 results
[i
].prefixlen
= results
[i
- 1].prefixlen
;
2160 results
[i
].index
= results
[i
- 1].index
;
2164 results
[i
].got_source_addr
= false;
2165 results
[i
].source_addr_flags
= 0;
2166 results
[i
].prefixlen
= 0;
2167 results
[i
].index
= 0xffffffffu
;
2169 /* We overwrite the type with SOCK_DGRAM since we do not
2170 want connect() to connect to the other side. If we
2171 cannot determine the source address remember this
2173 if (fd
== -1 || (af
== AF_INET
&& q
->ai_family
== AF_INET6
))
2177 close_not_cancel_no_status (fd
);
2179 fd
= __socket (af
, SOCK_DGRAM
, IPPROTO_IP
);
2183 /* Reset the connection. */
2184 struct sockaddr sa
= { .sa_family
= AF_UNSPEC
};
2185 __connect (fd
, &sa
, sizeof (sa
));
2188 socklen_t sl
= sizeof (results
[i
].source_addr
);
2190 && __connect (fd
, q
->ai_addr
, q
->ai_addrlen
) == 0
2191 && __getsockname (fd
,
2192 (struct sockaddr
*) &results
[i
].source_addr
,
2195 results
[i
].source_addr_len
= sl
;
2196 results
[i
].got_source_addr
= true;
2200 /* See whether the source address is on the list of
2201 deprecated or temporary addresses. */
2202 struct in6addrinfo tmp
;
2204 if (q
->ai_family
== AF_INET
&& af
== AF_INET
)
2206 struct sockaddr_in
*sinp
2207 = (struct sockaddr_in
*) &results
[i
].source_addr
;
2210 tmp
.addr
[2] = htonl (0xffff);
2211 tmp
.addr
[3] = sinp
->sin_addr
.s_addr
;
2215 struct sockaddr_in6
*sin6p
2216 = (struct sockaddr_in6
*) &results
[i
].source_addr
;
2217 memcpy (tmp
.addr
, &sin6p
->sin6_addr
, IN6ADDRSZ
);
2220 struct in6addrinfo
*found
2221 = bsearch (&tmp
, in6ai
, in6ailen
, sizeof (*in6ai
),
2225 results
[i
].source_addr_flags
= found
->flags
;
2226 results
[i
].prefixlen
= found
->prefixlen
;
2227 results
[i
].index
= found
->index
;
2231 if (q
->ai_family
== AF_INET
&& af
== AF_INET6
)
2233 /* We have to convert the address. The socket is
2234 IPv6 and the request is for IPv4. */
2235 struct sockaddr_in6
*sin6
2236 = (struct sockaddr_in6
*) &results
[i
].source_addr
;
2237 struct sockaddr_in
*sin
2238 = (struct sockaddr_in
*) &results
[i
].source_addr
;
2239 assert (IN6_IS_ADDR_V4MAPPED (sin6
->sin6_addr
.s6_addr32
));
2240 sin
->sin_family
= AF_INET
;
2241 /* We do not have to initialize sin_port since this
2242 fields has the same position and size in the IPv6
2244 assert (offsetof (struct sockaddr_in
, sin_port
)
2245 == offsetof (struct sockaddr_in6
, sin6_port
));
2246 assert (sizeof (sin
->sin_port
)
2247 == sizeof (sin6
->sin6_port
));
2248 memcpy (&sin
->sin_addr
,
2249 &sin6
->sin6_addr
.s6_addr32
[3], INADDRSZ
);
2250 results
[i
].source_addr_len
= sizeof (struct sockaddr_in
);
2253 else if (errno
== EAFNOSUPPORT
&& af
== AF_INET6
2254 && q
->ai_family
== AF_INET
)
2255 /* This could mean IPv6 sockets are IPv6-only. */
2258 /* Just make sure that if we have to process the same
2259 address again we do not copy any memory. */
2260 results
[i
].source_addr_len
= 0;
2263 /* Remember the canonical name. */
2264 if (q
->ai_canonname
!= NULL
)
2266 assert (canonname
== NULL
);
2267 canonname
= q
->ai_canonname
;
2268 q
->ai_canonname
= NULL
;
2273 close_not_cancel_no_status (fd
);
2275 /* We got all the source addresses we can get, now sort using
2277 struct sort_result_combo src
2278 = { .results
= results
, .nresults
= nresults
};
2279 if (__builtin_expect (gaiconf_reload_flag_ever_set
, 0))
2281 __libc_lock_define_initialized (static, lock
);
2283 __libc_lock_lock (lock
);
2284 if (old_once
&& gaiconf_reload_flag
)
2286 qsort_r (order
, nresults
, sizeof (order
[0]), rfc3484_sort
, &src
);
2287 __libc_lock_unlock (lock
);
2290 qsort_r (order
, nresults
, sizeof (order
[0]), rfc3484_sort
, &src
);
2292 /* Queue the results up as they come out of sorting. */
2293 q
= p
= results
[order
[0]].dest_addr
;
2294 for (i
= 1; i
< nresults
; ++i
)
2295 q
= q
->ai_next
= results
[order
[i
]].dest_addr
;
2298 /* Fill in the canonical name into the new first entry. */
2299 p
->ai_canonname
= canonname
;
2310 if (pai
== NULL
&& last_i
== 0)
2313 return last_i
? -(last_i
& GAIH_EAI
) : EAI_NONAME
;
2315 libc_hidden_def (getaddrinfo
)
2317 static_link_warning (getaddrinfo
)
2320 freeaddrinfo (struct addrinfo
*ai
)
2328 free (p
->ai_canonname
);
2332 libc_hidden_def (freeaddrinfo
)