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) \
288 char *tmpbuf = NULL; \
292 tmpbuf = extend_alloca (tmpbuf, tmpbuflen, 2 * tmpbuflen); \
293 rc = __gethostbyname2_r (name, _family, &th, tmpbuf, \
294 tmpbuflen, &h, &herrno); \
295 } while (rc == ERANGE && herrno == NETDB_INTERNAL); \
298 if (herrno == NETDB_INTERNAL) \
300 __set_h_errno (herrno); \
301 return -EAI_SYSTEM; \
303 if (herrno == TRY_AGAIN) \
304 no_data = EAI_AGAIN; \
306 no_data = herrno == NO_DATA; \
308 else if (h != NULL) \
310 for (i = 0; h->h_addr_list[i]; i++) \
312 if (*pat == NULL) { \
313 *pat = __alloca (sizeof (struct gaih_addrtuple)); \
314 (*pat)->scopeid = 0; \
316 (*pat)->next = NULL; \
317 (*pat)->family = _family; \
318 memcpy ((*pat)->addr, h->h_addr_list[i], \
320 pat = &((*pat)->next); \
322 if (_family == AF_INET6) \
325 else if (_family == AF_INET6 && (req->ai_flags & AI_V4MAPPED)) \
327 /* We have to add V4 mapped addresses. Maybe we discard them \
328 later again but we get them anyhow for now. */ \
329 while ((rc = __gethostbyname2_r (name, AF_INET6, &th, tmpbuf, \
330 tmpbuflen, &h, &herrno)) == ERANGE \
331 && herrno == NETDB_INTERNAL) \
332 tmpbuf = extend_alloca (tmpbuf, tmpbuflen, 2 * tmpbuflen); \
336 if (herrno == NETDB_INTERNAL) \
338 __set_h_errno (herrno); \
339 return -EAI_SYSTEM; \
341 if (herrno == TRY_AGAIN) \
342 no_data = EAI_AGAIN; \
344 no_data = herrno == NO_DATA; \
346 else if (h != NULL) \
348 for (i = 0; h->h_addr_list[i]; ++i) \
352 *pat = __alloca (sizeof (struct gaih_addrtuple)); \
353 (*pat)->scopeid = 0; \
355 uint32_t *addr = (uint32_t *) (*pat)->addr; \
356 (*pat)->next = NULL; \
357 (*pat)->family = _family; \
358 addr[3] = *(uint32_t *) h->h_addr_list[i]; \
359 addr[2] = htonl (0xffff); \
362 pat = &((*pat)->next); \
369 #define gethosts2(_family, _type) \
374 char *tmpbuf = NULL; \
378 tmpbuf = extend_alloca (tmpbuf, tmpbuflen, 2 * tmpbuflen); \
380 status = DL_CALL_FCT (fct, (name, _family, &th, tmpbuf, \
381 tmpbuflen, &rc, &herrno)); \
382 } while (rc == ERANGE && herrno == NETDB_INTERNAL); \
383 if (status == NSS_STATUS_SUCCESS && rc == 0) \
389 if (herrno == NETDB_INTERNAL) \
391 __set_h_errno (herrno); \
392 return -EAI_SYSTEM; \
394 if (herrno == TRY_AGAIN) \
395 no_data = EAI_AGAIN; \
397 no_data = herrno == NO_DATA; \
399 else if (h != NULL) \
401 for (i = 0; h->h_addr_list[i]; i++) \
403 if (*pat == NULL) { \
404 *pat = __alloca (sizeof (struct gaih_addrtuple)); \
405 (*pat)->scopeid = 0; \
407 (*pat)->next = NULL; \
408 (*pat)->family = _family; \
409 memcpy ((*pat)->addr, h->h_addr_list[i], \
411 pat = &((*pat)->next); \
416 typedef enum nss_status (*nss_gethostbyname2_r
)
417 (const char *name
, int af
, struct hostent
*host
,
418 char *buffer
, size_t buflen
, int *errnop
,
420 extern service_user
*__nss_hosts_database attribute_hidden
;
423 gaih_inet (const char *name
, const struct gaih_service
*service
,
424 const struct addrinfo
*req
, struct addrinfo
**pai
)
426 const struct gaih_typeproto
*tp
= gaih_inet_typeproto
;
427 struct gaih_servtuple
*st
= (struct gaih_servtuple
*) &nullserv
;
428 struct gaih_addrtuple
*at
= NULL
;
430 bool got_ipv6
= false;
432 if (req
->ai_protocol
|| req
->ai_socktype
)
437 && ((req
->ai_socktype
!= 0 && req
->ai_socktype
!= tp
->socktype
)
438 || (req
->ai_protocol
!= 0
439 && !(tp
->protoflag
& GAI_PROTO_PROTOANY
)
440 && req
->ai_protocol
!= tp
->protocol
)))
445 if (req
->ai_socktype
)
446 return (GAIH_OKIFUNSPEC
| -EAI_SOCKTYPE
);
448 return (GAIH_OKIFUNSPEC
| -EAI_SERVICE
);
454 if ((tp
->protoflag
& GAI_PROTO_NOSERVICE
) != 0)
455 return (GAIH_OKIFUNSPEC
| -EAI_SERVICE
);
457 if (service
->num
< 0)
461 st
= (struct gaih_servtuple
*)
462 __alloca (sizeof (struct gaih_servtuple
));
464 if ((rc
= gaih_inet_serv (service
->name
, tp
, req
, st
)))
469 struct gaih_servtuple
**pst
= &st
;
470 for (tp
++; tp
->name
[0]; tp
++)
472 struct gaih_servtuple
*newp
;
474 if ((tp
->protoflag
& GAI_PROTO_NOSERVICE
) != 0)
477 if (req
->ai_socktype
!= 0
478 && req
->ai_socktype
!= tp
->socktype
)
480 if (req
->ai_protocol
!= 0
481 && !(tp
->protoflag
& GAI_PROTO_PROTOANY
)
482 && req
->ai_protocol
!= tp
->protocol
)
485 newp
= (struct gaih_servtuple
*)
486 __alloca (sizeof (struct gaih_servtuple
));
488 if ((rc
= gaih_inet_serv (service
->name
, tp
, req
, newp
)))
490 if (rc
& GAIH_OKIFUNSPEC
)
498 if (st
== (struct gaih_servtuple
*) &nullserv
)
499 return (GAIH_OKIFUNSPEC
| -EAI_SERVICE
);
504 st
= __alloca (sizeof (struct gaih_servtuple
));
506 st
->socktype
= tp
->socktype
;
507 st
->protocol
= ((tp
->protoflag
& GAI_PROTO_PROTOANY
)
508 ? req
->ai_protocol
: tp
->protocol
);
509 st
->port
= htons (service
->num
);
512 else if (req
->ai_socktype
|| req
->ai_protocol
)
514 st
= __alloca (sizeof (struct gaih_servtuple
));
516 st
->socktype
= tp
->socktype
;
517 st
->protocol
= ((tp
->protoflag
& GAI_PROTO_PROTOANY
)
518 ? req
->ai_protocol
: tp
->protocol
);
523 /* Neither socket type nor protocol is set. Return all socket types
525 struct gaih_servtuple
**lastp
= &st
;
526 for (++tp
; tp
->name
[0]; ++tp
)
528 struct gaih_servtuple
*newp
;
530 newp
= __alloca (sizeof (struct gaih_servtuple
));
532 newp
->socktype
= tp
->socktype
;
533 newp
->protocol
= tp
->protocol
;
543 at
= __alloca (sizeof (struct gaih_addrtuple
));
545 at
->family
= AF_UNSPEC
;
550 if (req
->ai_flags
& AI_IDN
)
553 if (req
->ai_flags
& AI_IDN_ALLOW_UNASSIGNED
)
554 idn_flags
|= IDNA_ALLOW_UNASSIGNED
;
555 if (req
->ai_flags
& AI_IDN_USE_STD3_ASCII_RULES
)
556 idn_flags
|= IDNA_USE_STD3_ASCII_RULES
;
559 rc
= __idna_to_ascii_lz (name
, &p
, idn_flags
);
560 if (rc
!= IDNA_SUCCESS
)
562 if (rc
== IDNA_MALLOC_ERROR
)
564 if (rc
== IDNA_DLOPEN_ERROR
)
566 return -EAI_IDN_ENCODE
;
568 /* In case the output string is the same as the input string
569 no new string has been allocated. */
578 if (__inet_aton (name
, (struct in_addr
*) at
->addr
) != 0)
580 if (req
->ai_family
== AF_UNSPEC
|| req
->ai_family
== AF_INET
)
581 at
->family
= AF_INET
;
582 else if (req
->ai_family
== AF_INET6
&& req
->ai_flags
& AI_V4MAPPED
)
584 ((uint32_t *) at
->addr
)[3] = *(uint32_t *) at
->addr
;
585 ((uint32_t *) at
->addr
)[2] = htonl (0xffff);
586 ((uint32_t *) at
->addr
)[1] = 0;
587 ((uint32_t *) at
->addr
)[0] = 0;
588 at
->family
= AF_INET6
;
591 return -EAI_ADDRFAMILY
;
594 if (at
->family
== AF_UNSPEC
)
596 char *namebuf
= strdupa (name
);
599 scope_delim
= strchr (namebuf
, SCOPE_DELIMITER
);
600 if (scope_delim
!= NULL
)
603 if (inet_pton (AF_INET6
, namebuf
, at
->addr
) > 0)
605 if (req
->ai_family
== AF_UNSPEC
|| req
->ai_family
== AF_INET6
)
606 at
->family
= AF_INET6
;
607 else if (req
->ai_family
== AF_INET
608 && IN6_IS_ADDR_V4MAPPED (at
->addr
))
610 *(uint32_t *) at
->addr
= ((uint32_t *) at
->addr
)[3];
611 at
->family
= AF_INET
;
614 return -EAI_ADDRFAMILY
;
616 if (scope_delim
!= NULL
)
618 int try_numericscope
= 0;
619 if (IN6_IS_ADDR_LINKLOCAL (at
->addr
)
620 || IN6_IS_ADDR_MC_LINKLOCAL (at
->addr
))
622 at
->scopeid
= if_nametoindex (scope_delim
+ 1);
623 if (at
->scopeid
== 0)
624 try_numericscope
= 1;
627 try_numericscope
= 1;
629 if (try_numericscope
!= 0)
632 assert (sizeof (uint32_t) <= sizeof (unsigned long));
633 at
->scopeid
= (uint32_t) strtoul (scope_delim
+ 1, &end
,
636 return GAIH_OKIFUNSPEC
| -EAI_NONAME
;
642 if (at
->family
== AF_UNSPEC
&& (req
->ai_flags
& AI_NUMERICHOST
) == 0)
645 struct gaih_addrtuple
**pat
= &at
;
647 int no_inet6_data
= 0;
648 /* If we are looking for both IPv4 and IPv6 address we don't
649 want the lookup functions to automatically promote IPv4
650 addresses to IPv6 addresses. Currently this is decided
651 by setting the RES_USE_INET6 bit in _res.options. */
652 if (req
->ai_family
== AF_UNSPEC
)
654 service_user
*nip
= NULL
;
655 enum nss_status inet6_status
, status
= NSS_STATUS_UNAVAIL
;
657 nss_gethostbyname2_r fct
;
660 if (__nss_hosts_database
!= NULL
)
663 nip
= __nss_hosts_database
;
666 no_more
= __nss_database_lookup ("hosts", NULL
,
667 "dns [!UNAVAIL=return] files",
670 if (__res_maybe_init (&_res
, 0) == -1)
672 old_res_options
= _res
.options
;
673 _res
.options
&= ~RES_USE_INET6
;
677 fct
= __nss_lookup_function (nip
, "gethostbyname2_r");
681 gethosts2 (AF_INET6
, struct in6_addr
);
682 no_inet6_data
= no_data
;
683 inet6_status
= status
;
684 gethosts2 (AF_INET
, struct in_addr
);
686 /* If we found one address for AF_INET or AF_INET6,
687 don't continue the search. */
688 if (inet6_status
== NSS_STATUS_SUCCESS
||
689 status
== NSS_STATUS_SUCCESS
)
692 /* We can have different states for AF_INET
693 and AF_INET6. Try to find a usefull one for
695 if (inet6_status
== NSS_STATUS_TRYAGAIN
)
696 status
= NSS_STATUS_TRYAGAIN
;
697 else if (status
== NSS_STATUS_UNAVAIL
&&
698 inet6_status
!= NSS_STATUS_UNAVAIL
)
699 status
= inet6_status
;
702 if (nss_next_action (nip
, status
) == NSS_ACTION_RETURN
)
705 if (nip
->next
== NULL
)
711 _res
.options
= old_res_options
;
713 else if (req
->ai_family
== AF_INET6
)
715 gethosts (AF_INET6
, struct in6_addr
);
716 no_inet6_data
= no_data
;
718 else if (req
->ai_family
== AF_INET
)
720 gethosts (AF_INET
, struct in_addr
);
721 no_inet6_data
= no_data
;
724 if (no_data
!= 0 && no_inet6_data
!= 0)
726 /* If both requests timed out report this. */
727 if (no_data
== EAI_AGAIN
&& no_inet6_data
== EAI_AGAIN
)
730 /* We made requests but they turned out no data. The name
732 return (GAIH_OKIFUNSPEC
| -EAI_NODATA
);
736 if (at
->family
== AF_UNSPEC
)
737 return (GAIH_OKIFUNSPEC
| -EAI_NONAME
);
741 struct gaih_addrtuple
*atr
;
742 atr
= at
= __alloca (sizeof (struct gaih_addrtuple
));
743 memset (at
, '\0', sizeof (struct gaih_addrtuple
));
745 if (req
->ai_family
== 0)
747 at
->next
= __alloca (sizeof (struct gaih_addrtuple
));
748 memset (at
->next
, '\0', sizeof (struct gaih_addrtuple
));
751 if (req
->ai_family
== 0 || req
->ai_family
== AF_INET6
)
753 at
->family
= AF_INET6
;
754 if ((req
->ai_flags
& AI_PASSIVE
) == 0)
755 memcpy (at
->addr
, &in6addr_loopback
, sizeof (struct in6_addr
));
759 if (req
->ai_family
== 0 || req
->ai_family
== AF_INET
)
761 atr
->family
= AF_INET
;
762 if ((req
->ai_flags
& AI_PASSIVE
) == 0)
763 *(uint32_t *) atr
->addr
= htonl (INADDR_LOOPBACK
);
771 struct gaih_servtuple
*st2
;
772 struct gaih_addrtuple
*at2
= at
;
773 size_t socklen
, namelen
;
777 buffer is the size of an unformatted IPv6 address in printable format.
781 const char *c
= NULL
;
783 /* Only the first entry gets the canonical name. */
784 if (at2
== at
&& (req
->ai_flags
& AI_CANONNAME
) != 0)
786 struct hostent
*h
= NULL
;
790 size_t tmpbuflen
= 512;
795 tmpbuf
= extend_alloca (tmpbuf
, tmpbuflen
, tmpbuflen
* 2);
796 rc
= __gethostbyaddr_r (at2
->addr
,
797 ((at2
->family
== AF_INET6
)
798 ? sizeof(struct in6_addr
)
799 : sizeof(struct in_addr
)),
800 at2
->family
, &th
, tmpbuf
, tmpbuflen
,
804 while (rc
== ERANGE
&& herrno
== NETDB_INTERNAL
);
806 if (rc
!= 0 && herrno
== NETDB_INTERNAL
)
808 __set_h_errno (herrno
);
816 /* We have to try to get the canonical in some other
817 way. If we are looking for either AF_INET or
818 AF_INET6 try the other line. */
819 if (req
->ai_family
== AF_UNSPEC
)
821 struct addrinfo
*p
= NULL
;
822 struct addrinfo
**end
= &p
;
823 struct addrinfo localreq
= *req
;
824 struct addrinfo
*runp
;
826 localreq
.ai_family
= AF_INET
+ AF_INET6
- at2
->family
;
827 (void) gaih_inet (name
, service
, &localreq
, end
);
832 if (p
->ai_canonname
!= name
)
834 c
= strdupa (p
->ai_canonname
);
837 runp
= runp
->ai_next
;
843 /* If this code is used the missing canonical name is
844 substituted with the name passed in by the user. */
850 return GAIH_OKIFUNSPEC
| -EAI_NONAME
;
853 if (req
->ai_flags
& AI_CANONIDN
)
856 if (req
->ai_flags
& AI_IDN_ALLOW_UNASSIGNED
)
857 idn_flags
|= IDNA_ALLOW_UNASSIGNED
;
858 if (req
->ai_flags
& AI_IDN_USE_STD3_ASCII_RULES
)
859 idn_flags
|= IDNA_USE_STD3_ASCII_RULES
;
862 int rc
= __idna_to_unicode_lzlz (c
, &out
, idn_flags
);
863 if (rc
!= IDNA_SUCCESS
)
865 if (rc
== IDNA_MALLOC_ERROR
)
867 if (rc
== IDNA_DLOPEN_ERROR
)
869 return -EAI_IDN_ENCODE
;
871 /* In case the output string is the same as the input
872 string no new string has been allocated. */
881 namelen
= strlen (c
) + 1;
886 if (at2
->family
== AF_INET6
)
889 socklen
= sizeof (struct sockaddr_in6
);
891 /* If we looked up IPv4 mapped address discard them here if
892 the caller isn't interested in all address and we have
893 found at least one IPv6 address. */
895 && (req
->ai_flags
& (AI_V4MAPPED
|AI_ALL
)) == AI_V4MAPPED
896 && IN6_IS_ADDR_V4MAPPED (at2
->addr
))
902 socklen
= sizeof (struct sockaddr_in
);
905 for (st2
= st
; st2
!= NULL
; st2
= st2
->next
)
907 *pai
= malloc (sizeof (struct addrinfo
) + socklen
+ namelen
);
911 (*pai
)->ai_flags
= req
->ai_flags
;
912 (*pai
)->ai_family
= family
;
913 (*pai
)->ai_socktype
= st2
->socktype
;
914 (*pai
)->ai_protocol
= st2
->protocol
;
915 (*pai
)->ai_addrlen
= socklen
;
916 (*pai
)->ai_addr
= (void *) (*pai
) + sizeof (struct addrinfo
);
918 (*pai
)->ai_addr
->sa_len
= socklen
;
920 (*pai
)->ai_addr
->sa_family
= family
;
922 if (family
== AF_INET6
)
924 struct sockaddr_in6
*sin6p
=
925 (struct sockaddr_in6
*) (*pai
)->ai_addr
;
927 sin6p
->sin6_flowinfo
= 0;
928 memcpy (&sin6p
->sin6_addr
,
929 at2
->addr
, sizeof (struct in6_addr
));
930 sin6p
->sin6_port
= st2
->port
;
931 sin6p
->sin6_scope_id
= at2
->scopeid
;
935 struct sockaddr_in
*sinp
=
936 (struct sockaddr_in
*) (*pai
)->ai_addr
;
937 memcpy (&sinp
->sin_addr
,
938 at2
->addr
, sizeof (struct in_addr
));
939 sinp
->sin_port
= st2
->port
;
940 memset (sinp
->sin_zero
, '\0', sizeof (sinp
->sin_zero
));
945 (*pai
)->ai_canonname
= ((void *) (*pai
) +
946 sizeof (struct addrinfo
) + socklen
);
947 strcpy ((*pai
)->ai_canonname
, c
);
949 /* We do not need to allocate the canonical name anymore. */
953 (*pai
)->ai_canonname
= NULL
;
955 (*pai
)->ai_next
= NULL
;
956 pai
= &((*pai
)->ai_next
);
966 static struct gaih gaih
[] =
968 { PF_INET6
, gaih_inet
},
969 { PF_INET
, gaih_inet
},
971 { PF_LOCAL
, gaih_local
},
978 struct addrinfo
*dest_addr
;
979 struct sockaddr_storage source_addr
;
980 bool got_source_addr
;
985 get_scope (const struct sockaddr_storage
*ss
)
988 if (ss
->ss_family
== PF_INET6
)
990 const struct sockaddr_in6
*in6
= (const struct sockaddr_in6
*) ss
;
992 if (! IN6_IS_ADDR_MULTICAST (&in6
->sin6_addr
))
994 if (IN6_IS_ADDR_LINKLOCAL (&in6
->sin6_addr
))
996 else if (IN6_IS_ADDR_SITELOCAL (&in6
->sin6_addr
))
999 /* XXX Is this the correct default behavior? */
1003 scope
= in6
->sin6_addr
.s6_addr
[1] & 0xf;
1005 else if (ss
->ss_family
== PF_INET
)
1007 const struct sockaddr_in
*in
= (const struct sockaddr_in
*) ss
;
1008 const uint8_t *addr
= (const uint8_t *) &in
->sin_addr
;
1010 /* RFC 3484 specifies how to map IPv6 addresses to scopes.
1011 169.254/16 and 127/8 are link-local. */
1012 if ((addr
[0] == 169 && addr
[1] == 254) || addr
[0] == 127)
1014 else if (addr
[0] == 10 || (addr
[0] == 172 && addr
[1] == 16)
1015 || (addr
[0] == 192 && addr
[1] == 168))
1021 /* XXX What is a good default? */
1028 /* XXX The system administrator should be able to install other
1029 tables. We need to make this configurable. The problem is that
1030 the kernel is also involved since it needs the same table. */
1031 static const struct prefixlist
1033 struct in6_addr prefix
;
1036 } default_labels
[] =
1038 /* See RFC 3484 for the details. */
1039 { { .in6_u
= { .u6_addr16
= { 0x0000, 0x0000, 0x0000, 0x0000,
1040 0x0000, 0x0000, 0x0000, 0x0001 } } },
1042 { { .in6_u
= { .u6_addr16
= { 0x2002, 0x0000, 0x0000, 0x0000,
1043 0x0000, 0x0000, 0x0000, 0x0000 } } },
1045 { { .in6_u
= { .u6_addr16
= { 0x0000, 0x0000, 0x0000, 0x0000,
1046 0x0000, 0x0000, 0x0000, 0x0000 } } },
1048 { { .in6_u
= { .u6_addr16
= { 0x0000, 0x0000, 0x0000, 0x0000,
1049 0x0000, 0xffff, 0x0000, 0x0000 } } },
1051 { { .in6_u
= { .u6_addr16
= { 0x0000, 0x0000, 0x0000, 0x0000,
1052 0x0000, 0x0000, 0x0000, 0x0000 } } },
1057 static const struct prefixlist default_precedence
[] =
1059 /* See RFC 3484 for the details. */
1060 { { .in6_u
= { .u6_addr16
= { 0x0000, 0x0000, 0x0000, 0x0000,
1061 0x0000, 0x0000, 0x0000, 0x0001 } } },
1063 { { .in6_u
= { .u6_addr16
= { 0x2002, 0x0000, 0x0000, 0x0000,
1064 0x0000, 0x0000, 0x0000, 0x0000 } } },
1066 { { .in6_u
= { .u6_addr16
= { 0x0000, 0x0000, 0x0000, 0x0000,
1067 0x0000, 0x0000, 0x0000, 0x0000 } } },
1069 { { .in6_u
= { .u6_addr16
= { 0x0000, 0x0000, 0x0000, 0x0000,
1070 0x0000, 0xffff, 0x0000, 0x0000 } } },
1072 { { .in6_u
= { .u6_addr16
= { 0x0000, 0x0000, 0x0000, 0x0000,
1073 0x0000, 0x0000, 0x0000, 0x0000 } } },
1079 match_prefix (const struct sockaddr_storage
*ss
, const struct prefixlist
*list
,
1083 struct sockaddr_in6 in6_mem
;
1084 const struct sockaddr_in6
*in6
;
1086 if (ss
->ss_family
== PF_INET6
)
1087 in6
= (const struct sockaddr_in6
*) ss
;
1088 else if (ss
->ss_family
== PF_INET
)
1090 const struct sockaddr_in
*in
= (const struct sockaddr_in
*) ss
;
1092 /* Convert to IPv6 address. */
1093 in6_mem
.sin6_family
= PF_INET6
;
1094 in6_mem
.sin6_port
= in
->sin_port
;
1095 in6_mem
.sin6_flowinfo
= 0;
1096 if (in
->sin_addr
.s_addr
== htonl (0x7f000001))
1097 in6_mem
.sin6_addr
= (struct in6_addr
) IN6ADDR_LOOPBACK_INIT
;
1100 /* Construct a V4-to-6 mapped address. */
1101 memset (&in6_mem
.sin6_addr
, '\0', sizeof (in6_mem
.sin6_addr
));
1102 in6_mem
.sin6_addr
.s6_addr16
[5] = 0xffff;
1103 in6_mem
.sin6_addr
.s6_addr32
[3] = in
->sin_addr
.s_addr
;
1104 in6_mem
.sin6_scope_id
= 0;
1112 for (idx
= 0; ; ++idx
)
1114 unsigned int bits
= list
[idx
].bits
;
1115 uint8_t *mask
= list
[idx
].prefix
.s6_addr
;
1116 uint8_t *val
= in6
->sin6_addr
.s6_addr
;
1130 if ((*mask
& (0xff00 >> bits
)) == (*val
& (0xff00 >> bits
)))
1136 return list
[idx
].val
;
1141 get_label (const struct sockaddr_storage
*ss
)
1143 /* XXX What is a good default value? */
1144 return match_prefix (ss
, default_labels
, INT_MAX
);
1149 get_precedence (const struct sockaddr_storage
*ss
)
1151 /* XXX What is a good default value? */
1152 return match_prefix (ss
, default_precedence
, 0);
1157 rfc3484_sort (const void *p1
, const void *p2
)
1159 const struct sort_result
*a1
= (const struct sort_result
*) p1
;
1160 const struct sort_result
*a2
= (const struct sort_result
*) p2
;
1162 /* Rule 1: Avoid unusable destinations.
1163 We have the got_source_addr flag set if the destination is reachable. */
1164 if (a1
->got_source_addr
&& ! a2
->got_source_addr
)
1166 if (! a1
->got_source_addr
&& a2
->got_source_addr
)
1170 /* Rule 2: Prefer matching scope. Only interesting if both
1171 destination addresses are IPv6. */
1173 = get_scope ((struct sockaddr_storage
*) a1
->dest_addr
->ai_addr
);
1176 = get_scope ((struct sockaddr_storage
*) a2
->dest_addr
->ai_addr
);
1178 if (a1
->got_source_addr
)
1180 int a1_src_scope
= get_scope (&a1
->source_addr
);
1181 int a2_src_scope
= get_scope (&a2
->source_addr
);
1183 if (a1_dst_scope
== a1_src_scope
&& a2_dst_scope
!= a2_src_scope
)
1185 if (a1_dst_scope
!= a1_src_scope
&& a2_dst_scope
== a2_src_scope
)
1190 /* Rule 3: Avoid deprecated addresses.
1191 That's something only the kernel could decide. */
1193 /* Rule 4: Prefer home addresses.
1194 Another thing only the kernel can decide. */
1196 /* Rule 5: Prefer matching label. */
1197 if (a1
->got_source_addr
)
1200 = get_label ((struct sockaddr_storage
*) a1
->dest_addr
->ai_addr
);
1201 int a1_src_label
= get_label (&a1
->source_addr
);
1204 = get_label ((struct sockaddr_storage
*) a2
->dest_addr
->ai_addr
);
1205 int a2_src_label
= get_label (&a2
->source_addr
);
1207 if (a1_dst_label
== a1_src_label
&& a2_dst_label
!= a2_src_label
)
1209 if (a1_dst_label
!= a1_src_label
&& a2_dst_label
== a2_src_label
)
1214 /* Rule 6: Prefer higher precedence. */
1216 = get_precedence ((struct sockaddr_storage
*) a1
->dest_addr
->ai_addr
);
1218 = get_precedence ((struct sockaddr_storage
*) a2
->dest_addr
->ai_addr
);
1220 if (a1_prec
> a2_prec
)
1222 if (a1_prec
< a2_prec
)
1226 /* Rule 7: Prefer native transport.
1227 XXX How to recognize tunnels? */
1230 /* Rule 8: Prefer smaller scope. */
1231 if (a1_dst_scope
< a2_dst_scope
)
1233 if (a1_dst_scope
> a2_dst_scope
)
1237 /* Rule 9: Use longest matching prefix. */
1238 if (a1
->got_source_addr
1239 && a1
->dest_addr
->ai_family
== a2
->dest_addr
->ai_family
)
1244 if (a1
->dest_addr
->ai_family
== PF_INET
)
1246 assert (a1
->source_addr
.ss_family
== PF_INET
);
1247 assert (a2
->source_addr
.ss_family
== PF_INET
);
1249 struct sockaddr_in
*in1_dst
;
1250 struct sockaddr_in
*in1_src
;
1251 struct sockaddr_in
*in2_dst
;
1252 struct sockaddr_in
*in2_src
;
1254 in1_dst
= (struct sockaddr_in
*) a1
->dest_addr
->ai_addr
;
1255 in1_src
= (struct sockaddr_in
*) &a1
->source_addr
;
1256 in2_dst
= (struct sockaddr_in
*) a2
->dest_addr
->ai_addr
;
1257 in2_src
= (struct sockaddr_in
*) &a2
->source_addr
;
1259 bit1
= ffs (in1_dst
->sin_addr
.s_addr
^ in1_src
->sin_addr
.s_addr
);
1260 bit2
= ffs (in2_dst
->sin_addr
.s_addr
^ in2_src
->sin_addr
.s_addr
);
1262 else if (a1
->dest_addr
->ai_family
== PF_INET6
)
1264 assert (a1
->source_addr
.ss_family
== PF_INET6
);
1265 assert (a2
->source_addr
.ss_family
== PF_INET6
);
1267 struct sockaddr_in6
*in1_dst
;
1268 struct sockaddr_in6
*in1_src
;
1269 struct sockaddr_in6
*in2_dst
;
1270 struct sockaddr_in6
*in2_src
;
1272 in1_dst
= (struct sockaddr_in6
*) a1
->dest_addr
->ai_addr
;
1273 in1_src
= (struct sockaddr_in6
*) &a1
->source_addr
;
1274 in2_dst
= (struct sockaddr_in6
*) a2
->dest_addr
->ai_addr
;
1275 in2_src
= (struct sockaddr_in6
*) &a2
->source_addr
;
1278 for (i
= 0; i
< 4; ++i
)
1279 if (in1_dst
->sin6_addr
.s6_addr32
[i
]
1280 != in1_src
->sin6_addr
.s6_addr32
[i
]
1281 || (in2_dst
->sin6_addr
.s6_addr32
[i
]
1282 != in2_src
->sin6_addr
.s6_addr32
[i
]))
1287 bit1
= ffs (in1_dst
->sin6_addr
.s6_addr32
[i
]
1288 ^ in1_src
->sin6_addr
.s6_addr32
[i
]);
1289 bit2
= ffs (in2_dst
->sin6_addr
.s6_addr32
[i
]
1290 ^ in2_src
->sin6_addr
.s6_addr32
[i
]);
1301 /* Rule 10: Otherwise, leave the order unchanged. */
1307 getaddrinfo (const char *name
, const char *service
,
1308 const struct addrinfo
*hints
, struct addrinfo
**pai
)
1310 int i
= 0, j
= 0, last_i
= 0;
1312 struct addrinfo
*p
= NULL
, **end
;
1313 struct gaih
*g
= gaih
, *pg
= NULL
;
1314 struct gaih_service gaih_service
, *pservice
;
1315 struct addrinfo local_hints
;
1317 if (name
!= NULL
&& name
[0] == '*' && name
[1] == 0)
1320 if (service
!= NULL
&& service
[0] == '*' && service
[1] == 0)
1323 if (name
== NULL
&& service
== NULL
)
1327 hints
= &default_hints
;
1330 & ~(AI_PASSIVE
|AI_CANONNAME
|AI_NUMERICHOST
|AI_ADDRCONFIG
|AI_V4MAPPED
1332 |AI_IDN
|AI_CANONIDN
|AI_IDN_ALLOW_UNASSIGNED
1333 |AI_IDN_USE_STD3_ASCII_RULES
1335 |AI_NUMERICSERV
|AI_ALL
))
1336 return EAI_BADFLAGS
;
1338 if ((hints
->ai_flags
& AI_CANONNAME
) && name
== NULL
)
1339 return EAI_BADFLAGS
;
1341 if (hints
->ai_flags
& AI_ADDRCONFIG
)
1343 /* Determine whether we have IPv4 or IPv6 interfaces or both.
1344 We cannot cache the results since new interfaces could be
1345 added at any time. */
1348 __check_pf (&seen_ipv4
, &seen_ipv6
);
1350 /* Now make a decision on what we return, if anything. */
1351 if (hints
->ai_family
== PF_UNSPEC
&& (seen_ipv4
|| seen_ipv6
))
1353 /* If we haven't seen both IPv4 and IPv6 interfaces we can
1354 narrow down the search. */
1355 if (! seen_ipv4
|| ! seen_ipv6
)
1357 local_hints
= *hints
;
1358 local_hints
.ai_family
= seen_ipv4
? PF_INET
: PF_INET6
;
1359 hints
= &local_hints
;
1362 else if ((hints
->ai_family
== PF_INET
&& ! seen_ipv4
)
1363 || (hints
->ai_family
== PF_INET6
&& ! seen_ipv6
))
1364 /* We cannot possibly return a valid answer. */
1368 if (service
&& service
[0])
1371 gaih_service
.name
= service
;
1372 gaih_service
.num
= strtoul (gaih_service
.name
, &c
, 10);
1375 if (hints
->ai_flags
& AI_NUMERICSERV
)
1378 gaih_service
.num
= -1;
1381 /* Can't specify a numerical socket unless a protocol family was
1383 if (hints
->ai_socktype
== 0 && hints
->ai_protocol
== 0)
1385 pservice
= &gaih_service
;
1397 if (hints
->ai_family
== g
->family
|| hints
->ai_family
== AF_UNSPEC
)
1400 if (pg
== NULL
|| pg
->gaih
!= g
->gaih
)
1403 i
= g
->gaih (name
, pservice
, hints
, end
);
1406 /* EAI_NODATA is a more specific result as it says that
1407 we found a result but it is not usable. */
1408 if (last_i
!= (GAIH_OKIFUNSPEC
| -EAI_NODATA
))
1411 if (hints
->ai_family
== AF_UNSPEC
&& (i
& GAIH_OKIFUNSPEC
))
1419 return -(i
& GAIH_EAI
);
1424 end
= &((*end
)->ai_next
);
1437 /* Sort results according to RFC 3484. */
1438 struct sort_result results
[nresults
];
1441 for (i
= 0, q
= p
; q
!= NULL
; ++i
, q
= q
->ai_next
)
1443 results
[i
].dest_addr
= q
;
1444 results
[i
].got_source_addr
= false;
1446 /* We overwrite the type with SOCK_DGRAM since we do not
1447 want connect() to connect to the other side. If we
1448 cannot determine the source address remember this
1450 int fd
= __socket (q
->ai_family
, SOCK_DGRAM
, IPPROTO_IP
);
1453 socklen_t sl
= sizeof (results
[i
].source_addr
);
1454 if (__connect (fd
, q
->ai_addr
, q
->ai_addrlen
) == 0
1455 && __getsockname (fd
,
1456 (struct sockaddr
*) &results
[i
].source_addr
,
1458 results
[i
].got_source_addr
= true;
1460 close_not_cancel_no_status (fd
);
1464 /* We got all the source addresses we can get, now sort using
1466 qsort (results
, nresults
, sizeof (results
[0]), rfc3484_sort
);
1468 /* Queue the results up as they come out of sorting. */
1469 q
= p
= results
[0].dest_addr
;
1470 for (i
= 1; i
< nresults
; ++i
)
1471 q
= q
->ai_next
= results
[i
].dest_addr
;
1481 if (pai
== NULL
&& last_i
== 0)
1484 return last_i
? -(last_i
& GAIH_EAI
) : EAI_NONAME
;
1486 libc_hidden_def (getaddrinfo
)
1488 static_link_warning (getaddrinfo
)
1491 freeaddrinfo (struct addrinfo
*ai
)
1502 libc_hidden_def (freeaddrinfo
)