1*ebfedea0SLionel Sambuc /* $NetBSD: getaddrinfo.c,v 1.1.1.1 2011/04/13 18:15:41 elric Exp $ */
2*ebfedea0SLionel Sambuc
3*ebfedea0SLionel Sambuc /*
4*ebfedea0SLionel Sambuc * Copyright (c) 1999 - 2001 Kungliga Tekniska Högskolan
5*ebfedea0SLionel Sambuc * (Royal Institute of Technology, Stockholm, Sweden).
6*ebfedea0SLionel Sambuc * All rights reserved.
7*ebfedea0SLionel Sambuc *
8*ebfedea0SLionel Sambuc * Redistribution and use in source and binary forms, with or without
9*ebfedea0SLionel Sambuc * modification, are permitted provided that the following conditions
10*ebfedea0SLionel Sambuc * are met:
11*ebfedea0SLionel Sambuc *
12*ebfedea0SLionel Sambuc * 1. Redistributions of source code must retain the above copyright
13*ebfedea0SLionel Sambuc * notice, this list of conditions and the following disclaimer.
14*ebfedea0SLionel Sambuc *
15*ebfedea0SLionel Sambuc * 2. Redistributions in binary form must reproduce the above copyright
16*ebfedea0SLionel Sambuc * notice, this list of conditions and the following disclaimer in the
17*ebfedea0SLionel Sambuc * documentation and/or other materials provided with the distribution.
18*ebfedea0SLionel Sambuc *
19*ebfedea0SLionel Sambuc * 3. Neither the name of the Institute nor the names of its contributors
20*ebfedea0SLionel Sambuc * may be used to endorse or promote products derived from this software
21*ebfedea0SLionel Sambuc * without specific prior written permission.
22*ebfedea0SLionel Sambuc *
23*ebfedea0SLionel Sambuc * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24*ebfedea0SLionel Sambuc * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25*ebfedea0SLionel Sambuc * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26*ebfedea0SLionel Sambuc * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27*ebfedea0SLionel Sambuc * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28*ebfedea0SLionel Sambuc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29*ebfedea0SLionel Sambuc * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30*ebfedea0SLionel Sambuc * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31*ebfedea0SLionel Sambuc * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32*ebfedea0SLionel Sambuc * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33*ebfedea0SLionel Sambuc * SUCH DAMAGE.
34*ebfedea0SLionel Sambuc */
35*ebfedea0SLionel Sambuc
36*ebfedea0SLionel Sambuc #include <config.h>
37*ebfedea0SLionel Sambuc
38*ebfedea0SLionel Sambuc #include <krb5/roken.h>
39*ebfedea0SLionel Sambuc
40*ebfedea0SLionel Sambuc /*
41*ebfedea0SLionel Sambuc * uses hints->ai_socktype and hints->ai_protocol
42*ebfedea0SLionel Sambuc */
43*ebfedea0SLionel Sambuc
44*ebfedea0SLionel Sambuc static int
get_port_protocol_socktype(const char * servname,const struct addrinfo * hints,int * port,int * protocol,int * socktype)45*ebfedea0SLionel Sambuc get_port_protocol_socktype (const char *servname,
46*ebfedea0SLionel Sambuc const struct addrinfo *hints,
47*ebfedea0SLionel Sambuc int *port,
48*ebfedea0SLionel Sambuc int *protocol,
49*ebfedea0SLionel Sambuc int *socktype)
50*ebfedea0SLionel Sambuc {
51*ebfedea0SLionel Sambuc struct servent *se;
52*ebfedea0SLionel Sambuc const char *proto_str = NULL;
53*ebfedea0SLionel Sambuc
54*ebfedea0SLionel Sambuc *socktype = 0;
55*ebfedea0SLionel Sambuc
56*ebfedea0SLionel Sambuc if (hints != NULL && hints->ai_protocol != 0) {
57*ebfedea0SLionel Sambuc struct protoent *protoent = getprotobynumber (hints->ai_protocol);
58*ebfedea0SLionel Sambuc
59*ebfedea0SLionel Sambuc if (protoent == NULL)
60*ebfedea0SLionel Sambuc return EAI_SOCKTYPE; /* XXX */
61*ebfedea0SLionel Sambuc
62*ebfedea0SLionel Sambuc proto_str = protoent->p_name;
63*ebfedea0SLionel Sambuc *protocol = protoent->p_proto;
64*ebfedea0SLionel Sambuc }
65*ebfedea0SLionel Sambuc
66*ebfedea0SLionel Sambuc if (hints != NULL)
67*ebfedea0SLionel Sambuc *socktype = hints->ai_socktype;
68*ebfedea0SLionel Sambuc
69*ebfedea0SLionel Sambuc if (*socktype == SOCK_STREAM) {
70*ebfedea0SLionel Sambuc se = getservbyname (servname, proto_str ? proto_str : "tcp");
71*ebfedea0SLionel Sambuc if (proto_str == NULL)
72*ebfedea0SLionel Sambuc *protocol = IPPROTO_TCP;
73*ebfedea0SLionel Sambuc } else if (*socktype == SOCK_DGRAM) {
74*ebfedea0SLionel Sambuc se = getservbyname (servname, proto_str ? proto_str : "udp");
75*ebfedea0SLionel Sambuc if (proto_str == NULL)
76*ebfedea0SLionel Sambuc *protocol = IPPROTO_UDP;
77*ebfedea0SLionel Sambuc } else if (*socktype == 0) {
78*ebfedea0SLionel Sambuc if (proto_str != NULL) {
79*ebfedea0SLionel Sambuc se = getservbyname (servname, proto_str);
80*ebfedea0SLionel Sambuc } else {
81*ebfedea0SLionel Sambuc se = getservbyname (servname, "tcp");
82*ebfedea0SLionel Sambuc *protocol = IPPROTO_TCP;
83*ebfedea0SLionel Sambuc *socktype = SOCK_STREAM;
84*ebfedea0SLionel Sambuc if (se == NULL) {
85*ebfedea0SLionel Sambuc se = getservbyname (servname, "udp");
86*ebfedea0SLionel Sambuc *protocol = IPPROTO_UDP;
87*ebfedea0SLionel Sambuc *socktype = SOCK_DGRAM;
88*ebfedea0SLionel Sambuc }
89*ebfedea0SLionel Sambuc }
90*ebfedea0SLionel Sambuc } else
91*ebfedea0SLionel Sambuc return EAI_SOCKTYPE;
92*ebfedea0SLionel Sambuc
93*ebfedea0SLionel Sambuc if (se == NULL) {
94*ebfedea0SLionel Sambuc char *endstr;
95*ebfedea0SLionel Sambuc
96*ebfedea0SLionel Sambuc *port = htons(strtol (servname, &endstr, 10));
97*ebfedea0SLionel Sambuc if (servname == endstr)
98*ebfedea0SLionel Sambuc return EAI_NONAME;
99*ebfedea0SLionel Sambuc } else {
100*ebfedea0SLionel Sambuc *port = se->s_port;
101*ebfedea0SLionel Sambuc }
102*ebfedea0SLionel Sambuc return 0;
103*ebfedea0SLionel Sambuc }
104*ebfedea0SLionel Sambuc
105*ebfedea0SLionel Sambuc static int
add_one(int port,int protocol,int socktype,struct addrinfo *** ptr,int (* func)(struct addrinfo *,void * data,int port),void * data,char * canonname)106*ebfedea0SLionel Sambuc add_one (int port, int protocol, int socktype,
107*ebfedea0SLionel Sambuc struct addrinfo ***ptr,
108*ebfedea0SLionel Sambuc int (*func)(struct addrinfo *, void *data, int port),
109*ebfedea0SLionel Sambuc void *data,
110*ebfedea0SLionel Sambuc char *canonname)
111*ebfedea0SLionel Sambuc {
112*ebfedea0SLionel Sambuc struct addrinfo *a;
113*ebfedea0SLionel Sambuc int ret;
114*ebfedea0SLionel Sambuc
115*ebfedea0SLionel Sambuc a = malloc (sizeof (*a));
116*ebfedea0SLionel Sambuc if (a == NULL)
117*ebfedea0SLionel Sambuc return EAI_MEMORY;
118*ebfedea0SLionel Sambuc memset (a, 0, sizeof(*a));
119*ebfedea0SLionel Sambuc a->ai_flags = 0;
120*ebfedea0SLionel Sambuc a->ai_next = NULL;
121*ebfedea0SLionel Sambuc a->ai_protocol = protocol;
122*ebfedea0SLionel Sambuc a->ai_socktype = socktype;
123*ebfedea0SLionel Sambuc a->ai_canonname = canonname;
124*ebfedea0SLionel Sambuc ret = (*func)(a, data, port);
125*ebfedea0SLionel Sambuc if (ret) {
126*ebfedea0SLionel Sambuc free (a);
127*ebfedea0SLionel Sambuc return ret;
128*ebfedea0SLionel Sambuc }
129*ebfedea0SLionel Sambuc **ptr = a;
130*ebfedea0SLionel Sambuc *ptr = &a->ai_next;
131*ebfedea0SLionel Sambuc return 0;
132*ebfedea0SLionel Sambuc }
133*ebfedea0SLionel Sambuc
134*ebfedea0SLionel Sambuc static int
const_v4(struct addrinfo * a,void * data,int port)135*ebfedea0SLionel Sambuc const_v4 (struct addrinfo *a, void *data, int port)
136*ebfedea0SLionel Sambuc {
137*ebfedea0SLionel Sambuc struct sockaddr_in *sin4;
138*ebfedea0SLionel Sambuc struct in_addr *addr = (struct in_addr *)data;
139*ebfedea0SLionel Sambuc
140*ebfedea0SLionel Sambuc a->ai_family = PF_INET;
141*ebfedea0SLionel Sambuc a->ai_addrlen = sizeof(*sin4);
142*ebfedea0SLionel Sambuc a->ai_addr = malloc (sizeof(*sin4));
143*ebfedea0SLionel Sambuc if (a->ai_addr == NULL)
144*ebfedea0SLionel Sambuc return EAI_MEMORY;
145*ebfedea0SLionel Sambuc sin4 = (struct sockaddr_in *)a->ai_addr;
146*ebfedea0SLionel Sambuc memset (sin4, 0, sizeof(*sin4));
147*ebfedea0SLionel Sambuc sin4->sin_family = AF_INET;
148*ebfedea0SLionel Sambuc sin4->sin_port = port;
149*ebfedea0SLionel Sambuc sin4->sin_addr = *addr;
150*ebfedea0SLionel Sambuc return 0;
151*ebfedea0SLionel Sambuc }
152*ebfedea0SLionel Sambuc
153*ebfedea0SLionel Sambuc #ifdef HAVE_IPV6
154*ebfedea0SLionel Sambuc static int
const_v6(struct addrinfo * a,void * data,int port)155*ebfedea0SLionel Sambuc const_v6 (struct addrinfo *a, void *data, int port)
156*ebfedea0SLionel Sambuc {
157*ebfedea0SLionel Sambuc struct sockaddr_in6 *sin6;
158*ebfedea0SLionel Sambuc struct in6_addr *addr = (struct in6_addr *)data;
159*ebfedea0SLionel Sambuc
160*ebfedea0SLionel Sambuc a->ai_family = PF_INET6;
161*ebfedea0SLionel Sambuc a->ai_addrlen = sizeof(*sin6);
162*ebfedea0SLionel Sambuc a->ai_addr = malloc (sizeof(*sin6));
163*ebfedea0SLionel Sambuc if (a->ai_addr == NULL)
164*ebfedea0SLionel Sambuc return EAI_MEMORY;
165*ebfedea0SLionel Sambuc sin6 = (struct sockaddr_in6 *)a->ai_addr;
166*ebfedea0SLionel Sambuc memset (sin6, 0, sizeof(*sin6));
167*ebfedea0SLionel Sambuc sin6->sin6_family = AF_INET6;
168*ebfedea0SLionel Sambuc sin6->sin6_port = port;
169*ebfedea0SLionel Sambuc sin6->sin6_addr = *addr;
170*ebfedea0SLionel Sambuc return 0;
171*ebfedea0SLionel Sambuc }
172*ebfedea0SLionel Sambuc #endif
173*ebfedea0SLionel Sambuc
174*ebfedea0SLionel Sambuc /* this is mostly a hack for some versions of AIX that has a prototype
175*ebfedea0SLionel Sambuc for in6addr_loopback but no actual symbol in libc */
176*ebfedea0SLionel Sambuc #if defined(HAVE_IPV6) && !defined(HAVE_IN6ADDR_LOOPBACK) && defined(IN6ADDR_LOOPBACK_INIT)
177*ebfedea0SLionel Sambuc #define in6addr_loopback _roken_in6addr_loopback
178*ebfedea0SLionel Sambuc struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
179*ebfedea0SLionel Sambuc #endif
180*ebfedea0SLionel Sambuc
181*ebfedea0SLionel Sambuc static int
get_null(const struct addrinfo * hints,int port,int protocol,int socktype,struct addrinfo ** res)182*ebfedea0SLionel Sambuc get_null (const struct addrinfo *hints,
183*ebfedea0SLionel Sambuc int port, int protocol, int socktype,
184*ebfedea0SLionel Sambuc struct addrinfo **res)
185*ebfedea0SLionel Sambuc {
186*ebfedea0SLionel Sambuc struct in_addr v4_addr;
187*ebfedea0SLionel Sambuc #ifdef HAVE_IPV6
188*ebfedea0SLionel Sambuc struct in6_addr v6_addr;
189*ebfedea0SLionel Sambuc #endif
190*ebfedea0SLionel Sambuc struct addrinfo *first = NULL;
191*ebfedea0SLionel Sambuc struct addrinfo **current = &first;
192*ebfedea0SLionel Sambuc int family = PF_UNSPEC;
193*ebfedea0SLionel Sambuc int ret;
194*ebfedea0SLionel Sambuc
195*ebfedea0SLionel Sambuc if (hints != NULL)
196*ebfedea0SLionel Sambuc family = hints->ai_family;
197*ebfedea0SLionel Sambuc
198*ebfedea0SLionel Sambuc if (hints && hints->ai_flags & AI_PASSIVE) {
199*ebfedea0SLionel Sambuc v4_addr.s_addr = INADDR_ANY;
200*ebfedea0SLionel Sambuc #ifdef HAVE_IPV6
201*ebfedea0SLionel Sambuc v6_addr = in6addr_any;
202*ebfedea0SLionel Sambuc #endif
203*ebfedea0SLionel Sambuc } else {
204*ebfedea0SLionel Sambuc v4_addr.s_addr = htonl(INADDR_LOOPBACK);
205*ebfedea0SLionel Sambuc #ifdef HAVE_IPV6
206*ebfedea0SLionel Sambuc v6_addr = in6addr_loopback;
207*ebfedea0SLionel Sambuc #endif
208*ebfedea0SLionel Sambuc }
209*ebfedea0SLionel Sambuc
210*ebfedea0SLionel Sambuc #ifdef HAVE_IPV6
211*ebfedea0SLionel Sambuc if (family == PF_INET6 || family == PF_UNSPEC) {
212*ebfedea0SLionel Sambuc ret = add_one (port, protocol, socktype,
213*ebfedea0SLionel Sambuc ¤t, const_v6, &v6_addr, NULL);
214*ebfedea0SLionel Sambuc }
215*ebfedea0SLionel Sambuc #endif
216*ebfedea0SLionel Sambuc if (family == PF_INET || family == PF_UNSPEC) {
217*ebfedea0SLionel Sambuc ret = add_one (port, protocol, socktype,
218*ebfedea0SLionel Sambuc ¤t, const_v4, &v4_addr, NULL);
219*ebfedea0SLionel Sambuc }
220*ebfedea0SLionel Sambuc *res = first;
221*ebfedea0SLionel Sambuc return 0;
222*ebfedea0SLionel Sambuc }
223*ebfedea0SLionel Sambuc
224*ebfedea0SLionel Sambuc static int
add_hostent(int port,int protocol,int socktype,struct addrinfo *** current,int (* func)(struct addrinfo *,void * data,int port),struct hostent * he,int * flags)225*ebfedea0SLionel Sambuc add_hostent (int port, int protocol, int socktype,
226*ebfedea0SLionel Sambuc struct addrinfo ***current,
227*ebfedea0SLionel Sambuc int (*func)(struct addrinfo *, void *data, int port),
228*ebfedea0SLionel Sambuc struct hostent *he, int *flags)
229*ebfedea0SLionel Sambuc {
230*ebfedea0SLionel Sambuc int ret;
231*ebfedea0SLionel Sambuc char *canonname = NULL;
232*ebfedea0SLionel Sambuc char **h;
233*ebfedea0SLionel Sambuc
234*ebfedea0SLionel Sambuc if (*flags & AI_CANONNAME) {
235*ebfedea0SLionel Sambuc struct hostent *he2 = NULL;
236*ebfedea0SLionel Sambuc const char *tmp_canon;
237*ebfedea0SLionel Sambuc
238*ebfedea0SLionel Sambuc tmp_canon = hostent_find_fqdn (he);
239*ebfedea0SLionel Sambuc if (strchr (tmp_canon, '.') == NULL) {
240*ebfedea0SLionel Sambuc int error;
241*ebfedea0SLionel Sambuc
242*ebfedea0SLionel Sambuc he2 = getipnodebyaddr (he->h_addr_list[0], he->h_length,
243*ebfedea0SLionel Sambuc he->h_addrtype, &error);
244*ebfedea0SLionel Sambuc if (he2 != NULL) {
245*ebfedea0SLionel Sambuc const char *tmp = hostent_find_fqdn (he2);
246*ebfedea0SLionel Sambuc
247*ebfedea0SLionel Sambuc if (strchr (tmp, '.') != NULL)
248*ebfedea0SLionel Sambuc tmp_canon = tmp;
249*ebfedea0SLionel Sambuc }
250*ebfedea0SLionel Sambuc }
251*ebfedea0SLionel Sambuc
252*ebfedea0SLionel Sambuc canonname = strdup (tmp_canon);
253*ebfedea0SLionel Sambuc if (he2 != NULL)
254*ebfedea0SLionel Sambuc freehostent (he2);
255*ebfedea0SLionel Sambuc if (canonname == NULL)
256*ebfedea0SLionel Sambuc return EAI_MEMORY;
257*ebfedea0SLionel Sambuc }
258*ebfedea0SLionel Sambuc
259*ebfedea0SLionel Sambuc for (h = he->h_addr_list; *h != NULL; ++h) {
260*ebfedea0SLionel Sambuc ret = add_one (port, protocol, socktype,
261*ebfedea0SLionel Sambuc current, func, *h, canonname);
262*ebfedea0SLionel Sambuc if (ret)
263*ebfedea0SLionel Sambuc return ret;
264*ebfedea0SLionel Sambuc if (*flags & AI_CANONNAME) {
265*ebfedea0SLionel Sambuc *flags &= ~AI_CANONNAME;
266*ebfedea0SLionel Sambuc canonname = NULL;
267*ebfedea0SLionel Sambuc }
268*ebfedea0SLionel Sambuc }
269*ebfedea0SLionel Sambuc return 0;
270*ebfedea0SLionel Sambuc }
271*ebfedea0SLionel Sambuc
272*ebfedea0SLionel Sambuc static int
get_number(const char * nodename,const struct addrinfo * hints,int port,int protocol,int socktype,struct addrinfo ** res)273*ebfedea0SLionel Sambuc get_number (const char *nodename,
274*ebfedea0SLionel Sambuc const struct addrinfo *hints,
275*ebfedea0SLionel Sambuc int port, int protocol, int socktype,
276*ebfedea0SLionel Sambuc struct addrinfo **res)
277*ebfedea0SLionel Sambuc {
278*ebfedea0SLionel Sambuc struct addrinfo *first = NULL;
279*ebfedea0SLionel Sambuc struct addrinfo **current = &first;
280*ebfedea0SLionel Sambuc int family = PF_UNSPEC;
281*ebfedea0SLionel Sambuc int ret;
282*ebfedea0SLionel Sambuc
283*ebfedea0SLionel Sambuc if (hints != NULL) {
284*ebfedea0SLionel Sambuc family = hints->ai_family;
285*ebfedea0SLionel Sambuc }
286*ebfedea0SLionel Sambuc
287*ebfedea0SLionel Sambuc #ifdef HAVE_IPV6
288*ebfedea0SLionel Sambuc if (family == PF_INET6 || family == PF_UNSPEC) {
289*ebfedea0SLionel Sambuc struct in6_addr v6_addr;
290*ebfedea0SLionel Sambuc
291*ebfedea0SLionel Sambuc if (inet_pton (PF_INET6, nodename, &v6_addr) == 1) {
292*ebfedea0SLionel Sambuc ret = add_one (port, protocol, socktype,
293*ebfedea0SLionel Sambuc ¤t, const_v6, &v6_addr, NULL);
294*ebfedea0SLionel Sambuc *res = first;
295*ebfedea0SLionel Sambuc return ret;
296*ebfedea0SLionel Sambuc }
297*ebfedea0SLionel Sambuc }
298*ebfedea0SLionel Sambuc #endif
299*ebfedea0SLionel Sambuc if (family == PF_INET || family == PF_UNSPEC) {
300*ebfedea0SLionel Sambuc struct in_addr v4_addr;
301*ebfedea0SLionel Sambuc
302*ebfedea0SLionel Sambuc if (inet_pton (PF_INET, nodename, &v4_addr) == 1) {
303*ebfedea0SLionel Sambuc ret = add_one (port, protocol, socktype,
304*ebfedea0SLionel Sambuc ¤t, const_v4, &v4_addr, NULL);
305*ebfedea0SLionel Sambuc *res = first;
306*ebfedea0SLionel Sambuc return ret;
307*ebfedea0SLionel Sambuc }
308*ebfedea0SLionel Sambuc }
309*ebfedea0SLionel Sambuc return EAI_NONAME;
310*ebfedea0SLionel Sambuc }
311*ebfedea0SLionel Sambuc
312*ebfedea0SLionel Sambuc static int
get_nodes(const char * nodename,const struct addrinfo * hints,int port,int protocol,int socktype,struct addrinfo ** res)313*ebfedea0SLionel Sambuc get_nodes (const char *nodename,
314*ebfedea0SLionel Sambuc const struct addrinfo *hints,
315*ebfedea0SLionel Sambuc int port, int protocol, int socktype,
316*ebfedea0SLionel Sambuc struct addrinfo **res)
317*ebfedea0SLionel Sambuc {
318*ebfedea0SLionel Sambuc struct addrinfo *first = NULL;
319*ebfedea0SLionel Sambuc struct addrinfo **current = &first;
320*ebfedea0SLionel Sambuc int family = PF_UNSPEC;
321*ebfedea0SLionel Sambuc int flags = 0;
322*ebfedea0SLionel Sambuc int ret = EAI_NONAME;
323*ebfedea0SLionel Sambuc int error;
324*ebfedea0SLionel Sambuc
325*ebfedea0SLionel Sambuc if (hints != NULL) {
326*ebfedea0SLionel Sambuc family = hints->ai_family;
327*ebfedea0SLionel Sambuc flags = hints->ai_flags;
328*ebfedea0SLionel Sambuc }
329*ebfedea0SLionel Sambuc
330*ebfedea0SLionel Sambuc #ifdef HAVE_IPV6
331*ebfedea0SLionel Sambuc if (family == PF_INET6 || family == PF_UNSPEC) {
332*ebfedea0SLionel Sambuc struct hostent *he;
333*ebfedea0SLionel Sambuc
334*ebfedea0SLionel Sambuc he = getipnodebyname (nodename, PF_INET6, 0, &error);
335*ebfedea0SLionel Sambuc
336*ebfedea0SLionel Sambuc if (he != NULL) {
337*ebfedea0SLionel Sambuc ret = add_hostent (port, protocol, socktype,
338*ebfedea0SLionel Sambuc ¤t, const_v6, he, &flags);
339*ebfedea0SLionel Sambuc freehostent (he);
340*ebfedea0SLionel Sambuc }
341*ebfedea0SLionel Sambuc }
342*ebfedea0SLionel Sambuc #endif
343*ebfedea0SLionel Sambuc if (family == PF_INET || family == PF_UNSPEC) {
344*ebfedea0SLionel Sambuc struct hostent *he;
345*ebfedea0SLionel Sambuc
346*ebfedea0SLionel Sambuc he = getipnodebyname (nodename, PF_INET, 0, &error);
347*ebfedea0SLionel Sambuc
348*ebfedea0SLionel Sambuc if (he != NULL) {
349*ebfedea0SLionel Sambuc ret = add_hostent (port, protocol, socktype,
350*ebfedea0SLionel Sambuc ¤t, const_v4, he, &flags);
351*ebfedea0SLionel Sambuc freehostent (he);
352*ebfedea0SLionel Sambuc }
353*ebfedea0SLionel Sambuc }
354*ebfedea0SLionel Sambuc *res = first;
355*ebfedea0SLionel Sambuc return ret;
356*ebfedea0SLionel Sambuc }
357*ebfedea0SLionel Sambuc
358*ebfedea0SLionel Sambuc /*
359*ebfedea0SLionel Sambuc * hints:
360*ebfedea0SLionel Sambuc *
361*ebfedea0SLionel Sambuc * struct addrinfo {
362*ebfedea0SLionel Sambuc * int ai_flags;
363*ebfedea0SLionel Sambuc * int ai_family;
364*ebfedea0SLionel Sambuc * int ai_socktype;
365*ebfedea0SLionel Sambuc * int ai_protocol;
366*ebfedea0SLionel Sambuc * ...
367*ebfedea0SLionel Sambuc * };
368*ebfedea0SLionel Sambuc */
369*ebfedea0SLionel Sambuc
370*ebfedea0SLionel Sambuc ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
getaddrinfo(const char * nodename,const char * servname,const struct addrinfo * hints,struct addrinfo ** res)371*ebfedea0SLionel Sambuc getaddrinfo(const char *nodename,
372*ebfedea0SLionel Sambuc const char *servname,
373*ebfedea0SLionel Sambuc const struct addrinfo *hints,
374*ebfedea0SLionel Sambuc struct addrinfo **res)
375*ebfedea0SLionel Sambuc {
376*ebfedea0SLionel Sambuc int ret;
377*ebfedea0SLionel Sambuc int port = 0;
378*ebfedea0SLionel Sambuc int protocol = 0;
379*ebfedea0SLionel Sambuc int socktype = 0;
380*ebfedea0SLionel Sambuc
381*ebfedea0SLionel Sambuc *res = NULL;
382*ebfedea0SLionel Sambuc
383*ebfedea0SLionel Sambuc if (servname == NULL && nodename == NULL)
384*ebfedea0SLionel Sambuc return EAI_NONAME;
385*ebfedea0SLionel Sambuc
386*ebfedea0SLionel Sambuc if (hints != NULL
387*ebfedea0SLionel Sambuc && hints->ai_family != PF_UNSPEC
388*ebfedea0SLionel Sambuc && hints->ai_family != PF_INET
389*ebfedea0SLionel Sambuc #ifdef HAVE_IPV6
390*ebfedea0SLionel Sambuc && hints->ai_family != PF_INET6
391*ebfedea0SLionel Sambuc #endif
392*ebfedea0SLionel Sambuc )
393*ebfedea0SLionel Sambuc return EAI_FAMILY;
394*ebfedea0SLionel Sambuc
395*ebfedea0SLionel Sambuc if (servname != NULL) {
396*ebfedea0SLionel Sambuc ret = get_port_protocol_socktype (servname, hints,
397*ebfedea0SLionel Sambuc &port, &protocol, &socktype);
398*ebfedea0SLionel Sambuc if (ret)
399*ebfedea0SLionel Sambuc return ret;
400*ebfedea0SLionel Sambuc }
401*ebfedea0SLionel Sambuc if (nodename != NULL) {
402*ebfedea0SLionel Sambuc ret = get_number (nodename, hints, port, protocol, socktype, res);
403*ebfedea0SLionel Sambuc if (ret) {
404*ebfedea0SLionel Sambuc if(hints && hints->ai_flags & AI_NUMERICHOST)
405*ebfedea0SLionel Sambuc ret = EAI_NONAME;
406*ebfedea0SLionel Sambuc else
407*ebfedea0SLionel Sambuc ret = get_nodes (nodename, hints, port, protocol, socktype,
408*ebfedea0SLionel Sambuc res);
409*ebfedea0SLionel Sambuc }
410*ebfedea0SLionel Sambuc } else {
411*ebfedea0SLionel Sambuc ret = get_null (hints, port, protocol, socktype, res);
412*ebfedea0SLionel Sambuc }
413*ebfedea0SLionel Sambuc if (ret)
414*ebfedea0SLionel Sambuc freeaddrinfo (*res);
415*ebfedea0SLionel Sambuc return ret;
416*ebfedea0SLionel Sambuc }
417