1bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/*
2bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Copyright (C) 2000-2003 Damien Miller.  All rights reserved.
3bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Copyright (C) 1999 WIDE Project.  All rights reserved.
4bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman *
5bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Redistribution and use in source and binary forms, with or without
6bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * modification, are permitted provided that the following conditions
7bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * are met:
8bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * 1. Redistributions of source code must retain the above copyright
9bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman *    notice, this list of conditions and the following disclaimer.
10bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * 2. Redistributions in binary form must reproduce the above copyright
11bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman *    notice, this list of conditions and the following disclaimer in the
12bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman *    documentation and/or other materials provided with the distribution.
13bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * 3. Neither the name of the project nor the names of its contributors
14bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman *    may be used to endorse or promote products derived from this software
15bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman *    without specific prior written permission.
16bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman *
17bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
18bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
21bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * SUCH DAMAGE.
28bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman */
29bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
30bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/*
31bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Pseudo-implementation of RFC2553 name / address resolution functions
32bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman *
33bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * But these functions are not implemented correctly. The minimum subset
34bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * is implemented for ssh use only. For example, this routine assumes
35bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * that ai_family is AF_INET. Don't use it for another purpose.
36bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman */
37bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
38bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "includes.h"
39bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
40bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <stdlib.h>
41bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <string.h>
42bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
43bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <netinet/in.h>
44bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <arpa/inet.h>
45bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
46bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#ifndef HAVE_GETNAMEINFO
47bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanint getnameinfo(const struct sockaddr *sa, size_t salen, char *host,
48bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman                size_t hostlen, char *serv, size_t servlen, int flags)
49bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{
50bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	struct sockaddr_in *sin = (struct sockaddr_in *)sa;
51bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	struct hostent *hp;
52bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	char tmpserv[16];
53bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
54bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	if (sa->sa_family != AF_UNSPEC && sa->sa_family != AF_INET)
55bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		return (EAI_FAMILY);
56bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	if (serv != NULL) {
57bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		snprintf(tmpserv, sizeof(tmpserv), "%d", ntohs(sin->sin_port));
58bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		if (strlcpy(serv, tmpserv, servlen) >= servlen)
59bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman			return (EAI_MEMORY);
60bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	}
61bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
62bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	if (host != NULL) {
63bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		if (flags & NI_NUMERICHOST) {
64bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman			if (strlcpy(host, inet_ntoa(sin->sin_addr),
65bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman			    hostlen) >= hostlen)
66bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman				return (EAI_MEMORY);
67bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman			else
68bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman				return (0);
69bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		} else {
70bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman			hp = gethostbyaddr((char *)&sin->sin_addr,
71bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman			    sizeof(struct in_addr), AF_INET);
72bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman			if (hp == NULL)
73bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman				return (EAI_NODATA);
74bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
75bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman			if (strlcpy(host, hp->h_name, hostlen) >= hostlen)
76bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman				return (EAI_MEMORY);
77bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman			else
78bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman				return (0);
79bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		}
80bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	}
81bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	return (0);
82bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman}
83bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#endif /* !HAVE_GETNAMEINFO */
84bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
85bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#ifndef HAVE_GAI_STRERROR
86bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#ifdef HAVE_CONST_GAI_STRERROR_PROTO
87bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanconst char *
88bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#else
89bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanchar *
90bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#endif
91bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmangai_strerror(int err)
92bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{
93bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	switch (err) {
94bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	case EAI_NODATA:
95bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		return ("no address associated with name");
96bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	case EAI_MEMORY:
97bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		return ("memory allocation failure.");
98bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	case EAI_NONAME:
99bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		return ("nodename nor servname provided, or not known");
100bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	case EAI_FAMILY:
101bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		return ("ai_family not supported");
102bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	default:
103bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		return ("unknown/invalid error.");
104bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	}
105bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman}
106bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#endif /* !HAVE_GAI_STRERROR */
107bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
108bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#ifndef HAVE_FREEADDRINFO
109bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanvoid
110bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanfreeaddrinfo(struct addrinfo *ai)
111bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{
112bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	struct addrinfo *next;
113bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
114bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	for(; ai != NULL;) {
115bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		next = ai->ai_next;
116bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		free(ai);
117bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		ai = next;
118bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	}
119bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman}
120bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#endif /* !HAVE_FREEADDRINFO */
121bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
122bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#ifndef HAVE_GETADDRINFO
123bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanstatic struct
124bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanaddrinfo *malloc_ai(int port, u_long addr, const struct addrinfo *hints)
125bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{
126bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	struct addrinfo *ai;
127bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
128bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	ai = malloc(sizeof(*ai) + sizeof(struct sockaddr_in));
129bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	if (ai == NULL)
130bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		return (NULL);
131bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
132bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	memset(ai, '\0', sizeof(*ai) + sizeof(struct sockaddr_in));
133bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
134bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	ai->ai_addr = (struct sockaddr *)(ai + 1);
135bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	/* XXX -- ssh doesn't use sa_len */
136bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	ai->ai_addrlen = sizeof(struct sockaddr_in);
137bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	ai->ai_addr->sa_family = ai->ai_family = AF_INET;
138bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
139bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	((struct sockaddr_in *)(ai)->ai_addr)->sin_port = port;
140bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	((struct sockaddr_in *)(ai)->ai_addr)->sin_addr.s_addr = addr;
141bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
142bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	/* XXX: the following is not generally correct, but does what we want */
143bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	if (hints->ai_socktype)
144bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		ai->ai_socktype = hints->ai_socktype;
145bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	else
146bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		ai->ai_socktype = SOCK_STREAM;
147bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
148bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	if (hints->ai_protocol)
149bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		ai->ai_protocol = hints->ai_protocol;
150bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
151bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	return (ai);
152bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman}
153bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
154bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanint
155bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmangetaddrinfo(const char *hostname, const char *servname,
156bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman    const struct addrinfo *hints, struct addrinfo **res)
157bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{
158bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	struct hostent *hp;
159bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	struct servent *sp;
160bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	struct in_addr in;
161bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	int i;
162bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	long int port;
163bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	u_long addr;
164bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
165bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	port = 0;
166bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	if (hints && hints->ai_family != AF_UNSPEC &&
167bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	    hints->ai_family != AF_INET)
168bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		return (EAI_FAMILY);
169bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	if (servname != NULL) {
170bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		char *cp;
171bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
172bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		port = strtol(servname, &cp, 10);
173bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		if (port > 0 && port <= 65535 && *cp == '\0')
174bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman			port = htons(port);
175bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		else if ((sp = getservbyname(servname, NULL)) != NULL)
176bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman			port = sp->s_port;
177bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		else
178bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman			port = 0;
179bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	}
180bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
181bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	if (hints && hints->ai_flags & AI_PASSIVE) {
182bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		addr = htonl(0x00000000);
183bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		if (hostname && inet_aton(hostname, &in) != 0)
184bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman			addr = in.s_addr;
185bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		*res = malloc_ai(port, addr, hints);
186bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		if (*res == NULL)
187bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman			return (EAI_MEMORY);
188bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		return (0);
189bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	}
190bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
191bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	if (!hostname) {
192bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		*res = malloc_ai(port, htonl(0x7f000001), hints);
193bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		if (*res == NULL)
194bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman			return (EAI_MEMORY);
195bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		return (0);
196bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	}
197bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
198bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	if (inet_aton(hostname, &in)) {
199bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		*res = malloc_ai(port, in.s_addr, hints);
200bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		if (*res == NULL)
201bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman			return (EAI_MEMORY);
202bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		return (0);
203bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	}
204bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
205bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	/* Don't try DNS if AI_NUMERICHOST is set */
206bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	if (hints && hints->ai_flags & AI_NUMERICHOST)
207bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		return (EAI_NONAME);
208bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
209bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	hp = gethostbyname(hostname);
210bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	if (hp && hp->h_name && hp->h_name[0] && hp->h_addr_list[0]) {
211bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		struct addrinfo *cur, *prev;
212bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
213bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		cur = prev = *res = NULL;
214bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		for (i = 0; hp->h_addr_list[i]; i++) {
215bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman			struct in_addr *in = (struct in_addr *)hp->h_addr_list[i];
216bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
217bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman			cur = malloc_ai(port, in->s_addr, hints);
218bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman			if (cur == NULL) {
219bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman				if (*res != NULL)
220bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman					freeaddrinfo(*res);
221bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman				return (EAI_MEMORY);
222bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman			}
223bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman			if (prev)
224bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman				prev->ai_next = cur;
225bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman			else
226bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman				*res = cur;
227bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
228bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman			prev = cur;
229bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		}
230bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		return (0);
231bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	}
232bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
233bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	return (EAI_NODATA);
234bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman}
235bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#endif /* !HAVE_GETADDRINFO */
236