1*d56f51eaSDavid van Moolenbroek /*
2*d56f51eaSDavid van Moolenbroek * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
3*d56f51eaSDavid van Moolenbroek * All rights reserved.
4*d56f51eaSDavid van Moolenbroek *
5*d56f51eaSDavid van Moolenbroek * Redistribution and use in source and binary forms, with or without
6*d56f51eaSDavid van Moolenbroek * modification, are permitted provided that the following conditions
7*d56f51eaSDavid van Moolenbroek * are met:
8*d56f51eaSDavid van Moolenbroek * 1. Redistributions of source code must retain the above copyright
9*d56f51eaSDavid van Moolenbroek * notice, this list of conditions and the following disclaimer.
10*d56f51eaSDavid van Moolenbroek * 2. Redistributions in binary form must reproduce the above copyright
11*d56f51eaSDavid van Moolenbroek * notice, this list of conditions and the following disclaimer in the
12*d56f51eaSDavid van Moolenbroek * documentation and/or other materials provided with the distribution.
13*d56f51eaSDavid van Moolenbroek * 3. Neither the name of the project nor the names of its contributors
14*d56f51eaSDavid van Moolenbroek * may be used to endorse or promote products derived from this software
15*d56f51eaSDavid van Moolenbroek * without specific prior written permission.
16*d56f51eaSDavid van Moolenbroek *
17*d56f51eaSDavid van Moolenbroek * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
18*d56f51eaSDavid van Moolenbroek * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19*d56f51eaSDavid van Moolenbroek * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20*d56f51eaSDavid van Moolenbroek * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
21*d56f51eaSDavid van Moolenbroek * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22*d56f51eaSDavid van Moolenbroek * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23*d56f51eaSDavid van Moolenbroek * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24*d56f51eaSDavid van Moolenbroek * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25*d56f51eaSDavid van Moolenbroek * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26*d56f51eaSDavid van Moolenbroek * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27*d56f51eaSDavid van Moolenbroek * SUCH DAMAGE.
28*d56f51eaSDavid van Moolenbroek */
29*d56f51eaSDavid van Moolenbroek
30*d56f51eaSDavid van Moolenbroek /*
31*d56f51eaSDavid van Moolenbroek * "#ifdef FAITH" part is local hack for supporting IPv4-v6 translator.
32*d56f51eaSDavid van Moolenbroek *
33*d56f51eaSDavid van Moolenbroek * Issues to be discussed:
34*d56f51eaSDavid van Moolenbroek * - Thread safe-ness must be checked.
35*d56f51eaSDavid van Moolenbroek * - Return values. There are nonstandard return values defined and used
36*d56f51eaSDavid van Moolenbroek * in the source code. This is because RFC2553 is silent about which error
37*d56f51eaSDavid van Moolenbroek * code must be returned for which situation.
38*d56f51eaSDavid van Moolenbroek * Note:
39*d56f51eaSDavid van Moolenbroek * - We use getipnodebyname() just for thread-safeness. There's no intent
40*d56f51eaSDavid van Moolenbroek * to let it do PF_UNSPEC (actually we never pass PF_UNSPEC to
41*d56f51eaSDavid van Moolenbroek * getipnodebyname().
42*d56f51eaSDavid van Moolenbroek * - The code filters out AFs that are not supported by the kernel,
43*d56f51eaSDavid van Moolenbroek * when globbing NULL hostname (to loopback, or wildcard). Is it the right
44*d56f51eaSDavid van Moolenbroek * thing to do? What is the relationship with post-RFC2553 AI_ADDRCONFIG
45*d56f51eaSDavid van Moolenbroek * in ai_flags?
46*d56f51eaSDavid van Moolenbroek */
47*d56f51eaSDavid van Moolenbroek
48*d56f51eaSDavid van Moolenbroek /*
49*d56f51eaSDavid van Moolenbroek * Mingw64 has its own implementation of getaddrinfo, mingw32 no
50*d56f51eaSDavid van Moolenbroek */
51*d56f51eaSDavid van Moolenbroek #ifndef __MINGW64__
52*d56f51eaSDavid van Moolenbroek
53*d56f51eaSDavid van Moolenbroek
54*d56f51eaSDavid van Moolenbroek #ifdef HAVE_CONFIG_H
55*d56f51eaSDavid van Moolenbroek #include <config.h>
56*d56f51eaSDavid van Moolenbroek #endif
57*d56f51eaSDavid van Moolenbroek
58*d56f51eaSDavid van Moolenbroek #include <pcap-stdinc.h>
59*d56f51eaSDavid van Moolenbroek #if 0
60*d56f51eaSDavid van Moolenbroek #include <sys/sysctl.h>
61*d56f51eaSDavid van Moolenbroek #endif
62*d56f51eaSDavid van Moolenbroek #ifndef __MINGW32__
63*d56f51eaSDavid van Moolenbroek #include <arpa/nameser.h>
64*d56f51eaSDavid van Moolenbroek #endif
65*d56f51eaSDavid van Moolenbroek #include <string.h>
66*d56f51eaSDavid van Moolenbroek #include <stdlib.h>
67*d56f51eaSDavid van Moolenbroek #include <stddef.h>
68*d56f51eaSDavid van Moolenbroek #include <ctype.h>
69*d56f51eaSDavid van Moolenbroek #include <stdio.h>
70*d56f51eaSDavid van Moolenbroek #include <errno.h>
71*d56f51eaSDavid van Moolenbroek
72*d56f51eaSDavid van Moolenbroek #ifndef HAVE_PORTABLE_PROTOTYPE
73*d56f51eaSDavid van Moolenbroek #include "cdecl_ext.h"
74*d56f51eaSDavid van Moolenbroek #endif
75*d56f51eaSDavid van Moolenbroek
76*d56f51eaSDavid van Moolenbroek #ifndef HAVE_U_INT32_T
77*d56f51eaSDavid van Moolenbroek #include "bittypes.h"
78*d56f51eaSDavid van Moolenbroek #endif
79*d56f51eaSDavid van Moolenbroek
80*d56f51eaSDavid van Moolenbroek #ifndef HAVE_SOCKADDR_STORAGE
81*d56f51eaSDavid van Moolenbroek #ifndef __MINGW32__
82*d56f51eaSDavid van Moolenbroek #include "sockstorage.h"
83*d56f51eaSDavid van Moolenbroek #endif
84*d56f51eaSDavid van Moolenbroek #endif
85*d56f51eaSDavid van Moolenbroek
86*d56f51eaSDavid van Moolenbroek #ifdef NEED_ADDRINFO_H
87*d56f51eaSDavid van Moolenbroek #include "addrinfo.h"
88*d56f51eaSDavid van Moolenbroek #ifdef WIN32
89*d56f51eaSDavid van Moolenbroek #include "ip6_misc.h"
90*d56f51eaSDavid van Moolenbroek #endif
91*d56f51eaSDavid van Moolenbroek #endif
92*d56f51eaSDavid van Moolenbroek
93*d56f51eaSDavid van Moolenbroek
94*d56f51eaSDavid van Moolenbroek #if defined(__KAME__) && defined(INET6)
95*d56f51eaSDavid van Moolenbroek # define FAITH
96*d56f51eaSDavid van Moolenbroek #endif
97*d56f51eaSDavid van Moolenbroek
98*d56f51eaSDavid van Moolenbroek #define SUCCESS 0
99*d56f51eaSDavid van Moolenbroek #define ANY 0
100*d56f51eaSDavid van Moolenbroek #define YES 1
101*d56f51eaSDavid van Moolenbroek #define NO 0
102*d56f51eaSDavid van Moolenbroek
103*d56f51eaSDavid van Moolenbroek #ifdef FAITH
104*d56f51eaSDavid van Moolenbroek static int translate = NO;
105*d56f51eaSDavid van Moolenbroek static struct in6_addr faith_prefix = IN6ADDR_ANY_INIT;
106*d56f51eaSDavid van Moolenbroek #endif
107*d56f51eaSDavid van Moolenbroek
108*d56f51eaSDavid van Moolenbroek static const char in_addrany[] = { 0, 0, 0, 0 };
109*d56f51eaSDavid van Moolenbroek static const char in6_addrany[] = {
110*d56f51eaSDavid van Moolenbroek 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
111*d56f51eaSDavid van Moolenbroek };
112*d56f51eaSDavid van Moolenbroek static const char in_loopback[] = { 127, 0, 0, 1 };
113*d56f51eaSDavid van Moolenbroek static const char in6_loopback[] = {
114*d56f51eaSDavid van Moolenbroek 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
115*d56f51eaSDavid van Moolenbroek };
116*d56f51eaSDavid van Moolenbroek
117*d56f51eaSDavid van Moolenbroek struct sockinet {
118*d56f51eaSDavid van Moolenbroek u_char si_len;
119*d56f51eaSDavid van Moolenbroek u_char si_family;
120*d56f51eaSDavid van Moolenbroek u_short si_port;
121*d56f51eaSDavid van Moolenbroek u_int32_t si_scope_id;
122*d56f51eaSDavid van Moolenbroek };
123*d56f51eaSDavid van Moolenbroek
124*d56f51eaSDavid van Moolenbroek static const struct afd {
125*d56f51eaSDavid van Moolenbroek int a_af;
126*d56f51eaSDavid van Moolenbroek int a_addrlen;
127*d56f51eaSDavid van Moolenbroek int a_socklen;
128*d56f51eaSDavid van Moolenbroek int a_off;
129*d56f51eaSDavid van Moolenbroek const char *a_addrany;
130*d56f51eaSDavid van Moolenbroek const char *a_loopback;
131*d56f51eaSDavid van Moolenbroek int a_scoped;
132*d56f51eaSDavid van Moolenbroek } afdl [] = {
133*d56f51eaSDavid van Moolenbroek #ifdef INET6
134*d56f51eaSDavid van Moolenbroek {PF_INET6, sizeof(struct in6_addr),
135*d56f51eaSDavid van Moolenbroek sizeof(struct sockaddr_in6),
136*d56f51eaSDavid van Moolenbroek offsetof(struct sockaddr_in6, sin6_addr),
137*d56f51eaSDavid van Moolenbroek in6_addrany, in6_loopback, 1},
138*d56f51eaSDavid van Moolenbroek #endif
139*d56f51eaSDavid van Moolenbroek {PF_INET, sizeof(struct in_addr),
140*d56f51eaSDavid van Moolenbroek sizeof(struct sockaddr_in),
141*d56f51eaSDavid van Moolenbroek offsetof(struct sockaddr_in, sin_addr),
142*d56f51eaSDavid van Moolenbroek in_addrany, in_loopback, 0},
143*d56f51eaSDavid van Moolenbroek {0, 0, 0, 0, NULL, NULL, 0},
144*d56f51eaSDavid van Moolenbroek };
145*d56f51eaSDavid van Moolenbroek
146*d56f51eaSDavid van Moolenbroek struct explore {
147*d56f51eaSDavid van Moolenbroek int e_af;
148*d56f51eaSDavid van Moolenbroek int e_socktype;
149*d56f51eaSDavid van Moolenbroek int e_protocol;
150*d56f51eaSDavid van Moolenbroek const char *e_protostr;
151*d56f51eaSDavid van Moolenbroek int e_wild;
152*d56f51eaSDavid van Moolenbroek #define WILD_AF(ex) ((ex)->e_wild & 0x01)
153*d56f51eaSDavid van Moolenbroek #define WILD_SOCKTYPE(ex) ((ex)->e_wild & 0x02)
154*d56f51eaSDavid van Moolenbroek #define WILD_PROTOCOL(ex) ((ex)->e_wild & 0x04)
155*d56f51eaSDavid van Moolenbroek };
156*d56f51eaSDavid van Moolenbroek
157*d56f51eaSDavid van Moolenbroek static const struct explore explore[] = {
158*d56f51eaSDavid van Moolenbroek #if 0
159*d56f51eaSDavid van Moolenbroek { PF_LOCAL, 0, ANY, ANY, NULL, 0x01 },
160*d56f51eaSDavid van Moolenbroek #endif
161*d56f51eaSDavid van Moolenbroek #ifdef INET6
162*d56f51eaSDavid van Moolenbroek { PF_INET6, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
163*d56f51eaSDavid van Moolenbroek { PF_INET6, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
164*d56f51eaSDavid van Moolenbroek { PF_INET6, SOCK_RAW, ANY, NULL, 0x05 },
165*d56f51eaSDavid van Moolenbroek #endif
166*d56f51eaSDavid van Moolenbroek { PF_INET, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
167*d56f51eaSDavid van Moolenbroek { PF_INET, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
168*d56f51eaSDavid van Moolenbroek { PF_INET, SOCK_RAW, ANY, NULL, 0x05 },
169*d56f51eaSDavid van Moolenbroek { -1, 0, 0, NULL, 0 },
170*d56f51eaSDavid van Moolenbroek };
171*d56f51eaSDavid van Moolenbroek
172*d56f51eaSDavid van Moolenbroek #ifdef INET6
173*d56f51eaSDavid van Moolenbroek #define PTON_MAX 16
174*d56f51eaSDavid van Moolenbroek #else
175*d56f51eaSDavid van Moolenbroek #define PTON_MAX 4
176*d56f51eaSDavid van Moolenbroek #endif
177*d56f51eaSDavid van Moolenbroek
178*d56f51eaSDavid van Moolenbroek
179*d56f51eaSDavid van Moolenbroek static int str_isnumber __P((const char *));
180*d56f51eaSDavid van Moolenbroek static int explore_fqdn __P((const struct addrinfo *, const char *,
181*d56f51eaSDavid van Moolenbroek const char *, struct addrinfo **));
182*d56f51eaSDavid van Moolenbroek static int explore_null __P((const struct addrinfo *, const char *,
183*d56f51eaSDavid van Moolenbroek const char *, struct addrinfo **));
184*d56f51eaSDavid van Moolenbroek static int explore_numeric __P((const struct addrinfo *, const char *,
185*d56f51eaSDavid van Moolenbroek const char *, struct addrinfo **));
186*d56f51eaSDavid van Moolenbroek static int explore_numeric_scope __P((const struct addrinfo *, const char *,
187*d56f51eaSDavid van Moolenbroek const char *, struct addrinfo **));
188*d56f51eaSDavid van Moolenbroek static int get_name __P((const char *, const struct afd *, struct addrinfo **,
189*d56f51eaSDavid van Moolenbroek char *, const struct addrinfo *, const char *));
190*d56f51eaSDavid van Moolenbroek static int get_canonname __P((const struct addrinfo *,
191*d56f51eaSDavid van Moolenbroek struct addrinfo *, const char *));
192*d56f51eaSDavid van Moolenbroek static struct addrinfo *get_ai __P((const struct addrinfo *,
193*d56f51eaSDavid van Moolenbroek const struct afd *, const char *));
194*d56f51eaSDavid van Moolenbroek static int get_portmatch __P((const struct addrinfo *, const char *));
195*d56f51eaSDavid van Moolenbroek static int get_port __P((struct addrinfo *, const char *, int));
196*d56f51eaSDavid van Moolenbroek static const struct afd *find_afd __P((int));
197*d56f51eaSDavid van Moolenbroek
198*d56f51eaSDavid van Moolenbroek static char *ai_errlist[] = {
199*d56f51eaSDavid van Moolenbroek "Success",
200*d56f51eaSDavid van Moolenbroek "Address family for hostname not supported", /* EAI_ADDRFAMILY */
201*d56f51eaSDavid van Moolenbroek "Temporary failure in name resolution", /* EAI_AGAIN */
202*d56f51eaSDavid van Moolenbroek "Invalid value for ai_flags", /* EAI_BADFLAGS */
203*d56f51eaSDavid van Moolenbroek "Non-recoverable failure in name resolution", /* EAI_FAIL */
204*d56f51eaSDavid van Moolenbroek "ai_family not supported", /* EAI_FAMILY */
205*d56f51eaSDavid van Moolenbroek "Memory allocation failure", /* EAI_MEMORY */
206*d56f51eaSDavid van Moolenbroek "No address associated with hostname", /* EAI_NODATA */
207*d56f51eaSDavid van Moolenbroek "hostname nor servname provided, or not known", /* EAI_NONAME */
208*d56f51eaSDavid van Moolenbroek "servname not supported for ai_socktype", /* EAI_SERVICE */
209*d56f51eaSDavid van Moolenbroek "ai_socktype not supported", /* EAI_SOCKTYPE */
210*d56f51eaSDavid van Moolenbroek "System error returned in errno", /* EAI_SYSTEM */
211*d56f51eaSDavid van Moolenbroek "Invalid value for hints", /* EAI_BADHINTS */
212*d56f51eaSDavid van Moolenbroek "Resolved protocol is unknown", /* EAI_PROTOCOL */
213*d56f51eaSDavid van Moolenbroek "Unknown error", /* EAI_MAX */
214*d56f51eaSDavid van Moolenbroek };
215*d56f51eaSDavid van Moolenbroek
216*d56f51eaSDavid van Moolenbroek /* XXX macros that make external reference is BAD. */
217*d56f51eaSDavid van Moolenbroek
218*d56f51eaSDavid van Moolenbroek #define GET_AI(ai, afd, addr) \
219*d56f51eaSDavid van Moolenbroek do { \
220*d56f51eaSDavid van Moolenbroek /* external reference: pai, error, and label free */ \
221*d56f51eaSDavid van Moolenbroek (ai) = get_ai(pai, (afd), (addr)); \
222*d56f51eaSDavid van Moolenbroek if ((ai) == NULL) { \
223*d56f51eaSDavid van Moolenbroek error = EAI_MEMORY; \
224*d56f51eaSDavid van Moolenbroek goto free; \
225*d56f51eaSDavid van Moolenbroek } \
226*d56f51eaSDavid van Moolenbroek } while (0)
227*d56f51eaSDavid van Moolenbroek
228*d56f51eaSDavid van Moolenbroek #define GET_PORT(ai, serv) \
229*d56f51eaSDavid van Moolenbroek do { \
230*d56f51eaSDavid van Moolenbroek /* external reference: error and label free */ \
231*d56f51eaSDavid van Moolenbroek error = get_port((ai), (serv), 0); \
232*d56f51eaSDavid van Moolenbroek if (error != 0) \
233*d56f51eaSDavid van Moolenbroek goto free; \
234*d56f51eaSDavid van Moolenbroek } while (0)
235*d56f51eaSDavid van Moolenbroek
236*d56f51eaSDavid van Moolenbroek #define GET_CANONNAME(ai, str) \
237*d56f51eaSDavid van Moolenbroek do { \
238*d56f51eaSDavid van Moolenbroek /* external reference: pai, error and label free */ \
239*d56f51eaSDavid van Moolenbroek error = get_canonname(pai, (ai), (str)); \
240*d56f51eaSDavid van Moolenbroek if (error != 0) \
241*d56f51eaSDavid van Moolenbroek goto free; \
242*d56f51eaSDavid van Moolenbroek } while (0)
243*d56f51eaSDavid van Moolenbroek
244*d56f51eaSDavid van Moolenbroek #define ERR(err) \
245*d56f51eaSDavid van Moolenbroek do { \
246*d56f51eaSDavid van Moolenbroek /* external reference: error, and label bad */ \
247*d56f51eaSDavid van Moolenbroek error = (err); \
248*d56f51eaSDavid van Moolenbroek goto bad; \
249*d56f51eaSDavid van Moolenbroek } while (0)
250*d56f51eaSDavid van Moolenbroek
251*d56f51eaSDavid van Moolenbroek #define MATCH_FAMILY(x, y, w) \
252*d56f51eaSDavid van Moolenbroek ((x) == (y) || ((w) && ((x) == PF_UNSPEC || (y) == PF_UNSPEC)))
253*d56f51eaSDavid van Moolenbroek #define MATCH(x, y, w) \
254*d56f51eaSDavid van Moolenbroek ((x) == (y) || ((w) && ((x) == ANY || (y) == ANY)))
255*d56f51eaSDavid van Moolenbroek
256*d56f51eaSDavid van Moolenbroek #if defined(DEFINE_ADDITIONAL_IPV6_STUFF)
257*d56f51eaSDavid van Moolenbroek char *
gai_strerror(ecode)258*d56f51eaSDavid van Moolenbroek gai_strerror(ecode)
259*d56f51eaSDavid van Moolenbroek int ecode;
260*d56f51eaSDavid van Moolenbroek {
261*d56f51eaSDavid van Moolenbroek if (ecode < 0 || ecode > EAI_MAX)
262*d56f51eaSDavid van Moolenbroek ecode = EAI_MAX;
263*d56f51eaSDavid van Moolenbroek return ai_errlist[ecode];
264*d56f51eaSDavid van Moolenbroek }
265*d56f51eaSDavid van Moolenbroek #endif
266*d56f51eaSDavid van Moolenbroek
267*d56f51eaSDavid van Moolenbroek void
freeaddrinfo(ai)268*d56f51eaSDavid van Moolenbroek freeaddrinfo(ai)
269*d56f51eaSDavid van Moolenbroek struct addrinfo *ai;
270*d56f51eaSDavid van Moolenbroek {
271*d56f51eaSDavid van Moolenbroek struct addrinfo *next;
272*d56f51eaSDavid van Moolenbroek
273*d56f51eaSDavid van Moolenbroek do {
274*d56f51eaSDavid van Moolenbroek next = ai->ai_next;
275*d56f51eaSDavid van Moolenbroek if (ai->ai_canonname)
276*d56f51eaSDavid van Moolenbroek free(ai->ai_canonname);
277*d56f51eaSDavid van Moolenbroek /* no need to free(ai->ai_addr) */
278*d56f51eaSDavid van Moolenbroek free(ai);
279*d56f51eaSDavid van Moolenbroek } while ((ai = next) != NULL);
280*d56f51eaSDavid van Moolenbroek }
281*d56f51eaSDavid van Moolenbroek
282*d56f51eaSDavid van Moolenbroek static int
str_isnumber(p)283*d56f51eaSDavid van Moolenbroek str_isnumber(p)
284*d56f51eaSDavid van Moolenbroek const char *p;
285*d56f51eaSDavid van Moolenbroek {
286*d56f51eaSDavid van Moolenbroek char *q = (char *)p;
287*d56f51eaSDavid van Moolenbroek while (*q) {
288*d56f51eaSDavid van Moolenbroek if (! isdigit(*q))
289*d56f51eaSDavid van Moolenbroek return NO;
290*d56f51eaSDavid van Moolenbroek q++;
291*d56f51eaSDavid van Moolenbroek }
292*d56f51eaSDavid van Moolenbroek return YES;
293*d56f51eaSDavid van Moolenbroek }
294*d56f51eaSDavid van Moolenbroek
295*d56f51eaSDavid van Moolenbroek int
getaddrinfo(hostname,servname,hints,res)296*d56f51eaSDavid van Moolenbroek getaddrinfo(hostname, servname, hints, res)
297*d56f51eaSDavid van Moolenbroek const char *hostname, *servname;
298*d56f51eaSDavid van Moolenbroek const struct addrinfo *hints;
299*d56f51eaSDavid van Moolenbroek struct addrinfo **res;
300*d56f51eaSDavid van Moolenbroek {
301*d56f51eaSDavid van Moolenbroek struct addrinfo sentinel;
302*d56f51eaSDavid van Moolenbroek struct addrinfo *cur;
303*d56f51eaSDavid van Moolenbroek int error = 0;
304*d56f51eaSDavid van Moolenbroek struct addrinfo ai;
305*d56f51eaSDavid van Moolenbroek struct addrinfo ai0;
306*d56f51eaSDavid van Moolenbroek struct addrinfo *pai;
307*d56f51eaSDavid van Moolenbroek const struct afd *afd;
308*d56f51eaSDavid van Moolenbroek const struct explore *ex;
309*d56f51eaSDavid van Moolenbroek
310*d56f51eaSDavid van Moolenbroek #ifdef FAITH
311*d56f51eaSDavid van Moolenbroek static int firsttime = 1;
312*d56f51eaSDavid van Moolenbroek
313*d56f51eaSDavid van Moolenbroek if (firsttime) {
314*d56f51eaSDavid van Moolenbroek /* translator hack */
315*d56f51eaSDavid van Moolenbroek char *q = getenv("GAI");
316*d56f51eaSDavid van Moolenbroek if (q && inet_pton(AF_INET6, q, &faith_prefix) == 1)
317*d56f51eaSDavid van Moolenbroek translate = YES;
318*d56f51eaSDavid van Moolenbroek firsttime = 0;
319*d56f51eaSDavid van Moolenbroek }
320*d56f51eaSDavid van Moolenbroek #endif
321*d56f51eaSDavid van Moolenbroek
322*d56f51eaSDavid van Moolenbroek sentinel.ai_next = NULL;
323*d56f51eaSDavid van Moolenbroek cur = &sentinel;
324*d56f51eaSDavid van Moolenbroek pai = &ai;
325*d56f51eaSDavid van Moolenbroek pai->ai_flags = 0;
326*d56f51eaSDavid van Moolenbroek pai->ai_family = PF_UNSPEC;
327*d56f51eaSDavid van Moolenbroek pai->ai_socktype = ANY;
328*d56f51eaSDavid van Moolenbroek pai->ai_protocol = ANY;
329*d56f51eaSDavid van Moolenbroek pai->ai_addrlen = 0;
330*d56f51eaSDavid van Moolenbroek pai->ai_canonname = NULL;
331*d56f51eaSDavid van Moolenbroek pai->ai_addr = NULL;
332*d56f51eaSDavid van Moolenbroek pai->ai_next = NULL;
333*d56f51eaSDavid van Moolenbroek
334*d56f51eaSDavid van Moolenbroek if (hostname == NULL && servname == NULL)
335*d56f51eaSDavid van Moolenbroek return EAI_NONAME;
336*d56f51eaSDavid van Moolenbroek if (hints) {
337*d56f51eaSDavid van Moolenbroek /* error check for hints */
338*d56f51eaSDavid van Moolenbroek if (hints->ai_addrlen || hints->ai_canonname ||
339*d56f51eaSDavid van Moolenbroek hints->ai_addr || hints->ai_next)
340*d56f51eaSDavid van Moolenbroek ERR(EAI_BADHINTS); /* xxx */
341*d56f51eaSDavid van Moolenbroek if (hints->ai_flags & ~AI_MASK)
342*d56f51eaSDavid van Moolenbroek ERR(EAI_BADFLAGS);
343*d56f51eaSDavid van Moolenbroek switch (hints->ai_family) {
344*d56f51eaSDavid van Moolenbroek case PF_UNSPEC:
345*d56f51eaSDavid van Moolenbroek case PF_INET:
346*d56f51eaSDavid van Moolenbroek #ifdef INET6
347*d56f51eaSDavid van Moolenbroek case PF_INET6:
348*d56f51eaSDavid van Moolenbroek #endif
349*d56f51eaSDavid van Moolenbroek break;
350*d56f51eaSDavid van Moolenbroek default:
351*d56f51eaSDavid van Moolenbroek ERR(EAI_FAMILY);
352*d56f51eaSDavid van Moolenbroek }
353*d56f51eaSDavid van Moolenbroek memcpy(pai, hints, sizeof(*pai));
354*d56f51eaSDavid van Moolenbroek
355*d56f51eaSDavid van Moolenbroek /*
356*d56f51eaSDavid van Moolenbroek * if both socktype/protocol are specified, check if they
357*d56f51eaSDavid van Moolenbroek * are meaningful combination.
358*d56f51eaSDavid van Moolenbroek */
359*d56f51eaSDavid van Moolenbroek if (pai->ai_socktype != ANY && pai->ai_protocol != ANY) {
360*d56f51eaSDavid van Moolenbroek for (ex = explore; ex->e_af >= 0; ex++) {
361*d56f51eaSDavid van Moolenbroek if (pai->ai_family != ex->e_af)
362*d56f51eaSDavid van Moolenbroek continue;
363*d56f51eaSDavid van Moolenbroek if (ex->e_socktype == ANY)
364*d56f51eaSDavid van Moolenbroek continue;
365*d56f51eaSDavid van Moolenbroek if (ex->e_protocol == ANY)
366*d56f51eaSDavid van Moolenbroek continue;
367*d56f51eaSDavid van Moolenbroek if (pai->ai_socktype == ex->e_socktype
368*d56f51eaSDavid van Moolenbroek && pai->ai_protocol != ex->e_protocol) {
369*d56f51eaSDavid van Moolenbroek ERR(EAI_BADHINTS);
370*d56f51eaSDavid van Moolenbroek }
371*d56f51eaSDavid van Moolenbroek }
372*d56f51eaSDavid van Moolenbroek }
373*d56f51eaSDavid van Moolenbroek }
374*d56f51eaSDavid van Moolenbroek
375*d56f51eaSDavid van Moolenbroek /*
376*d56f51eaSDavid van Moolenbroek * check for special cases. (1) numeric servname is disallowed if
377*d56f51eaSDavid van Moolenbroek * socktype/protocol are left unspecified. (2) servname is disallowed
378*d56f51eaSDavid van Moolenbroek * for raw and other inet{,6} sockets.
379*d56f51eaSDavid van Moolenbroek */
380*d56f51eaSDavid van Moolenbroek if (MATCH_FAMILY(pai->ai_family, PF_INET, 1)
381*d56f51eaSDavid van Moolenbroek #ifdef PF_INET6
382*d56f51eaSDavid van Moolenbroek || MATCH_FAMILY(pai->ai_family, PF_INET6, 1)
383*d56f51eaSDavid van Moolenbroek #endif
384*d56f51eaSDavid van Moolenbroek ) {
385*d56f51eaSDavid van Moolenbroek ai0 = *pai;
386*d56f51eaSDavid van Moolenbroek
387*d56f51eaSDavid van Moolenbroek if (pai->ai_family == PF_UNSPEC) {
388*d56f51eaSDavid van Moolenbroek #ifdef PF_INET6
389*d56f51eaSDavid van Moolenbroek pai->ai_family = PF_INET6;
390*d56f51eaSDavid van Moolenbroek #else
391*d56f51eaSDavid van Moolenbroek pai->ai_family = PF_INET;
392*d56f51eaSDavid van Moolenbroek #endif
393*d56f51eaSDavid van Moolenbroek }
394*d56f51eaSDavid van Moolenbroek error = get_portmatch(pai, servname);
395*d56f51eaSDavid van Moolenbroek if (error)
396*d56f51eaSDavid van Moolenbroek ERR(error);
397*d56f51eaSDavid van Moolenbroek
398*d56f51eaSDavid van Moolenbroek *pai = ai0;
399*d56f51eaSDavid van Moolenbroek }
400*d56f51eaSDavid van Moolenbroek
401*d56f51eaSDavid van Moolenbroek ai0 = *pai;
402*d56f51eaSDavid van Moolenbroek
403*d56f51eaSDavid van Moolenbroek /* NULL hostname, or numeric hostname */
404*d56f51eaSDavid van Moolenbroek for (ex = explore; ex->e_af >= 0; ex++) {
405*d56f51eaSDavid van Moolenbroek *pai = ai0;
406*d56f51eaSDavid van Moolenbroek
407*d56f51eaSDavid van Moolenbroek if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex)))
408*d56f51eaSDavid van Moolenbroek continue;
409*d56f51eaSDavid van Moolenbroek if (!MATCH(pai->ai_socktype, ex->e_socktype, WILD_SOCKTYPE(ex)))
410*d56f51eaSDavid van Moolenbroek continue;
411*d56f51eaSDavid van Moolenbroek if (!MATCH(pai->ai_protocol, ex->e_protocol, WILD_PROTOCOL(ex)))
412*d56f51eaSDavid van Moolenbroek continue;
413*d56f51eaSDavid van Moolenbroek
414*d56f51eaSDavid van Moolenbroek if (pai->ai_family == PF_UNSPEC)
415*d56f51eaSDavid van Moolenbroek pai->ai_family = ex->e_af;
416*d56f51eaSDavid van Moolenbroek if (pai->ai_socktype == ANY && ex->e_socktype != ANY)
417*d56f51eaSDavid van Moolenbroek pai->ai_socktype = ex->e_socktype;
418*d56f51eaSDavid van Moolenbroek if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
419*d56f51eaSDavid van Moolenbroek pai->ai_protocol = ex->e_protocol;
420*d56f51eaSDavid van Moolenbroek
421*d56f51eaSDavid van Moolenbroek if (hostname == NULL)
422*d56f51eaSDavid van Moolenbroek error = explore_null(pai, hostname, servname, &cur->ai_next);
423*d56f51eaSDavid van Moolenbroek else
424*d56f51eaSDavid van Moolenbroek error = explore_numeric_scope(pai, hostname, servname, &cur->ai_next);
425*d56f51eaSDavid van Moolenbroek
426*d56f51eaSDavid van Moolenbroek if (error)
427*d56f51eaSDavid van Moolenbroek goto free;
428*d56f51eaSDavid van Moolenbroek
429*d56f51eaSDavid van Moolenbroek while (cur && cur->ai_next)
430*d56f51eaSDavid van Moolenbroek cur = cur->ai_next;
431*d56f51eaSDavid van Moolenbroek }
432*d56f51eaSDavid van Moolenbroek
433*d56f51eaSDavid van Moolenbroek /*
434*d56f51eaSDavid van Moolenbroek * XXX
435*d56f51eaSDavid van Moolenbroek * If numreic representation of AF1 can be interpreted as FQDN
436*d56f51eaSDavid van Moolenbroek * representation of AF2, we need to think again about the code below.
437*d56f51eaSDavid van Moolenbroek */
438*d56f51eaSDavid van Moolenbroek if (sentinel.ai_next)
439*d56f51eaSDavid van Moolenbroek goto good;
440*d56f51eaSDavid van Moolenbroek
441*d56f51eaSDavid van Moolenbroek if (pai->ai_flags & AI_NUMERICHOST)
442*d56f51eaSDavid van Moolenbroek ERR(EAI_NONAME);
443*d56f51eaSDavid van Moolenbroek if (hostname == NULL)
444*d56f51eaSDavid van Moolenbroek ERR(EAI_NONAME);
445*d56f51eaSDavid van Moolenbroek
446*d56f51eaSDavid van Moolenbroek /*
447*d56f51eaSDavid van Moolenbroek * hostname as alphabetical name.
448*d56f51eaSDavid van Moolenbroek * we would like to prefer AF_INET6 than AF_INET, so we'll make a
449*d56f51eaSDavid van Moolenbroek * outer loop by AFs.
450*d56f51eaSDavid van Moolenbroek */
451*d56f51eaSDavid van Moolenbroek for (afd = afdl; afd->a_af; afd++) {
452*d56f51eaSDavid van Moolenbroek *pai = ai0;
453*d56f51eaSDavid van Moolenbroek
454*d56f51eaSDavid van Moolenbroek if (!MATCH_FAMILY(pai->ai_family, afd->a_af, 1))
455*d56f51eaSDavid van Moolenbroek continue;
456*d56f51eaSDavid van Moolenbroek
457*d56f51eaSDavid van Moolenbroek for (ex = explore; ex->e_af >= 0; ex++) {
458*d56f51eaSDavid van Moolenbroek *pai = ai0;
459*d56f51eaSDavid van Moolenbroek
460*d56f51eaSDavid van Moolenbroek if (pai->ai_family == PF_UNSPEC)
461*d56f51eaSDavid van Moolenbroek pai->ai_family = afd->a_af;
462*d56f51eaSDavid van Moolenbroek
463*d56f51eaSDavid van Moolenbroek if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex)))
464*d56f51eaSDavid van Moolenbroek continue;
465*d56f51eaSDavid van Moolenbroek if (!MATCH(pai->ai_socktype, ex->e_socktype,
466*d56f51eaSDavid van Moolenbroek WILD_SOCKTYPE(ex))) {
467*d56f51eaSDavid van Moolenbroek continue;
468*d56f51eaSDavid van Moolenbroek }
469*d56f51eaSDavid van Moolenbroek if (!MATCH(pai->ai_protocol, ex->e_protocol,
470*d56f51eaSDavid van Moolenbroek WILD_PROTOCOL(ex))) {
471*d56f51eaSDavid van Moolenbroek continue;
472*d56f51eaSDavid van Moolenbroek }
473*d56f51eaSDavid van Moolenbroek
474*d56f51eaSDavid van Moolenbroek if (pai->ai_family == PF_UNSPEC)
475*d56f51eaSDavid van Moolenbroek pai->ai_family = ex->e_af;
476*d56f51eaSDavid van Moolenbroek if (pai->ai_socktype == ANY && ex->e_socktype != ANY)
477*d56f51eaSDavid van Moolenbroek pai->ai_socktype = ex->e_socktype;
478*d56f51eaSDavid van Moolenbroek if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
479*d56f51eaSDavid van Moolenbroek pai->ai_protocol = ex->e_protocol;
480*d56f51eaSDavid van Moolenbroek
481*d56f51eaSDavid van Moolenbroek error = explore_fqdn(pai, hostname, servname,
482*d56f51eaSDavid van Moolenbroek &cur->ai_next);
483*d56f51eaSDavid van Moolenbroek
484*d56f51eaSDavid van Moolenbroek while (cur && cur->ai_next)
485*d56f51eaSDavid van Moolenbroek cur = cur->ai_next;
486*d56f51eaSDavid van Moolenbroek }
487*d56f51eaSDavid van Moolenbroek }
488*d56f51eaSDavid van Moolenbroek
489*d56f51eaSDavid van Moolenbroek /* XXX */
490*d56f51eaSDavid van Moolenbroek if (sentinel.ai_next)
491*d56f51eaSDavid van Moolenbroek error = 0;
492*d56f51eaSDavid van Moolenbroek
493*d56f51eaSDavid van Moolenbroek if (error)
494*d56f51eaSDavid van Moolenbroek goto free;
495*d56f51eaSDavid van Moolenbroek if (error == 0) {
496*d56f51eaSDavid van Moolenbroek if (sentinel.ai_next) {
497*d56f51eaSDavid van Moolenbroek good:
498*d56f51eaSDavid van Moolenbroek *res = sentinel.ai_next;
499*d56f51eaSDavid van Moolenbroek return SUCCESS;
500*d56f51eaSDavid van Moolenbroek } else
501*d56f51eaSDavid van Moolenbroek error = EAI_FAIL;
502*d56f51eaSDavid van Moolenbroek }
503*d56f51eaSDavid van Moolenbroek free:
504*d56f51eaSDavid van Moolenbroek bad:
505*d56f51eaSDavid van Moolenbroek if (sentinel.ai_next)
506*d56f51eaSDavid van Moolenbroek freeaddrinfo(sentinel.ai_next);
507*d56f51eaSDavid van Moolenbroek *res = NULL;
508*d56f51eaSDavid van Moolenbroek return error;
509*d56f51eaSDavid van Moolenbroek }
510*d56f51eaSDavid van Moolenbroek
511*d56f51eaSDavid van Moolenbroek /*
512*d56f51eaSDavid van Moolenbroek * FQDN hostname, DNS lookup
513*d56f51eaSDavid van Moolenbroek */
514*d56f51eaSDavid van Moolenbroek static int
explore_fqdn(pai,hostname,servname,res)515*d56f51eaSDavid van Moolenbroek explore_fqdn(pai, hostname, servname, res)
516*d56f51eaSDavid van Moolenbroek const struct addrinfo *pai;
517*d56f51eaSDavid van Moolenbroek const char *hostname;
518*d56f51eaSDavid van Moolenbroek const char *servname;
519*d56f51eaSDavid van Moolenbroek struct addrinfo **res;
520*d56f51eaSDavid van Moolenbroek {
521*d56f51eaSDavid van Moolenbroek struct hostent *hp;
522*d56f51eaSDavid van Moolenbroek int h_error;
523*d56f51eaSDavid van Moolenbroek int af;
524*d56f51eaSDavid van Moolenbroek char **aplist = NULL, *apbuf = NULL;
525*d56f51eaSDavid van Moolenbroek char *ap;
526*d56f51eaSDavid van Moolenbroek struct addrinfo sentinel, *cur;
527*d56f51eaSDavid van Moolenbroek int i;
528*d56f51eaSDavid van Moolenbroek #ifndef USE_GETIPNODEBY
529*d56f51eaSDavid van Moolenbroek int naddrs;
530*d56f51eaSDavid van Moolenbroek #endif
531*d56f51eaSDavid van Moolenbroek const struct afd *afd;
532*d56f51eaSDavid van Moolenbroek int error;
533*d56f51eaSDavid van Moolenbroek
534*d56f51eaSDavid van Moolenbroek *res = NULL;
535*d56f51eaSDavid van Moolenbroek sentinel.ai_next = NULL;
536*d56f51eaSDavid van Moolenbroek cur = &sentinel;
537*d56f51eaSDavid van Moolenbroek
538*d56f51eaSDavid van Moolenbroek /*
539*d56f51eaSDavid van Moolenbroek * Do not filter unsupported AFs here. We need to honor content of
540*d56f51eaSDavid van Moolenbroek * databases (/etc/hosts, DNS and others). Otherwise we cannot
541*d56f51eaSDavid van Moolenbroek * replace gethostbyname() by getaddrinfo().
542*d56f51eaSDavid van Moolenbroek */
543*d56f51eaSDavid van Moolenbroek
544*d56f51eaSDavid van Moolenbroek /*
545*d56f51eaSDavid van Moolenbroek * if the servname does not match socktype/protocol, ignore it.
546*d56f51eaSDavid van Moolenbroek */
547*d56f51eaSDavid van Moolenbroek if (get_portmatch(pai, servname) != 0)
548*d56f51eaSDavid van Moolenbroek return 0;
549*d56f51eaSDavid van Moolenbroek
550*d56f51eaSDavid van Moolenbroek afd = find_afd(pai->ai_family);
551*d56f51eaSDavid van Moolenbroek
552*d56f51eaSDavid van Moolenbroek /*
553*d56f51eaSDavid van Moolenbroek * post-RFC2553: should look at (pai->ai_flags & AI_ADDRCONFIG)
554*d56f51eaSDavid van Moolenbroek * rather than hardcoding it. we may need to add AI_ADDRCONFIG
555*d56f51eaSDavid van Moolenbroek * handling code by ourselves in case we don't have getipnodebyname().
556*d56f51eaSDavid van Moolenbroek */
557*d56f51eaSDavid van Moolenbroek #ifdef USE_GETIPNODEBY
558*d56f51eaSDavid van Moolenbroek hp = getipnodebyname(hostname, pai->ai_family, AI_ADDRCONFIG, &h_error);
559*d56f51eaSDavid van Moolenbroek #else
560*d56f51eaSDavid van Moolenbroek #ifdef HAVE_GETHOSTBYNAME2
561*d56f51eaSDavid van Moolenbroek hp = gethostbyname2(hostname, pai->ai_family);
562*d56f51eaSDavid van Moolenbroek #else
563*d56f51eaSDavid van Moolenbroek if (pai->ai_family != AF_INET)
564*d56f51eaSDavid van Moolenbroek return 0;
565*d56f51eaSDavid van Moolenbroek hp = gethostbyname(hostname);
566*d56f51eaSDavid van Moolenbroek #ifdef HAVE_H_ERRNO
567*d56f51eaSDavid van Moolenbroek h_error = h_errno;
568*d56f51eaSDavid van Moolenbroek #else
569*d56f51eaSDavid van Moolenbroek h_error = EINVAL;
570*d56f51eaSDavid van Moolenbroek #endif
571*d56f51eaSDavid van Moolenbroek #endif /*HAVE_GETHOSTBYNAME2*/
572*d56f51eaSDavid van Moolenbroek #endif /*USE_GETIPNODEBY*/
573*d56f51eaSDavid van Moolenbroek
574*d56f51eaSDavid van Moolenbroek if (hp == NULL) {
575*d56f51eaSDavid van Moolenbroek switch (h_error) {
576*d56f51eaSDavid van Moolenbroek case HOST_NOT_FOUND:
577*d56f51eaSDavid van Moolenbroek case NO_DATA:
578*d56f51eaSDavid van Moolenbroek error = EAI_NODATA;
579*d56f51eaSDavid van Moolenbroek break;
580*d56f51eaSDavid van Moolenbroek case TRY_AGAIN:
581*d56f51eaSDavid van Moolenbroek error = EAI_AGAIN;
582*d56f51eaSDavid van Moolenbroek break;
583*d56f51eaSDavid van Moolenbroek case NO_RECOVERY:
584*d56f51eaSDavid van Moolenbroek case NETDB_INTERNAL:
585*d56f51eaSDavid van Moolenbroek default:
586*d56f51eaSDavid van Moolenbroek error = EAI_FAIL;
587*d56f51eaSDavid van Moolenbroek break;
588*d56f51eaSDavid van Moolenbroek }
589*d56f51eaSDavid van Moolenbroek } else if ((hp->h_name == NULL) || (hp->h_name[0] == 0)
590*d56f51eaSDavid van Moolenbroek || (hp->h_addr_list[0] == NULL)) {
591*d56f51eaSDavid van Moolenbroek #ifdef USE_GETIPNODEBY
592*d56f51eaSDavid van Moolenbroek freehostent(hp);
593*d56f51eaSDavid van Moolenbroek #endif
594*d56f51eaSDavid van Moolenbroek hp = NULL;
595*d56f51eaSDavid van Moolenbroek error = EAI_FAIL;
596*d56f51eaSDavid van Moolenbroek }
597*d56f51eaSDavid van Moolenbroek
598*d56f51eaSDavid van Moolenbroek if (hp == NULL)
599*d56f51eaSDavid van Moolenbroek goto free;
600*d56f51eaSDavid van Moolenbroek
601*d56f51eaSDavid van Moolenbroek #ifdef USE_GETIPNODEBY
602*d56f51eaSDavid van Moolenbroek aplist = hp->h_addr_list;
603*d56f51eaSDavid van Moolenbroek #else
604*d56f51eaSDavid van Moolenbroek /*
605*d56f51eaSDavid van Moolenbroek * hp will be overwritten if we use gethostbyname2().
606*d56f51eaSDavid van Moolenbroek * always deep copy for simplification.
607*d56f51eaSDavid van Moolenbroek */
608*d56f51eaSDavid van Moolenbroek for (naddrs = 0; hp->h_addr_list[naddrs] != NULL; naddrs++)
609*d56f51eaSDavid van Moolenbroek ;
610*d56f51eaSDavid van Moolenbroek naddrs++;
611*d56f51eaSDavid van Moolenbroek aplist = (char **)malloc(sizeof(aplist[0]) * naddrs);
612*d56f51eaSDavid van Moolenbroek apbuf = (char *)malloc(hp->h_length * naddrs);
613*d56f51eaSDavid van Moolenbroek if (aplist == NULL || apbuf == NULL) {
614*d56f51eaSDavid van Moolenbroek error = EAI_MEMORY;
615*d56f51eaSDavid van Moolenbroek goto free;
616*d56f51eaSDavid van Moolenbroek }
617*d56f51eaSDavid van Moolenbroek memset(aplist, 0, sizeof(aplist[0]) * naddrs);
618*d56f51eaSDavid van Moolenbroek for (i = 0; i < naddrs; i++) {
619*d56f51eaSDavid van Moolenbroek if (hp->h_addr_list[i] == NULL) {
620*d56f51eaSDavid van Moolenbroek aplist[i] = NULL;
621*d56f51eaSDavid van Moolenbroek continue;
622*d56f51eaSDavid van Moolenbroek }
623*d56f51eaSDavid van Moolenbroek memcpy(&apbuf[i * hp->h_length], hp->h_addr_list[i],
624*d56f51eaSDavid van Moolenbroek hp->h_length);
625*d56f51eaSDavid van Moolenbroek aplist[i] = &apbuf[i * hp->h_length];
626*d56f51eaSDavid van Moolenbroek }
627*d56f51eaSDavid van Moolenbroek #endif
628*d56f51eaSDavid van Moolenbroek
629*d56f51eaSDavid van Moolenbroek for (i = 0; aplist[i] != NULL; i++) {
630*d56f51eaSDavid van Moolenbroek af = hp->h_addrtype;
631*d56f51eaSDavid van Moolenbroek ap = aplist[i];
632*d56f51eaSDavid van Moolenbroek #ifdef AF_INET6
633*d56f51eaSDavid van Moolenbroek if (af == AF_INET6
634*d56f51eaSDavid van Moolenbroek && IN6_IS_ADDR_V4MAPPED((struct in6_addr *)ap)) {
635*d56f51eaSDavid van Moolenbroek af = AF_INET;
636*d56f51eaSDavid van Moolenbroek ap = ap + sizeof(struct in6_addr)
637*d56f51eaSDavid van Moolenbroek - sizeof(struct in_addr);
638*d56f51eaSDavid van Moolenbroek }
639*d56f51eaSDavid van Moolenbroek #endif
640*d56f51eaSDavid van Moolenbroek
641*d56f51eaSDavid van Moolenbroek if (af != pai->ai_family)
642*d56f51eaSDavid van Moolenbroek continue;
643*d56f51eaSDavid van Moolenbroek
644*d56f51eaSDavid van Moolenbroek if ((pai->ai_flags & AI_CANONNAME) == 0) {
645*d56f51eaSDavid van Moolenbroek GET_AI(cur->ai_next, afd, ap);
646*d56f51eaSDavid van Moolenbroek GET_PORT(cur->ai_next, servname);
647*d56f51eaSDavid van Moolenbroek } else {
648*d56f51eaSDavid van Moolenbroek /*
649*d56f51eaSDavid van Moolenbroek * if AI_CANONNAME and if reverse lookup
650*d56f51eaSDavid van Moolenbroek * fail, return ai anyway to pacify
651*d56f51eaSDavid van Moolenbroek * calling application.
652*d56f51eaSDavid van Moolenbroek *
653*d56f51eaSDavid van Moolenbroek * XXX getaddrinfo() is a name->address
654*d56f51eaSDavid van Moolenbroek * translation function, and it looks
655*d56f51eaSDavid van Moolenbroek * strange that we do addr->name
656*d56f51eaSDavid van Moolenbroek * translation here.
657*d56f51eaSDavid van Moolenbroek */
658*d56f51eaSDavid van Moolenbroek get_name(ap, afd, &cur->ai_next,
659*d56f51eaSDavid van Moolenbroek ap, pai, servname);
660*d56f51eaSDavid van Moolenbroek }
661*d56f51eaSDavid van Moolenbroek
662*d56f51eaSDavid van Moolenbroek while (cur && cur->ai_next)
663*d56f51eaSDavid van Moolenbroek cur = cur->ai_next;
664*d56f51eaSDavid van Moolenbroek }
665*d56f51eaSDavid van Moolenbroek
666*d56f51eaSDavid van Moolenbroek *res = sentinel.ai_next;
667*d56f51eaSDavid van Moolenbroek return 0;
668*d56f51eaSDavid van Moolenbroek
669*d56f51eaSDavid van Moolenbroek free:
670*d56f51eaSDavid van Moolenbroek #ifdef USE_GETIPNODEBY
671*d56f51eaSDavid van Moolenbroek if (hp)
672*d56f51eaSDavid van Moolenbroek freehostent(hp);
673*d56f51eaSDavid van Moolenbroek #endif
674*d56f51eaSDavid van Moolenbroek if (aplist)
675*d56f51eaSDavid van Moolenbroek free(aplist);
676*d56f51eaSDavid van Moolenbroek if (apbuf)
677*d56f51eaSDavid van Moolenbroek free(apbuf);
678*d56f51eaSDavid van Moolenbroek if (sentinel.ai_next)
679*d56f51eaSDavid van Moolenbroek freeaddrinfo(sentinel.ai_next);
680*d56f51eaSDavid van Moolenbroek return error;
681*d56f51eaSDavid van Moolenbroek }
682*d56f51eaSDavid van Moolenbroek
683*d56f51eaSDavid van Moolenbroek /*
684*d56f51eaSDavid van Moolenbroek * hostname == NULL.
685*d56f51eaSDavid van Moolenbroek * passive socket -> anyaddr (0.0.0.0 or ::)
686*d56f51eaSDavid van Moolenbroek * non-passive socket -> localhost (127.0.0.1 or ::1)
687*d56f51eaSDavid van Moolenbroek */
688*d56f51eaSDavid van Moolenbroek static int
explore_null(pai,hostname,servname,res)689*d56f51eaSDavid van Moolenbroek explore_null(pai, hostname, servname, res)
690*d56f51eaSDavid van Moolenbroek const struct addrinfo *pai;
691*d56f51eaSDavid van Moolenbroek const char *hostname;
692*d56f51eaSDavid van Moolenbroek const char *servname;
693*d56f51eaSDavid van Moolenbroek struct addrinfo **res;
694*d56f51eaSDavid van Moolenbroek {
695*d56f51eaSDavid van Moolenbroek int s;
696*d56f51eaSDavid van Moolenbroek const struct afd *afd;
697*d56f51eaSDavid van Moolenbroek struct addrinfo *cur;
698*d56f51eaSDavid van Moolenbroek struct addrinfo sentinel;
699*d56f51eaSDavid van Moolenbroek int error;
700*d56f51eaSDavid van Moolenbroek
701*d56f51eaSDavid van Moolenbroek *res = NULL;
702*d56f51eaSDavid van Moolenbroek sentinel.ai_next = NULL;
703*d56f51eaSDavid van Moolenbroek cur = &sentinel;
704*d56f51eaSDavid van Moolenbroek
705*d56f51eaSDavid van Moolenbroek /*
706*d56f51eaSDavid van Moolenbroek * filter out AFs that are not supported by the kernel
707*d56f51eaSDavid van Moolenbroek * XXX errno?
708*d56f51eaSDavid van Moolenbroek */
709*d56f51eaSDavid van Moolenbroek s = socket(pai->ai_family, SOCK_DGRAM, 0);
710*d56f51eaSDavid van Moolenbroek if (s < 0) {
711*d56f51eaSDavid van Moolenbroek if (errno != EMFILE)
712*d56f51eaSDavid van Moolenbroek return 0;
713*d56f51eaSDavid van Moolenbroek } else
714*d56f51eaSDavid van Moolenbroek close(s);
715*d56f51eaSDavid van Moolenbroek
716*d56f51eaSDavid van Moolenbroek /*
717*d56f51eaSDavid van Moolenbroek * if the servname does not match socktype/protocol, ignore it.
718*d56f51eaSDavid van Moolenbroek */
719*d56f51eaSDavid van Moolenbroek if (get_portmatch(pai, servname) != 0)
720*d56f51eaSDavid van Moolenbroek return 0;
721*d56f51eaSDavid van Moolenbroek
722*d56f51eaSDavid van Moolenbroek afd = find_afd(pai->ai_family);
723*d56f51eaSDavid van Moolenbroek
724*d56f51eaSDavid van Moolenbroek if (pai->ai_flags & AI_PASSIVE) {
725*d56f51eaSDavid van Moolenbroek GET_AI(cur->ai_next, afd, afd->a_addrany);
726*d56f51eaSDavid van Moolenbroek /* xxx meaningless?
727*d56f51eaSDavid van Moolenbroek * GET_CANONNAME(cur->ai_next, "anyaddr");
728*d56f51eaSDavid van Moolenbroek */
729*d56f51eaSDavid van Moolenbroek GET_PORT(cur->ai_next, servname);
730*d56f51eaSDavid van Moolenbroek } else {
731*d56f51eaSDavid van Moolenbroek GET_AI(cur->ai_next, afd, afd->a_loopback);
732*d56f51eaSDavid van Moolenbroek /* xxx meaningless?
733*d56f51eaSDavid van Moolenbroek * GET_CANONNAME(cur->ai_next, "localhost");
734*d56f51eaSDavid van Moolenbroek */
735*d56f51eaSDavid van Moolenbroek GET_PORT(cur->ai_next, servname);
736*d56f51eaSDavid van Moolenbroek }
737*d56f51eaSDavid van Moolenbroek cur = cur->ai_next;
738*d56f51eaSDavid van Moolenbroek
739*d56f51eaSDavid van Moolenbroek *res = sentinel.ai_next;
740*d56f51eaSDavid van Moolenbroek return 0;
741*d56f51eaSDavid van Moolenbroek
742*d56f51eaSDavid van Moolenbroek free:
743*d56f51eaSDavid van Moolenbroek if (sentinel.ai_next)
744*d56f51eaSDavid van Moolenbroek freeaddrinfo(sentinel.ai_next);
745*d56f51eaSDavid van Moolenbroek return error;
746*d56f51eaSDavid van Moolenbroek }
747*d56f51eaSDavid van Moolenbroek
748*d56f51eaSDavid van Moolenbroek /*
749*d56f51eaSDavid van Moolenbroek * numeric hostname
750*d56f51eaSDavid van Moolenbroek */
751*d56f51eaSDavid van Moolenbroek static int
explore_numeric(pai,hostname,servname,res)752*d56f51eaSDavid van Moolenbroek explore_numeric(pai, hostname, servname, res)
753*d56f51eaSDavid van Moolenbroek const struct addrinfo *pai;
754*d56f51eaSDavid van Moolenbroek const char *hostname;
755*d56f51eaSDavid van Moolenbroek const char *servname;
756*d56f51eaSDavid van Moolenbroek struct addrinfo **res;
757*d56f51eaSDavid van Moolenbroek {
758*d56f51eaSDavid van Moolenbroek const struct afd *afd;
759*d56f51eaSDavid van Moolenbroek struct addrinfo *cur;
760*d56f51eaSDavid van Moolenbroek struct addrinfo sentinel;
761*d56f51eaSDavid van Moolenbroek int error;
762*d56f51eaSDavid van Moolenbroek char pton[PTON_MAX];
763*d56f51eaSDavid van Moolenbroek int flags;
764*d56f51eaSDavid van Moolenbroek
765*d56f51eaSDavid van Moolenbroek *res = NULL;
766*d56f51eaSDavid van Moolenbroek sentinel.ai_next = NULL;
767*d56f51eaSDavid van Moolenbroek cur = &sentinel;
768*d56f51eaSDavid van Moolenbroek
769*d56f51eaSDavid van Moolenbroek /*
770*d56f51eaSDavid van Moolenbroek * if the servname does not match socktype/protocol, ignore it.
771*d56f51eaSDavid van Moolenbroek */
772*d56f51eaSDavid van Moolenbroek if (get_portmatch(pai, servname) != 0)
773*d56f51eaSDavid van Moolenbroek return 0;
774*d56f51eaSDavid van Moolenbroek
775*d56f51eaSDavid van Moolenbroek afd = find_afd(pai->ai_family);
776*d56f51eaSDavid van Moolenbroek flags = pai->ai_flags;
777*d56f51eaSDavid van Moolenbroek
778*d56f51eaSDavid van Moolenbroek if (inet_pton(afd->a_af, hostname, pton) == 1) {
779*d56f51eaSDavid van Moolenbroek u_int32_t v4a;
780*d56f51eaSDavid van Moolenbroek #ifdef INET6
781*d56f51eaSDavid van Moolenbroek u_char pfx;
782*d56f51eaSDavid van Moolenbroek #endif
783*d56f51eaSDavid van Moolenbroek
784*d56f51eaSDavid van Moolenbroek switch (afd->a_af) {
785*d56f51eaSDavid van Moolenbroek case AF_INET:
786*d56f51eaSDavid van Moolenbroek v4a = (u_int32_t)ntohl(((struct in_addr *)pton)->s_addr);
787*d56f51eaSDavid van Moolenbroek if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a))
788*d56f51eaSDavid van Moolenbroek flags &= ~AI_CANONNAME;
789*d56f51eaSDavid van Moolenbroek v4a >>= IN_CLASSA_NSHIFT;
790*d56f51eaSDavid van Moolenbroek if (v4a == 0 || v4a == IN_LOOPBACKNET)
791*d56f51eaSDavid van Moolenbroek flags &= ~AI_CANONNAME;
792*d56f51eaSDavid van Moolenbroek break;
793*d56f51eaSDavid van Moolenbroek #ifdef INET6
794*d56f51eaSDavid van Moolenbroek case AF_INET6:
795*d56f51eaSDavid van Moolenbroek pfx = ((struct in6_addr *)pton)->s6_addr[0];
796*d56f51eaSDavid van Moolenbroek if (pfx == 0 || pfx == 0xfe || pfx == 0xff)
797*d56f51eaSDavid van Moolenbroek flags &= ~AI_CANONNAME;
798*d56f51eaSDavid van Moolenbroek break;
799*d56f51eaSDavid van Moolenbroek #endif
800*d56f51eaSDavid van Moolenbroek }
801*d56f51eaSDavid van Moolenbroek
802*d56f51eaSDavid van Moolenbroek if (pai->ai_family == afd->a_af ||
803*d56f51eaSDavid van Moolenbroek pai->ai_family == PF_UNSPEC /*?*/) {
804*d56f51eaSDavid van Moolenbroek if ((flags & AI_CANONNAME) == 0) {
805*d56f51eaSDavid van Moolenbroek GET_AI(cur->ai_next, afd, pton);
806*d56f51eaSDavid van Moolenbroek GET_PORT(cur->ai_next, servname);
807*d56f51eaSDavid van Moolenbroek } else {
808*d56f51eaSDavid van Moolenbroek /*
809*d56f51eaSDavid van Moolenbroek * if AI_CANONNAME and if reverse lookup
810*d56f51eaSDavid van Moolenbroek * fail, return ai anyway to pacify
811*d56f51eaSDavid van Moolenbroek * calling application.
812*d56f51eaSDavid van Moolenbroek *
813*d56f51eaSDavid van Moolenbroek * XXX getaddrinfo() is a name->address
814*d56f51eaSDavid van Moolenbroek * translation function, and it looks
815*d56f51eaSDavid van Moolenbroek * strange that we do addr->name
816*d56f51eaSDavid van Moolenbroek * translation here.
817*d56f51eaSDavid van Moolenbroek */
818*d56f51eaSDavid van Moolenbroek get_name(pton, afd, &cur->ai_next,
819*d56f51eaSDavid van Moolenbroek pton, pai, servname);
820*d56f51eaSDavid van Moolenbroek }
821*d56f51eaSDavid van Moolenbroek while (cur && cur->ai_next)
822*d56f51eaSDavid van Moolenbroek cur = cur->ai_next;
823*d56f51eaSDavid van Moolenbroek } else
824*d56f51eaSDavid van Moolenbroek ERR(EAI_FAMILY); /*xxx*/
825*d56f51eaSDavid van Moolenbroek }
826*d56f51eaSDavid van Moolenbroek
827*d56f51eaSDavid van Moolenbroek *res = sentinel.ai_next;
828*d56f51eaSDavid van Moolenbroek return 0;
829*d56f51eaSDavid van Moolenbroek
830*d56f51eaSDavid van Moolenbroek free:
831*d56f51eaSDavid van Moolenbroek bad:
832*d56f51eaSDavid van Moolenbroek if (sentinel.ai_next)
833*d56f51eaSDavid van Moolenbroek freeaddrinfo(sentinel.ai_next);
834*d56f51eaSDavid van Moolenbroek return error;
835*d56f51eaSDavid van Moolenbroek }
836*d56f51eaSDavid van Moolenbroek
837*d56f51eaSDavid van Moolenbroek /*
838*d56f51eaSDavid van Moolenbroek * numeric hostname with scope
839*d56f51eaSDavid van Moolenbroek */
840*d56f51eaSDavid van Moolenbroek static int
explore_numeric_scope(pai,hostname,servname,res)841*d56f51eaSDavid van Moolenbroek explore_numeric_scope(pai, hostname, servname, res)
842*d56f51eaSDavid van Moolenbroek const struct addrinfo *pai;
843*d56f51eaSDavid van Moolenbroek const char *hostname;
844*d56f51eaSDavid van Moolenbroek const char *servname;
845*d56f51eaSDavid van Moolenbroek struct addrinfo **res;
846*d56f51eaSDavid van Moolenbroek {
847*d56f51eaSDavid van Moolenbroek #ifndef SCOPE_DELIMITER
848*d56f51eaSDavid van Moolenbroek return explore_numeric(pai, hostname, servname, res);
849*d56f51eaSDavid van Moolenbroek #else
850*d56f51eaSDavid van Moolenbroek const struct afd *afd;
851*d56f51eaSDavid van Moolenbroek struct addrinfo *cur;
852*d56f51eaSDavid van Moolenbroek int error;
853*d56f51eaSDavid van Moolenbroek char *cp, *hostname2 = NULL;
854*d56f51eaSDavid van Moolenbroek int scope;
855*d56f51eaSDavid van Moolenbroek struct sockaddr_in6 *sin6;
856*d56f51eaSDavid van Moolenbroek
857*d56f51eaSDavid van Moolenbroek /*
858*d56f51eaSDavid van Moolenbroek * if the servname does not match socktype/protocol, ignore it.
859*d56f51eaSDavid van Moolenbroek */
860*d56f51eaSDavid van Moolenbroek if (get_portmatch(pai, servname) != 0)
861*d56f51eaSDavid van Moolenbroek return 0;
862*d56f51eaSDavid van Moolenbroek
863*d56f51eaSDavid van Moolenbroek afd = find_afd(pai->ai_family);
864*d56f51eaSDavid van Moolenbroek if (!afd->a_scoped)
865*d56f51eaSDavid van Moolenbroek return explore_numeric(pai, hostname, servname, res);
866*d56f51eaSDavid van Moolenbroek
867*d56f51eaSDavid van Moolenbroek cp = strchr(hostname, SCOPE_DELIMITER);
868*d56f51eaSDavid van Moolenbroek if (cp == NULL)
869*d56f51eaSDavid van Moolenbroek return explore_numeric(pai, hostname, servname, res);
870*d56f51eaSDavid van Moolenbroek
871*d56f51eaSDavid van Moolenbroek /*
872*d56f51eaSDavid van Moolenbroek * Handle special case of <scoped_address><delimiter><scope id>
873*d56f51eaSDavid van Moolenbroek */
874*d56f51eaSDavid van Moolenbroek hostname2 = strdup(hostname);
875*d56f51eaSDavid van Moolenbroek if (hostname2 == NULL)
876*d56f51eaSDavid van Moolenbroek return EAI_MEMORY;
877*d56f51eaSDavid van Moolenbroek /* terminate at the delimiter */
878*d56f51eaSDavid van Moolenbroek hostname2[cp - hostname] = '\0';
879*d56f51eaSDavid van Moolenbroek
880*d56f51eaSDavid van Moolenbroek cp++;
881*d56f51eaSDavid van Moolenbroek switch (pai->ai_family) {
882*d56f51eaSDavid van Moolenbroek #ifdef INET6
883*d56f51eaSDavid van Moolenbroek case AF_INET6:
884*d56f51eaSDavid van Moolenbroek scope = if_nametoindex(cp);
885*d56f51eaSDavid van Moolenbroek if (scope == 0) {
886*d56f51eaSDavid van Moolenbroek free(hostname2);
887*d56f51eaSDavid van Moolenbroek return (EAI_NONAME);
888*d56f51eaSDavid van Moolenbroek }
889*d56f51eaSDavid van Moolenbroek break;
890*d56f51eaSDavid van Moolenbroek #endif
891*d56f51eaSDavid van Moolenbroek }
892*d56f51eaSDavid van Moolenbroek
893*d56f51eaSDavid van Moolenbroek error = explore_numeric(pai, hostname2, servname, res);
894*d56f51eaSDavid van Moolenbroek if (error == 0) {
895*d56f51eaSDavid van Moolenbroek for (cur = *res; cur; cur = cur->ai_next) {
896*d56f51eaSDavid van Moolenbroek if (cur->ai_family != AF_INET6)
897*d56f51eaSDavid van Moolenbroek continue;
898*d56f51eaSDavid van Moolenbroek sin6 = (struct sockaddr_in6 *)cur->ai_addr;
899*d56f51eaSDavid van Moolenbroek if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) ||
900*d56f51eaSDavid van Moolenbroek IN6_IS_ADDR_MC_LINKLOCAL(&sin6->sin6_addr))
901*d56f51eaSDavid van Moolenbroek sin6->sin6_scope_id = scope;
902*d56f51eaSDavid van Moolenbroek }
903*d56f51eaSDavid van Moolenbroek }
904*d56f51eaSDavid van Moolenbroek
905*d56f51eaSDavid van Moolenbroek free(hostname2);
906*d56f51eaSDavid van Moolenbroek
907*d56f51eaSDavid van Moolenbroek return error;
908*d56f51eaSDavid van Moolenbroek #endif
909*d56f51eaSDavid van Moolenbroek }
910*d56f51eaSDavid van Moolenbroek
911*d56f51eaSDavid van Moolenbroek static int
get_name(addr,afd,res,numaddr,pai,servname)912*d56f51eaSDavid van Moolenbroek get_name(addr, afd, res, numaddr, pai, servname)
913*d56f51eaSDavid van Moolenbroek const char *addr;
914*d56f51eaSDavid van Moolenbroek const struct afd *afd;
915*d56f51eaSDavid van Moolenbroek struct addrinfo **res;
916*d56f51eaSDavid van Moolenbroek char *numaddr;
917*d56f51eaSDavid van Moolenbroek const struct addrinfo *pai;
918*d56f51eaSDavid van Moolenbroek const char *servname;
919*d56f51eaSDavid van Moolenbroek {
920*d56f51eaSDavid van Moolenbroek struct hostent *hp = NULL;
921*d56f51eaSDavid van Moolenbroek struct addrinfo *cur = NULL;
922*d56f51eaSDavid van Moolenbroek int error = 0;
923*d56f51eaSDavid van Moolenbroek char *ap = NULL, *cn = NULL;
924*d56f51eaSDavid van Moolenbroek #ifdef USE_GETIPNODEBY
925*d56f51eaSDavid van Moolenbroek int h_error;
926*d56f51eaSDavid van Moolenbroek
927*d56f51eaSDavid van Moolenbroek hp = getipnodebyaddr(addr, afd->a_addrlen, afd->a_af, &h_error);
928*d56f51eaSDavid van Moolenbroek #else
929*d56f51eaSDavid van Moolenbroek hp = gethostbyaddr(addr, afd->a_addrlen, afd->a_af);
930*d56f51eaSDavid van Moolenbroek #endif
931*d56f51eaSDavid van Moolenbroek if (hp && hp->h_name && hp->h_name[0] && hp->h_addr_list[0]) {
932*d56f51eaSDavid van Moolenbroek #ifdef USE_GETIPNODEBY
933*d56f51eaSDavid van Moolenbroek GET_AI(cur, afd, hp->h_addr_list[0]);
934*d56f51eaSDavid van Moolenbroek GET_PORT(cur, servname);
935*d56f51eaSDavid van Moolenbroek GET_CANONNAME(cur, hp->h_name);
936*d56f51eaSDavid van Moolenbroek #else
937*d56f51eaSDavid van Moolenbroek /* hp will be damaged if we use gethostbyaddr() */
938*d56f51eaSDavid van Moolenbroek if ((ap = (char *)malloc(hp->h_length)) == NULL) {
939*d56f51eaSDavid van Moolenbroek error = EAI_MEMORY;
940*d56f51eaSDavid van Moolenbroek goto free;
941*d56f51eaSDavid van Moolenbroek }
942*d56f51eaSDavid van Moolenbroek memcpy(ap, hp->h_addr_list[0], hp->h_length);
943*d56f51eaSDavid van Moolenbroek if ((cn = strdup(hp->h_name)) == NULL) {
944*d56f51eaSDavid van Moolenbroek error = EAI_MEMORY;
945*d56f51eaSDavid van Moolenbroek goto free;
946*d56f51eaSDavid van Moolenbroek }
947*d56f51eaSDavid van Moolenbroek
948*d56f51eaSDavid van Moolenbroek GET_AI(cur, afd, ap);
949*d56f51eaSDavid van Moolenbroek GET_PORT(cur, servname);
950*d56f51eaSDavid van Moolenbroek GET_CANONNAME(cur, cn);
951*d56f51eaSDavid van Moolenbroek free(ap); ap = NULL;
952*d56f51eaSDavid van Moolenbroek free(cn); cn = NULL;
953*d56f51eaSDavid van Moolenbroek #endif
954*d56f51eaSDavid van Moolenbroek } else {
955*d56f51eaSDavid van Moolenbroek GET_AI(cur, afd, numaddr);
956*d56f51eaSDavid van Moolenbroek GET_PORT(cur, servname);
957*d56f51eaSDavid van Moolenbroek }
958*d56f51eaSDavid van Moolenbroek
959*d56f51eaSDavid van Moolenbroek #ifdef USE_GETIPNODEBY
960*d56f51eaSDavid van Moolenbroek if (hp)
961*d56f51eaSDavid van Moolenbroek freehostent(hp);
962*d56f51eaSDavid van Moolenbroek #endif
963*d56f51eaSDavid van Moolenbroek *res = cur;
964*d56f51eaSDavid van Moolenbroek return SUCCESS;
965*d56f51eaSDavid van Moolenbroek free:
966*d56f51eaSDavid van Moolenbroek if (cur)
967*d56f51eaSDavid van Moolenbroek freeaddrinfo(cur);
968*d56f51eaSDavid van Moolenbroek if (ap)
969*d56f51eaSDavid van Moolenbroek free(ap);
970*d56f51eaSDavid van Moolenbroek if (cn)
971*d56f51eaSDavid van Moolenbroek free(cn);
972*d56f51eaSDavid van Moolenbroek #ifdef USE_GETIPNODEBY
973*d56f51eaSDavid van Moolenbroek if (hp)
974*d56f51eaSDavid van Moolenbroek freehostent(hp);
975*d56f51eaSDavid van Moolenbroek #endif
976*d56f51eaSDavid van Moolenbroek *res = NULL;
977*d56f51eaSDavid van Moolenbroek return error;
978*d56f51eaSDavid van Moolenbroek }
979*d56f51eaSDavid van Moolenbroek
980*d56f51eaSDavid van Moolenbroek static int
get_canonname(pai,ai,str)981*d56f51eaSDavid van Moolenbroek get_canonname(pai, ai, str)
982*d56f51eaSDavid van Moolenbroek const struct addrinfo *pai;
983*d56f51eaSDavid van Moolenbroek struct addrinfo *ai;
984*d56f51eaSDavid van Moolenbroek const char *str;
985*d56f51eaSDavid van Moolenbroek {
986*d56f51eaSDavid van Moolenbroek if ((pai->ai_flags & AI_CANONNAME) != 0) {
987*d56f51eaSDavid van Moolenbroek ai->ai_canonname = strdup(str);
988*d56f51eaSDavid van Moolenbroek if (ai->ai_canonname == NULL)
989*d56f51eaSDavid van Moolenbroek return EAI_MEMORY;
990*d56f51eaSDavid van Moolenbroek }
991*d56f51eaSDavid van Moolenbroek return 0;
992*d56f51eaSDavid van Moolenbroek }
993*d56f51eaSDavid van Moolenbroek
994*d56f51eaSDavid van Moolenbroek static struct addrinfo *
get_ai(pai,afd,addr)995*d56f51eaSDavid van Moolenbroek get_ai(pai, afd, addr)
996*d56f51eaSDavid van Moolenbroek const struct addrinfo *pai;
997*d56f51eaSDavid van Moolenbroek const struct afd *afd;
998*d56f51eaSDavid van Moolenbroek const char *addr;
999*d56f51eaSDavid van Moolenbroek {
1000*d56f51eaSDavid van Moolenbroek char *p;
1001*d56f51eaSDavid van Moolenbroek struct addrinfo *ai;
1002*d56f51eaSDavid van Moolenbroek
1003*d56f51eaSDavid van Moolenbroek ai = (struct addrinfo *)malloc(sizeof(struct addrinfo)
1004*d56f51eaSDavid van Moolenbroek + (afd->a_socklen));
1005*d56f51eaSDavid van Moolenbroek if (ai == NULL)
1006*d56f51eaSDavid van Moolenbroek return NULL;
1007*d56f51eaSDavid van Moolenbroek
1008*d56f51eaSDavid van Moolenbroek memcpy(ai, pai, sizeof(struct addrinfo));
1009*d56f51eaSDavid van Moolenbroek ai->ai_addr = (struct sockaddr *)(ai + 1);
1010*d56f51eaSDavid van Moolenbroek memset(ai->ai_addr, 0, afd->a_socklen);
1011*d56f51eaSDavid van Moolenbroek #ifdef HAVE_SOCKADDR_SA_LEN
1012*d56f51eaSDavid van Moolenbroek ai->ai_addr->sa_len = afd->a_socklen;
1013*d56f51eaSDavid van Moolenbroek #endif
1014*d56f51eaSDavid van Moolenbroek ai->ai_addrlen = afd->a_socklen;
1015*d56f51eaSDavid van Moolenbroek ai->ai_addr->sa_family = ai->ai_family = afd->a_af;
1016*d56f51eaSDavid van Moolenbroek p = (char *)(ai->ai_addr);
1017*d56f51eaSDavid van Moolenbroek memcpy(p + afd->a_off, addr, afd->a_addrlen);
1018*d56f51eaSDavid van Moolenbroek return ai;
1019*d56f51eaSDavid van Moolenbroek }
1020*d56f51eaSDavid van Moolenbroek
1021*d56f51eaSDavid van Moolenbroek static int
get_portmatch(ai,servname)1022*d56f51eaSDavid van Moolenbroek get_portmatch(ai, servname)
1023*d56f51eaSDavid van Moolenbroek const struct addrinfo *ai;
1024*d56f51eaSDavid van Moolenbroek const char *servname;
1025*d56f51eaSDavid van Moolenbroek {
1026*d56f51eaSDavid van Moolenbroek
1027*d56f51eaSDavid van Moolenbroek /* get_port does not touch first argument. when matchonly == 1. */
1028*d56f51eaSDavid van Moolenbroek return get_port((struct addrinfo *)ai, servname, 1);
1029*d56f51eaSDavid van Moolenbroek }
1030*d56f51eaSDavid van Moolenbroek
1031*d56f51eaSDavid van Moolenbroek static int
get_port(ai,servname,matchonly)1032*d56f51eaSDavid van Moolenbroek get_port(ai, servname, matchonly)
1033*d56f51eaSDavid van Moolenbroek struct addrinfo *ai;
1034*d56f51eaSDavid van Moolenbroek const char *servname;
1035*d56f51eaSDavid van Moolenbroek int matchonly;
1036*d56f51eaSDavid van Moolenbroek {
1037*d56f51eaSDavid van Moolenbroek const char *proto;
1038*d56f51eaSDavid van Moolenbroek struct servent *sp;
1039*d56f51eaSDavid van Moolenbroek int port;
1040*d56f51eaSDavid van Moolenbroek int allownumeric;
1041*d56f51eaSDavid van Moolenbroek
1042*d56f51eaSDavid van Moolenbroek if (servname == NULL)
1043*d56f51eaSDavid van Moolenbroek return 0;
1044*d56f51eaSDavid van Moolenbroek switch (ai->ai_family) {
1045*d56f51eaSDavid van Moolenbroek case AF_INET:
1046*d56f51eaSDavid van Moolenbroek #ifdef AF_INET6
1047*d56f51eaSDavid van Moolenbroek case AF_INET6:
1048*d56f51eaSDavid van Moolenbroek #endif
1049*d56f51eaSDavid van Moolenbroek break;
1050*d56f51eaSDavid van Moolenbroek default:
1051*d56f51eaSDavid van Moolenbroek return 0;
1052*d56f51eaSDavid van Moolenbroek }
1053*d56f51eaSDavid van Moolenbroek
1054*d56f51eaSDavid van Moolenbroek switch (ai->ai_socktype) {
1055*d56f51eaSDavid van Moolenbroek case SOCK_RAW:
1056*d56f51eaSDavid van Moolenbroek return EAI_SERVICE;
1057*d56f51eaSDavid van Moolenbroek case SOCK_DGRAM:
1058*d56f51eaSDavid van Moolenbroek case SOCK_STREAM:
1059*d56f51eaSDavid van Moolenbroek allownumeric = 1;
1060*d56f51eaSDavid van Moolenbroek break;
1061*d56f51eaSDavid van Moolenbroek case ANY:
1062*d56f51eaSDavid van Moolenbroek allownumeric = 0;
1063*d56f51eaSDavid van Moolenbroek break;
1064*d56f51eaSDavid van Moolenbroek default:
1065*d56f51eaSDavid van Moolenbroek return EAI_SOCKTYPE;
1066*d56f51eaSDavid van Moolenbroek }
1067*d56f51eaSDavid van Moolenbroek
1068*d56f51eaSDavid van Moolenbroek if (str_isnumber(servname)) {
1069*d56f51eaSDavid van Moolenbroek if (!allownumeric)
1070*d56f51eaSDavid van Moolenbroek return EAI_SERVICE;
1071*d56f51eaSDavid van Moolenbroek port = htons(atoi(servname));
1072*d56f51eaSDavid van Moolenbroek if (port < 0 || port > 65535)
1073*d56f51eaSDavid van Moolenbroek return EAI_SERVICE;
1074*d56f51eaSDavid van Moolenbroek } else {
1075*d56f51eaSDavid van Moolenbroek switch (ai->ai_socktype) {
1076*d56f51eaSDavid van Moolenbroek case SOCK_DGRAM:
1077*d56f51eaSDavid van Moolenbroek proto = "udp";
1078*d56f51eaSDavid van Moolenbroek break;
1079*d56f51eaSDavid van Moolenbroek case SOCK_STREAM:
1080*d56f51eaSDavid van Moolenbroek proto = "tcp";
1081*d56f51eaSDavid van Moolenbroek break;
1082*d56f51eaSDavid van Moolenbroek default:
1083*d56f51eaSDavid van Moolenbroek proto = NULL;
1084*d56f51eaSDavid van Moolenbroek break;
1085*d56f51eaSDavid van Moolenbroek }
1086*d56f51eaSDavid van Moolenbroek
1087*d56f51eaSDavid van Moolenbroek if ((sp = getservbyname(servname, proto)) == NULL)
1088*d56f51eaSDavid van Moolenbroek return EAI_SERVICE;
1089*d56f51eaSDavid van Moolenbroek port = sp->s_port;
1090*d56f51eaSDavid van Moolenbroek }
1091*d56f51eaSDavid van Moolenbroek
1092*d56f51eaSDavid van Moolenbroek if (!matchonly) {
1093*d56f51eaSDavid van Moolenbroek switch (ai->ai_family) {
1094*d56f51eaSDavid van Moolenbroek case AF_INET:
1095*d56f51eaSDavid van Moolenbroek ((struct sockaddr_in *)ai->ai_addr)->sin_port = port;
1096*d56f51eaSDavid van Moolenbroek break;
1097*d56f51eaSDavid van Moolenbroek #ifdef INET6
1098*d56f51eaSDavid van Moolenbroek case AF_INET6:
1099*d56f51eaSDavid van Moolenbroek ((struct sockaddr_in6 *)ai->ai_addr)->sin6_port = port;
1100*d56f51eaSDavid van Moolenbroek break;
1101*d56f51eaSDavid van Moolenbroek #endif
1102*d56f51eaSDavid van Moolenbroek }
1103*d56f51eaSDavid van Moolenbroek }
1104*d56f51eaSDavid van Moolenbroek
1105*d56f51eaSDavid van Moolenbroek return 0;
1106*d56f51eaSDavid van Moolenbroek }
1107*d56f51eaSDavid van Moolenbroek
1108*d56f51eaSDavid van Moolenbroek static const struct afd *
find_afd(af)1109*d56f51eaSDavid van Moolenbroek find_afd(af)
1110*d56f51eaSDavid van Moolenbroek int af;
1111*d56f51eaSDavid van Moolenbroek {
1112*d56f51eaSDavid van Moolenbroek const struct afd *afd;
1113*d56f51eaSDavid van Moolenbroek
1114*d56f51eaSDavid van Moolenbroek if (af == PF_UNSPEC)
1115*d56f51eaSDavid van Moolenbroek return NULL;
1116*d56f51eaSDavid van Moolenbroek for (afd = afdl; afd->a_af; afd++) {
1117*d56f51eaSDavid van Moolenbroek if (afd->a_af == af)
1118*d56f51eaSDavid van Moolenbroek return afd;
1119*d56f51eaSDavid van Moolenbroek }
1120*d56f51eaSDavid van Moolenbroek return NULL;
1121*d56f51eaSDavid van Moolenbroek }
1122*d56f51eaSDavid van Moolenbroek
1123*d56f51eaSDavid van Moolenbroek
1124*d56f51eaSDavid van Moolenbroek #endif /*__MING64__*/
1125