4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
30 #include <arpa/inet.h>
31 #include <nss_dbdefs.h>
32 #include <netinet/in.h>
33 #include <sys/socket.h>
38 #include <sys/types.h>
43 #define ai2sin(x) ((struct sockaddr_in *)((x)->ai_addr))
44 #define ai2sin6(x) ((struct sockaddr_in6 *)((x)->ai_addr))
46 #define HOST_BROADCAST "255.255.255.255"
49 * getaddrinfo() returns EAI_NONAME in some cases, however
50 * since EAI_NONAME is not part of SUSv3 it needed to be
51 * masked in the standards compliant environment.
52 * GAIV_DEFAULT and GAIV_XPG6 accomplish this.
54 #define GAIV_DEFAULT 0
58 * Storage allocation for global variables in6addr_any and
59 * in6addr_loopback. The extern declarations for these
60 * variables are defined in <netinet/in.h>. These two
61 * variables could have been defined in any of the "C" files
62 * in libsocket. They are defined here with other IPv6
65 const struct in6_addr in6addr_any
= IN6ADDR_ANY_INIT
;
66 const struct in6_addr in6addr_loopback
= IN6ADDR_LOOPBACK_INIT
;
68 /* AI_MASK: all valid flags for addrinfo */
69 #define AI_MASK (AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST \
70 | AI_ADDRCONFIG | AI_NUMERICSERV | AI_V4MAPPED | AI_ALL)
74 * This is a private, undocumented, flag that getaddrinfo() uses for
75 * getipnodebyname(). In the case of AI_ADDRCONFIG && AI_V4MAPPED, if there are
76 * no IPv6 addresses, getaddrinfo() should return non-IPv4 mapped addresses. On
77 * the flip side, getipnodebyname() is defined by RFC 2553 to explicitly do so.
78 * Therefore this private flag indicates to getaddrinfo that we shouldn't do
81 #define AI_ADDRINFO 0x8000
83 /* function prototypes for used by getaddrinfo() routine */
84 static int get_addr(int family
, const char *hostname
, struct addrinfo
*aip
,
85 struct addrinfo
*cur
, ushort_t port
, int version
);
86 static uint_t
getscopeidfromzone(const struct sockaddr_in6
*sa
,
87 const char *zone
, uint32_t *sin6_scope_id
);
88 static boolean_t
str_isnumber(const char *p
);
94 * Routine for performing Address-to-nodename in a
95 * protocol-independent fashion.
96 * Description and history of the routine:
97 * Nodename-to-address translation is done in a protocol-
98 * independent fashion using the getaddrinfo() function
99 * that is taken from the IEEE POSIX 1003.1g.
101 * The official specification for this function will be the
102 * final POSIX standard, with the following additional
105 * - getaddrinfo() must be thread safe
106 * - The AI_NUMERICHOST is new.
107 * - All fields in socket address structures returned by
109 * getaddrinfo() that are not filled in through an explicit
110 * argument (e.g., sin6_flowinfo and sin_zero) must be set to 0.
111 * (This makes it easier to compare socket address structures).
114 * nodename - pointer to null-terminated strings that represents
115 * a hostname or literal ip address (IPv4/IPv6) or this
116 * pointer can be NULL.
117 * servname - pointer to null-terminated strings that represents
118 * a servicename or literal port number or this
119 * pointer can be NULL.
120 * hints - optional argument that points to an addrinfo structure
121 * to provide hints on the type of socket that the caller
123 * Possible setting of the ai_flags member of the hints structure:
124 * AI_PASSIVE - If set, the caller plans to use the returned socket
125 * address in a call to bind(). In this case, it the
126 * nodename argument is NULL, then the IP address portion
127 * of the socket address structure will be set to
128 * INADDR_ANY for IPv4 or IN6ADDR_ANY_INIT for IPv6.
129 * AI_PASSIVE - If not set, then the returned socket address will be
130 * ready for a call to connect() (for conn-oriented) or
131 * connect(), sendto(), or sendmsg() (for connectionless).
132 * In this case, if nodename is NULL, then the IP address
133 * portion of the socket address structure will be set to
134 * the loopback address.
135 * AI_CANONNAME - If set, then upon successful return the ai_canonname
136 * field of the first addrinfo structure in the linked
137 * list will point to a NULL-terminated string
138 * containing the canonical name of the specified nodename.
139 * AI_NUMERICHOST - If set, then a non-NULL nodename string must be a numeric
140 * host address string. Otherwise an error of EAI_NONAME
141 * is returned. This flag prevents any type of name
142 * resolution service from being called.
143 * AI_NUMERICSERV - If set, then a non-null servname string supplied shall
144 * be a numeric port string. Otherwise, an [EAI_NONAME]
145 * error shall be returned. This flag shall prevent any
146 * type of name resolution service from being invoked.
147 * AI_V4MAPPED - If set, along with an ai_family of AF_INET6, then
148 * getaddrinfo() shall return IPv4-mapped IPv6 addresses
149 * on finding no matching IPv6 addresses ( ai_addrlen shall
150 * be 16). The AI_V4MAPPED flag shall be ignored unless
151 * ai_family equals AF_INET6.
152 * AI_ALL - If the AI_ALL flag is used with the AI_V4MAPPED flag,
153 * then getaddrinfo() shall return all matching IPv6 and
154 * IPv4 addresses. The AI_ALL flag without the AI_V4MAPPED
157 * res - upon successful return a pointer to a linked list of one
158 * or more addrinfo structures is returned through this
159 * argument. The caller can process each addrinfo structures
160 * in this list by following the ai_next pointer, until a
161 * NULL pointer is encountered. In each returned addrinfo
162 * structure the three members ai_family, ai_socktype, and
163 * ai_protocol are corresponding arguments for a call to the
164 * socket() function. In each addrinfo structure the ai_addr
165 * field points to filled-in socket address structure whose
166 * length is specified by the ai_addrlen member.
169 * This function returns 0 upon success or a nonzero error code. The
170 * following names are nonzero error codes from getaddrinfo(), and are
171 * defined in <netdb.h>.
172 * EAI_ADDRFAMILY - address family not supported
173 * EAI_AGAIN - DNS temporary failure
174 * EAI_BADFLAGS - invalid ai_flags
175 * EAI_FAIL - DNS non-recoverable failure
176 * EAI_FAMILY - ai_family not supported
177 * EAI_MEMORY - memory allocation failure
178 * EAI_NODATA - no address associated with nodename
179 * EAI_NONAME - host/servname not known
180 * EAI_SERVICE - servname not supported for ai_socktype
181 * EAI_SOCKTYPE - ai_socktype not supported
182 * EAI_SYSTEM - system error in errno
185 * All of the information returned by getaddrinfo() is dynamically
186 * allocated: the addrinfo structures, and the socket address
187 * structures and canonical node name strings pointed to by the
188 * addrinfo structures.
193 _getaddrinfo(const char *hostname
, const char *servname
,
194 const struct addrinfo
*hints
, struct addrinfo
**res
, int version
)
196 struct addrinfo
*cur
;
197 struct addrinfo
*aip
;
206 aip
->ai_family
= PF_UNSPEC
;
207 aip
->ai_socktype
= 0;
208 aip
->ai_protocol
= 0;
210 aip
->ai_canonname
= NULL
;
215 /* if nodename nor servname provided */
216 if (hostname
== NULL
&& servname
== NULL
) {
221 /* check for bad flags in hints */
222 if ((hints
->ai_flags
!= 0) && (hints
->ai_flags
& ~AI_MASK
)) {
224 return (EAI_BADFLAGS
);
226 if ((hostname
== NULL
|| *hostname
== '\0') &&
227 (hints
->ai_flags
& AI_CANONNAME
)) {
229 return (EAI_BADFLAGS
);
231 if (hints
->ai_family
!= PF_UNSPEC
&&
232 hints
->ai_family
!= PF_INET
&&
233 hints
->ai_family
!= PF_INET6
) {
238 (void) memcpy(aip
, hints
, sizeof (*aip
));
239 switch (aip
->ai_socktype
) {
241 switch (aip
->ai_protocol
) {
245 aip
->ai_socktype
= SOCK_DGRAM
;
249 aip
->ai_socktype
= SOCK_STREAM
;
252 aip
->ai_socktype
= SOCK_RAW
;
260 * If the hint does not have a preference on the
261 * protocol, use SCTP as the default for
264 if (aip
->ai_protocol
== ANY
)
265 aip
->ai_protocol
= IPPROTO_SCTP
;
268 aip
->ai_protocol
= IPPROTO_UDP
;
272 * If the hint does not have a preference on the
273 * protocol, use TCP as the default for SOCK_STREAM.
275 if (aip
->ai_protocol
== ANY
)
276 aip
->ai_protocol
= IPPROTO_TCP
;
280 return (EAI_SOCKTYPE
);
288 if (servname
!= NULL
) {
289 struct servent result
;
295 switch (aip
->ai_socktype
) {
304 * If there is no hint given, use TCP as the default
307 switch (aip
->ai_protocol
) {
319 /* Default to SCTP if no hint given. */
320 switch (aip
->ai_protocol
) {
329 * Servname string can be a decimal port number.
330 * If we already know the socket type there is no need
331 * to call getservbyport.
333 if (aip
->ai_flags
& AI_NUMERICSERV
) {
334 if (!str_isnumber(servname
)) {
337 port
= htons(atoi(servname
));
338 } else if (str_isnumber(servname
)) {
339 port
= htons(atoi(servname
));
340 if (aip
->ai_socktype
== ANY
) {
344 buf
= malloc(bufsize
);
350 sp
= getservbyport_r(port
, proto
,
351 &result
, buf
, bufsize
);
352 if (sp
== NULL
&& errno
!= ERANGE
) {
355 return (EAI_SERVICE
);
358 * errno == ERANGE so our scratch buffer space
359 * wasn't big enough. Double it and try
362 } while (sp
== NULL
);
368 buf
= malloc(bufsize
);
374 sp
= getservbyname_r(servname
, proto
, &result
,
376 if (sp
== NULL
&& errno
!= ERANGE
) {
379 return (EAI_SERVICE
);
382 * errno == ERANGE so our scratch buffer space wasn't
383 * big enough. Double it and try again.
385 } while (sp
== NULL
);
389 if (aip
->ai_socktype
== ANY
) {
390 if (aip
->ai_flags
& AI_NUMERICSERV
) {
392 * RFC 2553bis doesn't allow us to use the
393 * any resolver to find out if there is a
394 * match. We could walk the service file
395 * with *servent(). Given the commonality of
396 * calling getaddrinfo() with a number and
397 * ANY protocol we won't add that at this time.
402 if (strcmp(sp
->s_proto
, "udp") == 0) {
403 aip
->ai_socktype
= SOCK_DGRAM
;
404 aip
->ai_protocol
= IPPROTO_UDP
;
405 } else if (strcmp(sp
->s_proto
, "tcp") == 0) {
406 aip
->ai_socktype
= SOCK_STREAM
;
407 aip
->ai_protocol
= IPPROTO_TCP
;
408 } else if (strcmp(sp
->s_proto
, "sctp") == 0) {
409 aip
->ai_socktype
= SOCK_STREAM
;
410 aip
->ai_protocol
= IPPROTO_SCTP
;
415 errno
= EPROTONOSUPPORT
;
425 * case 1: AI_PASSIVE bit set : anyaddr 0.0.0.0 or ::
426 * case 2: AI_PASSIVE bit not set : localhost 127.0.0.1 or ::1
429 if (hostname
== NULL
) {
430 struct addrinfo
*nai
;
434 if (aip
->ai_family
== PF_INET
)
436 /* create IPv6 addrinfo */
437 nai
= malloc(sizeof (struct addrinfo
));
441 addrlen
= sizeof (struct sockaddr_in6
);
442 nai
->ai_addr
= malloc(addrlen
);
443 if (nai
->ai_addr
== NULL
) {
447 bzero(nai
->ai_addr
, addrlen
);
448 nai
->ai_addrlen
= addrlen
;
449 nai
->ai_family
= PF_INET6
;
450 nai
->ai_canonname
= NULL
;
451 if (nai
->ai_flags
& AI_PASSIVE
) {
452 ai2sin6(nai
)->sin6_addr
= in6addr_any
;
454 ai2sin6(nai
)->sin6_addr
= in6addr_loopback
;
455 if (nai
->ai_flags
& AI_CANONNAME
) {
456 canonname
= strdup("loopback");
457 if (canonname
== NULL
) {
461 nai
->ai_canonname
= canonname
;
464 ai2sin6(nai
)->sin6_family
= PF_INET6
;
465 ai2sin6(nai
)->sin6_port
= port
;
468 if (aip
->ai_family
== PF_INET6
) {
472 /* If address family is PF_UNSPEC or PF_INET */
474 /* create IPv4 addrinfo */
475 nai
= malloc(sizeof (struct addrinfo
));
479 addrlen
= sizeof (struct sockaddr_in
);
480 nai
->ai_addr
= malloc(addrlen
);
481 if (nai
->ai_addr
== NULL
) {
485 bzero(nai
->ai_addr
, addrlen
);
486 nai
->ai_addrlen
= addrlen
;
487 nai
->ai_family
= PF_INET
;
488 nai
->ai_canonname
= NULL
;
489 if (nai
->ai_flags
& AI_PASSIVE
) {
490 ai2sin(nai
)->sin_addr
.s_addr
= INADDR_ANY
;
492 ai2sin(nai
)->sin_addr
.s_addr
= htonl(INADDR_LOOPBACK
);
493 if (nai
->ai_flags
& AI_CANONNAME
&&
494 nai
->ai_family
!= PF_UNSPEC
) {
495 canonname
= strdup("loopback");
496 if (canonname
== NULL
) {
500 nai
->ai_canonname
= canonname
;
503 ai2sin(nai
)->sin_family
= PF_INET
;
504 ai2sin(nai
)->sin_port
= port
;
511 /* hostname string is a literal address or an alphabetical name */
512 error
= get_addr(aip
->ai_family
, hostname
, aip
, cur
, port
, version
);
527 getaddrinfo(const char *hostname
, const char *servname
,
528 const struct addrinfo
*hints
, struct addrinfo
**res
)
530 return (_getaddrinfo(hostname
, servname
, hints
, res
, GAIV_DEFAULT
));
534 __xnet_getaddrinfo(const char *hostname
, const char *servname
,
535 const struct addrinfo
*hints
, struct addrinfo
**res
)
537 return (_getaddrinfo(hostname
, servname
, hints
, res
, GAIV_XPG6
));
541 get_addr(int family
, const char *hostname
, struct addrinfo
*aip
, struct
542 addrinfo
*cur
, ushort_t port
, int version
)
545 char _hostname
[MAXHOSTNAMELEN
];
547 struct addrinfo
*nai
;
550 boolean_t firsttime
= B_TRUE
;
551 boolean_t create_v6_addrinfo
;
552 struct in_addr v4addr
;
553 struct in6_addr v6addr
;
554 struct in6_addr
*v6addrp
;
555 char *zonestr
= NULL
;
558 * Check for existence of address-zoneid delimiter '%'
559 * If the delimiter exists, parse the zoneid portion of
562 if ((zonestr
= strchr(hostname
, '%')) != NULL
) {
563 /* make sure we have room for <addr> portion of hostname */
564 if (((zonestr
- hostname
) + 1) > sizeof (_hostname
)) {
568 /* chop off and save <zone_id> portion */
569 (void) strlcpy(_hostname
, hostname
, (zonestr
- hostname
) + 1);
570 ++zonestr
; /* make zonestr point at start of <zone-id> */
571 /* ensure zone is valid */
572 if ((*zonestr
== '\0') || (strlen(zonestr
) > LIFNAMSIZ
)) {
576 size_t hlen
= sizeof (_hostname
);
578 if (strlcpy(_hostname
, hostname
, hlen
) >= hlen
) {
583 /* Check to see if AI_NUMERICHOST bit is set */
584 if (aip
->ai_flags
& AI_NUMERICHOST
) {
585 /* check to see if _hostname points to a literal IP address */
586 if (!((inet_addr(_hostname
) != ((in_addr_t
)-1)) ||
587 (strcmp(_hostname
, HOST_BROADCAST
) == 0) ||
588 (inet_pton(AF_INET6
, _hostname
, &v6addr
) > 0))) {
593 /* if hostname argument is literal, name service doesn't get called */
594 if (family
== PF_UNSPEC
) {
595 hp
= getipnodebyname(_hostname
, AF_INET6
, AI_ALL
|
596 aip
->ai_flags
| AI_V4MAPPED
| AI_ADDRINFO
, &errnum
);
598 hp
= getipnodebyname(_hostname
, family
, aip
->ai_flags
, &errnum
);
610 if (version
== GAIV_XPG6
)
618 for (i
= 0; hp
->h_addr_list
[i
]; i
++) {
619 /* Determine if an IPv6 addrinfo structure should be created */
620 create_v6_addrinfo
= B_TRUE
;
621 if (hp
->h_addrtype
== AF_INET6
) {
622 v6addrp
= (struct in6_addr
*)hp
->h_addr_list
[i
];
623 if (!(aip
->ai_flags
& AI_V4MAPPED
) &&
624 IN6_IS_ADDR_V4MAPPED(v6addrp
)) {
625 create_v6_addrinfo
= B_FALSE
;
626 IN6_V4MAPPED_TO_INADDR(v6addrp
, &v4addr
);
628 } else if (hp
->h_addrtype
== AF_INET
) {
629 create_v6_addrinfo
= B_FALSE
;
630 (void) memcpy(&v4addr
, hp
->h_addr_list
[i
],
631 sizeof (struct in_addr
));
636 if (create_v6_addrinfo
) {
637 /* create IPv6 addrinfo */
638 nai
= malloc(sizeof (struct addrinfo
));
642 addrlen
= sizeof (struct sockaddr_in6
);
643 nai
->ai_addr
= malloc(addrlen
);
644 if (nai
->ai_addr
== NULL
) {
648 bzero(nai
->ai_addr
, addrlen
);
649 nai
->ai_addrlen
= addrlen
;
650 nai
->ai_family
= PF_INET6
;
652 (void) memcpy(ai2sin6(nai
)->sin6_addr
.s6_addr
,
653 hp
->h_addr_list
[i
], sizeof (struct in6_addr
));
654 nai
->ai_canonname
= NULL
;
655 if ((nai
->ai_flags
& AI_CANONNAME
) && firsttime
) {
656 canonname
= strdup(hp
->h_name
);
657 if (canonname
== NULL
) {
661 nai
->ai_canonname
= canonname
;
664 ai2sin6(nai
)->sin6_family
= PF_INET6
;
665 ai2sin6(nai
)->sin6_port
= port
;
666 /* set sin6_scope_id */
667 if (zonestr
!= NULL
) {
669 * Translate 'zonestr' into a valid
673 getscopeidfromzone(ai2sin6(nai
), zonestr
,
674 &ai2sin6(nai
)->sin6_scope_id
)) != 0) {
678 ai2sin6(nai
)->sin6_scope_id
= 0;
681 /* create IPv4 addrinfo */
682 nai
= malloc(sizeof (struct addrinfo
));
686 addrlen
= sizeof (struct sockaddr_in
);
687 nai
->ai_addr
= malloc(addrlen
);
688 if (nai
->ai_addr
== NULL
) {
692 bzero(nai
->ai_addr
, addrlen
);
693 nai
->ai_addrlen
= addrlen
;
694 nai
->ai_family
= PF_INET
;
695 (void) memcpy(&(ai2sin(nai
)->sin_addr
.s_addr
),
696 &v4addr
, sizeof (struct in_addr
));
697 nai
->ai_canonname
= NULL
;
698 if (nai
->ai_flags
& AI_CANONNAME
&& firsttime
) {
699 canonname
= strdup(hp
->h_name
);
700 if (canonname
== NULL
) {
704 nai
->ai_canonname
= canonname
;
707 ai2sin(nai
)->sin_family
= PF_INET
;
708 ai2sin(nai
)->sin_port
= port
;
725 * getscopeidfromzone(sa, zone, sin6_scope_id)
727 * Converts the string pointed to by 'zone' into a sin6_scope_id.
728 * 'zone' will either be a pointer to an interface name or will
729 * be a literal sin6_scope_id.
731 * 0 is returned on success and the output parameter 'sin6_scope_id' will
732 * be set to a valid sin6_scope_id.
733 * EAI_NONAME is returned for either of two reasons:
734 * 1. The IPv6 address pointed to by sa->sin6_addr is not
735 * part of the 'link scope' (ie link local, nodelocal multicast or
736 * linklocal multicast address)
737 * 2. The string pointed to by 'zone' can not be translate to a valid
741 getscopeidfromzone(const struct sockaddr_in6
*sa
, const char *zone
,
742 uint32_t *sin6_scope_id
) {
743 const in6_addr_t
*addr
= &sa
->sin6_addr
;
747 if (IN6_IS_ADDR_LINKSCOPE(addr
)) {
749 * Look up interface index associated with interface name
750 * pointed to by 'zone'. Since the address is part of the link
751 * scope, there is a one-to-one relationship between interface
752 * index and sin6_scope_id.
753 * If an interface index can not be found for 'zone', then
754 * treat 'zone' as a literal sin6_scope_id value.
756 if ((*sin6_scope_id
= if_nametoindex(zone
)) != 0) {
759 if ((ul_scope_id
= strtoul(zone
, &endp
, 10)) != 0) {
760 /* check that entire string was read */
765 (uint32_t)(ul_scope_id
& 0xffffffffUL
);
778 freeaddrinfo(struct addrinfo
*ai
)
780 struct addrinfo
*next
;
784 free(ai
->ai_canonname
);
788 } while (ai
!= NULL
);
792 str_isnumber(const char *p
)
802 static const char *gai_errlist
[] = {
803 "name translation error 0 (no error)", /* 0 */
804 "specified address family not supported", /* 1 EAI_ADDRFAMILY */
805 "temporary name resolution failure", /* 2 EAI_AGAIN */
806 "invalid flags", /* 3 EAI_BADFLAGS */
807 "non-recoverable name resolution failure", /* 4 EAI_FAIL */
808 "specified address family not supported", /* 5 EAI_FAMILY */
809 "memory allocation failure", /* 6 EAI_MEMORY */
810 "no address for the specified node name", /* 7 EAI_NODATA */
811 "node name or service name not known", /* 8 EAI_NONAME */
812 "service name not available for the specified socket type",
814 "specified socket type not supported", /* 10 EAI_SOCKTYPE */
815 "system error", /* 11 EAI_SYSTEM */
817 static int gai_nerr
= { sizeof (gai_errlist
)/sizeof (gai_errlist
[0]) };
820 gai_strerror(int ecode
)
823 return (dgettext(TEXT_DOMAIN
,
824 "name translation internal error"));
825 else if (ecode
< gai_nerr
)
826 return (dgettext(TEXT_DOMAIN
, gai_errlist
[ecode
]));
827 return (dgettext(TEXT_DOMAIN
, "unknown name translation error"));