10Sstevel@tonic-gate /* $KAME: getaddrinfo.c,v 1.14 2001/01/06 09:41:15 jinmei Exp $ */
20Sstevel@tonic-gate
30Sstevel@tonic-gate /*
40Sstevel@tonic-gate * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
50Sstevel@tonic-gate * All rights reserved.
60Sstevel@tonic-gate *
70Sstevel@tonic-gate * Redistribution and use in source and binary forms, with or without
80Sstevel@tonic-gate * modification, are permitted provided that the following conditions
90Sstevel@tonic-gate * are met:
100Sstevel@tonic-gate * 1. Redistributions of source code must retain the above copyright
110Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer.
120Sstevel@tonic-gate * 2. Redistributions in binary form must reproduce the above copyright
130Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer in the
140Sstevel@tonic-gate * documentation and/or other materials provided with the distribution.
150Sstevel@tonic-gate * 3. Neither the name of the project nor the names of its contributors
160Sstevel@tonic-gate * may be used to endorse or promote products derived from this software
170Sstevel@tonic-gate * without specific prior written permission.
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
200Sstevel@tonic-gate * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
210Sstevel@tonic-gate * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
220Sstevel@tonic-gate * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
230Sstevel@tonic-gate * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
240Sstevel@tonic-gate * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
250Sstevel@tonic-gate * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
260Sstevel@tonic-gate * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
270Sstevel@tonic-gate * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
280Sstevel@tonic-gate * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
290Sstevel@tonic-gate * SUCH DAMAGE.
300Sstevel@tonic-gate */
310Sstevel@tonic-gate
32*11038SRao.Shoaib@Sun.COM /*! \file
330Sstevel@tonic-gate * Issues to be discussed:
34*11038SRao.Shoaib@Sun.COM *\li Thread safe-ness must be checked.
35*11038SRao.Shoaib@Sun.COM *\li Return values. There are nonstandard return values defined and used
360Sstevel@tonic-gate * in the source code. This is because RFC2553 is silent about which error
370Sstevel@tonic-gate * code must be returned for which situation.
38*11038SRao.Shoaib@Sun.COM *\li IPv4 classful (shortened) form. RFC2553 is silent about it. XNET 5.2
390Sstevel@tonic-gate * says to use inet_aton() to convert IPv4 numeric to binary (allows
400Sstevel@tonic-gate * classful form as a result).
410Sstevel@tonic-gate * current code - disallow classful form for IPv4 (due to use of inet_pton).
42*11038SRao.Shoaib@Sun.COM *\li freeaddrinfo(NULL). RFC2553 is silent about it. XNET 5.2 says it is
430Sstevel@tonic-gate * invalid.
440Sstevel@tonic-gate * current code - SEGV on freeaddrinfo(NULL)
450Sstevel@tonic-gate * Note:
46*11038SRao.Shoaib@Sun.COM *\li We use getipnodebyname() just for thread-safeness. There's no intent
470Sstevel@tonic-gate * to let it do PF_UNSPEC (actually we never pass PF_UNSPEC to
480Sstevel@tonic-gate * getipnodebyname().
49*11038SRao.Shoaib@Sun.COM *\li The code filters out AFs that are not supported by the kernel,
500Sstevel@tonic-gate * when globbing NULL hostname (to loopback, or wildcard). Is it the right
510Sstevel@tonic-gate * thing to do? What is the relationship with post-RFC2553 AI_ADDRCONFIG
520Sstevel@tonic-gate * in ai_flags?
53*11038SRao.Shoaib@Sun.COM *\li (post-2553) semantics of AI_ADDRCONFIG itself is too vague.
540Sstevel@tonic-gate * (1) what should we do against numeric hostname (2) what should we do
550Sstevel@tonic-gate * against NULL hostname (3) what is AI_ADDRCONFIG itself. AF not ready?
560Sstevel@tonic-gate * non-loopback address configured? global address configured?
57*11038SRao.Shoaib@Sun.COM * \par Additional Issue:
58*11038SRao.Shoaib@Sun.COM * To avoid search order issue, we have a big amount of code duplicate
590Sstevel@tonic-gate * from gethnamaddr.c and some other places. The issues that there's no
600Sstevel@tonic-gate * lower layer function to lookup "IPv4 or IPv6" record. Calling
610Sstevel@tonic-gate * gethostbyname2 from getaddrinfo will end up in wrong search order, as
620Sstevel@tonic-gate * follows:
63*11038SRao.Shoaib@Sun.COM * \li The code makes use of following calls when asked to resolver with
640Sstevel@tonic-gate * ai_family = PF_UNSPEC:
65*11038SRao.Shoaib@Sun.COM *\code getipnodebyname(host, AF_INET6);
660Sstevel@tonic-gate * getipnodebyname(host, AF_INET);
67*11038SRao.Shoaib@Sun.COM *\endcode
68*11038SRao.Shoaib@Sun.COM * \li This will result in the following queries if the node is configure to
690Sstevel@tonic-gate * prefer /etc/hosts than DNS:
70*11038SRao.Shoaib@Sun.COM *\code
710Sstevel@tonic-gate * lookup /etc/hosts for IPv6 address
720Sstevel@tonic-gate * lookup DNS for IPv6 address
730Sstevel@tonic-gate * lookup /etc/hosts for IPv4 address
740Sstevel@tonic-gate * lookup DNS for IPv4 address
75*11038SRao.Shoaib@Sun.COM *\endcode
760Sstevel@tonic-gate * which may not meet people's requirement.
77*11038SRao.Shoaib@Sun.COM * \li The right thing to happen is to have underlying layer which does
780Sstevel@tonic-gate * PF_UNSPEC lookup (lookup both) and return chain of addrinfos.
790Sstevel@tonic-gate * This would result in a bit of code duplicate with _dns_ghbyname() and
800Sstevel@tonic-gate * friends.
810Sstevel@tonic-gate */
820Sstevel@tonic-gate
830Sstevel@tonic-gate #include "port_before.h"
840Sstevel@tonic-gate
850Sstevel@tonic-gate #include <sys/types.h>
860Sstevel@tonic-gate #include <sys/param.h>
870Sstevel@tonic-gate #include <sys/socket.h>
880Sstevel@tonic-gate
890Sstevel@tonic-gate #include <net/if.h>
900Sstevel@tonic-gate #include <netinet/in.h>
910Sstevel@tonic-gate
920Sstevel@tonic-gate #include <arpa/inet.h>
930Sstevel@tonic-gate #include <arpa/nameser.h>
940Sstevel@tonic-gate
950Sstevel@tonic-gate #include <netdb.h>
960Sstevel@tonic-gate #include <resolv.h>
970Sstevel@tonic-gate #include <string.h>
980Sstevel@tonic-gate #include <stdlib.h>
990Sstevel@tonic-gate #include <stddef.h>
1000Sstevel@tonic-gate #include <ctype.h>
1010Sstevel@tonic-gate #include <unistd.h>
1020Sstevel@tonic-gate #include <stdio.h>
1030Sstevel@tonic-gate #include <errno.h>
1040Sstevel@tonic-gate
1050Sstevel@tonic-gate #include <stdarg.h>
1060Sstevel@tonic-gate
1070Sstevel@tonic-gate #include <irs.h>
1080Sstevel@tonic-gate #include <isc/assertions.h>
1090Sstevel@tonic-gate
1100Sstevel@tonic-gate #include "port_after.h"
1110Sstevel@tonic-gate
1120Sstevel@tonic-gate #include "irs_data.h"
1130Sstevel@tonic-gate
1140Sstevel@tonic-gate #define SUCCESS 0
1150Sstevel@tonic-gate #define ANY 0
1160Sstevel@tonic-gate #define YES 1
1170Sstevel@tonic-gate #define NO 0
1180Sstevel@tonic-gate
1190Sstevel@tonic-gate static const char in_addrany[] = { 0, 0, 0, 0 };
1200Sstevel@tonic-gate static const char in6_addrany[] = {
1210Sstevel@tonic-gate 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
1220Sstevel@tonic-gate };
1230Sstevel@tonic-gate static const char in_loopback[] = { 127, 0, 0, 1 };
1240Sstevel@tonic-gate static const char in6_loopback[] = {
1250Sstevel@tonic-gate 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
1260Sstevel@tonic-gate };
1270Sstevel@tonic-gate
1280Sstevel@tonic-gate static const struct afd {
1290Sstevel@tonic-gate int a_af;
1300Sstevel@tonic-gate int a_addrlen;
1310Sstevel@tonic-gate int a_socklen;
1320Sstevel@tonic-gate int a_off;
1330Sstevel@tonic-gate const char *a_addrany;
1340Sstevel@tonic-gate const char *a_loopback;
1350Sstevel@tonic-gate int a_scoped;
1360Sstevel@tonic-gate } afdl [] = {
1370Sstevel@tonic-gate {PF_INET6, sizeof(struct in6_addr),
1380Sstevel@tonic-gate sizeof(struct sockaddr_in6),
1390Sstevel@tonic-gate offsetof(struct sockaddr_in6, sin6_addr),
1400Sstevel@tonic-gate in6_addrany, in6_loopback, 1},
1410Sstevel@tonic-gate {PF_INET, sizeof(struct in_addr),
1420Sstevel@tonic-gate sizeof(struct sockaddr_in),
1430Sstevel@tonic-gate offsetof(struct sockaddr_in, sin_addr),
1440Sstevel@tonic-gate in_addrany, in_loopback, 0},
1450Sstevel@tonic-gate {0, 0, 0, 0, NULL, NULL, 0},
1460Sstevel@tonic-gate };
1470Sstevel@tonic-gate
1480Sstevel@tonic-gate struct explore {
1490Sstevel@tonic-gate int e_af;
1500Sstevel@tonic-gate int e_socktype;
1510Sstevel@tonic-gate int e_protocol;
1520Sstevel@tonic-gate const char *e_protostr;
1530Sstevel@tonic-gate int e_wild;
1540Sstevel@tonic-gate #define WILD_AF(ex) ((ex)->e_wild & 0x01)
1550Sstevel@tonic-gate #define WILD_SOCKTYPE(ex) ((ex)->e_wild & 0x02)
1560Sstevel@tonic-gate #define WILD_PROTOCOL(ex) ((ex)->e_wild & 0x04)
1570Sstevel@tonic-gate };
1580Sstevel@tonic-gate
1590Sstevel@tonic-gate static const struct explore explore[] = {
1600Sstevel@tonic-gate #if 0
1610Sstevel@tonic-gate { PF_LOCAL, 0, ANY, ANY, NULL, 0x01 },
1620Sstevel@tonic-gate #endif
1630Sstevel@tonic-gate { PF_INET6, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
1640Sstevel@tonic-gate { PF_INET6, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
1650Sstevel@tonic-gate { PF_INET6, SOCK_RAW, ANY, NULL, 0x05 },
1660Sstevel@tonic-gate { PF_INET, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
1670Sstevel@tonic-gate { PF_INET, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
1680Sstevel@tonic-gate { PF_INET, SOCK_RAW, ANY, NULL, 0x05 },
1690Sstevel@tonic-gate { -1, 0, 0, NULL, 0 },
1700Sstevel@tonic-gate };
1710Sstevel@tonic-gate
1720Sstevel@tonic-gate #define PTON_MAX 16
1730Sstevel@tonic-gate
1740Sstevel@tonic-gate static int str_isnumber __P((const char *));
1750Sstevel@tonic-gate static int explore_fqdn __P((const struct addrinfo *, const char *,
1760Sstevel@tonic-gate const char *, struct addrinfo **));
1770Sstevel@tonic-gate static int explore_copy __P((const struct addrinfo *, const struct addrinfo *,
1780Sstevel@tonic-gate struct addrinfo **));
1790Sstevel@tonic-gate static int explore_null __P((const struct addrinfo *,
1800Sstevel@tonic-gate const char *, struct addrinfo **));
1810Sstevel@tonic-gate static int explore_numeric __P((const struct addrinfo *, const char *,
1820Sstevel@tonic-gate const char *, struct addrinfo **));
1830Sstevel@tonic-gate static int explore_numeric_scope __P((const struct addrinfo *, const char *,
1840Sstevel@tonic-gate const char *, struct addrinfo **));
1850Sstevel@tonic-gate static int get_canonname __P((const struct addrinfo *,
1860Sstevel@tonic-gate struct addrinfo *, const char *));
1870Sstevel@tonic-gate static struct addrinfo *get_ai __P((const struct addrinfo *,
1880Sstevel@tonic-gate const struct afd *, const char *));
1890Sstevel@tonic-gate static struct addrinfo *copy_ai __P((const struct addrinfo *));
1900Sstevel@tonic-gate static int get_portmatch __P((const struct addrinfo *, const char *));
1910Sstevel@tonic-gate static int get_port __P((const struct addrinfo *, const char *, int));
1920Sstevel@tonic-gate static const struct afd *find_afd __P((int));
1930Sstevel@tonic-gate static int addrconfig __P((int));
1940Sstevel@tonic-gate static int ip6_str2scopeid __P((char *, struct sockaddr_in6 *,
1950Sstevel@tonic-gate u_int32_t *scopeidp));
1960Sstevel@tonic-gate static struct net_data *init __P((void));
1970Sstevel@tonic-gate
1980Sstevel@tonic-gate struct addrinfo *hostent2addrinfo __P((struct hostent *,
1990Sstevel@tonic-gate const struct addrinfo *));
2000Sstevel@tonic-gate struct addrinfo *addr2addrinfo __P((const struct addrinfo *,
2010Sstevel@tonic-gate const char *));
2020Sstevel@tonic-gate
2030Sstevel@tonic-gate #if 0
2040Sstevel@tonic-gate static const char *ai_errlist[] = {
2050Sstevel@tonic-gate "Success",
206*11038SRao.Shoaib@Sun.COM "Address family for hostname not supported", /*%< EAI_ADDRFAMILY */
207*11038SRao.Shoaib@Sun.COM "Temporary failure in name resolution", /*%< EAI_AGAIN */
208*11038SRao.Shoaib@Sun.COM "Invalid value for ai_flags", /*%< EAI_BADFLAGS */
209*11038SRao.Shoaib@Sun.COM "Non-recoverable failure in name resolution", /*%< EAI_FAIL */
210*11038SRao.Shoaib@Sun.COM "ai_family not supported", /*%< EAI_FAMILY */
211*11038SRao.Shoaib@Sun.COM "Memory allocation failure", /*%< EAI_MEMORY */
212*11038SRao.Shoaib@Sun.COM "No address associated with hostname", /*%< EAI_NODATA */
213*11038SRao.Shoaib@Sun.COM "hostname nor servname provided, or not known", /*%< EAI_NONAME */
214*11038SRao.Shoaib@Sun.COM "servname not supported for ai_socktype", /*%< EAI_SERVICE */
215*11038SRao.Shoaib@Sun.COM "ai_socktype not supported", /*%< EAI_SOCKTYPE */
216*11038SRao.Shoaib@Sun.COM "System error returned in errno", /*%< EAI_SYSTEM */
217*11038SRao.Shoaib@Sun.COM "Invalid value for hints", /*%< EAI_BADHINTS */
218*11038SRao.Shoaib@Sun.COM "Resolved protocol is unknown", /*%< EAI_PROTOCOL */
219*11038SRao.Shoaib@Sun.COM "Unknown error", /*%< EAI_MAX */
2200Sstevel@tonic-gate };
2210Sstevel@tonic-gate #endif
2220Sstevel@tonic-gate
2230Sstevel@tonic-gate /* XXX macros that make external reference is BAD. */
2240Sstevel@tonic-gate
2250Sstevel@tonic-gate #define GET_AI(ai, afd, addr) \
2260Sstevel@tonic-gate do { \
2270Sstevel@tonic-gate /* external reference: pai, error, and label free */ \
2280Sstevel@tonic-gate (ai) = get_ai(pai, (afd), (addr)); \
2290Sstevel@tonic-gate if ((ai) == NULL) { \
2300Sstevel@tonic-gate error = EAI_MEMORY; \
2310Sstevel@tonic-gate goto free; \
2320Sstevel@tonic-gate } \
2330Sstevel@tonic-gate } while (/*CONSTCOND*/0)
2340Sstevel@tonic-gate
2350Sstevel@tonic-gate #define GET_PORT(ai, serv) \
2360Sstevel@tonic-gate do { \
2370Sstevel@tonic-gate /* external reference: error and label free */ \
2380Sstevel@tonic-gate error = get_port((ai), (serv), 0); \
2390Sstevel@tonic-gate if (error != 0) \
2400Sstevel@tonic-gate goto free; \
2410Sstevel@tonic-gate } while (/*CONSTCOND*/0)
2420Sstevel@tonic-gate
2430Sstevel@tonic-gate #define GET_CANONNAME(ai, str) \
2440Sstevel@tonic-gate do { \
2450Sstevel@tonic-gate /* external reference: pai, error and label free */ \
2460Sstevel@tonic-gate error = get_canonname(pai, (ai), (str)); \
2470Sstevel@tonic-gate if (error != 0) \
2480Sstevel@tonic-gate goto free; \
2490Sstevel@tonic-gate } while (/*CONSTCOND*/0)
2500Sstevel@tonic-gate
251*11038SRao.Shoaib@Sun.COM #ifndef SOLARIS2
252*11038SRao.Shoaib@Sun.COM #define SETERROR(err) \
2530Sstevel@tonic-gate do { \
2540Sstevel@tonic-gate /* external reference: error, and label bad */ \
2550Sstevel@tonic-gate error = (err); \
2560Sstevel@tonic-gate goto bad; \
2570Sstevel@tonic-gate /*NOTREACHED*/ \
2580Sstevel@tonic-gate } while (/*CONSTCOND*/0)
2590Sstevel@tonic-gate #else
260*11038SRao.Shoaib@Sun.COM #define SETERROR(err) \
2610Sstevel@tonic-gate do { \
262*11038SRao.Shoaib@Sun.COM /* external reference: error, and label bad */ \
2630Sstevel@tonic-gate error = (err); \
264*11038SRao.Shoaib@Sun.COM if (error == error) \
265*11038SRao.Shoaib@Sun.COM goto bad; \
2660Sstevel@tonic-gate } while (/*CONSTCOND*/0)
2670Sstevel@tonic-gate #endif
2680Sstevel@tonic-gate
269*11038SRao.Shoaib@Sun.COM
2700Sstevel@tonic-gate #define MATCH_FAMILY(x, y, w) \
2710Sstevel@tonic-gate ((x) == (y) || (/*CONSTCOND*/(w) && ((x) == PF_UNSPEC || (y) == PF_UNSPEC)))
2720Sstevel@tonic-gate #define MATCH(x, y, w) \
2730Sstevel@tonic-gate ((x) == (y) || (/*CONSTCOND*/(w) && ((x) == ANY || (y) == ANY)))
2740Sstevel@tonic-gate
275*11038SRao.Shoaib@Sun.COM #if 0 /*%< bind8 has its own version */
2760Sstevel@tonic-gate char *
2770Sstevel@tonic-gate gai_strerror(ecode)
2780Sstevel@tonic-gate int ecode;
2790Sstevel@tonic-gate {
2800Sstevel@tonic-gate if (ecode < 0 || ecode > EAI_MAX)
2810Sstevel@tonic-gate ecode = EAI_MAX;
2820Sstevel@tonic-gate return ai_errlist[ecode];
2830Sstevel@tonic-gate }
2840Sstevel@tonic-gate #endif
2850Sstevel@tonic-gate
2860Sstevel@tonic-gate void
freeaddrinfo(ai)2870Sstevel@tonic-gate freeaddrinfo(ai)
2880Sstevel@tonic-gate struct addrinfo *ai;
2890Sstevel@tonic-gate {
2900Sstevel@tonic-gate struct addrinfo *next;
2910Sstevel@tonic-gate
2920Sstevel@tonic-gate do {
2930Sstevel@tonic-gate next = ai->ai_next;
2940Sstevel@tonic-gate if (ai->ai_canonname)
2950Sstevel@tonic-gate free(ai->ai_canonname);
2960Sstevel@tonic-gate /* no need to free(ai->ai_addr) */
2970Sstevel@tonic-gate free(ai);
2980Sstevel@tonic-gate ai = next;
2990Sstevel@tonic-gate } while (ai);
3000Sstevel@tonic-gate }
3010Sstevel@tonic-gate
3020Sstevel@tonic-gate static int
str_isnumber(p)3030Sstevel@tonic-gate str_isnumber(p)
3040Sstevel@tonic-gate const char *p;
3050Sstevel@tonic-gate {
3060Sstevel@tonic-gate char *ep;
3070Sstevel@tonic-gate
3080Sstevel@tonic-gate if (*p == '\0')
3090Sstevel@tonic-gate return NO;
3100Sstevel@tonic-gate ep = NULL;
3110Sstevel@tonic-gate errno = 0;
3120Sstevel@tonic-gate (void)strtoul(p, &ep, 10);
3130Sstevel@tonic-gate if (errno == 0 && ep && *ep == '\0')
3140Sstevel@tonic-gate return YES;
3150Sstevel@tonic-gate else
3160Sstevel@tonic-gate return NO;
3170Sstevel@tonic-gate }
3180Sstevel@tonic-gate
3190Sstevel@tonic-gate int
getaddrinfo(hostname,servname,hints,res)3200Sstevel@tonic-gate getaddrinfo(hostname, servname, hints, res)
3210Sstevel@tonic-gate const char *hostname, *servname;
3220Sstevel@tonic-gate const struct addrinfo *hints;
3230Sstevel@tonic-gate struct addrinfo **res;
3240Sstevel@tonic-gate {
3250Sstevel@tonic-gate struct addrinfo sentinel;
3260Sstevel@tonic-gate struct addrinfo *cur;
3270Sstevel@tonic-gate int error = 0;
3280Sstevel@tonic-gate struct addrinfo ai, ai0, *afai = NULL;
3290Sstevel@tonic-gate struct addrinfo *pai;
3300Sstevel@tonic-gate const struct explore *ex;
3310Sstevel@tonic-gate
3320Sstevel@tonic-gate memset(&sentinel, 0, sizeof(sentinel));
3330Sstevel@tonic-gate cur = &sentinel;
3340Sstevel@tonic-gate pai = &ai;
3350Sstevel@tonic-gate pai->ai_flags = 0;
3360Sstevel@tonic-gate pai->ai_family = PF_UNSPEC;
3370Sstevel@tonic-gate pai->ai_socktype = ANY;
3380Sstevel@tonic-gate pai->ai_protocol = ANY;
339*11038SRao.Shoaib@Sun.COM #if defined(sun) && defined(_SOCKLEN_T) && defined(__sparcv9)
3400Sstevel@tonic-gate /*
341*11038SRao.Shoaib@Sun.COM * clear _ai_pad to preserve binary
3420Sstevel@tonic-gate * compatibility with previously compiled 64-bit
3430Sstevel@tonic-gate * applications in a pre-SUSv3 environment by
3440Sstevel@tonic-gate * guaranteeing the upper 32-bits are empty.
3450Sstevel@tonic-gate */
3460Sstevel@tonic-gate pai->_ai_pad = 0;
347*11038SRao.Shoaib@Sun.COM #endif
3480Sstevel@tonic-gate pai->ai_addrlen = 0;
3490Sstevel@tonic-gate pai->ai_canonname = NULL;
3500Sstevel@tonic-gate pai->ai_addr = NULL;
3510Sstevel@tonic-gate pai->ai_next = NULL;
3520Sstevel@tonic-gate
3530Sstevel@tonic-gate if (hostname == NULL && servname == NULL)
3540Sstevel@tonic-gate return EAI_NONAME;
3550Sstevel@tonic-gate if (hints) {
3560Sstevel@tonic-gate /* error check for hints */
3570Sstevel@tonic-gate if (hints->ai_addrlen || hints->ai_canonname ||
358*11038SRao.Shoaib@Sun.COM hints->ai_addr || hints->ai_next)
359*11038SRao.Shoaib@Sun.COM SETERROR(EAI_BADHINTS); /*%< xxx */
360*11038SRao.Shoaib@Sun.COM if (hints->ai_flags & ~AI_MASK)
361*11038SRao.Shoaib@Sun.COM SETERROR(EAI_BADFLAGS);
3620Sstevel@tonic-gate switch (hints->ai_family) {
3630Sstevel@tonic-gate case PF_UNSPEC:
3640Sstevel@tonic-gate case PF_INET:
3650Sstevel@tonic-gate case PF_INET6:
3660Sstevel@tonic-gate break;
3670Sstevel@tonic-gate default:
368*11038SRao.Shoaib@Sun.COM SETERROR(EAI_FAMILY);
3690Sstevel@tonic-gate }
3700Sstevel@tonic-gate memcpy(pai, hints, sizeof(*pai));
3710Sstevel@tonic-gate
372*11038SRao.Shoaib@Sun.COM #if defined(sun) && defined(_SOCKLEN_T) && defined(__sparcv9)
3730Sstevel@tonic-gate /*
3740Sstevel@tonic-gate * We need to clear _ai_pad to preserve binary
3750Sstevel@tonic-gate * compatibility. See prior comment.
3760Sstevel@tonic-gate */
3770Sstevel@tonic-gate pai->_ai_pad = 0;
378*11038SRao.Shoaib@Sun.COM #endif
3790Sstevel@tonic-gate /*
3800Sstevel@tonic-gate * if both socktype/protocol are specified, check if they
3810Sstevel@tonic-gate * are meaningful combination.
3820Sstevel@tonic-gate */
3830Sstevel@tonic-gate if (pai->ai_socktype != ANY && pai->ai_protocol != ANY) {
3840Sstevel@tonic-gate for (ex = explore; ex->e_af >= 0; ex++) {
3850Sstevel@tonic-gate if (pai->ai_family != ex->e_af)
3860Sstevel@tonic-gate continue;
3870Sstevel@tonic-gate if (ex->e_socktype == ANY)
3880Sstevel@tonic-gate continue;
3890Sstevel@tonic-gate if (ex->e_protocol == ANY)
3900Sstevel@tonic-gate continue;
3910Sstevel@tonic-gate if (pai->ai_socktype == ex->e_socktype &&
3920Sstevel@tonic-gate pai->ai_protocol != ex->e_protocol) {
393*11038SRao.Shoaib@Sun.COM SETERROR(EAI_BADHINTS);
3940Sstevel@tonic-gate }
3950Sstevel@tonic-gate }
3960Sstevel@tonic-gate }
3970Sstevel@tonic-gate }
3980Sstevel@tonic-gate
3990Sstevel@tonic-gate /*
4000Sstevel@tonic-gate * post-2553: AI_ALL and AI_V4MAPPED are effective only against
4010Sstevel@tonic-gate * AF_INET6 query. They needs to be ignored if specified in other
4020Sstevel@tonic-gate * occassions.
4030Sstevel@tonic-gate */
4040Sstevel@tonic-gate switch (pai->ai_flags & (AI_ALL | AI_V4MAPPED)) {
4050Sstevel@tonic-gate case AI_V4MAPPED:
4060Sstevel@tonic-gate case AI_ALL | AI_V4MAPPED:
4070Sstevel@tonic-gate if (pai->ai_family != AF_INET6)
4080Sstevel@tonic-gate pai->ai_flags &= ~(AI_ALL | AI_V4MAPPED);
4090Sstevel@tonic-gate break;
4100Sstevel@tonic-gate case AI_ALL:
4110Sstevel@tonic-gate #if 1
4120Sstevel@tonic-gate /* illegal */
413*11038SRao.Shoaib@Sun.COM SETERROR(EAI_BADFLAGS);
4140Sstevel@tonic-gate #else
4150Sstevel@tonic-gate pai->ai_flags &= ~(AI_ALL | AI_V4MAPPED);
4160Sstevel@tonic-gate break;
4170Sstevel@tonic-gate #endif
4180Sstevel@tonic-gate }
4190Sstevel@tonic-gate
4200Sstevel@tonic-gate /*
4210Sstevel@tonic-gate * check for special cases. (1) numeric servname is disallowed if
4220Sstevel@tonic-gate * socktype/protocol are left unspecified. (2) servname is disallowed
4230Sstevel@tonic-gate * for raw and other inet{,6} sockets.
4240Sstevel@tonic-gate */
4250Sstevel@tonic-gate if (MATCH_FAMILY(pai->ai_family, PF_INET, 1)
4260Sstevel@tonic-gate #ifdef PF_INET6
4270Sstevel@tonic-gate || MATCH_FAMILY(pai->ai_family, PF_INET6, 1)
4280Sstevel@tonic-gate #endif
4290Sstevel@tonic-gate ) {
4300Sstevel@tonic-gate ai0 = *pai; /* backup *pai */
4310Sstevel@tonic-gate
4320Sstevel@tonic-gate if (pai->ai_family == PF_UNSPEC) {
4330Sstevel@tonic-gate #ifdef PF_INET6
4340Sstevel@tonic-gate pai->ai_family = PF_INET6;
4350Sstevel@tonic-gate #else
4360Sstevel@tonic-gate pai->ai_family = PF_INET;
4370Sstevel@tonic-gate #endif
4380Sstevel@tonic-gate }
4390Sstevel@tonic-gate error = get_portmatch(pai, servname);
440*11038SRao.Shoaib@Sun.COM if (error)
441*11038SRao.Shoaib@Sun.COM SETERROR(error);
4420Sstevel@tonic-gate
4430Sstevel@tonic-gate *pai = ai0;
4440Sstevel@tonic-gate }
4450Sstevel@tonic-gate
4460Sstevel@tonic-gate ai0 = *pai;
4470Sstevel@tonic-gate
4480Sstevel@tonic-gate /* NULL hostname, or numeric hostname */
4490Sstevel@tonic-gate for (ex = explore; ex->e_af >= 0; ex++) {
4500Sstevel@tonic-gate *pai = ai0;
4510Sstevel@tonic-gate
4520Sstevel@tonic-gate if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex)))
4530Sstevel@tonic-gate continue;
4540Sstevel@tonic-gate if (!MATCH(pai->ai_socktype, ex->e_socktype, WILD_SOCKTYPE(ex)))
4550Sstevel@tonic-gate continue;
4560Sstevel@tonic-gate if (!MATCH(pai->ai_protocol, ex->e_protocol, WILD_PROTOCOL(ex)))
4570Sstevel@tonic-gate continue;
4580Sstevel@tonic-gate
4590Sstevel@tonic-gate if (pai->ai_family == PF_UNSPEC)
4600Sstevel@tonic-gate pai->ai_family = ex->e_af;
4610Sstevel@tonic-gate if (pai->ai_socktype == ANY && ex->e_socktype != ANY)
4620Sstevel@tonic-gate pai->ai_socktype = ex->e_socktype;
4630Sstevel@tonic-gate if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
4640Sstevel@tonic-gate pai->ai_protocol = ex->e_protocol;
4650Sstevel@tonic-gate
4660Sstevel@tonic-gate /*
4670Sstevel@tonic-gate * if the servname does not match socktype/protocol, ignore it.
4680Sstevel@tonic-gate */
4690Sstevel@tonic-gate if (get_portmatch(pai, servname) != 0)
4700Sstevel@tonic-gate continue;
4710Sstevel@tonic-gate
4720Sstevel@tonic-gate if (hostname == NULL) {
4730Sstevel@tonic-gate /*
4740Sstevel@tonic-gate * filter out AFs that are not supported by the kernel
4750Sstevel@tonic-gate * XXX errno?
4760Sstevel@tonic-gate */
4770Sstevel@tonic-gate if (!addrconfig(pai->ai_family))
4780Sstevel@tonic-gate continue;
4790Sstevel@tonic-gate error = explore_null(pai, servname, &cur->ai_next);
4800Sstevel@tonic-gate } else
4810Sstevel@tonic-gate error = explore_numeric_scope(pai, hostname, servname,
4820Sstevel@tonic-gate &cur->ai_next);
4830Sstevel@tonic-gate
4840Sstevel@tonic-gate if (error)
4850Sstevel@tonic-gate goto free;
4860Sstevel@tonic-gate
4870Sstevel@tonic-gate while (cur && cur->ai_next)
4880Sstevel@tonic-gate cur = cur->ai_next;
4890Sstevel@tonic-gate }
4900Sstevel@tonic-gate
4910Sstevel@tonic-gate /*
4920Sstevel@tonic-gate * XXX
4930Sstevel@tonic-gate * If numreic representation of AF1 can be interpreted as FQDN
4940Sstevel@tonic-gate * representation of AF2, we need to think again about the code below.
4950Sstevel@tonic-gate */
4960Sstevel@tonic-gate if (sentinel.ai_next)
4970Sstevel@tonic-gate goto good;
4980Sstevel@tonic-gate
499*11038SRao.Shoaib@Sun.COM if (pai->ai_flags & AI_NUMERICHOST)
500*11038SRao.Shoaib@Sun.COM SETERROR(EAI_NONAME);
501*11038SRao.Shoaib@Sun.COM if (hostname == NULL)
502*11038SRao.Shoaib@Sun.COM SETERROR(EAI_NONAME);
5030Sstevel@tonic-gate
5040Sstevel@tonic-gate /*
5050Sstevel@tonic-gate * hostname as alphabetical name.
5060Sstevel@tonic-gate * We'll make sure that
5070Sstevel@tonic-gate * - if returning addrinfo list is empty, return non-zero error
5080Sstevel@tonic-gate * value (already known one or EAI_NONAME).
5090Sstevel@tonic-gate * - otherwise,
5100Sstevel@tonic-gate * + if we haven't had any errors, return 0 (i.e. success).
5110Sstevel@tonic-gate * + if we've had an error, free the list and return the error.
5120Sstevel@tonic-gate * without any assumption on the behavior of explore_fqdn().
5130Sstevel@tonic-gate */
5140Sstevel@tonic-gate
5150Sstevel@tonic-gate /* first, try to query DNS for all possible address families. */
5160Sstevel@tonic-gate *pai = ai0;
5170Sstevel@tonic-gate error = explore_fqdn(pai, hostname, servname, &afai);
5180Sstevel@tonic-gate if (error) {
5190Sstevel@tonic-gate if (afai != NULL)
5200Sstevel@tonic-gate freeaddrinfo(afai);
5210Sstevel@tonic-gate goto free;
5220Sstevel@tonic-gate }
5230Sstevel@tonic-gate if (afai == NULL) {
524*11038SRao.Shoaib@Sun.COM error = EAI_NONAME; /*%< we've had no errors. */
5250Sstevel@tonic-gate goto free;
5260Sstevel@tonic-gate }
5270Sstevel@tonic-gate
5280Sstevel@tonic-gate /*
5290Sstevel@tonic-gate * we would like to prefer AF_INET6 than AF_INET, so we'll make an
5300Sstevel@tonic-gate * outer loop by AFs.
5310Sstevel@tonic-gate */
5320Sstevel@tonic-gate for (ex = explore; ex->e_af >= 0; ex++) {
5330Sstevel@tonic-gate *pai = ai0;
5340Sstevel@tonic-gate
5350Sstevel@tonic-gate if (pai->ai_family == PF_UNSPEC)
5360Sstevel@tonic-gate pai->ai_family = ex->e_af;
5370Sstevel@tonic-gate
5380Sstevel@tonic-gate if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex)))
5390Sstevel@tonic-gate continue;
5400Sstevel@tonic-gate if (!MATCH(pai->ai_socktype, ex->e_socktype,
5410Sstevel@tonic-gate WILD_SOCKTYPE(ex))) {
5420Sstevel@tonic-gate continue;
5430Sstevel@tonic-gate }
5440Sstevel@tonic-gate if (!MATCH(pai->ai_protocol, ex->e_protocol,
5450Sstevel@tonic-gate WILD_PROTOCOL(ex))) {
5460Sstevel@tonic-gate continue;
5470Sstevel@tonic-gate }
5480Sstevel@tonic-gate
5490Sstevel@tonic-gate #ifdef AI_ADDRCONFIG
5500Sstevel@tonic-gate /*
5510Sstevel@tonic-gate * If AI_ADDRCONFIG is specified, check if we are
5520Sstevel@tonic-gate * expected to return the address family or not.
5530Sstevel@tonic-gate */
5540Sstevel@tonic-gate if ((pai->ai_flags & AI_ADDRCONFIG) != 0 &&
5550Sstevel@tonic-gate !addrconfig(pai->ai_family))
5560Sstevel@tonic-gate continue;
5570Sstevel@tonic-gate #endif
5580Sstevel@tonic-gate
5590Sstevel@tonic-gate if (pai->ai_family == PF_UNSPEC)
5600Sstevel@tonic-gate pai->ai_family = ex->e_af;
5610Sstevel@tonic-gate if (pai->ai_socktype == ANY && ex->e_socktype != ANY)
5620Sstevel@tonic-gate pai->ai_socktype = ex->e_socktype;
5630Sstevel@tonic-gate if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
5640Sstevel@tonic-gate pai->ai_protocol = ex->e_protocol;
5650Sstevel@tonic-gate
5660Sstevel@tonic-gate /*
5670Sstevel@tonic-gate * if the servname does not match socktype/protocol, ignore it.
5680Sstevel@tonic-gate */
5690Sstevel@tonic-gate if (get_portmatch(pai, servname) != 0)
5700Sstevel@tonic-gate continue;
5710Sstevel@tonic-gate
5720Sstevel@tonic-gate if ((error = explore_copy(pai, afai, &cur->ai_next)) != 0) {
5730Sstevel@tonic-gate freeaddrinfo(afai);
5740Sstevel@tonic-gate goto free;
5750Sstevel@tonic-gate }
5760Sstevel@tonic-gate
5770Sstevel@tonic-gate while (cur && cur->ai_next)
5780Sstevel@tonic-gate cur = cur->ai_next;
5790Sstevel@tonic-gate }
5800Sstevel@tonic-gate
581*11038SRao.Shoaib@Sun.COM freeaddrinfo(afai); /*%< afai must not be NULL at this point. */
5820Sstevel@tonic-gate
5830Sstevel@tonic-gate if (sentinel.ai_next) {
5840Sstevel@tonic-gate good:
5850Sstevel@tonic-gate *res = sentinel.ai_next;
5860Sstevel@tonic-gate return(SUCCESS);
5870Sstevel@tonic-gate } else {
5880Sstevel@tonic-gate /*
5890Sstevel@tonic-gate * All the process succeeded, but we've had an empty list.
5900Sstevel@tonic-gate * This can happen if the given hints do not match our
5910Sstevel@tonic-gate * candidates.
5920Sstevel@tonic-gate */
5930Sstevel@tonic-gate error = EAI_NONAME;
5940Sstevel@tonic-gate }
5950Sstevel@tonic-gate
5960Sstevel@tonic-gate free:
5970Sstevel@tonic-gate bad:
5980Sstevel@tonic-gate if (sentinel.ai_next)
5990Sstevel@tonic-gate freeaddrinfo(sentinel.ai_next);
6000Sstevel@tonic-gate *res = NULL;
6010Sstevel@tonic-gate return(error);
6020Sstevel@tonic-gate }
6030Sstevel@tonic-gate
604*11038SRao.Shoaib@Sun.COM /*%
6050Sstevel@tonic-gate * FQDN hostname, DNS lookup
6060Sstevel@tonic-gate */
6070Sstevel@tonic-gate static int
explore_fqdn(pai,hostname,servname,res)6080Sstevel@tonic-gate explore_fqdn(pai, hostname, servname, res)
6090Sstevel@tonic-gate const struct addrinfo *pai;
6100Sstevel@tonic-gate const char *hostname;
6110Sstevel@tonic-gate const char *servname;
6120Sstevel@tonic-gate struct addrinfo **res;
6130Sstevel@tonic-gate {
6140Sstevel@tonic-gate struct addrinfo *result;
6150Sstevel@tonic-gate struct addrinfo *cur;
6160Sstevel@tonic-gate struct net_data *net_data = init();
6170Sstevel@tonic-gate struct irs_ho *ho;
6180Sstevel@tonic-gate int error = 0;
6190Sstevel@tonic-gate char tmp[NS_MAXDNAME];
6200Sstevel@tonic-gate const char *cp;
6210Sstevel@tonic-gate
6220Sstevel@tonic-gate INSIST(res != NULL && *res == NULL);
6230Sstevel@tonic-gate
6240Sstevel@tonic-gate /*
6250Sstevel@tonic-gate * if the servname does not match socktype/protocol, ignore it.
6260Sstevel@tonic-gate */
6270Sstevel@tonic-gate if (get_portmatch(pai, servname) != 0)
6280Sstevel@tonic-gate return(0);
6290Sstevel@tonic-gate
6300Sstevel@tonic-gate if (!net_data || !(ho = net_data->ho))
6310Sstevel@tonic-gate return(0);
632*11038SRao.Shoaib@Sun.COM #if 0 /*%< XXX (notyet) */
6330Sstevel@tonic-gate if (net_data->ho_stayopen && net_data->ho_last &&
6340Sstevel@tonic-gate net_data->ho_last->h_addrtype == af) {
6350Sstevel@tonic-gate if (ns_samename(name, net_data->ho_last->h_name) == 1)
6360Sstevel@tonic-gate return (net_data->ho_last);
6370Sstevel@tonic-gate for (hap = net_data->ho_last->h_aliases; hap && *hap; hap++)
6380Sstevel@tonic-gate if (ns_samename(name, *hap) == 1)
6390Sstevel@tonic-gate return (net_data->ho_last);
6400Sstevel@tonic-gate }
6410Sstevel@tonic-gate #endif
6420Sstevel@tonic-gate if (!strchr(hostname, '.') &&
6430Sstevel@tonic-gate (cp = res_hostalias(net_data->res, hostname,
6440Sstevel@tonic-gate tmp, sizeof(tmp))))
6450Sstevel@tonic-gate hostname = cp;
6460Sstevel@tonic-gate result = (*ho->addrinfo)(ho, hostname, pai);
6470Sstevel@tonic-gate if (!net_data->ho_stayopen) {
6480Sstevel@tonic-gate (*ho->minimize)(ho);
6490Sstevel@tonic-gate }
6500Sstevel@tonic-gate if (result == NULL) {
6510Sstevel@tonic-gate int e = h_errno;
6520Sstevel@tonic-gate
6530Sstevel@tonic-gate switch(e) {
6540Sstevel@tonic-gate case NETDB_INTERNAL:
6550Sstevel@tonic-gate error = EAI_SYSTEM;
6560Sstevel@tonic-gate break;
6570Sstevel@tonic-gate case TRY_AGAIN:
6580Sstevel@tonic-gate error = EAI_AGAIN;
6590Sstevel@tonic-gate break;
6600Sstevel@tonic-gate case NO_RECOVERY:
6610Sstevel@tonic-gate error = EAI_FAIL;
6620Sstevel@tonic-gate break;
6630Sstevel@tonic-gate case HOST_NOT_FOUND:
6640Sstevel@tonic-gate case NO_DATA:
6650Sstevel@tonic-gate error = EAI_NONAME;
6660Sstevel@tonic-gate break;
6670Sstevel@tonic-gate default:
668*11038SRao.Shoaib@Sun.COM case NETDB_SUCCESS: /*%< should be impossible... */
6690Sstevel@tonic-gate error = EAI_NONAME;
6700Sstevel@tonic-gate break;
6710Sstevel@tonic-gate }
6720Sstevel@tonic-gate goto free;
6730Sstevel@tonic-gate }
6740Sstevel@tonic-gate
6750Sstevel@tonic-gate for (cur = result; cur; cur = cur->ai_next) {
676*11038SRao.Shoaib@Sun.COM GET_PORT(cur, servname); /*%< XXX: redundant lookups... */
6770Sstevel@tonic-gate /* canonname should already be filled. */
6780Sstevel@tonic-gate }
6790Sstevel@tonic-gate
6800Sstevel@tonic-gate *res = result;
6810Sstevel@tonic-gate
6820Sstevel@tonic-gate return(0);
6830Sstevel@tonic-gate
6840Sstevel@tonic-gate free:
6850Sstevel@tonic-gate if (result)
6860Sstevel@tonic-gate freeaddrinfo(result);
6870Sstevel@tonic-gate return error;
6880Sstevel@tonic-gate }
6890Sstevel@tonic-gate
6900Sstevel@tonic-gate static int
explore_copy(pai,src0,res)6910Sstevel@tonic-gate explore_copy(pai, src0, res)
692*11038SRao.Shoaib@Sun.COM const struct addrinfo *pai; /*%< seed */
693*11038SRao.Shoaib@Sun.COM const struct addrinfo *src0; /*%< source */
6940Sstevel@tonic-gate struct addrinfo **res;
6950Sstevel@tonic-gate {
6960Sstevel@tonic-gate int error;
6970Sstevel@tonic-gate struct addrinfo sentinel, *cur;
6980Sstevel@tonic-gate const struct addrinfo *src;
6990Sstevel@tonic-gate
7000Sstevel@tonic-gate error = 0;
7010Sstevel@tonic-gate sentinel.ai_next = NULL;
7020Sstevel@tonic-gate cur = &sentinel;
7030Sstevel@tonic-gate
7040Sstevel@tonic-gate for (src = src0; src != NULL; src = src->ai_next) {
7050Sstevel@tonic-gate if (src->ai_family != pai->ai_family)
7060Sstevel@tonic-gate continue;
7070Sstevel@tonic-gate
7080Sstevel@tonic-gate cur->ai_next = copy_ai(src);
7090Sstevel@tonic-gate if (!cur->ai_next) {
7100Sstevel@tonic-gate error = EAI_MEMORY;
7110Sstevel@tonic-gate goto fail;
7120Sstevel@tonic-gate }
7130Sstevel@tonic-gate
7140Sstevel@tonic-gate cur->ai_next->ai_socktype = pai->ai_socktype;
7150Sstevel@tonic-gate cur->ai_next->ai_protocol = pai->ai_protocol;
7160Sstevel@tonic-gate cur = cur->ai_next;
7170Sstevel@tonic-gate }
7180Sstevel@tonic-gate
7190Sstevel@tonic-gate *res = sentinel.ai_next;
7200Sstevel@tonic-gate return 0;
7210Sstevel@tonic-gate
7220Sstevel@tonic-gate fail:
7230Sstevel@tonic-gate freeaddrinfo(sentinel.ai_next);
7240Sstevel@tonic-gate return error;
7250Sstevel@tonic-gate }
7260Sstevel@tonic-gate
727*11038SRao.Shoaib@Sun.COM /*%
7280Sstevel@tonic-gate * hostname == NULL.
7290Sstevel@tonic-gate * passive socket -> anyaddr (0.0.0.0 or ::)
7300Sstevel@tonic-gate * non-passive socket -> localhost (127.0.0.1 or ::1)
7310Sstevel@tonic-gate */
7320Sstevel@tonic-gate static int
explore_null(pai,servname,res)7330Sstevel@tonic-gate explore_null(pai, servname, res)
7340Sstevel@tonic-gate const struct addrinfo *pai;
7350Sstevel@tonic-gate const char *servname;
7360Sstevel@tonic-gate struct addrinfo **res;
7370Sstevel@tonic-gate {
7380Sstevel@tonic-gate const struct afd *afd;
7390Sstevel@tonic-gate struct addrinfo *cur;
7400Sstevel@tonic-gate struct addrinfo sentinel;
7410Sstevel@tonic-gate int error;
7420Sstevel@tonic-gate
7430Sstevel@tonic-gate *res = NULL;
7440Sstevel@tonic-gate sentinel.ai_next = NULL;
7450Sstevel@tonic-gate cur = &sentinel;
7460Sstevel@tonic-gate
7470Sstevel@tonic-gate afd = find_afd(pai->ai_family);
7480Sstevel@tonic-gate if (afd == NULL)
7490Sstevel@tonic-gate return 0;
7500Sstevel@tonic-gate
7510Sstevel@tonic-gate if (pai->ai_flags & AI_PASSIVE) {
7520Sstevel@tonic-gate GET_AI(cur->ai_next, afd, afd->a_addrany);
7530Sstevel@tonic-gate /* xxx meaningless?
7540Sstevel@tonic-gate * GET_CANONNAME(cur->ai_next, "anyaddr");
7550Sstevel@tonic-gate */
7560Sstevel@tonic-gate GET_PORT(cur->ai_next, servname);
7570Sstevel@tonic-gate } else {
7580Sstevel@tonic-gate GET_AI(cur->ai_next, afd, afd->a_loopback);
7590Sstevel@tonic-gate /* xxx meaningless?
7600Sstevel@tonic-gate * GET_CANONNAME(cur->ai_next, "localhost");
7610Sstevel@tonic-gate */
7620Sstevel@tonic-gate GET_PORT(cur->ai_next, servname);
7630Sstevel@tonic-gate }
7640Sstevel@tonic-gate cur = cur->ai_next;
7650Sstevel@tonic-gate
7660Sstevel@tonic-gate *res = sentinel.ai_next;
7670Sstevel@tonic-gate return 0;
7680Sstevel@tonic-gate
7690Sstevel@tonic-gate free:
7700Sstevel@tonic-gate if (sentinel.ai_next)
7710Sstevel@tonic-gate freeaddrinfo(sentinel.ai_next);
7720Sstevel@tonic-gate return error;
7730Sstevel@tonic-gate }
7740Sstevel@tonic-gate
775*11038SRao.Shoaib@Sun.COM /*%
7760Sstevel@tonic-gate * numeric hostname
7770Sstevel@tonic-gate */
7780Sstevel@tonic-gate static int
explore_numeric(pai,hostname,servname,res)7790Sstevel@tonic-gate explore_numeric(pai, hostname, servname, res)
7800Sstevel@tonic-gate const struct addrinfo *pai;
7810Sstevel@tonic-gate const char *hostname;
7820Sstevel@tonic-gate const char *servname;
7830Sstevel@tonic-gate struct addrinfo **res;
7840Sstevel@tonic-gate {
7850Sstevel@tonic-gate const struct afd *afd;
7860Sstevel@tonic-gate struct addrinfo *cur;
7870Sstevel@tonic-gate struct addrinfo sentinel;
7880Sstevel@tonic-gate int error;
7890Sstevel@tonic-gate char pton[PTON_MAX];
7900Sstevel@tonic-gate
7910Sstevel@tonic-gate *res = NULL;
7920Sstevel@tonic-gate sentinel.ai_next = NULL;
7930Sstevel@tonic-gate cur = &sentinel;
7940Sstevel@tonic-gate
7950Sstevel@tonic-gate afd = find_afd(pai->ai_family);
7960Sstevel@tonic-gate if (afd == NULL)
7970Sstevel@tonic-gate return 0;
7980Sstevel@tonic-gate
7990Sstevel@tonic-gate switch (afd->a_af) {
8000Sstevel@tonic-gate #if 0 /*X/Open spec*/
8010Sstevel@tonic-gate case AF_INET:
8020Sstevel@tonic-gate if (inet_aton(hostname, (struct in_addr *)pton) == 1) {
8030Sstevel@tonic-gate if (pai->ai_family == afd->a_af ||
8040Sstevel@tonic-gate pai->ai_family == PF_UNSPEC /*?*/) {
8050Sstevel@tonic-gate GET_AI(cur->ai_next, afd, pton);
8060Sstevel@tonic-gate GET_PORT(cur->ai_next, servname);
807*11038SRao.Shoaib@Sun.COM while (cur->ai_next)
8080Sstevel@tonic-gate cur = cur->ai_next;
8090Sstevel@tonic-gate } else
810*11038SRao.Shoaib@Sun.COM SETERROR(EAI_FAMILY); /*xxx*/
8110Sstevel@tonic-gate }
8120Sstevel@tonic-gate break;
8130Sstevel@tonic-gate #endif
8140Sstevel@tonic-gate default:
8150Sstevel@tonic-gate if (inet_pton(afd->a_af, hostname, pton) == 1) {
8160Sstevel@tonic-gate if (pai->ai_family == afd->a_af ||
8170Sstevel@tonic-gate pai->ai_family == PF_UNSPEC /*?*/) {
8180Sstevel@tonic-gate GET_AI(cur->ai_next, afd, pton);
8190Sstevel@tonic-gate GET_PORT(cur->ai_next, servname);
820*11038SRao.Shoaib@Sun.COM while (cur->ai_next)
8210Sstevel@tonic-gate cur = cur->ai_next;
822*11038SRao.Shoaib@Sun.COM } else
823*11038SRao.Shoaib@Sun.COM SETERROR(EAI_FAMILY); /*xxx*/
8240Sstevel@tonic-gate }
8250Sstevel@tonic-gate break;
8260Sstevel@tonic-gate }
8270Sstevel@tonic-gate
8280Sstevel@tonic-gate *res = sentinel.ai_next;
8290Sstevel@tonic-gate return 0;
8300Sstevel@tonic-gate
8310Sstevel@tonic-gate free:
8320Sstevel@tonic-gate bad:
8330Sstevel@tonic-gate if (sentinel.ai_next)
8340Sstevel@tonic-gate freeaddrinfo(sentinel.ai_next);
8350Sstevel@tonic-gate return error;
8360Sstevel@tonic-gate }
8370Sstevel@tonic-gate
838*11038SRao.Shoaib@Sun.COM /*%
8390Sstevel@tonic-gate * numeric hostname with scope
8400Sstevel@tonic-gate */
8410Sstevel@tonic-gate static int
explore_numeric_scope(pai,hostname,servname,res)8420Sstevel@tonic-gate explore_numeric_scope(pai, hostname, servname, res)
8430Sstevel@tonic-gate const struct addrinfo *pai;
8440Sstevel@tonic-gate const char *hostname;
8450Sstevel@tonic-gate const char *servname;
8460Sstevel@tonic-gate struct addrinfo **res;
8470Sstevel@tonic-gate {
8480Sstevel@tonic-gate #ifndef SCOPE_DELIMITER
8490Sstevel@tonic-gate return explore_numeric(pai, hostname, servname, res);
8500Sstevel@tonic-gate #else
8510Sstevel@tonic-gate const struct afd *afd;
8520Sstevel@tonic-gate struct addrinfo *cur;
8530Sstevel@tonic-gate int error;
8540Sstevel@tonic-gate char *cp, *hostname2 = NULL, *scope, *addr;
8550Sstevel@tonic-gate struct sockaddr_in6 *sin6;
8560Sstevel@tonic-gate
8570Sstevel@tonic-gate afd = find_afd(pai->ai_family);
8580Sstevel@tonic-gate if (afd == NULL)
8590Sstevel@tonic-gate return 0;
8600Sstevel@tonic-gate
8610Sstevel@tonic-gate if (!afd->a_scoped)
8620Sstevel@tonic-gate return explore_numeric(pai, hostname, servname, res);
8630Sstevel@tonic-gate
8640Sstevel@tonic-gate cp = strchr(hostname, SCOPE_DELIMITER);
8650Sstevel@tonic-gate if (cp == NULL)
8660Sstevel@tonic-gate return explore_numeric(pai, hostname, servname, res);
8670Sstevel@tonic-gate
8680Sstevel@tonic-gate /*
8690Sstevel@tonic-gate * Handle special case of <scoped_address><delimiter><scope id>
8700Sstevel@tonic-gate */
8710Sstevel@tonic-gate hostname2 = strdup(hostname);
8720Sstevel@tonic-gate if (hostname2 == NULL)
8730Sstevel@tonic-gate return EAI_MEMORY;
8740Sstevel@tonic-gate /* terminate at the delimiter */
8750Sstevel@tonic-gate hostname2[cp - hostname] = '\0';
8760Sstevel@tonic-gate addr = hostname2;
8770Sstevel@tonic-gate scope = cp + 1;
8780Sstevel@tonic-gate
8790Sstevel@tonic-gate error = explore_numeric(pai, addr, servname, res);
8800Sstevel@tonic-gate if (error == 0) {
8810Sstevel@tonic-gate u_int32_t scopeid = 0;
8820Sstevel@tonic-gate
8830Sstevel@tonic-gate for (cur = *res; cur; cur = cur->ai_next) {
8840Sstevel@tonic-gate if (cur->ai_family != AF_INET6)
8850Sstevel@tonic-gate continue;
8860Sstevel@tonic-gate sin6 = (struct sockaddr_in6 *)(void *)cur->ai_addr;
8870Sstevel@tonic-gate if (!ip6_str2scopeid(scope, sin6, &scopeid)) {
8880Sstevel@tonic-gate free(hostname2);
889*11038SRao.Shoaib@Sun.COM return(EAI_NONAME); /*%< XXX: is return OK? */
8900Sstevel@tonic-gate }
8910Sstevel@tonic-gate #ifdef HAVE_SIN6_SCOPE_ID
8920Sstevel@tonic-gate sin6->sin6_scope_id = scopeid;
8930Sstevel@tonic-gate #endif
8940Sstevel@tonic-gate }
8950Sstevel@tonic-gate }
8960Sstevel@tonic-gate
8970Sstevel@tonic-gate free(hostname2);
8980Sstevel@tonic-gate
8990Sstevel@tonic-gate return error;
9000Sstevel@tonic-gate #endif
9010Sstevel@tonic-gate }
9020Sstevel@tonic-gate
9030Sstevel@tonic-gate static int
get_canonname(pai,ai,str)9040Sstevel@tonic-gate get_canonname(pai, ai, str)
9050Sstevel@tonic-gate const struct addrinfo *pai;
9060Sstevel@tonic-gate struct addrinfo *ai;
9070Sstevel@tonic-gate const char *str;
9080Sstevel@tonic-gate {
9090Sstevel@tonic-gate if ((pai->ai_flags & AI_CANONNAME) != 0) {
9100Sstevel@tonic-gate ai->ai_canonname = (char *)malloc(strlen(str) + 1);
9110Sstevel@tonic-gate if (ai->ai_canonname == NULL)
9120Sstevel@tonic-gate return EAI_MEMORY;
9130Sstevel@tonic-gate strcpy(ai->ai_canonname, str);
9140Sstevel@tonic-gate }
9150Sstevel@tonic-gate return 0;
9160Sstevel@tonic-gate }
9170Sstevel@tonic-gate
9180Sstevel@tonic-gate static struct addrinfo *
get_ai(pai,afd,addr)9190Sstevel@tonic-gate get_ai(pai, afd, addr)
9200Sstevel@tonic-gate const struct addrinfo *pai;
9210Sstevel@tonic-gate const struct afd *afd;
9220Sstevel@tonic-gate const char *addr;
9230Sstevel@tonic-gate {
9240Sstevel@tonic-gate char *p;
9250Sstevel@tonic-gate struct addrinfo *ai;
9260Sstevel@tonic-gate
9270Sstevel@tonic-gate ai = (struct addrinfo *)malloc(sizeof(struct addrinfo)
9280Sstevel@tonic-gate + (afd->a_socklen));
9290Sstevel@tonic-gate if (ai == NULL)
9300Sstevel@tonic-gate return NULL;
9310Sstevel@tonic-gate
9320Sstevel@tonic-gate memcpy(ai, pai, sizeof(struct addrinfo));
9330Sstevel@tonic-gate ai->ai_addr = (struct sockaddr *)(void *)(ai + 1);
9340Sstevel@tonic-gate memset(ai->ai_addr, 0, (size_t)afd->a_socklen);
9350Sstevel@tonic-gate #ifdef HAVE_SA_LEN
9360Sstevel@tonic-gate ai->ai_addr->sa_len = afd->a_socklen;
9370Sstevel@tonic-gate #endif
9380Sstevel@tonic-gate ai->ai_addrlen = afd->a_socklen;
9390Sstevel@tonic-gate ai->ai_addr->sa_family = ai->ai_family = afd->a_af;
9400Sstevel@tonic-gate p = (char *)(void *)(ai->ai_addr);
9410Sstevel@tonic-gate memcpy(p + afd->a_off, addr, (size_t)afd->a_addrlen);
9420Sstevel@tonic-gate return ai;
9430Sstevel@tonic-gate }
9440Sstevel@tonic-gate
9450Sstevel@tonic-gate /* XXX need to malloc() the same way we do from other functions! */
9460Sstevel@tonic-gate static struct addrinfo *
copy_ai(pai)9470Sstevel@tonic-gate copy_ai(pai)
9480Sstevel@tonic-gate const struct addrinfo *pai;
9490Sstevel@tonic-gate {
9500Sstevel@tonic-gate struct addrinfo *ai;
9510Sstevel@tonic-gate size_t l;
9520Sstevel@tonic-gate
9530Sstevel@tonic-gate l = sizeof(*ai) + pai->ai_addrlen;
9540Sstevel@tonic-gate if ((ai = (struct addrinfo *)malloc(l)) == NULL)
9550Sstevel@tonic-gate return NULL;
9560Sstevel@tonic-gate memset(ai, 0, l);
9570Sstevel@tonic-gate memcpy(ai, pai, sizeof(*ai));
9580Sstevel@tonic-gate ai->ai_addr = (struct sockaddr *)(void *)(ai + 1);
9590Sstevel@tonic-gate memcpy(ai->ai_addr, pai->ai_addr, pai->ai_addrlen);
9600Sstevel@tonic-gate
9610Sstevel@tonic-gate if (pai->ai_canonname) {
9620Sstevel@tonic-gate l = strlen(pai->ai_canonname) + 1;
9630Sstevel@tonic-gate if ((ai->ai_canonname = malloc(l)) == NULL) {
9640Sstevel@tonic-gate free(ai);
9650Sstevel@tonic-gate return NULL;
9660Sstevel@tonic-gate }
967*11038SRao.Shoaib@Sun.COM strcpy(ai->ai_canonname, pai->ai_canonname); /* (checked) */
9680Sstevel@tonic-gate } else {
9690Sstevel@tonic-gate /* just to make sure */
9700Sstevel@tonic-gate ai->ai_canonname = NULL;
9710Sstevel@tonic-gate }
9720Sstevel@tonic-gate
9730Sstevel@tonic-gate ai->ai_next = NULL;
9740Sstevel@tonic-gate
9750Sstevel@tonic-gate return ai;
9760Sstevel@tonic-gate }
9770Sstevel@tonic-gate
9780Sstevel@tonic-gate static int
get_portmatch(const struct addrinfo * ai,const char * servname)9790Sstevel@tonic-gate get_portmatch(const struct addrinfo *ai, const char *servname) {
9800Sstevel@tonic-gate
9810Sstevel@tonic-gate /* get_port does not touch first argument. when matchonly == 1. */
9820Sstevel@tonic-gate /* LINTED const cast */
9830Sstevel@tonic-gate return get_port((const struct addrinfo *)ai, servname, 1);
9840Sstevel@tonic-gate }
9850Sstevel@tonic-gate
9860Sstevel@tonic-gate static int
get_port(const struct addrinfo * ai,const char * servname,int matchonly)9870Sstevel@tonic-gate get_port(const struct addrinfo *ai, const char *servname, int matchonly) {
9880Sstevel@tonic-gate const char *proto;
9890Sstevel@tonic-gate struct servent *sp;
9900Sstevel@tonic-gate int port;
9910Sstevel@tonic-gate int allownumeric;
9920Sstevel@tonic-gate
9930Sstevel@tonic-gate if (servname == NULL)
9940Sstevel@tonic-gate return 0;
9950Sstevel@tonic-gate switch (ai->ai_family) {
9960Sstevel@tonic-gate case AF_INET:
9970Sstevel@tonic-gate #ifdef AF_INET6
9980Sstevel@tonic-gate case AF_INET6:
9990Sstevel@tonic-gate #endif
10000Sstevel@tonic-gate break;
10010Sstevel@tonic-gate default:
10020Sstevel@tonic-gate return 0;
10030Sstevel@tonic-gate }
10040Sstevel@tonic-gate
10050Sstevel@tonic-gate switch (ai->ai_socktype) {
10060Sstevel@tonic-gate case SOCK_RAW:
10070Sstevel@tonic-gate return EAI_SERVICE;
10080Sstevel@tonic-gate case SOCK_DGRAM:
10090Sstevel@tonic-gate case SOCK_STREAM:
10100Sstevel@tonic-gate allownumeric = 1;
10110Sstevel@tonic-gate break;
10120Sstevel@tonic-gate case ANY:
10130Sstevel@tonic-gate switch (ai->ai_family) {
10140Sstevel@tonic-gate case AF_INET:
10150Sstevel@tonic-gate #ifdef AF_INET6
10160Sstevel@tonic-gate case AF_INET6:
10170Sstevel@tonic-gate #endif
10180Sstevel@tonic-gate allownumeric = 1;
10190Sstevel@tonic-gate break;
10200Sstevel@tonic-gate default:
10210Sstevel@tonic-gate allownumeric = 0;
10220Sstevel@tonic-gate break;
10230Sstevel@tonic-gate }
10240Sstevel@tonic-gate break;
10250Sstevel@tonic-gate default:
10260Sstevel@tonic-gate return EAI_SOCKTYPE;
10270Sstevel@tonic-gate }
10280Sstevel@tonic-gate
10290Sstevel@tonic-gate if (str_isnumber(servname)) {
10300Sstevel@tonic-gate if (!allownumeric)
10310Sstevel@tonic-gate return EAI_SERVICE;
10320Sstevel@tonic-gate port = atoi(servname);
10330Sstevel@tonic-gate if (port < 0 || port > 65535)
10340Sstevel@tonic-gate return EAI_SERVICE;
10350Sstevel@tonic-gate port = htons(port);
10360Sstevel@tonic-gate } else {
10370Sstevel@tonic-gate switch (ai->ai_socktype) {
10380Sstevel@tonic-gate case SOCK_DGRAM:
10390Sstevel@tonic-gate proto = "udp";
10400Sstevel@tonic-gate break;
10410Sstevel@tonic-gate case SOCK_STREAM:
10420Sstevel@tonic-gate proto = "tcp";
10430Sstevel@tonic-gate break;
10440Sstevel@tonic-gate default:
10450Sstevel@tonic-gate proto = NULL;
10460Sstevel@tonic-gate break;
10470Sstevel@tonic-gate }
10480Sstevel@tonic-gate
10490Sstevel@tonic-gate if ((sp = getservbyname(servname, proto)) == NULL)
10500Sstevel@tonic-gate return EAI_SERVICE;
10510Sstevel@tonic-gate port = sp->s_port;
10520Sstevel@tonic-gate }
10530Sstevel@tonic-gate
10540Sstevel@tonic-gate if (!matchonly) {
10550Sstevel@tonic-gate switch (ai->ai_family) {
10560Sstevel@tonic-gate case AF_INET:
10570Sstevel@tonic-gate ((struct sockaddr_in *)(void *)
10580Sstevel@tonic-gate ai->ai_addr)->sin_port = port;
10590Sstevel@tonic-gate break;
10600Sstevel@tonic-gate case AF_INET6:
10610Sstevel@tonic-gate ((struct sockaddr_in6 *)(void *)
10620Sstevel@tonic-gate ai->ai_addr)->sin6_port = port;
10630Sstevel@tonic-gate break;
10640Sstevel@tonic-gate }
10650Sstevel@tonic-gate }
10660Sstevel@tonic-gate
10670Sstevel@tonic-gate return 0;
10680Sstevel@tonic-gate }
10690Sstevel@tonic-gate
10700Sstevel@tonic-gate static const struct afd *
find_afd(af)10710Sstevel@tonic-gate find_afd(af)
10720Sstevel@tonic-gate int af;
10730Sstevel@tonic-gate {
10740Sstevel@tonic-gate const struct afd *afd;
10750Sstevel@tonic-gate
10760Sstevel@tonic-gate if (af == PF_UNSPEC)
10770Sstevel@tonic-gate return NULL;
10780Sstevel@tonic-gate for (afd = afdl; afd->a_af; afd++) {
10790Sstevel@tonic-gate if (afd->a_af == af)
10800Sstevel@tonic-gate return afd;
10810Sstevel@tonic-gate }
10820Sstevel@tonic-gate return NULL;
10830Sstevel@tonic-gate }
10840Sstevel@tonic-gate
1085*11038SRao.Shoaib@Sun.COM /*%
10860Sstevel@tonic-gate * post-2553: AI_ADDRCONFIG check. if we use getipnodeby* as backend, backend
10870Sstevel@tonic-gate * will take care of it.
10880Sstevel@tonic-gate * the semantics of AI_ADDRCONFIG is not defined well. we are not sure
10890Sstevel@tonic-gate * if the code is right or not.
10900Sstevel@tonic-gate */
10910Sstevel@tonic-gate static int
addrconfig(af)10920Sstevel@tonic-gate addrconfig(af)
10930Sstevel@tonic-gate int af;
10940Sstevel@tonic-gate {
10950Sstevel@tonic-gate int s;
10960Sstevel@tonic-gate
10970Sstevel@tonic-gate /* XXX errno */
10980Sstevel@tonic-gate s = socket(af, SOCK_DGRAM, 0);
10990Sstevel@tonic-gate if (s < 0) {
11000Sstevel@tonic-gate if (errno != EMFILE)
11010Sstevel@tonic-gate return 0;
11020Sstevel@tonic-gate } else
11030Sstevel@tonic-gate close(s);
11040Sstevel@tonic-gate return 1;
11050Sstevel@tonic-gate }
11060Sstevel@tonic-gate
11070Sstevel@tonic-gate /* convert a string to a scope identifier. XXX: IPv6 specific */
11080Sstevel@tonic-gate static int
ip6_str2scopeid(char * scope,struct sockaddr_in6 * sin6,u_int32_t * scopeidp)11090Sstevel@tonic-gate ip6_str2scopeid(char *scope, struct sockaddr_in6 *sin6,
11100Sstevel@tonic-gate u_int32_t *scopeidp)
11110Sstevel@tonic-gate {
11120Sstevel@tonic-gate u_int32_t scopeid;
11130Sstevel@tonic-gate u_long lscopeid;
11140Sstevel@tonic-gate struct in6_addr *a6 = &sin6->sin6_addr;
11150Sstevel@tonic-gate char *ep;
11160Sstevel@tonic-gate
11170Sstevel@tonic-gate /* empty scopeid portion is invalid */
11180Sstevel@tonic-gate if (*scope == '\0')
11190Sstevel@tonic-gate return (0);
11200Sstevel@tonic-gate
11210Sstevel@tonic-gate #ifdef USE_IFNAMELINKID
1122*11038SRao.Shoaib@Sun.COM if (IN6_IS_ADDR_LINKLOCAL(a6) || IN6_IS_ADDR_MC_LINKLOCAL(a6) ||
1123*11038SRao.Shoaib@Sun.COM IN6_IS_ADDR_MC_NODELOCAL(a6)) {
11240Sstevel@tonic-gate /*
11250Sstevel@tonic-gate * Using interface names as link indices can be allowed
11260Sstevel@tonic-gate * only when we can assume a one-to-one mappings between
11270Sstevel@tonic-gate * links and interfaces. See comments in getnameinfo.c.
11280Sstevel@tonic-gate */
11290Sstevel@tonic-gate scopeid = if_nametoindex(scope);
11300Sstevel@tonic-gate if (scopeid == 0)
11310Sstevel@tonic-gate goto trynumeric;
11320Sstevel@tonic-gate *scopeidp = scopeid;
11330Sstevel@tonic-gate return (1);
11340Sstevel@tonic-gate }
11350Sstevel@tonic-gate #endif
11360Sstevel@tonic-gate
11370Sstevel@tonic-gate /* still unclear about literal, allow numeric only - placeholder */
11380Sstevel@tonic-gate if (IN6_IS_ADDR_SITELOCAL(a6) || IN6_IS_ADDR_MC_SITELOCAL(a6))
11390Sstevel@tonic-gate goto trynumeric;
11400Sstevel@tonic-gate if (IN6_IS_ADDR_MC_ORGLOCAL(a6))
11410Sstevel@tonic-gate goto trynumeric;
11420Sstevel@tonic-gate else
1143*11038SRao.Shoaib@Sun.COM goto trynumeric; /*%< global */
11440Sstevel@tonic-gate /* try to convert to a numeric id as a last resort */
11450Sstevel@tonic-gate trynumeric:
11460Sstevel@tonic-gate errno = 0;
11470Sstevel@tonic-gate lscopeid = strtoul(scope, &ep, 10);
11480Sstevel@tonic-gate scopeid = lscopeid & 0xffffffff;
11490Sstevel@tonic-gate if (errno == 0 && ep && *ep == '\0' && scopeid == lscopeid) {
11500Sstevel@tonic-gate *scopeidp = scopeid;
11510Sstevel@tonic-gate return (1);
11520Sstevel@tonic-gate } else
11530Sstevel@tonic-gate return (0);
11540Sstevel@tonic-gate }
11550Sstevel@tonic-gate
11560Sstevel@tonic-gate struct addrinfo *
hostent2addrinfo(hp,pai)11570Sstevel@tonic-gate hostent2addrinfo(hp, pai)
11580Sstevel@tonic-gate struct hostent *hp;
11590Sstevel@tonic-gate const struct addrinfo *pai;
11600Sstevel@tonic-gate {
11610Sstevel@tonic-gate int i, af, error = 0;
11620Sstevel@tonic-gate char **aplist = NULL, *ap;
11630Sstevel@tonic-gate struct addrinfo sentinel, *cur;
11640Sstevel@tonic-gate const struct afd *afd;
11650Sstevel@tonic-gate
11660Sstevel@tonic-gate af = hp->h_addrtype;
11670Sstevel@tonic-gate if (pai->ai_family != AF_UNSPEC && af != pai->ai_family)
11680Sstevel@tonic-gate return(NULL);
11690Sstevel@tonic-gate
11700Sstevel@tonic-gate afd = find_afd(af);
11710Sstevel@tonic-gate if (afd == NULL)
11720Sstevel@tonic-gate return(NULL);
11730Sstevel@tonic-gate
11740Sstevel@tonic-gate aplist = hp->h_addr_list;
11750Sstevel@tonic-gate
11760Sstevel@tonic-gate memset(&sentinel, 0, sizeof(sentinel));
11770Sstevel@tonic-gate cur = &sentinel;
11780Sstevel@tonic-gate
11790Sstevel@tonic-gate for (i = 0; (ap = aplist[i]) != NULL; i++) {
1180*11038SRao.Shoaib@Sun.COM #if 0 /*%< the trick seems too much */
11810Sstevel@tonic-gate af = hp->h_addr_list;
11820Sstevel@tonic-gate if (af == AF_INET6 &&
11830Sstevel@tonic-gate IN6_IS_ADDR_V4MAPPED((struct in6_addr *)ap)) {
11840Sstevel@tonic-gate af = AF_INET;
11850Sstevel@tonic-gate ap = ap + sizeof(struct in6_addr)
11860Sstevel@tonic-gate - sizeof(struct in_addr);
11870Sstevel@tonic-gate }
11880Sstevel@tonic-gate afd = find_afd(af);
11890Sstevel@tonic-gate if (afd == NULL)
11900Sstevel@tonic-gate continue;
11910Sstevel@tonic-gate #endif /* 0 */
11920Sstevel@tonic-gate
11930Sstevel@tonic-gate GET_AI(cur->ai_next, afd, ap);
11940Sstevel@tonic-gate
11950Sstevel@tonic-gate /* GET_PORT(cur->ai_next, servname); */
11960Sstevel@tonic-gate if ((pai->ai_flags & AI_CANONNAME) != 0) {
11970Sstevel@tonic-gate /*
11980Sstevel@tonic-gate * RFC2553 says that ai_canonname will be set only for
11990Sstevel@tonic-gate * the first element. we do it for all the elements,
12000Sstevel@tonic-gate * just for convenience.
12010Sstevel@tonic-gate */
12020Sstevel@tonic-gate GET_CANONNAME(cur->ai_next, hp->h_name);
12030Sstevel@tonic-gate }
1204*11038SRao.Shoaib@Sun.COM while (cur->ai_next) /*%< no need to loop, actually. */
12050Sstevel@tonic-gate cur = cur->ai_next;
12060Sstevel@tonic-gate continue;
12070Sstevel@tonic-gate
12080Sstevel@tonic-gate free:
12090Sstevel@tonic-gate if (cur->ai_next)
12100Sstevel@tonic-gate freeaddrinfo(cur->ai_next);
12110Sstevel@tonic-gate cur->ai_next = NULL;
12120Sstevel@tonic-gate /* continue, without tht pointer CUR advanced. */
12130Sstevel@tonic-gate }
12140Sstevel@tonic-gate
12150Sstevel@tonic-gate return(sentinel.ai_next);
12160Sstevel@tonic-gate }
12170Sstevel@tonic-gate
12180Sstevel@tonic-gate struct addrinfo *
addr2addrinfo(pai,cp)12190Sstevel@tonic-gate addr2addrinfo(pai, cp)
12200Sstevel@tonic-gate const struct addrinfo *pai;
12210Sstevel@tonic-gate const char *cp;
12220Sstevel@tonic-gate {
12230Sstevel@tonic-gate const struct afd *afd;
12240Sstevel@tonic-gate
12250Sstevel@tonic-gate afd = find_afd(pai->ai_family);
12260Sstevel@tonic-gate if (afd == NULL)
12270Sstevel@tonic-gate return(NULL);
12280Sstevel@tonic-gate
12290Sstevel@tonic-gate return(get_ai(pai, afd, cp));
12300Sstevel@tonic-gate }
12310Sstevel@tonic-gate
12320Sstevel@tonic-gate static struct net_data *
init()12330Sstevel@tonic-gate init()
12340Sstevel@tonic-gate {
12350Sstevel@tonic-gate struct net_data *net_data;
12360Sstevel@tonic-gate
12370Sstevel@tonic-gate if (!(net_data = net_data_init(NULL)))
12380Sstevel@tonic-gate goto error;
12390Sstevel@tonic-gate if (!net_data->ho) {
12400Sstevel@tonic-gate net_data->ho = (*net_data->irs->ho_map)(net_data->irs);
12410Sstevel@tonic-gate if (!net_data->ho || !net_data->res) {
12420Sstevel@tonic-gate error:
12430Sstevel@tonic-gate errno = EIO;
12440Sstevel@tonic-gate if (net_data && net_data->res)
12450Sstevel@tonic-gate RES_SET_H_ERRNO(net_data->res, NETDB_INTERNAL);
12460Sstevel@tonic-gate return (NULL);
12470Sstevel@tonic-gate }
12480Sstevel@tonic-gate
12490Sstevel@tonic-gate (*net_data->ho->res_set)(net_data->ho, net_data->res, NULL);
12500Sstevel@tonic-gate }
12510Sstevel@tonic-gate
12520Sstevel@tonic-gate return (net_data);
12530Sstevel@tonic-gate }
1254