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. */
48 #include <arpa/inet.h>
49 #include <sys/socket.h>
50 #include <netinet/in.h>
51 #include <sys/types.h>
53 #include <sys/utsname.h>
56 #include <not-cancel.h>
59 extern int __idna_to_ascii_lz (const char *input
, char **output
, int flags
);
60 extern int __idna_to_unicode_lzlz (const char *input
, char **output
,
62 # include <libidn/idna.h>
65 #define GAIH_OKIFUNSPEC 0x0100
66 #define GAIH_EAI ~(GAIH_OKIFUNSPEC)
69 #define UNIX_PATH_MAX 108
80 struct gaih_servtuple
*next
;
86 static const struct gaih_servtuple nullserv
;
90 struct gaih_addrtuple
*next
;
104 /* Values for `protoflag'. */
105 #define GAI_PROTO_NOSERVICE 1
106 #define GAI_PROTO_PROTOANY 2
108 static const struct gaih_typeproto gaih_inet_typeproto
[] =
111 { SOCK_STREAM
, IPPROTO_TCP
, "tcp", 0 },
112 { SOCK_DGRAM
, IPPROTO_UDP
, "udp", 0 },
113 { SOCK_RAW
, 0, "raw", GAI_PROTO_PROTOANY
|GAI_PROTO_NOSERVICE
},
120 int (*gaih
)(const char *name
, const struct gaih_service
*service
,
121 const struct addrinfo
*req
, struct addrinfo
**pai
);
124 static const struct addrinfo default_hints
=
126 .ai_flags
= AI_DEFAULT
,
127 .ai_family
= PF_UNSPEC
,
132 .ai_canonname
= NULL
,
138 /* Using Unix sockets this way is a security risk. */
140 gaih_local (const char *name
, const struct gaih_service
*service
,
141 const struct addrinfo
*req
, struct addrinfo
**pai
)
143 struct utsname utsname
;
145 if ((name
!= NULL
) && (req
->ai_flags
& AI_NUMERICHOST
))
146 return GAIH_OKIFUNSPEC
| -EAI_NONAME
;
148 if ((name
!= NULL
) || (req
->ai_flags
& AI_CANONNAME
))
149 if (uname (&utsname
) < 0)
154 if (strcmp(name
, "localhost") &&
155 strcmp(name
, "local") &&
156 strcmp(name
, "unix") &&
157 strcmp(name
, utsname
.nodename
))
158 return GAIH_OKIFUNSPEC
| -EAI_NONAME
;
161 if (req
->ai_protocol
|| req
->ai_socktype
)
163 const struct gaih_typeproto
*tp
= gaih_inet_typeproto
+ 1;
166 && ((tp
->protoflag
& GAI_PROTO_NOSERVICE
) != 0
167 || (req
->ai_socktype
!= 0 && req
->ai_socktype
!= tp
->socktype
)
168 || (req
->ai_protocol
!= 0
169 && !(tp
->protoflag
& GAI_PROTO_PROTOANY
)
170 && req
->ai_protocol
!= tp
->protocol
)))
175 if (req
->ai_socktype
)
176 return (GAIH_OKIFUNSPEC
| -EAI_SOCKTYPE
);
178 return (GAIH_OKIFUNSPEC
| -EAI_SERVICE
);
182 *pai
= malloc (sizeof (struct addrinfo
) + sizeof (struct sockaddr_un
)
183 + ((req
->ai_flags
& AI_CANONNAME
)
184 ? (strlen(utsname
.nodename
) + 1): 0));
188 (*pai
)->ai_next
= NULL
;
189 (*pai
)->ai_flags
= req
->ai_flags
;
190 (*pai
)->ai_family
= AF_LOCAL
;
191 (*pai
)->ai_socktype
= req
->ai_socktype
? req
->ai_socktype
: SOCK_STREAM
;
192 (*pai
)->ai_protocol
= req
->ai_protocol
;
193 (*pai
)->ai_addrlen
= sizeof (struct sockaddr_un
);
194 (*pai
)->ai_addr
= (void *) (*pai
) + sizeof (struct addrinfo
);
197 ((struct sockaddr_un
*) (*pai
)->ai_addr
)->sun_len
=
198 sizeof (struct sockaddr_un
);
201 ((struct sockaddr_un
*)(*pai
)->ai_addr
)->sun_family
= AF_LOCAL
;
202 memset(((struct sockaddr_un
*)(*pai
)->ai_addr
)->sun_path
, 0, UNIX_PATH_MAX
);
206 struct sockaddr_un
*sunp
= (struct sockaddr_un
*) (*pai
)->ai_addr
;
208 if (strchr (service
->name
, '/') != NULL
)
210 if (strlen (service
->name
) >= sizeof (sunp
->sun_path
))
211 return GAIH_OKIFUNSPEC
| -EAI_SERVICE
;
213 strcpy (sunp
->sun_path
, service
->name
);
217 if (strlen (P_tmpdir
"/") + 1 + strlen (service
->name
) >=
218 sizeof (sunp
->sun_path
))
219 return GAIH_OKIFUNSPEC
| -EAI_SERVICE
;
221 __stpcpy (__stpcpy (sunp
->sun_path
, P_tmpdir
"/"), service
->name
);
226 /* This is a dangerous use of the interface since there is a time
227 window between the test for the file and the actual creation
228 (done by the caller) in which a file with the same name could
230 char *buf
= ((struct sockaddr_un
*) (*pai
)->ai_addr
)->sun_path
;
232 if (__builtin_expect (__path_search (buf
, L_tmpnam
, NULL
, NULL
, 0),
234 || __builtin_expect (__gen_tempname (buf
, __GT_NOCREATE
), 0) != 0)
238 if (req
->ai_flags
& AI_CANONNAME
)
239 (*pai
)->ai_canonname
= strcpy ((char *) *pai
+ sizeof (struct addrinfo
)
240 + sizeof (struct sockaddr_un
),
243 (*pai
)->ai_canonname
= NULL
;
249 gaih_inet_serv (const char *servicename
, const struct gaih_typeproto
*tp
,
250 const struct addrinfo
*req
, struct gaih_servtuple
*st
)
253 size_t tmpbuflen
= 1024;
260 tmpbuf
= __alloca (tmpbuflen
);
262 r
= __getservbyname_r (servicename
, tp
->name
, &ts
, tmpbuf
, tmpbuflen
,
264 if (r
!= 0 || s
== NULL
)
269 return GAIH_OKIFUNSPEC
| -EAI_SERVICE
;
275 st
->socktype
= tp
->socktype
;
276 st
->protocol
= ((tp
->protoflag
& GAI_PROTO_PROTOANY
)
277 ? req
->ai_protocol
: tp
->protocol
);
278 st
->port
= s
->s_port
;
283 #define gethosts(_family, _type) \
291 status = DL_CALL_FCT (fct, (name, _family, &th, tmpbuf, \
292 tmpbuflen, &rc, &herrno)); \
293 if (rc != ERANGE || herrno != NETDB_INTERNAL) \
295 tmpbuf = extend_alloca (tmpbuf, tmpbuflen, 2 * tmpbuflen); \
297 if (status == NSS_STATUS_SUCCESS && rc == 0) \
303 if (herrno == NETDB_INTERNAL) \
305 __set_h_errno (herrno); \
306 return -EAI_SYSTEM; \
308 if (herrno == TRY_AGAIN) \
309 no_data = EAI_AGAIN; \
311 no_data = herrno == NO_DATA; \
313 else if (h != NULL) \
315 for (i = 0; h->h_addr_list[i]; i++) \
319 *pat = __alloca (sizeof (struct gaih_addrtuple)); \
320 (*pat)->scopeid = 0; \
322 uint32_t *addr = (*pat)->addr; \
323 (*pat)->next = NULL; \
324 if (_family == AF_INET && req->ai_family == AF_INET6) \
326 (*pat)->family = AF_INET6; \
327 addr[3] = *(uint32_t *) h->h_addr_list[i]; \
328 addr[2] = htonl (0xffff); \
334 (*pat)->family = _family; \
335 memcpy (addr, h->h_addr_list[i], sizeof(_type)); \
337 pat = &((*pat)->next); \
340 if (_family == AF_INET6 && i > 0) \
346 typedef enum nss_status (*nss_gethostbyname2_r
)
347 (const char *name
, int af
, struct hostent
*host
,
348 char *buffer
, size_t buflen
, int *errnop
,
350 typedef enum nss_status (*nss_getcanonname_r
)
351 (const char *name
, char *buffer
, size_t buflen
, char **result
,
352 int *errnop
, int *h_errnop
);
353 extern service_user
*__nss_hosts_database attribute_hidden
;
356 gaih_inet (const char *name
, const struct gaih_service
*service
,
357 const struct addrinfo
*req
, struct addrinfo
**pai
)
359 const struct gaih_typeproto
*tp
= gaih_inet_typeproto
;
360 struct gaih_servtuple
*st
= (struct gaih_servtuple
*) &nullserv
;
361 struct gaih_addrtuple
*at
= NULL
;
363 bool got_ipv6
= false;
364 const char *canon
= NULL
;
366 if (req
->ai_protocol
|| req
->ai_socktype
)
371 && ((req
->ai_socktype
!= 0 && req
->ai_socktype
!= tp
->socktype
)
372 || (req
->ai_protocol
!= 0
373 && !(tp
->protoflag
& GAI_PROTO_PROTOANY
)
374 && req
->ai_protocol
!= tp
->protocol
)))
379 if (req
->ai_socktype
)
380 return (GAIH_OKIFUNSPEC
| -EAI_SOCKTYPE
);
382 return (GAIH_OKIFUNSPEC
| -EAI_SERVICE
);
388 if ((tp
->protoflag
& GAI_PROTO_NOSERVICE
) != 0)
389 return (GAIH_OKIFUNSPEC
| -EAI_SERVICE
);
391 if (service
->num
< 0)
395 st
= (struct gaih_servtuple
*)
396 __alloca (sizeof (struct gaih_servtuple
));
398 if ((rc
= gaih_inet_serv (service
->name
, tp
, req
, st
)))
403 struct gaih_servtuple
**pst
= &st
;
404 for (tp
++; tp
->name
[0]; tp
++)
406 struct gaih_servtuple
*newp
;
408 if ((tp
->protoflag
& GAI_PROTO_NOSERVICE
) != 0)
411 if (req
->ai_socktype
!= 0
412 && req
->ai_socktype
!= tp
->socktype
)
414 if (req
->ai_protocol
!= 0
415 && !(tp
->protoflag
& GAI_PROTO_PROTOANY
)
416 && req
->ai_protocol
!= tp
->protocol
)
419 newp
= (struct gaih_servtuple
*)
420 __alloca (sizeof (struct gaih_servtuple
));
422 if ((rc
= gaih_inet_serv (service
->name
, tp
, req
, newp
)))
424 if (rc
& GAIH_OKIFUNSPEC
)
432 if (st
== (struct gaih_servtuple
*) &nullserv
)
433 return (GAIH_OKIFUNSPEC
| -EAI_SERVICE
);
438 st
= __alloca (sizeof (struct gaih_servtuple
));
440 st
->socktype
= tp
->socktype
;
441 st
->protocol
= ((tp
->protoflag
& GAI_PROTO_PROTOANY
)
442 ? req
->ai_protocol
: tp
->protocol
);
443 st
->port
= htons (service
->num
);
446 else if (req
->ai_socktype
|| req
->ai_protocol
)
448 st
= __alloca (sizeof (struct gaih_servtuple
));
450 st
->socktype
= tp
->socktype
;
451 st
->protocol
= ((tp
->protoflag
& GAI_PROTO_PROTOANY
)
452 ? req
->ai_protocol
: tp
->protocol
);
457 /* Neither socket type nor protocol is set. Return all socket types
459 struct gaih_servtuple
**lastp
= &st
;
460 for (++tp
; tp
->name
[0]; ++tp
)
462 struct gaih_servtuple
*newp
;
464 newp
= __alloca (sizeof (struct gaih_servtuple
));
466 newp
->socktype
= tp
->socktype
;
467 newp
->protocol
= tp
->protocol
;
477 at
= __alloca (sizeof (struct gaih_addrtuple
));
479 at
->family
= AF_UNSPEC
;
484 if (req
->ai_flags
& AI_IDN
)
487 if (req
->ai_flags
& AI_IDN_ALLOW_UNASSIGNED
)
488 idn_flags
|= IDNA_ALLOW_UNASSIGNED
;
489 if (req
->ai_flags
& AI_IDN_USE_STD3_ASCII_RULES
)
490 idn_flags
|= IDNA_USE_STD3_ASCII_RULES
;
493 rc
= __idna_to_ascii_lz (name
, &p
, idn_flags
);
494 if (rc
!= IDNA_SUCCESS
)
496 if (rc
== IDNA_MALLOC_ERROR
)
498 if (rc
== IDNA_DLOPEN_ERROR
)
500 return -EAI_IDN_ENCODE
;
502 /* In case the output string is the same as the input string
503 no new string has been allocated. */
512 if (__inet_aton (name
, (struct in_addr
*) at
->addr
) != 0)
514 if (req
->ai_family
== AF_UNSPEC
|| req
->ai_family
== AF_INET
)
515 at
->family
= AF_INET
;
516 else if (req
->ai_family
== AF_INET6
&& req
->ai_flags
& AI_V4MAPPED
)
518 at
->addr
[3] = at
->addr
[0];
519 at
->addr
[2] = htonl (0xffff);
522 at
->family
= AF_INET6
;
525 return -EAI_ADDRFAMILY
;
528 if (at
->family
== AF_UNSPEC
)
530 char *namebuf
= strdupa (name
);
533 scope_delim
= strchr (namebuf
, SCOPE_DELIMITER
);
534 if (scope_delim
!= NULL
)
537 if (inet_pton (AF_INET6
, namebuf
, at
->addr
) > 0)
539 if (req
->ai_family
== AF_UNSPEC
|| req
->ai_family
== AF_INET6
)
540 at
->family
= AF_INET6
;
541 else if (req
->ai_family
== AF_INET
542 && IN6_IS_ADDR_V4MAPPED (at
->addr
))
544 at
->addr
[0] = at
->addr
[3];
545 at
->family
= AF_INET
;
548 return -EAI_ADDRFAMILY
;
550 if (scope_delim
!= NULL
)
552 int try_numericscope
= 0;
553 if (IN6_IS_ADDR_LINKLOCAL (at
->addr
)
554 || IN6_IS_ADDR_MC_LINKLOCAL (at
->addr
))
556 at
->scopeid
= if_nametoindex (scope_delim
+ 1);
557 if (at
->scopeid
== 0)
558 try_numericscope
= 1;
561 try_numericscope
= 1;
563 if (try_numericscope
!= 0)
566 assert (sizeof (uint32_t) <= sizeof (unsigned long));
567 at
->scopeid
= (uint32_t) strtoul (scope_delim
+ 1, &end
,
570 return GAIH_OKIFUNSPEC
| -EAI_NONAME
;
576 if (at
->family
== AF_UNSPEC
&& (req
->ai_flags
& AI_NUMERICHOST
) == 0)
579 struct gaih_addrtuple
**pat
= &at
;
581 int no_inet6_data
= 0;
582 service_user
*nip
= NULL
;
583 enum nss_status inet6_status
= NSS_STATUS_UNAVAIL
;
584 enum nss_status status
= NSS_STATUS_UNAVAIL
;
586 nss_gethostbyname2_r fct
;
588 size_t tmpbuflen
= 512;
589 char *tmpbuf
= alloca (tmpbuflen
);
591 if (__nss_hosts_database
!= NULL
)
594 nip
= __nss_hosts_database
;
597 no_more
= __nss_database_lookup ("hosts", NULL
,
598 "dns [!UNAVAIL=return] files",
601 if (__res_maybe_init (&_res
, 0) == -1)
604 /* If we are looking for both IPv4 and IPv6 address we don't
605 want the lookup functions to automatically promote IPv4
606 addresses to IPv6 addresses. Currently this is decided
607 by setting the RES_USE_INET6 bit in _res.options. */
608 old_res_options
= _res
.options
;
609 _res
.options
&= ~RES_USE_INET6
;
613 fct
= __nss_lookup_function (nip
, "gethostbyname2_r");
617 if (req
->ai_family
== AF_INET6
618 || req
->ai_family
== AF_UNSPEC
)
620 gethosts (AF_INET6
, struct in6_addr
);
621 no_inet6_data
= no_data
;
622 inet6_status
= status
;
624 if (req
->ai_family
== AF_INET
625 || req
->ai_family
== AF_UNSPEC
626 || (req
->ai_family
== AF_INET6
627 && (req
->ai_flags
& AI_V4MAPPED
)
628 /* Avoid generating the mapped addresses if we
629 know we are not going to need them. */
630 && ((req
->ai_flags
& AI_ALL
) || !got_ipv6
)))
632 gethosts (AF_INET
, struct in_addr
);
634 if (req
->ai_family
== AF_INET
)
636 no_inet6_data
= no_data
;
637 inet6_status
= status
;
641 /* If we found one address for AF_INET or AF_INET6,
642 don't continue the search. */
643 if (inet6_status
== NSS_STATUS_SUCCESS
644 || status
== NSS_STATUS_SUCCESS
)
646 /* If we need the canonical name, get it from the same
647 service as the result. */
648 nss_getcanonname_r cfct
;
651 cfct
= __nss_lookup_function (nip
, "getcanonname_r");
654 const size_t max_fqdn_len
= 256;
655 char *buf
= alloca (max_fqdn_len
);
658 if (DL_CALL_FCT (cfct
, (name
, buf
, max_fqdn_len
,
660 == NSS_STATUS_SUCCESS
)
663 /* Set to name now to avoid using
671 /* We can have different states for AF_INET and
672 AF_INET6. Try to find a useful one for both. */
673 if (inet6_status
== NSS_STATUS_TRYAGAIN
)
674 status
= NSS_STATUS_TRYAGAIN
;
675 else if (status
== NSS_STATUS_UNAVAIL
&&
676 inet6_status
!= NSS_STATUS_UNAVAIL
)
677 status
= inet6_status
;
680 if (nss_next_action (nip
, status
) == NSS_ACTION_RETURN
)
683 if (nip
->next
== NULL
)
689 _res
.options
= old_res_options
;
691 if (no_data
!= 0 && no_inet6_data
!= 0)
693 /* If both requests timed out report this. */
694 if (no_data
== EAI_AGAIN
&& no_inet6_data
== EAI_AGAIN
)
697 /* We made requests but they turned out no data. The name
699 return (GAIH_OKIFUNSPEC
| -EAI_NODATA
);
703 if (at
->family
== AF_UNSPEC
)
704 return (GAIH_OKIFUNSPEC
| -EAI_NONAME
);
708 struct gaih_addrtuple
*atr
;
709 atr
= at
= __alloca (sizeof (struct gaih_addrtuple
));
710 memset (at
, '\0', sizeof (struct gaih_addrtuple
));
712 if (req
->ai_family
== AF_UNSPEC
)
714 at
->next
= __alloca (sizeof (struct gaih_addrtuple
));
715 memset (at
->next
, '\0', sizeof (struct gaih_addrtuple
));
718 if (req
->ai_family
== AF_UNSPEC
|| req
->ai_family
== AF_INET6
)
720 at
->family
= AF_INET6
;
721 if ((req
->ai_flags
& AI_PASSIVE
) == 0)
722 memcpy (at
->addr
, &in6addr_loopback
, sizeof (struct in6_addr
));
726 if (req
->ai_family
== AF_UNSPEC
|| req
->ai_family
== AF_INET
)
728 atr
->family
= AF_INET
;
729 if ((req
->ai_flags
& AI_PASSIVE
) == 0)
730 atr
->addr
[0] = htonl (INADDR_LOOPBACK
);
738 struct gaih_servtuple
*st2
;
739 struct gaih_addrtuple
*at2
= at
;
744 buffer is the size of an unformatted IPv6 address in printable format.
748 /* Only the first entry gets the canonical name. */
749 if (at2
== at
&& (req
->ai_flags
& AI_CANONNAME
) != 0)
753 struct hostent
*h
= NULL
;
756 size_t tmpbuflen
= 512;
761 tmpbuf
= extend_alloca (tmpbuf
, tmpbuflen
, tmpbuflen
* 2);
762 rc
= __gethostbyaddr_r (at2
->addr
,
763 ((at2
->family
== AF_INET6
)
764 ? sizeof (struct in6_addr
)
765 : sizeof (struct in_addr
)),
766 at2
->family
, &th
, tmpbuf
,
767 tmpbuflen
, &h
, &herrno
);
769 while (rc
== ERANGE
&& herrno
== NETDB_INTERNAL
);
771 if (rc
!= 0 && herrno
== NETDB_INTERNAL
)
773 __set_h_errno (herrno
);
781 assert (name
!= NULL
);
782 /* If the canonical name cannot be determined, use
783 the passed in string. */
789 if (req
->ai_flags
& AI_CANONIDN
)
792 if (req
->ai_flags
& AI_IDN_ALLOW_UNASSIGNED
)
793 idn_flags
|= IDNA_ALLOW_UNASSIGNED
;
794 if (req
->ai_flags
& AI_IDN_USE_STD3_ASCII_RULES
)
795 idn_flags
|= IDNA_USE_STD3_ASCII_RULES
;
798 int rc
= __idna_to_unicode_lzlz (canon
, &out
, idn_flags
);
799 if (rc
!= IDNA_SUCCESS
)
801 if (rc
== IDNA_MALLOC_ERROR
)
803 if (rc
== IDNA_DLOPEN_ERROR
)
805 return -EAI_IDN_ENCODE
;
807 /* In case the output string is the same as the input
808 string no new string has been allocated. Otherwise
819 canon
= strdup (canon
);
825 if (at2
->family
== AF_INET6
)
828 socklen
= sizeof (struct sockaddr_in6
);
830 /* If we looked up IPv4 mapped address discard them here if
831 the caller isn't interested in all address and we have
832 found at least one IPv6 address. */
834 && (req
->ai_flags
& (AI_V4MAPPED
|AI_ALL
)) == AI_V4MAPPED
835 && IN6_IS_ADDR_V4MAPPED (at2
->addr
))
841 socklen
= sizeof (struct sockaddr_in
);
844 for (st2
= st
; st2
!= NULL
; st2
= st2
->next
)
846 *pai
= malloc (sizeof (struct addrinfo
) + socklen
);
850 (*pai
)->ai_flags
= req
->ai_flags
;
851 (*pai
)->ai_family
= family
;
852 (*pai
)->ai_socktype
= st2
->socktype
;
853 (*pai
)->ai_protocol
= st2
->protocol
;
854 (*pai
)->ai_addrlen
= socklen
;
855 (*pai
)->ai_addr
= (void *) (*pai
+ 1);
857 /* We only add the canonical name once. */
858 (*pai
)->ai_canonname
= canon
;
862 (*pai
)->ai_addr
->sa_len
= socklen
;
864 (*pai
)->ai_addr
->sa_family
= family
;
866 if (family
== AF_INET6
)
868 struct sockaddr_in6
*sin6p
=
869 (struct sockaddr_in6
*) (*pai
)->ai_addr
;
871 sin6p
->sin6_port
= st2
->port
;
872 sin6p
->sin6_flowinfo
= 0;
873 memcpy (&sin6p
->sin6_addr
,
874 at2
->addr
, sizeof (struct in6_addr
));
875 sin6p
->sin6_scope_id
= at2
->scopeid
;
879 struct sockaddr_in
*sinp
=
880 (struct sockaddr_in
*) (*pai
)->ai_addr
;
881 sinp
->sin_port
= st2
->port
;
882 memcpy (&sinp
->sin_addr
,
883 at2
->addr
, sizeof (struct in_addr
));
884 memset (sinp
->sin_zero
, '\0', sizeof (sinp
->sin_zero
));
887 (*pai
)->ai_next
= NULL
;
888 pai
= &((*pai
)->ai_next
);
898 static struct gaih gaih
[] =
900 { PF_INET6
, gaih_inet
},
901 { PF_INET
, gaih_inet
},
903 { PF_LOCAL
, gaih_local
},
910 struct addrinfo
*dest_addr
;
911 struct sockaddr_storage source_addr
;
912 bool got_source_addr
;
917 get_scope (const struct sockaddr_storage
*ss
)
920 if (ss
->ss_family
== PF_INET6
)
922 const struct sockaddr_in6
*in6
= (const struct sockaddr_in6
*) ss
;
924 if (! IN6_IS_ADDR_MULTICAST (&in6
->sin6_addr
))
926 if (IN6_IS_ADDR_LINKLOCAL (&in6
->sin6_addr
))
928 else if (IN6_IS_ADDR_SITELOCAL (&in6
->sin6_addr
))
931 /* XXX Is this the correct default behavior? */
935 scope
= in6
->sin6_addr
.s6_addr
[1] & 0xf;
937 else if (ss
->ss_family
== PF_INET
)
939 const struct sockaddr_in
*in
= (const struct sockaddr_in
*) ss
;
940 const uint8_t *addr
= (const uint8_t *) &in
->sin_addr
;
942 /* RFC 3484 specifies how to map IPv6 addresses to scopes.
943 169.254/16 and 127/8 are link-local. */
944 if ((addr
[0] == 169 && addr
[1] == 254) || addr
[0] == 127)
946 else if (addr
[0] == 10 || (addr
[0] == 172 && addr
[1] == 16)
947 || (addr
[0] == 192 && addr
[1] == 168))
953 /* XXX What is a good default? */
960 /* XXX The system administrator should be able to install other
961 tables. We need to make this configurable. The problem is that
962 the kernel is also involved since it needs the same table. */
963 static const struct prefixlist
965 struct in6_addr prefix
;
970 /* See RFC 3484 for the details. */
971 { { .in6_u
= { .u6_addr16
= { 0x0000, 0x0000, 0x0000, 0x0000,
972 0x0000, 0x0000, 0x0000, 0x0001 } } },
974 { { .in6_u
= { .u6_addr16
= { 0x2002, 0x0000, 0x0000, 0x0000,
975 0x0000, 0x0000, 0x0000, 0x0000 } } },
977 { { .in6_u
= { .u6_addr16
= { 0x0000, 0x0000, 0x0000, 0x0000,
978 0x0000, 0x0000, 0x0000, 0x0000 } } },
980 { { .in6_u
= { .u6_addr16
= { 0x0000, 0x0000, 0x0000, 0x0000,
981 0x0000, 0xffff, 0x0000, 0x0000 } } },
983 { { .in6_u
= { .u6_addr16
= { 0x0000, 0x0000, 0x0000, 0x0000,
984 0x0000, 0x0000, 0x0000, 0x0000 } } },
989 static const struct prefixlist default_precedence
[] =
991 /* See RFC 3484 for the details. */
992 { { .in6_u
= { .u6_addr16
= { 0x0000, 0x0000, 0x0000, 0x0000,
993 0x0000, 0x0000, 0x0000, 0x0001 } } },
995 { { .in6_u
= { .u6_addr16
= { 0x2002, 0x0000, 0x0000, 0x0000,
996 0x0000, 0x0000, 0x0000, 0x0000 } } },
998 { { .in6_u
= { .u6_addr16
= { 0x0000, 0x0000, 0x0000, 0x0000,
999 0x0000, 0x0000, 0x0000, 0x0000 } } },
1001 { { .in6_u
= { .u6_addr16
= { 0x0000, 0x0000, 0x0000, 0x0000,
1002 0x0000, 0xffff, 0x0000, 0x0000 } } },
1004 { { .in6_u
= { .u6_addr16
= { 0x0000, 0x0000, 0x0000, 0x0000,
1005 0x0000, 0x0000, 0x0000, 0x0000 } } },
1011 match_prefix (const struct sockaddr_storage
*ss
, const struct prefixlist
*list
,
1015 struct sockaddr_in6 in6_mem
;
1016 const struct sockaddr_in6
*in6
;
1018 if (ss
->ss_family
== PF_INET6
)
1019 in6
= (const struct sockaddr_in6
*) ss
;
1020 else if (ss
->ss_family
== PF_INET
)
1022 const struct sockaddr_in
*in
= (const struct sockaddr_in
*) ss
;
1024 /* Convert to IPv6 address. */
1025 in6_mem
.sin6_family
= PF_INET6
;
1026 in6_mem
.sin6_port
= in
->sin_port
;
1027 in6_mem
.sin6_flowinfo
= 0;
1028 if (in
->sin_addr
.s_addr
== htonl (0x7f000001))
1029 in6_mem
.sin6_addr
= (struct in6_addr
) IN6ADDR_LOOPBACK_INIT
;
1032 /* Construct a V4-to-6 mapped address. */
1033 memset (&in6_mem
.sin6_addr
, '\0', sizeof (in6_mem
.sin6_addr
));
1034 in6_mem
.sin6_addr
.s6_addr16
[5] = 0xffff;
1035 in6_mem
.sin6_addr
.s6_addr32
[3] = in
->sin_addr
.s_addr
;
1036 in6_mem
.sin6_scope_id
= 0;
1044 for (idx
= 0; ; ++idx
)
1046 unsigned int bits
= list
[idx
].bits
;
1047 uint8_t *mask
= list
[idx
].prefix
.s6_addr
;
1048 uint8_t *val
= in6
->sin6_addr
.s6_addr
;
1062 if ((*mask
& (0xff00 >> bits
)) == (*val
& (0xff00 >> bits
)))
1068 return list
[idx
].val
;
1073 get_label (const struct sockaddr_storage
*ss
)
1075 /* XXX What is a good default value? */
1076 return match_prefix (ss
, default_labels
, INT_MAX
);
1081 get_precedence (const struct sockaddr_storage
*ss
)
1083 /* XXX What is a good default value? */
1084 return match_prefix (ss
, default_precedence
, 0);
1089 rfc3484_sort (const void *p1
, const void *p2
)
1091 const struct sort_result
*a1
= (const struct sort_result
*) p1
;
1092 const struct sort_result
*a2
= (const struct sort_result
*) p2
;
1094 /* Rule 1: Avoid unusable destinations.
1095 We have the got_source_addr flag set if the destination is reachable. */
1096 if (a1
->got_source_addr
&& ! a2
->got_source_addr
)
1098 if (! a1
->got_source_addr
&& a2
->got_source_addr
)
1102 /* Rule 2: Prefer matching scope. Only interesting if both
1103 destination addresses are IPv6. */
1105 = get_scope ((struct sockaddr_storage
*) a1
->dest_addr
->ai_addr
);
1108 = get_scope ((struct sockaddr_storage
*) a2
->dest_addr
->ai_addr
);
1110 if (a1
->got_source_addr
)
1112 int a1_src_scope
= get_scope (&a1
->source_addr
);
1113 int a2_src_scope
= get_scope (&a2
->source_addr
);
1115 if (a1_dst_scope
== a1_src_scope
&& a2_dst_scope
!= a2_src_scope
)
1117 if (a1_dst_scope
!= a1_src_scope
&& a2_dst_scope
== a2_src_scope
)
1122 /* Rule 3: Avoid deprecated addresses.
1123 That's something only the kernel could decide. */
1125 /* Rule 4: Prefer home addresses.
1126 Another thing only the kernel can decide. */
1128 /* Rule 5: Prefer matching label. */
1129 if (a1
->got_source_addr
)
1132 = get_label ((struct sockaddr_storage
*) a1
->dest_addr
->ai_addr
);
1133 int a1_src_label
= get_label (&a1
->source_addr
);
1136 = get_label ((struct sockaddr_storage
*) a2
->dest_addr
->ai_addr
);
1137 int a2_src_label
= get_label (&a2
->source_addr
);
1139 if (a1_dst_label
== a1_src_label
&& a2_dst_label
!= a2_src_label
)
1141 if (a1_dst_label
!= a1_src_label
&& a2_dst_label
== a2_src_label
)
1146 /* Rule 6: Prefer higher precedence. */
1148 = get_precedence ((struct sockaddr_storage
*) a1
->dest_addr
->ai_addr
);
1150 = get_precedence ((struct sockaddr_storage
*) a2
->dest_addr
->ai_addr
);
1152 if (a1_prec
> a2_prec
)
1154 if (a1_prec
< a2_prec
)
1158 /* Rule 7: Prefer native transport.
1159 XXX How to recognize tunnels? */
1162 /* Rule 8: Prefer smaller scope. */
1163 if (a1_dst_scope
< a2_dst_scope
)
1165 if (a1_dst_scope
> a2_dst_scope
)
1169 /* Rule 9: Use longest matching prefix. */
1170 if (a1
->got_source_addr
1171 && a1
->dest_addr
->ai_family
== a2
->dest_addr
->ai_family
)
1176 if (a1
->dest_addr
->ai_family
== PF_INET
)
1178 assert (a1
->source_addr
.ss_family
== PF_INET
);
1179 assert (a2
->source_addr
.ss_family
== PF_INET
);
1181 struct sockaddr_in
*in1_dst
;
1182 struct sockaddr_in
*in1_src
;
1183 struct sockaddr_in
*in2_dst
;
1184 struct sockaddr_in
*in2_src
;
1186 in1_dst
= (struct sockaddr_in
*) a1
->dest_addr
->ai_addr
;
1187 in1_src
= (struct sockaddr_in
*) &a1
->source_addr
;
1188 in2_dst
= (struct sockaddr_in
*) a2
->dest_addr
->ai_addr
;
1189 in2_src
= (struct sockaddr_in
*) &a2
->source_addr
;
1191 bit1
= ffs (in1_dst
->sin_addr
.s_addr
^ in1_src
->sin_addr
.s_addr
);
1192 bit2
= ffs (in2_dst
->sin_addr
.s_addr
^ in2_src
->sin_addr
.s_addr
);
1194 else if (a1
->dest_addr
->ai_family
== PF_INET6
)
1196 assert (a1
->source_addr
.ss_family
== PF_INET6
);
1197 assert (a2
->source_addr
.ss_family
== PF_INET6
);
1199 struct sockaddr_in6
*in1_dst
;
1200 struct sockaddr_in6
*in1_src
;
1201 struct sockaddr_in6
*in2_dst
;
1202 struct sockaddr_in6
*in2_src
;
1204 in1_dst
= (struct sockaddr_in6
*) a1
->dest_addr
->ai_addr
;
1205 in1_src
= (struct sockaddr_in6
*) &a1
->source_addr
;
1206 in2_dst
= (struct sockaddr_in6
*) a2
->dest_addr
->ai_addr
;
1207 in2_src
= (struct sockaddr_in6
*) &a2
->source_addr
;
1210 for (i
= 0; i
< 4; ++i
)
1211 if (in1_dst
->sin6_addr
.s6_addr32
[i
]
1212 != in1_src
->sin6_addr
.s6_addr32
[i
]
1213 || (in2_dst
->sin6_addr
.s6_addr32
[i
]
1214 != in2_src
->sin6_addr
.s6_addr32
[i
]))
1219 bit1
= ffs (in1_dst
->sin6_addr
.s6_addr32
[i
]
1220 ^ in1_src
->sin6_addr
.s6_addr32
[i
]);
1221 bit2
= ffs (in2_dst
->sin6_addr
.s6_addr32
[i
]
1222 ^ in2_src
->sin6_addr
.s6_addr32
[i
]);
1233 /* Rule 10: Otherwise, leave the order unchanged. */
1239 getaddrinfo (const char *name
, const char *service
,
1240 const struct addrinfo
*hints
, struct addrinfo
**pai
)
1242 int i
= 0, j
= 0, last_i
= 0;
1244 struct addrinfo
*p
= NULL
, **end
;
1245 struct gaih
*g
= gaih
, *pg
= NULL
;
1246 struct gaih_service gaih_service
, *pservice
;
1247 struct addrinfo local_hints
;
1249 if (name
!= NULL
&& name
[0] == '*' && name
[1] == 0)
1252 if (service
!= NULL
&& service
[0] == '*' && service
[1] == 0)
1255 if (name
== NULL
&& service
== NULL
)
1259 hints
= &default_hints
;
1262 & ~(AI_PASSIVE
|AI_CANONNAME
|AI_NUMERICHOST
|AI_ADDRCONFIG
|AI_V4MAPPED
1264 |AI_IDN
|AI_CANONIDN
|AI_IDN_ALLOW_UNASSIGNED
1265 |AI_IDN_USE_STD3_ASCII_RULES
1267 |AI_NUMERICSERV
|AI_ALL
))
1268 return EAI_BADFLAGS
;
1270 if ((hints
->ai_flags
& AI_CANONNAME
) && name
== NULL
)
1271 return EAI_BADFLAGS
;
1273 if (hints
->ai_flags
& AI_ADDRCONFIG
)
1275 /* Determine whether we have IPv4 or IPv6 interfaces or both.
1276 We cannot cache the results since new interfaces could be
1277 added at any time. */
1280 __check_pf (&seen_ipv4
, &seen_ipv6
);
1282 /* Now make a decision on what we return, if anything. */
1283 if (hints
->ai_family
== PF_UNSPEC
&& (seen_ipv4
|| seen_ipv6
))
1285 /* If we haven't seen both IPv4 and IPv6 interfaces we can
1286 narrow down the search. */
1287 if (! seen_ipv4
|| ! seen_ipv6
)
1289 local_hints
= *hints
;
1290 local_hints
.ai_family
= seen_ipv4
? PF_INET
: PF_INET6
;
1291 hints
= &local_hints
;
1294 else if ((hints
->ai_family
== PF_INET
&& ! seen_ipv4
)
1295 || (hints
->ai_family
== PF_INET6
&& ! seen_ipv6
))
1296 /* We cannot possibly return a valid answer. */
1300 if (service
&& service
[0])
1303 gaih_service
.name
= service
;
1304 gaih_service
.num
= strtoul (gaih_service
.name
, &c
, 10);
1307 if (hints
->ai_flags
& AI_NUMERICSERV
)
1310 gaih_service
.num
= -1;
1313 /* Can't specify a numerical socket unless a protocol family was
1315 if (hints
->ai_socktype
== 0 && hints
->ai_protocol
== 0)
1317 pservice
= &gaih_service
;
1329 if (hints
->ai_family
== g
->family
|| hints
->ai_family
== AF_UNSPEC
)
1332 if (pg
== NULL
|| pg
->gaih
!= g
->gaih
)
1335 i
= g
->gaih (name
, pservice
, hints
, end
);
1338 /* EAI_NODATA is a more specific result as it says that
1339 we found a result but it is not usable. */
1340 if (last_i
!= (GAIH_OKIFUNSPEC
| -EAI_NODATA
))
1343 if (hints
->ai_family
== AF_UNSPEC
&& (i
& GAIH_OKIFUNSPEC
))
1351 return -(i
& GAIH_EAI
);
1356 end
= &((*end
)->ai_next
);
1369 /* Sort results according to RFC 3484. */
1370 struct sort_result results
[nresults
];
1372 char *canonname
= NULL
;
1374 for (i
= 0, q
= p
; q
!= NULL
; ++i
, q
= q
->ai_next
)
1376 results
[i
].dest_addr
= q
;
1377 results
[i
].got_source_addr
= false;
1379 /* We overwrite the type with SOCK_DGRAM since we do not
1380 want connect() to connect to the other side. If we
1381 cannot determine the source address remember this
1383 int fd
= __socket (q
->ai_family
, SOCK_DGRAM
, IPPROTO_IP
);
1386 socklen_t sl
= sizeof (results
[i
].source_addr
);
1387 if (__connect (fd
, q
->ai_addr
, q
->ai_addrlen
) == 0
1388 && __getsockname (fd
,
1389 (struct sockaddr
*) &results
[i
].source_addr
,
1391 results
[i
].got_source_addr
= true;
1393 close_not_cancel_no_status (fd
);
1396 /* Remember the canonical name. */
1397 if (q
->ai_canonname
!= NULL
)
1399 assert (canonname
== NULL
);
1400 canonname
= q
->ai_canonname
;
1401 q
->ai_canonname
= NULL
;
1405 /* We got all the source addresses we can get, now sort using
1407 qsort (results
, nresults
, sizeof (results
[0]), rfc3484_sort
);
1409 /* Queue the results up as they come out of sorting. */
1410 q
= p
= results
[0].dest_addr
;
1411 for (i
= 1; i
< nresults
; ++i
)
1412 q
= q
->ai_next
= results
[i
].dest_addr
;
1415 /* Fill in the canonical name into the new first entry. */
1416 p
->ai_canonname
= canonname
;
1425 if (pai
== NULL
&& last_i
== 0)
1428 return last_i
? -(last_i
& GAIH_EAI
) : EAI_NONAME
;
1430 libc_hidden_def (getaddrinfo
)
1432 static_link_warning (getaddrinfo
)
1435 freeaddrinfo (struct addrinfo
*ai
)
1443 free (p
->ai_canonname
);
1447 libc_hidden_def (freeaddrinfo
)