17c478bd9Sstevel@tonic-gate /* $KAME: getaddrinfo.c,v 1.14 2001/01/06 09:41:15 jinmei Exp $ */
27c478bd9Sstevel@tonic-gate
37c478bd9Sstevel@tonic-gate /*
47c478bd9Sstevel@tonic-gate * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
57c478bd9Sstevel@tonic-gate * All rights reserved.
67c478bd9Sstevel@tonic-gate *
77c478bd9Sstevel@tonic-gate * Redistribution and use in source and binary forms, with or without
87c478bd9Sstevel@tonic-gate * modification, are permitted provided that the following conditions
97c478bd9Sstevel@tonic-gate * are met:
107c478bd9Sstevel@tonic-gate * 1. Redistributions of source code must retain the above copyright
117c478bd9Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer.
127c478bd9Sstevel@tonic-gate * 2. Redistributions in binary form must reproduce the above copyright
137c478bd9Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer in the
147c478bd9Sstevel@tonic-gate * documentation and/or other materials provided with the distribution.
157c478bd9Sstevel@tonic-gate * 3. Neither the name of the project nor the names of its contributors
167c478bd9Sstevel@tonic-gate * may be used to endorse or promote products derived from this software
177c478bd9Sstevel@tonic-gate * without specific prior written permission.
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
207c478bd9Sstevel@tonic-gate * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
217c478bd9Sstevel@tonic-gate * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
227c478bd9Sstevel@tonic-gate * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
237c478bd9Sstevel@tonic-gate * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
247c478bd9Sstevel@tonic-gate * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
257c478bd9Sstevel@tonic-gate * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
267c478bd9Sstevel@tonic-gate * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
277c478bd9Sstevel@tonic-gate * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
287c478bd9Sstevel@tonic-gate * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
297c478bd9Sstevel@tonic-gate * SUCH DAMAGE.
307c478bd9Sstevel@tonic-gate */
317c478bd9Sstevel@tonic-gate
32*9525b14bSRao Shoaib /*! \file
337c478bd9Sstevel@tonic-gate * Issues to be discussed:
34*9525b14bSRao Shoaib *\li Thread safe-ness must be checked.
35*9525b14bSRao Shoaib *\li Return values. There are nonstandard return values defined and used
367c478bd9Sstevel@tonic-gate * in the source code. This is because RFC2553 is silent about which error
377c478bd9Sstevel@tonic-gate * code must be returned for which situation.
38*9525b14bSRao Shoaib *\li IPv4 classful (shortened) form. RFC2553 is silent about it. XNET 5.2
397c478bd9Sstevel@tonic-gate * says to use inet_aton() to convert IPv4 numeric to binary (allows
407c478bd9Sstevel@tonic-gate * classful form as a result).
417c478bd9Sstevel@tonic-gate * current code - disallow classful form for IPv4 (due to use of inet_pton).
42*9525b14bSRao Shoaib *\li freeaddrinfo(NULL). RFC2553 is silent about it. XNET 5.2 says it is
437c478bd9Sstevel@tonic-gate * invalid.
447c478bd9Sstevel@tonic-gate * current code - SEGV on freeaddrinfo(NULL)
457c478bd9Sstevel@tonic-gate * Note:
46*9525b14bSRao Shoaib *\li We use getipnodebyname() just for thread-safeness. There's no intent
477c478bd9Sstevel@tonic-gate * to let it do PF_UNSPEC (actually we never pass PF_UNSPEC to
487c478bd9Sstevel@tonic-gate * getipnodebyname().
49*9525b14bSRao Shoaib *\li The code filters out AFs that are not supported by the kernel,
507c478bd9Sstevel@tonic-gate * when globbing NULL hostname (to loopback, or wildcard). Is it the right
517c478bd9Sstevel@tonic-gate * thing to do? What is the relationship with post-RFC2553 AI_ADDRCONFIG
527c478bd9Sstevel@tonic-gate * in ai_flags?
53*9525b14bSRao Shoaib *\li (post-2553) semantics of AI_ADDRCONFIG itself is too vague.
547c478bd9Sstevel@tonic-gate * (1) what should we do against numeric hostname (2) what should we do
557c478bd9Sstevel@tonic-gate * against NULL hostname (3) what is AI_ADDRCONFIG itself. AF not ready?
567c478bd9Sstevel@tonic-gate * non-loopback address configured? global address configured?
57*9525b14bSRao Shoaib * \par Additional Issue:
58*9525b14bSRao Shoaib * To avoid search order issue, we have a big amount of code duplicate
597c478bd9Sstevel@tonic-gate * from gethnamaddr.c and some other places. The issues that there's no
607c478bd9Sstevel@tonic-gate * lower layer function to lookup "IPv4 or IPv6" record. Calling
617c478bd9Sstevel@tonic-gate * gethostbyname2 from getaddrinfo will end up in wrong search order, as
627c478bd9Sstevel@tonic-gate * follows:
63*9525b14bSRao Shoaib * \li The code makes use of following calls when asked to resolver with
647c478bd9Sstevel@tonic-gate * ai_family = PF_UNSPEC:
65*9525b14bSRao Shoaib *\code getipnodebyname(host, AF_INET6);
667c478bd9Sstevel@tonic-gate * getipnodebyname(host, AF_INET);
67*9525b14bSRao Shoaib *\endcode
68*9525b14bSRao Shoaib * \li This will result in the following queries if the node is configure to
697c478bd9Sstevel@tonic-gate * prefer /etc/hosts than DNS:
70*9525b14bSRao Shoaib *\code
717c478bd9Sstevel@tonic-gate * lookup /etc/hosts for IPv6 address
727c478bd9Sstevel@tonic-gate * lookup DNS for IPv6 address
737c478bd9Sstevel@tonic-gate * lookup /etc/hosts for IPv4 address
747c478bd9Sstevel@tonic-gate * lookup DNS for IPv4 address
75*9525b14bSRao Shoaib *\endcode
767c478bd9Sstevel@tonic-gate * which may not meet people's requirement.
77*9525b14bSRao Shoaib * \li The right thing to happen is to have underlying layer which does
787c478bd9Sstevel@tonic-gate * PF_UNSPEC lookup (lookup both) and return chain of addrinfos.
797c478bd9Sstevel@tonic-gate * This would result in a bit of code duplicate with _dns_ghbyname() and
807c478bd9Sstevel@tonic-gate * friends.
817c478bd9Sstevel@tonic-gate */
827c478bd9Sstevel@tonic-gate
837c478bd9Sstevel@tonic-gate #include "port_before.h"
847c478bd9Sstevel@tonic-gate
857c478bd9Sstevel@tonic-gate #include <sys/types.h>
867c478bd9Sstevel@tonic-gate #include <sys/param.h>
877c478bd9Sstevel@tonic-gate #include <sys/socket.h>
887c478bd9Sstevel@tonic-gate
897c478bd9Sstevel@tonic-gate #include <net/if.h>
907c478bd9Sstevel@tonic-gate #include <netinet/in.h>
917c478bd9Sstevel@tonic-gate
927c478bd9Sstevel@tonic-gate #include <arpa/inet.h>
937c478bd9Sstevel@tonic-gate #include <arpa/nameser.h>
947c478bd9Sstevel@tonic-gate
957c478bd9Sstevel@tonic-gate #include <netdb.h>
967c478bd9Sstevel@tonic-gate #include <resolv.h>
977c478bd9Sstevel@tonic-gate #include <string.h>
987c478bd9Sstevel@tonic-gate #include <stdlib.h>
997c478bd9Sstevel@tonic-gate #include <stddef.h>
1007c478bd9Sstevel@tonic-gate #include <ctype.h>
1017c478bd9Sstevel@tonic-gate #include <unistd.h>
1027c478bd9Sstevel@tonic-gate #include <stdio.h>
1037c478bd9Sstevel@tonic-gate #include <errno.h>
1047c478bd9Sstevel@tonic-gate
1057c478bd9Sstevel@tonic-gate #include <stdarg.h>
1067c478bd9Sstevel@tonic-gate
1077c478bd9Sstevel@tonic-gate #include <irs.h>
1087c478bd9Sstevel@tonic-gate #include <isc/assertions.h>
1097c478bd9Sstevel@tonic-gate
1107c478bd9Sstevel@tonic-gate #include "port_after.h"
1117c478bd9Sstevel@tonic-gate
1127c478bd9Sstevel@tonic-gate #include "irs_data.h"
1137c478bd9Sstevel@tonic-gate
1147c478bd9Sstevel@tonic-gate #define SUCCESS 0
1157c478bd9Sstevel@tonic-gate #define ANY 0
1167c478bd9Sstevel@tonic-gate #define YES 1
1177c478bd9Sstevel@tonic-gate #define NO 0
1187c478bd9Sstevel@tonic-gate
1197c478bd9Sstevel@tonic-gate static const char in_addrany[] = { 0, 0, 0, 0 };
1207c478bd9Sstevel@tonic-gate static const char in6_addrany[] = {
1217c478bd9Sstevel@tonic-gate 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
1227c478bd9Sstevel@tonic-gate };
1237c478bd9Sstevel@tonic-gate static const char in_loopback[] = { 127, 0, 0, 1 };
1247c478bd9Sstevel@tonic-gate static const char in6_loopback[] = {
1257c478bd9Sstevel@tonic-gate 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
1267c478bd9Sstevel@tonic-gate };
1277c478bd9Sstevel@tonic-gate
1287c478bd9Sstevel@tonic-gate static const struct afd {
1297c478bd9Sstevel@tonic-gate int a_af;
1307c478bd9Sstevel@tonic-gate int a_addrlen;
1317c478bd9Sstevel@tonic-gate int a_socklen;
1327c478bd9Sstevel@tonic-gate int a_off;
1337c478bd9Sstevel@tonic-gate const char *a_addrany;
1347c478bd9Sstevel@tonic-gate const char *a_loopback;
1357c478bd9Sstevel@tonic-gate int a_scoped;
1367c478bd9Sstevel@tonic-gate } afdl [] = {
1377c478bd9Sstevel@tonic-gate {PF_INET6, sizeof(struct in6_addr),
1387c478bd9Sstevel@tonic-gate sizeof(struct sockaddr_in6),
1397c478bd9Sstevel@tonic-gate offsetof(struct sockaddr_in6, sin6_addr),
1407c478bd9Sstevel@tonic-gate in6_addrany, in6_loopback, 1},
1417c478bd9Sstevel@tonic-gate {PF_INET, sizeof(struct in_addr),
1427c478bd9Sstevel@tonic-gate sizeof(struct sockaddr_in),
1437c478bd9Sstevel@tonic-gate offsetof(struct sockaddr_in, sin_addr),
1447c478bd9Sstevel@tonic-gate in_addrany, in_loopback, 0},
1457c478bd9Sstevel@tonic-gate {0, 0, 0, 0, NULL, NULL, 0},
1467c478bd9Sstevel@tonic-gate };
1477c478bd9Sstevel@tonic-gate
1487c478bd9Sstevel@tonic-gate struct explore {
1497c478bd9Sstevel@tonic-gate int e_af;
1507c478bd9Sstevel@tonic-gate int e_socktype;
1517c478bd9Sstevel@tonic-gate int e_protocol;
1527c478bd9Sstevel@tonic-gate const char *e_protostr;
1537c478bd9Sstevel@tonic-gate int e_wild;
1547c478bd9Sstevel@tonic-gate #define WILD_AF(ex) ((ex)->e_wild & 0x01)
1557c478bd9Sstevel@tonic-gate #define WILD_SOCKTYPE(ex) ((ex)->e_wild & 0x02)
1567c478bd9Sstevel@tonic-gate #define WILD_PROTOCOL(ex) ((ex)->e_wild & 0x04)
1577c478bd9Sstevel@tonic-gate };
1587c478bd9Sstevel@tonic-gate
1597c478bd9Sstevel@tonic-gate static const struct explore explore[] = {
1607c478bd9Sstevel@tonic-gate #if 0
1617c478bd9Sstevel@tonic-gate { PF_LOCAL, 0, ANY, ANY, NULL, 0x01 },
1627c478bd9Sstevel@tonic-gate #endif
1637c478bd9Sstevel@tonic-gate { PF_INET6, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
1647c478bd9Sstevel@tonic-gate { PF_INET6, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
1657c478bd9Sstevel@tonic-gate { PF_INET6, SOCK_RAW, ANY, NULL, 0x05 },
1667c478bd9Sstevel@tonic-gate { PF_INET, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
1677c478bd9Sstevel@tonic-gate { PF_INET, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
1687c478bd9Sstevel@tonic-gate { PF_INET, SOCK_RAW, ANY, NULL, 0x05 },
1697c478bd9Sstevel@tonic-gate { -1, 0, 0, NULL, 0 },
1707c478bd9Sstevel@tonic-gate };
1717c478bd9Sstevel@tonic-gate
1727c478bd9Sstevel@tonic-gate #define PTON_MAX 16
1737c478bd9Sstevel@tonic-gate
1747c478bd9Sstevel@tonic-gate static int str_isnumber __P((const char *));
1757c478bd9Sstevel@tonic-gate static int explore_fqdn __P((const struct addrinfo *, const char *,
1767c478bd9Sstevel@tonic-gate const char *, struct addrinfo **));
1777c478bd9Sstevel@tonic-gate static int explore_copy __P((const struct addrinfo *, const struct addrinfo *,
1787c478bd9Sstevel@tonic-gate struct addrinfo **));
1797c478bd9Sstevel@tonic-gate static int explore_null __P((const struct addrinfo *,
1807c478bd9Sstevel@tonic-gate const char *, struct addrinfo **));
1817c478bd9Sstevel@tonic-gate static int explore_numeric __P((const struct addrinfo *, const char *,
1827c478bd9Sstevel@tonic-gate const char *, struct addrinfo **));
1837c478bd9Sstevel@tonic-gate static int explore_numeric_scope __P((const struct addrinfo *, const char *,
1847c478bd9Sstevel@tonic-gate const char *, struct addrinfo **));
1857c478bd9Sstevel@tonic-gate static int get_canonname __P((const struct addrinfo *,
1867c478bd9Sstevel@tonic-gate struct addrinfo *, const char *));
1877c478bd9Sstevel@tonic-gate static struct addrinfo *get_ai __P((const struct addrinfo *,
1887c478bd9Sstevel@tonic-gate const struct afd *, const char *));
1897c478bd9Sstevel@tonic-gate static struct addrinfo *copy_ai __P((const struct addrinfo *));
1907c478bd9Sstevel@tonic-gate static int get_portmatch __P((const struct addrinfo *, const char *));
1917c478bd9Sstevel@tonic-gate static int get_port __P((const struct addrinfo *, const char *, int));
1927c478bd9Sstevel@tonic-gate static const struct afd *find_afd __P((int));
1937c478bd9Sstevel@tonic-gate static int addrconfig __P((int));
1947c478bd9Sstevel@tonic-gate static int ip6_str2scopeid __P((char *, struct sockaddr_in6 *,
1957c478bd9Sstevel@tonic-gate u_int32_t *scopeidp));
1967c478bd9Sstevel@tonic-gate static struct net_data *init __P((void));
1977c478bd9Sstevel@tonic-gate
1987c478bd9Sstevel@tonic-gate struct addrinfo *hostent2addrinfo __P((struct hostent *,
1997c478bd9Sstevel@tonic-gate const struct addrinfo *));
2007c478bd9Sstevel@tonic-gate struct addrinfo *addr2addrinfo __P((const struct addrinfo *,
2017c478bd9Sstevel@tonic-gate const char *));
2027c478bd9Sstevel@tonic-gate
2037c478bd9Sstevel@tonic-gate #if 0
2047c478bd9Sstevel@tonic-gate static const char *ai_errlist[] = {
2057c478bd9Sstevel@tonic-gate "Success",
206*9525b14bSRao Shoaib "Address family for hostname not supported", /*%< EAI_ADDRFAMILY */
207*9525b14bSRao Shoaib "Temporary failure in name resolution", /*%< EAI_AGAIN */
208*9525b14bSRao Shoaib "Invalid value for ai_flags", /*%< EAI_BADFLAGS */
209*9525b14bSRao Shoaib "Non-recoverable failure in name resolution", /*%< EAI_FAIL */
210*9525b14bSRao Shoaib "ai_family not supported", /*%< EAI_FAMILY */
211*9525b14bSRao Shoaib "Memory allocation failure", /*%< EAI_MEMORY */
212*9525b14bSRao Shoaib "No address associated with hostname", /*%< EAI_NODATA */
213*9525b14bSRao Shoaib "hostname nor servname provided, or not known", /*%< EAI_NONAME */
214*9525b14bSRao Shoaib "servname not supported for ai_socktype", /*%< EAI_SERVICE */
215*9525b14bSRao Shoaib "ai_socktype not supported", /*%< EAI_SOCKTYPE */
216*9525b14bSRao Shoaib "System error returned in errno", /*%< EAI_SYSTEM */
217*9525b14bSRao Shoaib "Invalid value for hints", /*%< EAI_BADHINTS */
218*9525b14bSRao Shoaib "Resolved protocol is unknown", /*%< EAI_PROTOCOL */
219*9525b14bSRao Shoaib "Unknown error", /*%< EAI_MAX */
2207c478bd9Sstevel@tonic-gate };
2217c478bd9Sstevel@tonic-gate #endif
2227c478bd9Sstevel@tonic-gate
2237c478bd9Sstevel@tonic-gate /* XXX macros that make external reference is BAD. */
2247c478bd9Sstevel@tonic-gate
2257c478bd9Sstevel@tonic-gate #define GET_AI(ai, afd, addr) \
2267c478bd9Sstevel@tonic-gate do { \
2277c478bd9Sstevel@tonic-gate /* external reference: pai, error, and label free */ \
2287c478bd9Sstevel@tonic-gate (ai) = get_ai(pai, (afd), (addr)); \
2297c478bd9Sstevel@tonic-gate if ((ai) == NULL) { \
2307c478bd9Sstevel@tonic-gate error = EAI_MEMORY; \
2317c478bd9Sstevel@tonic-gate goto free; \
2327c478bd9Sstevel@tonic-gate } \
2337c478bd9Sstevel@tonic-gate } while (/*CONSTCOND*/0)
2347c478bd9Sstevel@tonic-gate
2357c478bd9Sstevel@tonic-gate #define GET_PORT(ai, serv) \
2367c478bd9Sstevel@tonic-gate do { \
2377c478bd9Sstevel@tonic-gate /* external reference: error and label free */ \
2387c478bd9Sstevel@tonic-gate error = get_port((ai), (serv), 0); \
2397c478bd9Sstevel@tonic-gate if (error != 0) \
2407c478bd9Sstevel@tonic-gate goto free; \
2417c478bd9Sstevel@tonic-gate } while (/*CONSTCOND*/0)
2427c478bd9Sstevel@tonic-gate
2437c478bd9Sstevel@tonic-gate #define GET_CANONNAME(ai, str) \
2447c478bd9Sstevel@tonic-gate do { \
2457c478bd9Sstevel@tonic-gate /* external reference: pai, error and label free */ \
2467c478bd9Sstevel@tonic-gate error = get_canonname(pai, (ai), (str)); \
2477c478bd9Sstevel@tonic-gate if (error != 0) \
2487c478bd9Sstevel@tonic-gate goto free; \
2497c478bd9Sstevel@tonic-gate } while (/*CONSTCOND*/0)
2507c478bd9Sstevel@tonic-gate
251*9525b14bSRao Shoaib #ifndef SOLARIS2
252*9525b14bSRao Shoaib #define SETERROR(err) \
2537c478bd9Sstevel@tonic-gate do { \
2547c478bd9Sstevel@tonic-gate /* external reference: error, and label bad */ \
2557c478bd9Sstevel@tonic-gate error = (err); \
2567c478bd9Sstevel@tonic-gate goto bad; \
2577c478bd9Sstevel@tonic-gate /*NOTREACHED*/ \
2587c478bd9Sstevel@tonic-gate } while (/*CONSTCOND*/0)
2597c478bd9Sstevel@tonic-gate #else
260*9525b14bSRao Shoaib #define SETERROR(err) \
2617c478bd9Sstevel@tonic-gate do { \
262*9525b14bSRao Shoaib /* external reference: error, and label bad */ \
2637c478bd9Sstevel@tonic-gate error = (err); \
264*9525b14bSRao Shoaib if (error == error) \
265*9525b14bSRao Shoaib goto bad; \
2667c478bd9Sstevel@tonic-gate } while (/*CONSTCOND*/0)
2677c478bd9Sstevel@tonic-gate #endif
2687c478bd9Sstevel@tonic-gate
269*9525b14bSRao Shoaib
2707c478bd9Sstevel@tonic-gate #define MATCH_FAMILY(x, y, w) \
2717c478bd9Sstevel@tonic-gate ((x) == (y) || (/*CONSTCOND*/(w) && ((x) == PF_UNSPEC || (y) == PF_UNSPEC)))
2727c478bd9Sstevel@tonic-gate #define MATCH(x, y, w) \
2737c478bd9Sstevel@tonic-gate ((x) == (y) || (/*CONSTCOND*/(w) && ((x) == ANY || (y) == ANY)))
2747c478bd9Sstevel@tonic-gate
275*9525b14bSRao Shoaib #if 0 /*%< bind8 has its own version */
2767c478bd9Sstevel@tonic-gate char *
2777c478bd9Sstevel@tonic-gate gai_strerror(ecode)
2787c478bd9Sstevel@tonic-gate int ecode;
2797c478bd9Sstevel@tonic-gate {
2807c478bd9Sstevel@tonic-gate if (ecode < 0 || ecode > EAI_MAX)
2817c478bd9Sstevel@tonic-gate ecode = EAI_MAX;
2827c478bd9Sstevel@tonic-gate return ai_errlist[ecode];
2837c478bd9Sstevel@tonic-gate }
2847c478bd9Sstevel@tonic-gate #endif
2857c478bd9Sstevel@tonic-gate
2867c478bd9Sstevel@tonic-gate void
freeaddrinfo(ai)2877c478bd9Sstevel@tonic-gate freeaddrinfo(ai)
2887c478bd9Sstevel@tonic-gate struct addrinfo *ai;
2897c478bd9Sstevel@tonic-gate {
2907c478bd9Sstevel@tonic-gate struct addrinfo *next;
2917c478bd9Sstevel@tonic-gate
2927c478bd9Sstevel@tonic-gate do {
2937c478bd9Sstevel@tonic-gate next = ai->ai_next;
2947c478bd9Sstevel@tonic-gate if (ai->ai_canonname)
2957c478bd9Sstevel@tonic-gate free(ai->ai_canonname);
2967c478bd9Sstevel@tonic-gate /* no need to free(ai->ai_addr) */
2977c478bd9Sstevel@tonic-gate free(ai);
2987c478bd9Sstevel@tonic-gate ai = next;
2997c478bd9Sstevel@tonic-gate } while (ai);
3007c478bd9Sstevel@tonic-gate }
3017c478bd9Sstevel@tonic-gate
3027c478bd9Sstevel@tonic-gate static int
str_isnumber(p)3037c478bd9Sstevel@tonic-gate str_isnumber(p)
3047c478bd9Sstevel@tonic-gate const char *p;
3057c478bd9Sstevel@tonic-gate {
3067c478bd9Sstevel@tonic-gate char *ep;
3077c478bd9Sstevel@tonic-gate
3087c478bd9Sstevel@tonic-gate if (*p == '\0')
3097c478bd9Sstevel@tonic-gate return NO;
3107c478bd9Sstevel@tonic-gate ep = NULL;
3117c478bd9Sstevel@tonic-gate errno = 0;
3127c478bd9Sstevel@tonic-gate (void)strtoul(p, &ep, 10);
3137c478bd9Sstevel@tonic-gate if (errno == 0 && ep && *ep == '\0')
3147c478bd9Sstevel@tonic-gate return YES;
3157c478bd9Sstevel@tonic-gate else
3167c478bd9Sstevel@tonic-gate return NO;
3177c478bd9Sstevel@tonic-gate }
3187c478bd9Sstevel@tonic-gate
3197c478bd9Sstevel@tonic-gate int
getaddrinfo(hostname,servname,hints,res)3207c478bd9Sstevel@tonic-gate getaddrinfo(hostname, servname, hints, res)
3217c478bd9Sstevel@tonic-gate const char *hostname, *servname;
3227c478bd9Sstevel@tonic-gate const struct addrinfo *hints;
3237c478bd9Sstevel@tonic-gate struct addrinfo **res;
3247c478bd9Sstevel@tonic-gate {
3257c478bd9Sstevel@tonic-gate struct addrinfo sentinel;
3267c478bd9Sstevel@tonic-gate struct addrinfo *cur;
3277c478bd9Sstevel@tonic-gate int error = 0;
3287c478bd9Sstevel@tonic-gate struct addrinfo ai, ai0, *afai = NULL;
3297c478bd9Sstevel@tonic-gate struct addrinfo *pai;
3307c478bd9Sstevel@tonic-gate const struct explore *ex;
3317c478bd9Sstevel@tonic-gate
3327c478bd9Sstevel@tonic-gate memset(&sentinel, 0, sizeof(sentinel));
3337c478bd9Sstevel@tonic-gate cur = &sentinel;
3347c478bd9Sstevel@tonic-gate pai = &ai;
3357c478bd9Sstevel@tonic-gate pai->ai_flags = 0;
3367c478bd9Sstevel@tonic-gate pai->ai_family = PF_UNSPEC;
3377c478bd9Sstevel@tonic-gate pai->ai_socktype = ANY;
3387c478bd9Sstevel@tonic-gate pai->ai_protocol = ANY;
339*9525b14bSRao Shoaib #if defined(sun) && defined(_SOCKLEN_T) && defined(__sparcv9)
3407c478bd9Sstevel@tonic-gate /*
341*9525b14bSRao Shoaib * clear _ai_pad to preserve binary
3427c478bd9Sstevel@tonic-gate * compatibility with previously compiled 64-bit
3437c478bd9Sstevel@tonic-gate * applications in a pre-SUSv3 environment by
3447c478bd9Sstevel@tonic-gate * guaranteeing the upper 32-bits are empty.
3457c478bd9Sstevel@tonic-gate */
3467c478bd9Sstevel@tonic-gate pai->_ai_pad = 0;
347*9525b14bSRao Shoaib #endif
3487c478bd9Sstevel@tonic-gate pai->ai_addrlen = 0;
3497c478bd9Sstevel@tonic-gate pai->ai_canonname = NULL;
3507c478bd9Sstevel@tonic-gate pai->ai_addr = NULL;
3517c478bd9Sstevel@tonic-gate pai->ai_next = NULL;
3527c478bd9Sstevel@tonic-gate
3537c478bd9Sstevel@tonic-gate if (hostname == NULL && servname == NULL)
3547c478bd9Sstevel@tonic-gate return EAI_NONAME;
3557c478bd9Sstevel@tonic-gate if (hints) {
3567c478bd9Sstevel@tonic-gate /* error check for hints */
3577c478bd9Sstevel@tonic-gate if (hints->ai_addrlen || hints->ai_canonname ||
358*9525b14bSRao Shoaib hints->ai_addr || hints->ai_next)
359*9525b14bSRao Shoaib SETERROR(EAI_BADHINTS); /*%< xxx */
360*9525b14bSRao Shoaib if (hints->ai_flags & ~AI_MASK)
361*9525b14bSRao Shoaib SETERROR(EAI_BADFLAGS);
3627c478bd9Sstevel@tonic-gate switch (hints->ai_family) {
3637c478bd9Sstevel@tonic-gate case PF_UNSPEC:
3647c478bd9Sstevel@tonic-gate case PF_INET:
3657c478bd9Sstevel@tonic-gate case PF_INET6:
3667c478bd9Sstevel@tonic-gate break;
3677c478bd9Sstevel@tonic-gate default:
368*9525b14bSRao Shoaib SETERROR(EAI_FAMILY);
3697c478bd9Sstevel@tonic-gate }
3707c478bd9Sstevel@tonic-gate memcpy(pai, hints, sizeof(*pai));
3717c478bd9Sstevel@tonic-gate
372*9525b14bSRao Shoaib #if defined(sun) && defined(_SOCKLEN_T) && defined(__sparcv9)
3737c478bd9Sstevel@tonic-gate /*
3747c478bd9Sstevel@tonic-gate * We need to clear _ai_pad to preserve binary
3757c478bd9Sstevel@tonic-gate * compatibility. See prior comment.
3767c478bd9Sstevel@tonic-gate */
3777c478bd9Sstevel@tonic-gate pai->_ai_pad = 0;
378*9525b14bSRao Shoaib #endif
3797c478bd9Sstevel@tonic-gate /*
3807c478bd9Sstevel@tonic-gate * if both socktype/protocol are specified, check if they
3817c478bd9Sstevel@tonic-gate * are meaningful combination.
3827c478bd9Sstevel@tonic-gate */
3837c478bd9Sstevel@tonic-gate if (pai->ai_socktype != ANY && pai->ai_protocol != ANY) {
3847c478bd9Sstevel@tonic-gate for (ex = explore; ex->e_af >= 0; ex++) {
3857c478bd9Sstevel@tonic-gate if (pai->ai_family != ex->e_af)
3867c478bd9Sstevel@tonic-gate continue;
3877c478bd9Sstevel@tonic-gate if (ex->e_socktype == ANY)
3887c478bd9Sstevel@tonic-gate continue;
3897c478bd9Sstevel@tonic-gate if (ex->e_protocol == ANY)
3907c478bd9Sstevel@tonic-gate continue;
3917c478bd9Sstevel@tonic-gate if (pai->ai_socktype == ex->e_socktype &&
3927c478bd9Sstevel@tonic-gate pai->ai_protocol != ex->e_protocol) {
393*9525b14bSRao Shoaib SETERROR(EAI_BADHINTS);
3947c478bd9Sstevel@tonic-gate }
3957c478bd9Sstevel@tonic-gate }
3967c478bd9Sstevel@tonic-gate }
3977c478bd9Sstevel@tonic-gate }
3987c478bd9Sstevel@tonic-gate
3997c478bd9Sstevel@tonic-gate /*
4007c478bd9Sstevel@tonic-gate * post-2553: AI_ALL and AI_V4MAPPED are effective only against
4017c478bd9Sstevel@tonic-gate * AF_INET6 query. They needs to be ignored if specified in other
4027c478bd9Sstevel@tonic-gate * occassions.
4037c478bd9Sstevel@tonic-gate */
4047c478bd9Sstevel@tonic-gate switch (pai->ai_flags & (AI_ALL | AI_V4MAPPED)) {
4057c478bd9Sstevel@tonic-gate case AI_V4MAPPED:
4067c478bd9Sstevel@tonic-gate case AI_ALL | AI_V4MAPPED:
4077c478bd9Sstevel@tonic-gate if (pai->ai_family != AF_INET6)
4087c478bd9Sstevel@tonic-gate pai->ai_flags &= ~(AI_ALL | AI_V4MAPPED);
4097c478bd9Sstevel@tonic-gate break;
4107c478bd9Sstevel@tonic-gate case AI_ALL:
4117c478bd9Sstevel@tonic-gate #if 1
4127c478bd9Sstevel@tonic-gate /* illegal */
413*9525b14bSRao Shoaib SETERROR(EAI_BADFLAGS);
4147c478bd9Sstevel@tonic-gate #else
4157c478bd9Sstevel@tonic-gate pai->ai_flags &= ~(AI_ALL | AI_V4MAPPED);
4167c478bd9Sstevel@tonic-gate break;
4177c478bd9Sstevel@tonic-gate #endif
4187c478bd9Sstevel@tonic-gate }
4197c478bd9Sstevel@tonic-gate
4207c478bd9Sstevel@tonic-gate /*
4217c478bd9Sstevel@tonic-gate * check for special cases. (1) numeric servname is disallowed if
4227c478bd9Sstevel@tonic-gate * socktype/protocol are left unspecified. (2) servname is disallowed
4237c478bd9Sstevel@tonic-gate * for raw and other inet{,6} sockets.
4247c478bd9Sstevel@tonic-gate */
4257c478bd9Sstevel@tonic-gate if (MATCH_FAMILY(pai->ai_family, PF_INET, 1)
4267c478bd9Sstevel@tonic-gate #ifdef PF_INET6
4277c478bd9Sstevel@tonic-gate || MATCH_FAMILY(pai->ai_family, PF_INET6, 1)
4287c478bd9Sstevel@tonic-gate #endif
4297c478bd9Sstevel@tonic-gate ) {
4307c478bd9Sstevel@tonic-gate ai0 = *pai; /* backup *pai */
4317c478bd9Sstevel@tonic-gate
4327c478bd9Sstevel@tonic-gate if (pai->ai_family == PF_UNSPEC) {
4337c478bd9Sstevel@tonic-gate #ifdef PF_INET6
4347c478bd9Sstevel@tonic-gate pai->ai_family = PF_INET6;
4357c478bd9Sstevel@tonic-gate #else
4367c478bd9Sstevel@tonic-gate pai->ai_family = PF_INET;
4377c478bd9Sstevel@tonic-gate #endif
4387c478bd9Sstevel@tonic-gate }
4397c478bd9Sstevel@tonic-gate error = get_portmatch(pai, servname);
440*9525b14bSRao Shoaib if (error)
441*9525b14bSRao Shoaib SETERROR(error);
4427c478bd9Sstevel@tonic-gate
4437c478bd9Sstevel@tonic-gate *pai = ai0;
4447c478bd9Sstevel@tonic-gate }
4457c478bd9Sstevel@tonic-gate
4467c478bd9Sstevel@tonic-gate ai0 = *pai;
4477c478bd9Sstevel@tonic-gate
4487c478bd9Sstevel@tonic-gate /* NULL hostname, or numeric hostname */
4497c478bd9Sstevel@tonic-gate for (ex = explore; ex->e_af >= 0; ex++) {
4507c478bd9Sstevel@tonic-gate *pai = ai0;
4517c478bd9Sstevel@tonic-gate
4527c478bd9Sstevel@tonic-gate if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex)))
4537c478bd9Sstevel@tonic-gate continue;
4547c478bd9Sstevel@tonic-gate if (!MATCH(pai->ai_socktype, ex->e_socktype, WILD_SOCKTYPE(ex)))
4557c478bd9Sstevel@tonic-gate continue;
4567c478bd9Sstevel@tonic-gate if (!MATCH(pai->ai_protocol, ex->e_protocol, WILD_PROTOCOL(ex)))
4577c478bd9Sstevel@tonic-gate continue;
4587c478bd9Sstevel@tonic-gate
4597c478bd9Sstevel@tonic-gate if (pai->ai_family == PF_UNSPEC)
4607c478bd9Sstevel@tonic-gate pai->ai_family = ex->e_af;
4617c478bd9Sstevel@tonic-gate if (pai->ai_socktype == ANY && ex->e_socktype != ANY)
4627c478bd9Sstevel@tonic-gate pai->ai_socktype = ex->e_socktype;
4637c478bd9Sstevel@tonic-gate if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
4647c478bd9Sstevel@tonic-gate pai->ai_protocol = ex->e_protocol;
4657c478bd9Sstevel@tonic-gate
4667c478bd9Sstevel@tonic-gate /*
4677c478bd9Sstevel@tonic-gate * if the servname does not match socktype/protocol, ignore it.
4687c478bd9Sstevel@tonic-gate */
4697c478bd9Sstevel@tonic-gate if (get_portmatch(pai, servname) != 0)
4707c478bd9Sstevel@tonic-gate continue;
4717c478bd9Sstevel@tonic-gate
4727c478bd9Sstevel@tonic-gate if (hostname == NULL) {
4737c478bd9Sstevel@tonic-gate /*
4747c478bd9Sstevel@tonic-gate * filter out AFs that are not supported by the kernel
4757c478bd9Sstevel@tonic-gate * XXX errno?
4767c478bd9Sstevel@tonic-gate */
4777c478bd9Sstevel@tonic-gate if (!addrconfig(pai->ai_family))
4787c478bd9Sstevel@tonic-gate continue;
4797c478bd9Sstevel@tonic-gate error = explore_null(pai, servname, &cur->ai_next);
4807c478bd9Sstevel@tonic-gate } else
4817c478bd9Sstevel@tonic-gate error = explore_numeric_scope(pai, hostname, servname,
4827c478bd9Sstevel@tonic-gate &cur->ai_next);
4837c478bd9Sstevel@tonic-gate
4847c478bd9Sstevel@tonic-gate if (error)
4857c478bd9Sstevel@tonic-gate goto free;
4867c478bd9Sstevel@tonic-gate
4877c478bd9Sstevel@tonic-gate while (cur && cur->ai_next)
4887c478bd9Sstevel@tonic-gate cur = cur->ai_next;
4897c478bd9Sstevel@tonic-gate }
4907c478bd9Sstevel@tonic-gate
4917c478bd9Sstevel@tonic-gate /*
4927c478bd9Sstevel@tonic-gate * XXX
4937c478bd9Sstevel@tonic-gate * If numreic representation of AF1 can be interpreted as FQDN
4947c478bd9Sstevel@tonic-gate * representation of AF2, we need to think again about the code below.
4957c478bd9Sstevel@tonic-gate */
4967c478bd9Sstevel@tonic-gate if (sentinel.ai_next)
4977c478bd9Sstevel@tonic-gate goto good;
4987c478bd9Sstevel@tonic-gate
499*9525b14bSRao Shoaib if (pai->ai_flags & AI_NUMERICHOST)
500*9525b14bSRao Shoaib SETERROR(EAI_NONAME);
501*9525b14bSRao Shoaib if (hostname == NULL)
502*9525b14bSRao Shoaib SETERROR(EAI_NONAME);
5037c478bd9Sstevel@tonic-gate
5047c478bd9Sstevel@tonic-gate /*
5057c478bd9Sstevel@tonic-gate * hostname as alphabetical name.
5067c478bd9Sstevel@tonic-gate * We'll make sure that
5077c478bd9Sstevel@tonic-gate * - if returning addrinfo list is empty, return non-zero error
5087c478bd9Sstevel@tonic-gate * value (already known one or EAI_NONAME).
5097c478bd9Sstevel@tonic-gate * - otherwise,
5107c478bd9Sstevel@tonic-gate * + if we haven't had any errors, return 0 (i.e. success).
5117c478bd9Sstevel@tonic-gate * + if we've had an error, free the list and return the error.
5127c478bd9Sstevel@tonic-gate * without any assumption on the behavior of explore_fqdn().
5137c478bd9Sstevel@tonic-gate */
5147c478bd9Sstevel@tonic-gate
5157c478bd9Sstevel@tonic-gate /* first, try to query DNS for all possible address families. */
5167c478bd9Sstevel@tonic-gate *pai = ai0;
5177c478bd9Sstevel@tonic-gate error = explore_fqdn(pai, hostname, servname, &afai);
5187c478bd9Sstevel@tonic-gate if (error) {
5197c478bd9Sstevel@tonic-gate if (afai != NULL)
5207c478bd9Sstevel@tonic-gate freeaddrinfo(afai);
5217c478bd9Sstevel@tonic-gate goto free;
5227c478bd9Sstevel@tonic-gate }
5237c478bd9Sstevel@tonic-gate if (afai == NULL) {
524*9525b14bSRao Shoaib error = EAI_NONAME; /*%< we've had no errors. */
5257c478bd9Sstevel@tonic-gate goto free;
5267c478bd9Sstevel@tonic-gate }
5277c478bd9Sstevel@tonic-gate
5287c478bd9Sstevel@tonic-gate /*
5297c478bd9Sstevel@tonic-gate * we would like to prefer AF_INET6 than AF_INET, so we'll make an
5307c478bd9Sstevel@tonic-gate * outer loop by AFs.
5317c478bd9Sstevel@tonic-gate */
5327c478bd9Sstevel@tonic-gate for (ex = explore; ex->e_af >= 0; ex++) {
5337c478bd9Sstevel@tonic-gate *pai = ai0;
5347c478bd9Sstevel@tonic-gate
5357c478bd9Sstevel@tonic-gate if (pai->ai_family == PF_UNSPEC)
5367c478bd9Sstevel@tonic-gate pai->ai_family = ex->e_af;
5377c478bd9Sstevel@tonic-gate
5387c478bd9Sstevel@tonic-gate if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex)))
5397c478bd9Sstevel@tonic-gate continue;
5407c478bd9Sstevel@tonic-gate if (!MATCH(pai->ai_socktype, ex->e_socktype,
5417c478bd9Sstevel@tonic-gate WILD_SOCKTYPE(ex))) {
5427c478bd9Sstevel@tonic-gate continue;
5437c478bd9Sstevel@tonic-gate }
5447c478bd9Sstevel@tonic-gate if (!MATCH(pai->ai_protocol, ex->e_protocol,
5457c478bd9Sstevel@tonic-gate WILD_PROTOCOL(ex))) {
5467c478bd9Sstevel@tonic-gate continue;
5477c478bd9Sstevel@tonic-gate }
5487c478bd9Sstevel@tonic-gate
5497c478bd9Sstevel@tonic-gate #ifdef AI_ADDRCONFIG
5507c478bd9Sstevel@tonic-gate /*
5517c478bd9Sstevel@tonic-gate * If AI_ADDRCONFIG is specified, check if we are
5527c478bd9Sstevel@tonic-gate * expected to return the address family or not.
5537c478bd9Sstevel@tonic-gate */
5547c478bd9Sstevel@tonic-gate if ((pai->ai_flags & AI_ADDRCONFIG) != 0 &&
5557c478bd9Sstevel@tonic-gate !addrconfig(pai->ai_family))
5567c478bd9Sstevel@tonic-gate continue;
5577c478bd9Sstevel@tonic-gate #endif
5587c478bd9Sstevel@tonic-gate
5597c478bd9Sstevel@tonic-gate if (pai->ai_family == PF_UNSPEC)
5607c478bd9Sstevel@tonic-gate pai->ai_family = ex->e_af;
5617c478bd9Sstevel@tonic-gate if (pai->ai_socktype == ANY && ex->e_socktype != ANY)
5627c478bd9Sstevel@tonic-gate pai->ai_socktype = ex->e_socktype;
5637c478bd9Sstevel@tonic-gate if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
5647c478bd9Sstevel@tonic-gate pai->ai_protocol = ex->e_protocol;
5657c478bd9Sstevel@tonic-gate
5667c478bd9Sstevel@tonic-gate /*
5677c478bd9Sstevel@tonic-gate * if the servname does not match socktype/protocol, ignore it.
5687c478bd9Sstevel@tonic-gate */
5697c478bd9Sstevel@tonic-gate if (get_portmatch(pai, servname) != 0)
5707c478bd9Sstevel@tonic-gate continue;
5717c478bd9Sstevel@tonic-gate
5727c478bd9Sstevel@tonic-gate if ((error = explore_copy(pai, afai, &cur->ai_next)) != 0) {
5737c478bd9Sstevel@tonic-gate freeaddrinfo(afai);
5747c478bd9Sstevel@tonic-gate goto free;
5757c478bd9Sstevel@tonic-gate }
5767c478bd9Sstevel@tonic-gate
5777c478bd9Sstevel@tonic-gate while (cur && cur->ai_next)
5787c478bd9Sstevel@tonic-gate cur = cur->ai_next;
5797c478bd9Sstevel@tonic-gate }
5807c478bd9Sstevel@tonic-gate
581*9525b14bSRao Shoaib freeaddrinfo(afai); /*%< afai must not be NULL at this point. */
5827c478bd9Sstevel@tonic-gate
5837c478bd9Sstevel@tonic-gate if (sentinel.ai_next) {
5847c478bd9Sstevel@tonic-gate good:
5857c478bd9Sstevel@tonic-gate *res = sentinel.ai_next;
5867c478bd9Sstevel@tonic-gate return(SUCCESS);
5877c478bd9Sstevel@tonic-gate } else {
5887c478bd9Sstevel@tonic-gate /*
5897c478bd9Sstevel@tonic-gate * All the process succeeded, but we've had an empty list.
5907c478bd9Sstevel@tonic-gate * This can happen if the given hints do not match our
5917c478bd9Sstevel@tonic-gate * candidates.
5927c478bd9Sstevel@tonic-gate */
5937c478bd9Sstevel@tonic-gate error = EAI_NONAME;
5947c478bd9Sstevel@tonic-gate }
5957c478bd9Sstevel@tonic-gate
5967c478bd9Sstevel@tonic-gate free:
5977c478bd9Sstevel@tonic-gate bad:
5987c478bd9Sstevel@tonic-gate if (sentinel.ai_next)
5997c478bd9Sstevel@tonic-gate freeaddrinfo(sentinel.ai_next);
6007c478bd9Sstevel@tonic-gate *res = NULL;
6017c478bd9Sstevel@tonic-gate return(error);
6027c478bd9Sstevel@tonic-gate }
6037c478bd9Sstevel@tonic-gate
604*9525b14bSRao Shoaib /*%
6057c478bd9Sstevel@tonic-gate * FQDN hostname, DNS lookup
6067c478bd9Sstevel@tonic-gate */
6077c478bd9Sstevel@tonic-gate static int
explore_fqdn(pai,hostname,servname,res)6087c478bd9Sstevel@tonic-gate explore_fqdn(pai, hostname, servname, res)
6097c478bd9Sstevel@tonic-gate const struct addrinfo *pai;
6107c478bd9Sstevel@tonic-gate const char *hostname;
6117c478bd9Sstevel@tonic-gate const char *servname;
6127c478bd9Sstevel@tonic-gate struct addrinfo **res;
6137c478bd9Sstevel@tonic-gate {
6147c478bd9Sstevel@tonic-gate struct addrinfo *result;
6157c478bd9Sstevel@tonic-gate struct addrinfo *cur;
6167c478bd9Sstevel@tonic-gate struct net_data *net_data = init();
6177c478bd9Sstevel@tonic-gate struct irs_ho *ho;
6187c478bd9Sstevel@tonic-gate int error = 0;
6197c478bd9Sstevel@tonic-gate char tmp[NS_MAXDNAME];
6207c478bd9Sstevel@tonic-gate const char *cp;
6217c478bd9Sstevel@tonic-gate
6227c478bd9Sstevel@tonic-gate INSIST(res != NULL && *res == NULL);
6237c478bd9Sstevel@tonic-gate
6247c478bd9Sstevel@tonic-gate /*
6257c478bd9Sstevel@tonic-gate * if the servname does not match socktype/protocol, ignore it.
6267c478bd9Sstevel@tonic-gate */
6277c478bd9Sstevel@tonic-gate if (get_portmatch(pai, servname) != 0)
6287c478bd9Sstevel@tonic-gate return(0);
6297c478bd9Sstevel@tonic-gate
6307c478bd9Sstevel@tonic-gate if (!net_data || !(ho = net_data->ho))
6317c478bd9Sstevel@tonic-gate return(0);
632*9525b14bSRao Shoaib #if 0 /*%< XXX (notyet) */
6337c478bd9Sstevel@tonic-gate if (net_data->ho_stayopen && net_data->ho_last &&
6347c478bd9Sstevel@tonic-gate net_data->ho_last->h_addrtype == af) {
6357c478bd9Sstevel@tonic-gate if (ns_samename(name, net_data->ho_last->h_name) == 1)
6367c478bd9Sstevel@tonic-gate return (net_data->ho_last);
6377c478bd9Sstevel@tonic-gate for (hap = net_data->ho_last->h_aliases; hap && *hap; hap++)
6387c478bd9Sstevel@tonic-gate if (ns_samename(name, *hap) == 1)
6397c478bd9Sstevel@tonic-gate return (net_data->ho_last);
6407c478bd9Sstevel@tonic-gate }
6417c478bd9Sstevel@tonic-gate #endif
6427c478bd9Sstevel@tonic-gate if (!strchr(hostname, '.') &&
6437c478bd9Sstevel@tonic-gate (cp = res_hostalias(net_data->res, hostname,
6447c478bd9Sstevel@tonic-gate tmp, sizeof(tmp))))
6457c478bd9Sstevel@tonic-gate hostname = cp;
6467c478bd9Sstevel@tonic-gate result = (*ho->addrinfo)(ho, hostname, pai);
6477c478bd9Sstevel@tonic-gate if (!net_data->ho_stayopen) {
6487c478bd9Sstevel@tonic-gate (*ho->minimize)(ho);
6497c478bd9Sstevel@tonic-gate }
6507c478bd9Sstevel@tonic-gate if (result == NULL) {
6517c478bd9Sstevel@tonic-gate int e = h_errno;
6527c478bd9Sstevel@tonic-gate
6537c478bd9Sstevel@tonic-gate switch(e) {
6547c478bd9Sstevel@tonic-gate case NETDB_INTERNAL:
6557c478bd9Sstevel@tonic-gate error = EAI_SYSTEM;
6567c478bd9Sstevel@tonic-gate break;
6577c478bd9Sstevel@tonic-gate case TRY_AGAIN:
6587c478bd9Sstevel@tonic-gate error = EAI_AGAIN;
6597c478bd9Sstevel@tonic-gate break;
6607c478bd9Sstevel@tonic-gate case NO_RECOVERY:
6617c478bd9Sstevel@tonic-gate error = EAI_FAIL;
6627c478bd9Sstevel@tonic-gate break;
6637c478bd9Sstevel@tonic-gate case HOST_NOT_FOUND:
6647c478bd9Sstevel@tonic-gate case NO_DATA:
6657c478bd9Sstevel@tonic-gate error = EAI_NONAME;
6667c478bd9Sstevel@tonic-gate break;
6677c478bd9Sstevel@tonic-gate default:
668*9525b14bSRao Shoaib case NETDB_SUCCESS: /*%< should be impossible... */
6697c478bd9Sstevel@tonic-gate error = EAI_NONAME;
6707c478bd9Sstevel@tonic-gate break;
6717c478bd9Sstevel@tonic-gate }
6727c478bd9Sstevel@tonic-gate goto free;
6737c478bd9Sstevel@tonic-gate }
6747c478bd9Sstevel@tonic-gate
6757c478bd9Sstevel@tonic-gate for (cur = result; cur; cur = cur->ai_next) {
676*9525b14bSRao Shoaib GET_PORT(cur, servname); /*%< XXX: redundant lookups... */
6777c478bd9Sstevel@tonic-gate /* canonname should already be filled. */
6787c478bd9Sstevel@tonic-gate }
6797c478bd9Sstevel@tonic-gate
6807c478bd9Sstevel@tonic-gate *res = result;
6817c478bd9Sstevel@tonic-gate
6827c478bd9Sstevel@tonic-gate return(0);
6837c478bd9Sstevel@tonic-gate
6847c478bd9Sstevel@tonic-gate free:
6857c478bd9Sstevel@tonic-gate if (result)
6867c478bd9Sstevel@tonic-gate freeaddrinfo(result);
6877c478bd9Sstevel@tonic-gate return error;
6887c478bd9Sstevel@tonic-gate }
6897c478bd9Sstevel@tonic-gate
6907c478bd9Sstevel@tonic-gate static int
explore_copy(pai,src0,res)6917c478bd9Sstevel@tonic-gate explore_copy(pai, src0, res)
692*9525b14bSRao Shoaib const struct addrinfo *pai; /*%< seed */
693*9525b14bSRao Shoaib const struct addrinfo *src0; /*%< source */
6947c478bd9Sstevel@tonic-gate struct addrinfo **res;
6957c478bd9Sstevel@tonic-gate {
6967c478bd9Sstevel@tonic-gate int error;
6977c478bd9Sstevel@tonic-gate struct addrinfo sentinel, *cur;
6987c478bd9Sstevel@tonic-gate const struct addrinfo *src;
6997c478bd9Sstevel@tonic-gate
7007c478bd9Sstevel@tonic-gate error = 0;
7017c478bd9Sstevel@tonic-gate sentinel.ai_next = NULL;
7027c478bd9Sstevel@tonic-gate cur = &sentinel;
7037c478bd9Sstevel@tonic-gate
7047c478bd9Sstevel@tonic-gate for (src = src0; src != NULL; src = src->ai_next) {
7057c478bd9Sstevel@tonic-gate if (src->ai_family != pai->ai_family)
7067c478bd9Sstevel@tonic-gate continue;
7077c478bd9Sstevel@tonic-gate
7087c478bd9Sstevel@tonic-gate cur->ai_next = copy_ai(src);
7097c478bd9Sstevel@tonic-gate if (!cur->ai_next) {
7107c478bd9Sstevel@tonic-gate error = EAI_MEMORY;
7117c478bd9Sstevel@tonic-gate goto fail;
7127c478bd9Sstevel@tonic-gate }
7137c478bd9Sstevel@tonic-gate
7147c478bd9Sstevel@tonic-gate cur->ai_next->ai_socktype = pai->ai_socktype;
7157c478bd9Sstevel@tonic-gate cur->ai_next->ai_protocol = pai->ai_protocol;
7167c478bd9Sstevel@tonic-gate cur = cur->ai_next;
7177c478bd9Sstevel@tonic-gate }
7187c478bd9Sstevel@tonic-gate
7197c478bd9Sstevel@tonic-gate *res = sentinel.ai_next;
7207c478bd9Sstevel@tonic-gate return 0;
7217c478bd9Sstevel@tonic-gate
7227c478bd9Sstevel@tonic-gate fail:
7237c478bd9Sstevel@tonic-gate freeaddrinfo(sentinel.ai_next);
7247c478bd9Sstevel@tonic-gate return error;
7257c478bd9Sstevel@tonic-gate }
7267c478bd9Sstevel@tonic-gate
727*9525b14bSRao Shoaib /*%
7287c478bd9Sstevel@tonic-gate * hostname == NULL.
7297c478bd9Sstevel@tonic-gate * passive socket -> anyaddr (0.0.0.0 or ::)
7307c478bd9Sstevel@tonic-gate * non-passive socket -> localhost (127.0.0.1 or ::1)
7317c478bd9Sstevel@tonic-gate */
7327c478bd9Sstevel@tonic-gate static int
explore_null(pai,servname,res)7337c478bd9Sstevel@tonic-gate explore_null(pai, servname, res)
7347c478bd9Sstevel@tonic-gate const struct addrinfo *pai;
7357c478bd9Sstevel@tonic-gate const char *servname;
7367c478bd9Sstevel@tonic-gate struct addrinfo **res;
7377c478bd9Sstevel@tonic-gate {
7387c478bd9Sstevel@tonic-gate const struct afd *afd;
7397c478bd9Sstevel@tonic-gate struct addrinfo *cur;
7407c478bd9Sstevel@tonic-gate struct addrinfo sentinel;
7417c478bd9Sstevel@tonic-gate int error;
7427c478bd9Sstevel@tonic-gate
7437c478bd9Sstevel@tonic-gate *res = NULL;
7447c478bd9Sstevel@tonic-gate sentinel.ai_next = NULL;
7457c478bd9Sstevel@tonic-gate cur = &sentinel;
7467c478bd9Sstevel@tonic-gate
7477c478bd9Sstevel@tonic-gate afd = find_afd(pai->ai_family);
7487c478bd9Sstevel@tonic-gate if (afd == NULL)
7497c478bd9Sstevel@tonic-gate return 0;
7507c478bd9Sstevel@tonic-gate
7517c478bd9Sstevel@tonic-gate if (pai->ai_flags & AI_PASSIVE) {
7527c478bd9Sstevel@tonic-gate GET_AI(cur->ai_next, afd, afd->a_addrany);
7537c478bd9Sstevel@tonic-gate /* xxx meaningless?
7547c478bd9Sstevel@tonic-gate * GET_CANONNAME(cur->ai_next, "anyaddr");
7557c478bd9Sstevel@tonic-gate */
7567c478bd9Sstevel@tonic-gate GET_PORT(cur->ai_next, servname);
7577c478bd9Sstevel@tonic-gate } else {
7587c478bd9Sstevel@tonic-gate GET_AI(cur->ai_next, afd, afd->a_loopback);
7597c478bd9Sstevel@tonic-gate /* xxx meaningless?
7607c478bd9Sstevel@tonic-gate * GET_CANONNAME(cur->ai_next, "localhost");
7617c478bd9Sstevel@tonic-gate */
7627c478bd9Sstevel@tonic-gate GET_PORT(cur->ai_next, servname);
7637c478bd9Sstevel@tonic-gate }
7647c478bd9Sstevel@tonic-gate cur = cur->ai_next;
7657c478bd9Sstevel@tonic-gate
7667c478bd9Sstevel@tonic-gate *res = sentinel.ai_next;
7677c478bd9Sstevel@tonic-gate return 0;
7687c478bd9Sstevel@tonic-gate
7697c478bd9Sstevel@tonic-gate free:
7707c478bd9Sstevel@tonic-gate if (sentinel.ai_next)
7717c478bd9Sstevel@tonic-gate freeaddrinfo(sentinel.ai_next);
7727c478bd9Sstevel@tonic-gate return error;
7737c478bd9Sstevel@tonic-gate }
7747c478bd9Sstevel@tonic-gate
775*9525b14bSRao Shoaib /*%
7767c478bd9Sstevel@tonic-gate * numeric hostname
7777c478bd9Sstevel@tonic-gate */
7787c478bd9Sstevel@tonic-gate static int
explore_numeric(pai,hostname,servname,res)7797c478bd9Sstevel@tonic-gate explore_numeric(pai, hostname, servname, res)
7807c478bd9Sstevel@tonic-gate const struct addrinfo *pai;
7817c478bd9Sstevel@tonic-gate const char *hostname;
7827c478bd9Sstevel@tonic-gate const char *servname;
7837c478bd9Sstevel@tonic-gate struct addrinfo **res;
7847c478bd9Sstevel@tonic-gate {
7857c478bd9Sstevel@tonic-gate const struct afd *afd;
7867c478bd9Sstevel@tonic-gate struct addrinfo *cur;
7877c478bd9Sstevel@tonic-gate struct addrinfo sentinel;
7887c478bd9Sstevel@tonic-gate int error;
7897c478bd9Sstevel@tonic-gate char pton[PTON_MAX];
7907c478bd9Sstevel@tonic-gate
7917c478bd9Sstevel@tonic-gate *res = NULL;
7927c478bd9Sstevel@tonic-gate sentinel.ai_next = NULL;
7937c478bd9Sstevel@tonic-gate cur = &sentinel;
7947c478bd9Sstevel@tonic-gate
7957c478bd9Sstevel@tonic-gate afd = find_afd(pai->ai_family);
7967c478bd9Sstevel@tonic-gate if (afd == NULL)
7977c478bd9Sstevel@tonic-gate return 0;
7987c478bd9Sstevel@tonic-gate
7997c478bd9Sstevel@tonic-gate switch (afd->a_af) {
8007c478bd9Sstevel@tonic-gate #if 0 /*X/Open spec*/
8017c478bd9Sstevel@tonic-gate case AF_INET:
8027c478bd9Sstevel@tonic-gate if (inet_aton(hostname, (struct in_addr *)pton) == 1) {
8037c478bd9Sstevel@tonic-gate if (pai->ai_family == afd->a_af ||
8047c478bd9Sstevel@tonic-gate pai->ai_family == PF_UNSPEC /*?*/) {
8057c478bd9Sstevel@tonic-gate GET_AI(cur->ai_next, afd, pton);
8067c478bd9Sstevel@tonic-gate GET_PORT(cur->ai_next, servname);
807*9525b14bSRao Shoaib while (cur->ai_next)
8087c478bd9Sstevel@tonic-gate cur = cur->ai_next;
8097c478bd9Sstevel@tonic-gate } else
810*9525b14bSRao Shoaib SETERROR(EAI_FAMILY); /*xxx*/
8117c478bd9Sstevel@tonic-gate }
8127c478bd9Sstevel@tonic-gate break;
8137c478bd9Sstevel@tonic-gate #endif
8147c478bd9Sstevel@tonic-gate default:
8157c478bd9Sstevel@tonic-gate if (inet_pton(afd->a_af, hostname, pton) == 1) {
8167c478bd9Sstevel@tonic-gate if (pai->ai_family == afd->a_af ||
8177c478bd9Sstevel@tonic-gate pai->ai_family == PF_UNSPEC /*?*/) {
8187c478bd9Sstevel@tonic-gate GET_AI(cur->ai_next, afd, pton);
8197c478bd9Sstevel@tonic-gate GET_PORT(cur->ai_next, servname);
820*9525b14bSRao Shoaib while (cur->ai_next)
8217c478bd9Sstevel@tonic-gate cur = cur->ai_next;
822*9525b14bSRao Shoaib } else
823*9525b14bSRao Shoaib SETERROR(EAI_FAMILY); /*xxx*/
8247c478bd9Sstevel@tonic-gate }
8257c478bd9Sstevel@tonic-gate break;
8267c478bd9Sstevel@tonic-gate }
8277c478bd9Sstevel@tonic-gate
8287c478bd9Sstevel@tonic-gate *res = sentinel.ai_next;
8297c478bd9Sstevel@tonic-gate return 0;
8307c478bd9Sstevel@tonic-gate
8317c478bd9Sstevel@tonic-gate free:
8327c478bd9Sstevel@tonic-gate bad:
8337c478bd9Sstevel@tonic-gate if (sentinel.ai_next)
8347c478bd9Sstevel@tonic-gate freeaddrinfo(sentinel.ai_next);
8357c478bd9Sstevel@tonic-gate return error;
8367c478bd9Sstevel@tonic-gate }
8377c478bd9Sstevel@tonic-gate
838*9525b14bSRao Shoaib /*%
8397c478bd9Sstevel@tonic-gate * numeric hostname with scope
8407c478bd9Sstevel@tonic-gate */
8417c478bd9Sstevel@tonic-gate static int
explore_numeric_scope(pai,hostname,servname,res)8427c478bd9Sstevel@tonic-gate explore_numeric_scope(pai, hostname, servname, res)
8437c478bd9Sstevel@tonic-gate const struct addrinfo *pai;
8447c478bd9Sstevel@tonic-gate const char *hostname;
8457c478bd9Sstevel@tonic-gate const char *servname;
8467c478bd9Sstevel@tonic-gate struct addrinfo **res;
8477c478bd9Sstevel@tonic-gate {
8487c478bd9Sstevel@tonic-gate #ifndef SCOPE_DELIMITER
8497c478bd9Sstevel@tonic-gate return explore_numeric(pai, hostname, servname, res);
8507c478bd9Sstevel@tonic-gate #else
8517c478bd9Sstevel@tonic-gate const struct afd *afd;
8527c478bd9Sstevel@tonic-gate struct addrinfo *cur;
8537c478bd9Sstevel@tonic-gate int error;
8547c478bd9Sstevel@tonic-gate char *cp, *hostname2 = NULL, *scope, *addr;
8557c478bd9Sstevel@tonic-gate struct sockaddr_in6 *sin6;
8567c478bd9Sstevel@tonic-gate
8577c478bd9Sstevel@tonic-gate afd = find_afd(pai->ai_family);
8587c478bd9Sstevel@tonic-gate if (afd == NULL)
8597c478bd9Sstevel@tonic-gate return 0;
8607c478bd9Sstevel@tonic-gate
8617c478bd9Sstevel@tonic-gate if (!afd->a_scoped)
8627c478bd9Sstevel@tonic-gate return explore_numeric(pai, hostname, servname, res);
8637c478bd9Sstevel@tonic-gate
8647c478bd9Sstevel@tonic-gate cp = strchr(hostname, SCOPE_DELIMITER);
8657c478bd9Sstevel@tonic-gate if (cp == NULL)
8667c478bd9Sstevel@tonic-gate return explore_numeric(pai, hostname, servname, res);
8677c478bd9Sstevel@tonic-gate
8687c478bd9Sstevel@tonic-gate /*
8697c478bd9Sstevel@tonic-gate * Handle special case of <scoped_address><delimiter><scope id>
8707c478bd9Sstevel@tonic-gate */
8717c478bd9Sstevel@tonic-gate hostname2 = strdup(hostname);
8727c478bd9Sstevel@tonic-gate if (hostname2 == NULL)
8737c478bd9Sstevel@tonic-gate return EAI_MEMORY;
8747c478bd9Sstevel@tonic-gate /* terminate at the delimiter */
8757c478bd9Sstevel@tonic-gate hostname2[cp - hostname] = '\0';
8767c478bd9Sstevel@tonic-gate addr = hostname2;
8777c478bd9Sstevel@tonic-gate scope = cp + 1;
8787c478bd9Sstevel@tonic-gate
8797c478bd9Sstevel@tonic-gate error = explore_numeric(pai, addr, servname, res);
8807c478bd9Sstevel@tonic-gate if (error == 0) {
8817c478bd9Sstevel@tonic-gate u_int32_t scopeid = 0;
8827c478bd9Sstevel@tonic-gate
8837c478bd9Sstevel@tonic-gate for (cur = *res; cur; cur = cur->ai_next) {
8847c478bd9Sstevel@tonic-gate if (cur->ai_family != AF_INET6)
8857c478bd9Sstevel@tonic-gate continue;
8867c478bd9Sstevel@tonic-gate sin6 = (struct sockaddr_in6 *)(void *)cur->ai_addr;
8877c478bd9Sstevel@tonic-gate if (!ip6_str2scopeid(scope, sin6, &scopeid)) {
8887c478bd9Sstevel@tonic-gate free(hostname2);
889*9525b14bSRao Shoaib return(EAI_NONAME); /*%< XXX: is return OK? */
8907c478bd9Sstevel@tonic-gate }
8917c478bd9Sstevel@tonic-gate #ifdef HAVE_SIN6_SCOPE_ID
8927c478bd9Sstevel@tonic-gate sin6->sin6_scope_id = scopeid;
8937c478bd9Sstevel@tonic-gate #endif
8947c478bd9Sstevel@tonic-gate }
8957c478bd9Sstevel@tonic-gate }
8967c478bd9Sstevel@tonic-gate
8977c478bd9Sstevel@tonic-gate free(hostname2);
8987c478bd9Sstevel@tonic-gate
8997c478bd9Sstevel@tonic-gate return error;
9007c478bd9Sstevel@tonic-gate #endif
9017c478bd9Sstevel@tonic-gate }
9027c478bd9Sstevel@tonic-gate
9037c478bd9Sstevel@tonic-gate static int
get_canonname(pai,ai,str)9047c478bd9Sstevel@tonic-gate get_canonname(pai, ai, str)
9057c478bd9Sstevel@tonic-gate const struct addrinfo *pai;
9067c478bd9Sstevel@tonic-gate struct addrinfo *ai;
9077c478bd9Sstevel@tonic-gate const char *str;
9087c478bd9Sstevel@tonic-gate {
9097c478bd9Sstevel@tonic-gate if ((pai->ai_flags & AI_CANONNAME) != 0) {
9107c478bd9Sstevel@tonic-gate ai->ai_canonname = (char *)malloc(strlen(str) + 1);
9117c478bd9Sstevel@tonic-gate if (ai->ai_canonname == NULL)
9127c478bd9Sstevel@tonic-gate return EAI_MEMORY;
9137c478bd9Sstevel@tonic-gate strcpy(ai->ai_canonname, str);
9147c478bd9Sstevel@tonic-gate }
9157c478bd9Sstevel@tonic-gate return 0;
9167c478bd9Sstevel@tonic-gate }
9177c478bd9Sstevel@tonic-gate
9187c478bd9Sstevel@tonic-gate static struct addrinfo *
get_ai(pai,afd,addr)9197c478bd9Sstevel@tonic-gate get_ai(pai, afd, addr)
9207c478bd9Sstevel@tonic-gate const struct addrinfo *pai;
9217c478bd9Sstevel@tonic-gate const struct afd *afd;
9227c478bd9Sstevel@tonic-gate const char *addr;
9237c478bd9Sstevel@tonic-gate {
9247c478bd9Sstevel@tonic-gate char *p;
9257c478bd9Sstevel@tonic-gate struct addrinfo *ai;
9267c478bd9Sstevel@tonic-gate
9277c478bd9Sstevel@tonic-gate ai = (struct addrinfo *)malloc(sizeof(struct addrinfo)
9287c478bd9Sstevel@tonic-gate + (afd->a_socklen));
9297c478bd9Sstevel@tonic-gate if (ai == NULL)
9307c478bd9Sstevel@tonic-gate return NULL;
9317c478bd9Sstevel@tonic-gate
9327c478bd9Sstevel@tonic-gate memcpy(ai, pai, sizeof(struct addrinfo));
9337c478bd9Sstevel@tonic-gate ai->ai_addr = (struct sockaddr *)(void *)(ai + 1);
9347c478bd9Sstevel@tonic-gate memset(ai->ai_addr, 0, (size_t)afd->a_socklen);
9357c478bd9Sstevel@tonic-gate #ifdef HAVE_SA_LEN
9367c478bd9Sstevel@tonic-gate ai->ai_addr->sa_len = afd->a_socklen;
9377c478bd9Sstevel@tonic-gate #endif
9387c478bd9Sstevel@tonic-gate ai->ai_addrlen = afd->a_socklen;
9397c478bd9Sstevel@tonic-gate ai->ai_addr->sa_family = ai->ai_family = afd->a_af;
9407c478bd9Sstevel@tonic-gate p = (char *)(void *)(ai->ai_addr);
9417c478bd9Sstevel@tonic-gate memcpy(p + afd->a_off, addr, (size_t)afd->a_addrlen);
9427c478bd9Sstevel@tonic-gate return ai;
9437c478bd9Sstevel@tonic-gate }
9447c478bd9Sstevel@tonic-gate
9457c478bd9Sstevel@tonic-gate /* XXX need to malloc() the same way we do from other functions! */
9467c478bd9Sstevel@tonic-gate static struct addrinfo *
copy_ai(pai)9477c478bd9Sstevel@tonic-gate copy_ai(pai)
9487c478bd9Sstevel@tonic-gate const struct addrinfo *pai;
9497c478bd9Sstevel@tonic-gate {
9507c478bd9Sstevel@tonic-gate struct addrinfo *ai;
9517c478bd9Sstevel@tonic-gate size_t l;
9527c478bd9Sstevel@tonic-gate
9537c478bd9Sstevel@tonic-gate l = sizeof(*ai) + pai->ai_addrlen;
9547c478bd9Sstevel@tonic-gate if ((ai = (struct addrinfo *)malloc(l)) == NULL)
9557c478bd9Sstevel@tonic-gate return NULL;
9567c478bd9Sstevel@tonic-gate memset(ai, 0, l);
9577c478bd9Sstevel@tonic-gate memcpy(ai, pai, sizeof(*ai));
9587c478bd9Sstevel@tonic-gate ai->ai_addr = (struct sockaddr *)(void *)(ai + 1);
9597c478bd9Sstevel@tonic-gate memcpy(ai->ai_addr, pai->ai_addr, pai->ai_addrlen);
9607c478bd9Sstevel@tonic-gate
9617c478bd9Sstevel@tonic-gate if (pai->ai_canonname) {
9627c478bd9Sstevel@tonic-gate l = strlen(pai->ai_canonname) + 1;
9637c478bd9Sstevel@tonic-gate if ((ai->ai_canonname = malloc(l)) == NULL) {
9647c478bd9Sstevel@tonic-gate free(ai);
9657c478bd9Sstevel@tonic-gate return NULL;
9667c478bd9Sstevel@tonic-gate }
967*9525b14bSRao Shoaib strcpy(ai->ai_canonname, pai->ai_canonname); /* (checked) */
9687c478bd9Sstevel@tonic-gate } else {
9697c478bd9Sstevel@tonic-gate /* just to make sure */
9707c478bd9Sstevel@tonic-gate ai->ai_canonname = NULL;
9717c478bd9Sstevel@tonic-gate }
9727c478bd9Sstevel@tonic-gate
9737c478bd9Sstevel@tonic-gate ai->ai_next = NULL;
9747c478bd9Sstevel@tonic-gate
9757c478bd9Sstevel@tonic-gate return ai;
9767c478bd9Sstevel@tonic-gate }
9777c478bd9Sstevel@tonic-gate
9787c478bd9Sstevel@tonic-gate static int
get_portmatch(const struct addrinfo * ai,const char * servname)9797c478bd9Sstevel@tonic-gate get_portmatch(const struct addrinfo *ai, const char *servname) {
9807c478bd9Sstevel@tonic-gate
9817c478bd9Sstevel@tonic-gate /* get_port does not touch first argument. when matchonly == 1. */
9827c478bd9Sstevel@tonic-gate /* LINTED const cast */
9837c478bd9Sstevel@tonic-gate return get_port((const struct addrinfo *)ai, servname, 1);
9847c478bd9Sstevel@tonic-gate }
9857c478bd9Sstevel@tonic-gate
9867c478bd9Sstevel@tonic-gate static int
get_port(const struct addrinfo * ai,const char * servname,int matchonly)9877c478bd9Sstevel@tonic-gate get_port(const struct addrinfo *ai, const char *servname, int matchonly) {
9887c478bd9Sstevel@tonic-gate const char *proto;
9897c478bd9Sstevel@tonic-gate struct servent *sp;
9907c478bd9Sstevel@tonic-gate int port;
9917c478bd9Sstevel@tonic-gate int allownumeric;
9927c478bd9Sstevel@tonic-gate
9937c478bd9Sstevel@tonic-gate if (servname == NULL)
9947c478bd9Sstevel@tonic-gate return 0;
9957c478bd9Sstevel@tonic-gate switch (ai->ai_family) {
9967c478bd9Sstevel@tonic-gate case AF_INET:
9977c478bd9Sstevel@tonic-gate #ifdef AF_INET6
9987c478bd9Sstevel@tonic-gate case AF_INET6:
9997c478bd9Sstevel@tonic-gate #endif
10007c478bd9Sstevel@tonic-gate break;
10017c478bd9Sstevel@tonic-gate default:
10027c478bd9Sstevel@tonic-gate return 0;
10037c478bd9Sstevel@tonic-gate }
10047c478bd9Sstevel@tonic-gate
10057c478bd9Sstevel@tonic-gate switch (ai->ai_socktype) {
10067c478bd9Sstevel@tonic-gate case SOCK_RAW:
10077c478bd9Sstevel@tonic-gate return EAI_SERVICE;
10087c478bd9Sstevel@tonic-gate case SOCK_DGRAM:
10097c478bd9Sstevel@tonic-gate case SOCK_STREAM:
10107c478bd9Sstevel@tonic-gate allownumeric = 1;
10117c478bd9Sstevel@tonic-gate break;
10127c478bd9Sstevel@tonic-gate case ANY:
10137c478bd9Sstevel@tonic-gate switch (ai->ai_family) {
10147c478bd9Sstevel@tonic-gate case AF_INET:
10157c478bd9Sstevel@tonic-gate #ifdef AF_INET6
10167c478bd9Sstevel@tonic-gate case AF_INET6:
10177c478bd9Sstevel@tonic-gate #endif
10187c478bd9Sstevel@tonic-gate allownumeric = 1;
10197c478bd9Sstevel@tonic-gate break;
10207c478bd9Sstevel@tonic-gate default:
10217c478bd9Sstevel@tonic-gate allownumeric = 0;
10227c478bd9Sstevel@tonic-gate break;
10237c478bd9Sstevel@tonic-gate }
10247c478bd9Sstevel@tonic-gate break;
10257c478bd9Sstevel@tonic-gate default:
10267c478bd9Sstevel@tonic-gate return EAI_SOCKTYPE;
10277c478bd9Sstevel@tonic-gate }
10287c478bd9Sstevel@tonic-gate
10297c478bd9Sstevel@tonic-gate if (str_isnumber(servname)) {
10307c478bd9Sstevel@tonic-gate if (!allownumeric)
10317c478bd9Sstevel@tonic-gate return EAI_SERVICE;
10327c478bd9Sstevel@tonic-gate port = atoi(servname);
10337c478bd9Sstevel@tonic-gate if (port < 0 || port > 65535)
10347c478bd9Sstevel@tonic-gate return EAI_SERVICE;
10357c478bd9Sstevel@tonic-gate port = htons(port);
10367c478bd9Sstevel@tonic-gate } else {
10377c478bd9Sstevel@tonic-gate switch (ai->ai_socktype) {
10387c478bd9Sstevel@tonic-gate case SOCK_DGRAM:
10397c478bd9Sstevel@tonic-gate proto = "udp";
10407c478bd9Sstevel@tonic-gate break;
10417c478bd9Sstevel@tonic-gate case SOCK_STREAM:
10427c478bd9Sstevel@tonic-gate proto = "tcp";
10437c478bd9Sstevel@tonic-gate break;
10447c478bd9Sstevel@tonic-gate default:
10457c478bd9Sstevel@tonic-gate proto = NULL;
10467c478bd9Sstevel@tonic-gate break;
10477c478bd9Sstevel@tonic-gate }
10487c478bd9Sstevel@tonic-gate
10497c478bd9Sstevel@tonic-gate if ((sp = getservbyname(servname, proto)) == NULL)
10507c478bd9Sstevel@tonic-gate return EAI_SERVICE;
10517c478bd9Sstevel@tonic-gate port = sp->s_port;
10527c478bd9Sstevel@tonic-gate }
10537c478bd9Sstevel@tonic-gate
10547c478bd9Sstevel@tonic-gate if (!matchonly) {
10557c478bd9Sstevel@tonic-gate switch (ai->ai_family) {
10567c478bd9Sstevel@tonic-gate case AF_INET:
10577c478bd9Sstevel@tonic-gate ((struct sockaddr_in *)(void *)
10587c478bd9Sstevel@tonic-gate ai->ai_addr)->sin_port = port;
10597c478bd9Sstevel@tonic-gate break;
10607c478bd9Sstevel@tonic-gate case AF_INET6:
10617c478bd9Sstevel@tonic-gate ((struct sockaddr_in6 *)(void *)
10627c478bd9Sstevel@tonic-gate ai->ai_addr)->sin6_port = port;
10637c478bd9Sstevel@tonic-gate break;
10647c478bd9Sstevel@tonic-gate }
10657c478bd9Sstevel@tonic-gate }
10667c478bd9Sstevel@tonic-gate
10677c478bd9Sstevel@tonic-gate return 0;
10687c478bd9Sstevel@tonic-gate }
10697c478bd9Sstevel@tonic-gate
10707c478bd9Sstevel@tonic-gate static const struct afd *
find_afd(af)10717c478bd9Sstevel@tonic-gate find_afd(af)
10727c478bd9Sstevel@tonic-gate int af;
10737c478bd9Sstevel@tonic-gate {
10747c478bd9Sstevel@tonic-gate const struct afd *afd;
10757c478bd9Sstevel@tonic-gate
10767c478bd9Sstevel@tonic-gate if (af == PF_UNSPEC)
10777c478bd9Sstevel@tonic-gate return NULL;
10787c478bd9Sstevel@tonic-gate for (afd = afdl; afd->a_af; afd++) {
10797c478bd9Sstevel@tonic-gate if (afd->a_af == af)
10807c478bd9Sstevel@tonic-gate return afd;
10817c478bd9Sstevel@tonic-gate }
10827c478bd9Sstevel@tonic-gate return NULL;
10837c478bd9Sstevel@tonic-gate }
10847c478bd9Sstevel@tonic-gate
1085*9525b14bSRao Shoaib /*%
10867c478bd9Sstevel@tonic-gate * post-2553: AI_ADDRCONFIG check. if we use getipnodeby* as backend, backend
10877c478bd9Sstevel@tonic-gate * will take care of it.
10887c478bd9Sstevel@tonic-gate * the semantics of AI_ADDRCONFIG is not defined well. we are not sure
10897c478bd9Sstevel@tonic-gate * if the code is right or not.
10907c478bd9Sstevel@tonic-gate */
10917c478bd9Sstevel@tonic-gate static int
addrconfig(af)10927c478bd9Sstevel@tonic-gate addrconfig(af)
10937c478bd9Sstevel@tonic-gate int af;
10947c478bd9Sstevel@tonic-gate {
10957c478bd9Sstevel@tonic-gate int s;
10967c478bd9Sstevel@tonic-gate
10977c478bd9Sstevel@tonic-gate /* XXX errno */
10987c478bd9Sstevel@tonic-gate s = socket(af, SOCK_DGRAM, 0);
10997c478bd9Sstevel@tonic-gate if (s < 0) {
11007c478bd9Sstevel@tonic-gate if (errno != EMFILE)
11017c478bd9Sstevel@tonic-gate return 0;
11027c478bd9Sstevel@tonic-gate } else
11037c478bd9Sstevel@tonic-gate close(s);
11047c478bd9Sstevel@tonic-gate return 1;
11057c478bd9Sstevel@tonic-gate }
11067c478bd9Sstevel@tonic-gate
11077c478bd9Sstevel@tonic-gate /* convert a string to a scope identifier. XXX: IPv6 specific */
11087c478bd9Sstevel@tonic-gate static int
ip6_str2scopeid(char * scope,struct sockaddr_in6 * sin6,u_int32_t * scopeidp)11097c478bd9Sstevel@tonic-gate ip6_str2scopeid(char *scope, struct sockaddr_in6 *sin6,
11107c478bd9Sstevel@tonic-gate u_int32_t *scopeidp)
11117c478bd9Sstevel@tonic-gate {
11127c478bd9Sstevel@tonic-gate u_int32_t scopeid;
11137c478bd9Sstevel@tonic-gate u_long lscopeid;
11147c478bd9Sstevel@tonic-gate struct in6_addr *a6 = &sin6->sin6_addr;
11157c478bd9Sstevel@tonic-gate char *ep;
11167c478bd9Sstevel@tonic-gate
11177c478bd9Sstevel@tonic-gate /* empty scopeid portion is invalid */
11187c478bd9Sstevel@tonic-gate if (*scope == '\0')
11197c478bd9Sstevel@tonic-gate return (0);
11207c478bd9Sstevel@tonic-gate
11217c478bd9Sstevel@tonic-gate #ifdef USE_IFNAMELINKID
1122*9525b14bSRao Shoaib if (IN6_IS_ADDR_LINKLOCAL(a6) || IN6_IS_ADDR_MC_LINKLOCAL(a6) ||
1123*9525b14bSRao Shoaib IN6_IS_ADDR_MC_NODELOCAL(a6)) {
11247c478bd9Sstevel@tonic-gate /*
11257c478bd9Sstevel@tonic-gate * Using interface names as link indices can be allowed
11267c478bd9Sstevel@tonic-gate * only when we can assume a one-to-one mappings between
11277c478bd9Sstevel@tonic-gate * links and interfaces. See comments in getnameinfo.c.
11287c478bd9Sstevel@tonic-gate */
11297c478bd9Sstevel@tonic-gate scopeid = if_nametoindex(scope);
11307c478bd9Sstevel@tonic-gate if (scopeid == 0)
11317c478bd9Sstevel@tonic-gate goto trynumeric;
11327c478bd9Sstevel@tonic-gate *scopeidp = scopeid;
11337c478bd9Sstevel@tonic-gate return (1);
11347c478bd9Sstevel@tonic-gate }
11357c478bd9Sstevel@tonic-gate #endif
11367c478bd9Sstevel@tonic-gate
11377c478bd9Sstevel@tonic-gate /* still unclear about literal, allow numeric only - placeholder */
11387c478bd9Sstevel@tonic-gate if (IN6_IS_ADDR_SITELOCAL(a6) || IN6_IS_ADDR_MC_SITELOCAL(a6))
11397c478bd9Sstevel@tonic-gate goto trynumeric;
11407c478bd9Sstevel@tonic-gate if (IN6_IS_ADDR_MC_ORGLOCAL(a6))
11417c478bd9Sstevel@tonic-gate goto trynumeric;
11427c478bd9Sstevel@tonic-gate else
1143*9525b14bSRao Shoaib goto trynumeric; /*%< global */
11447c478bd9Sstevel@tonic-gate /* try to convert to a numeric id as a last resort */
11457c478bd9Sstevel@tonic-gate trynumeric:
11467c478bd9Sstevel@tonic-gate errno = 0;
11477c478bd9Sstevel@tonic-gate lscopeid = strtoul(scope, &ep, 10);
11487c478bd9Sstevel@tonic-gate scopeid = lscopeid & 0xffffffff;
11497c478bd9Sstevel@tonic-gate if (errno == 0 && ep && *ep == '\0' && scopeid == lscopeid) {
11507c478bd9Sstevel@tonic-gate *scopeidp = scopeid;
11517c478bd9Sstevel@tonic-gate return (1);
11527c478bd9Sstevel@tonic-gate } else
11537c478bd9Sstevel@tonic-gate return (0);
11547c478bd9Sstevel@tonic-gate }
11557c478bd9Sstevel@tonic-gate
11567c478bd9Sstevel@tonic-gate struct addrinfo *
hostent2addrinfo(hp,pai)11577c478bd9Sstevel@tonic-gate hostent2addrinfo(hp, pai)
11587c478bd9Sstevel@tonic-gate struct hostent *hp;
11597c478bd9Sstevel@tonic-gate const struct addrinfo *pai;
11607c478bd9Sstevel@tonic-gate {
11617c478bd9Sstevel@tonic-gate int i, af, error = 0;
11627c478bd9Sstevel@tonic-gate char **aplist = NULL, *ap;
11637c478bd9Sstevel@tonic-gate struct addrinfo sentinel, *cur;
11647c478bd9Sstevel@tonic-gate const struct afd *afd;
11657c478bd9Sstevel@tonic-gate
11667c478bd9Sstevel@tonic-gate af = hp->h_addrtype;
11677c478bd9Sstevel@tonic-gate if (pai->ai_family != AF_UNSPEC && af != pai->ai_family)
11687c478bd9Sstevel@tonic-gate return(NULL);
11697c478bd9Sstevel@tonic-gate
11707c478bd9Sstevel@tonic-gate afd = find_afd(af);
11717c478bd9Sstevel@tonic-gate if (afd == NULL)
11727c478bd9Sstevel@tonic-gate return(NULL);
11737c478bd9Sstevel@tonic-gate
11747c478bd9Sstevel@tonic-gate aplist = hp->h_addr_list;
11757c478bd9Sstevel@tonic-gate
11767c478bd9Sstevel@tonic-gate memset(&sentinel, 0, sizeof(sentinel));
11777c478bd9Sstevel@tonic-gate cur = &sentinel;
11787c478bd9Sstevel@tonic-gate
11797c478bd9Sstevel@tonic-gate for (i = 0; (ap = aplist[i]) != NULL; i++) {
1180*9525b14bSRao Shoaib #if 0 /*%< the trick seems too much */
11817c478bd9Sstevel@tonic-gate af = hp->h_addr_list;
11827c478bd9Sstevel@tonic-gate if (af == AF_INET6 &&
11837c478bd9Sstevel@tonic-gate IN6_IS_ADDR_V4MAPPED((struct in6_addr *)ap)) {
11847c478bd9Sstevel@tonic-gate af = AF_INET;
11857c478bd9Sstevel@tonic-gate ap = ap + sizeof(struct in6_addr)
11867c478bd9Sstevel@tonic-gate - sizeof(struct in_addr);
11877c478bd9Sstevel@tonic-gate }
11887c478bd9Sstevel@tonic-gate afd = find_afd(af);
11897c478bd9Sstevel@tonic-gate if (afd == NULL)
11907c478bd9Sstevel@tonic-gate continue;
11917c478bd9Sstevel@tonic-gate #endif /* 0 */
11927c478bd9Sstevel@tonic-gate
11937c478bd9Sstevel@tonic-gate GET_AI(cur->ai_next, afd, ap);
11947c478bd9Sstevel@tonic-gate
11957c478bd9Sstevel@tonic-gate /* GET_PORT(cur->ai_next, servname); */
11967c478bd9Sstevel@tonic-gate if ((pai->ai_flags & AI_CANONNAME) != 0) {
11977c478bd9Sstevel@tonic-gate /*
11987c478bd9Sstevel@tonic-gate * RFC2553 says that ai_canonname will be set only for
11997c478bd9Sstevel@tonic-gate * the first element. we do it for all the elements,
12007c478bd9Sstevel@tonic-gate * just for convenience.
12017c478bd9Sstevel@tonic-gate */
12027c478bd9Sstevel@tonic-gate GET_CANONNAME(cur->ai_next, hp->h_name);
12037c478bd9Sstevel@tonic-gate }
1204*9525b14bSRao Shoaib while (cur->ai_next) /*%< no need to loop, actually. */
12057c478bd9Sstevel@tonic-gate cur = cur->ai_next;
12067c478bd9Sstevel@tonic-gate continue;
12077c478bd9Sstevel@tonic-gate
12087c478bd9Sstevel@tonic-gate free:
12097c478bd9Sstevel@tonic-gate if (cur->ai_next)
12107c478bd9Sstevel@tonic-gate freeaddrinfo(cur->ai_next);
12117c478bd9Sstevel@tonic-gate cur->ai_next = NULL;
12127c478bd9Sstevel@tonic-gate /* continue, without tht pointer CUR advanced. */
12137c478bd9Sstevel@tonic-gate }
12147c478bd9Sstevel@tonic-gate
12157c478bd9Sstevel@tonic-gate return(sentinel.ai_next);
12167c478bd9Sstevel@tonic-gate }
12177c478bd9Sstevel@tonic-gate
12187c478bd9Sstevel@tonic-gate struct addrinfo *
addr2addrinfo(pai,cp)12197c478bd9Sstevel@tonic-gate addr2addrinfo(pai, cp)
12207c478bd9Sstevel@tonic-gate const struct addrinfo *pai;
12217c478bd9Sstevel@tonic-gate const char *cp;
12227c478bd9Sstevel@tonic-gate {
12237c478bd9Sstevel@tonic-gate const struct afd *afd;
12247c478bd9Sstevel@tonic-gate
12257c478bd9Sstevel@tonic-gate afd = find_afd(pai->ai_family);
12267c478bd9Sstevel@tonic-gate if (afd == NULL)
12277c478bd9Sstevel@tonic-gate return(NULL);
12287c478bd9Sstevel@tonic-gate
12297c478bd9Sstevel@tonic-gate return(get_ai(pai, afd, cp));
12307c478bd9Sstevel@tonic-gate }
12317c478bd9Sstevel@tonic-gate
12327c478bd9Sstevel@tonic-gate static struct net_data *
init()12337c478bd9Sstevel@tonic-gate init()
12347c478bd9Sstevel@tonic-gate {
12357c478bd9Sstevel@tonic-gate struct net_data *net_data;
12367c478bd9Sstevel@tonic-gate
12377c478bd9Sstevel@tonic-gate if (!(net_data = net_data_init(NULL)))
12387c478bd9Sstevel@tonic-gate goto error;
12397c478bd9Sstevel@tonic-gate if (!net_data->ho) {
12407c478bd9Sstevel@tonic-gate net_data->ho = (*net_data->irs->ho_map)(net_data->irs);
12417c478bd9Sstevel@tonic-gate if (!net_data->ho || !net_data->res) {
12427c478bd9Sstevel@tonic-gate error:
12437c478bd9Sstevel@tonic-gate errno = EIO;
12447c478bd9Sstevel@tonic-gate if (net_data && net_data->res)
12457c478bd9Sstevel@tonic-gate RES_SET_H_ERRNO(net_data->res, NETDB_INTERNAL);
12467c478bd9Sstevel@tonic-gate return (NULL);
12477c478bd9Sstevel@tonic-gate }
12487c478bd9Sstevel@tonic-gate
12497c478bd9Sstevel@tonic-gate (*net_data->ho->res_set)(net_data->ho, net_data->res, NULL);
12507c478bd9Sstevel@tonic-gate }
12517c478bd9Sstevel@tonic-gate
12527c478bd9Sstevel@tonic-gate return (net_data);
12537c478bd9Sstevel@tonic-gate }
1254