1/*	$NetBSD$	*/
2
3/*
4 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (c) 1998-1999 by Internet Software Consortium.
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
17 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20#if defined(LIBC_SCCS) && !defined(lint)
21static const char rcsid[] = "Id: gethostent_r.c,v 1.9 2005/09/03 12:41:37 marka Exp";
22#endif /* LIBC_SCCS and not lint */
23
24#include <port_before.h>
25#if !defined(_REENTRANT) || !defined(DO_PTHREADS)
26	static int gethostent_r_not_required = 0;
27#else
28#include <errno.h>
29#include <string.h>
30#include <stdio.h>
31#include <sys/types.h>
32#include <netinet/in.h>
33#include <netdb.h>
34#include <sys/param.h>
35#include <port_after.h>
36
37#ifdef HOST_R_RETURN
38
39static HOST_R_RETURN
40copy_hostent(struct hostent *, struct hostent *, HOST_R_COPY_ARGS);
41
42HOST_R_RETURN
43gethostbyname_r(const char *name,  struct hostent *hptr, HOST_R_ARGS) {
44	struct hostent *he = gethostbyname(name);
45#ifdef HOST_R_SETANSWER
46	int n = 0;
47#endif
48
49#ifdef HOST_R_ERRNO
50	HOST_R_ERRNO;
51#endif
52
53#ifdef HOST_R_SETANSWER
54	if (he == NULL || (n = copy_hostent(he, hptr, HOST_R_COPY)) != 0)
55		*answerp = NULL;
56	else
57		*answerp = hptr;
58
59	return (n);
60#else
61	if (he == NULL)
62		return (HOST_R_BAD);
63
64	return (copy_hostent(he, hptr, HOST_R_COPY));
65#endif
66}
67
68HOST_R_RETURN
69gethostbyaddr_r(const char *addr, int len, int type,
70		struct hostent *hptr, HOST_R_ARGS) {
71	struct hostent *he = gethostbyaddr(addr, len, type);
72#ifdef HOST_R_SETANSWER
73	int n = 0;
74#endif
75
76#ifdef HOST_R_ERRNO
77	HOST_R_ERRNO;
78#endif
79
80#ifdef HOST_R_SETANSWER
81	if (he == NULL || (n = copy_hostent(he, hptr, HOST_R_COPY)) != 0)
82		*answerp = NULL;
83	else
84		*answerp = hptr;
85
86	return (n);
87#else
88	if (he == NULL)
89		return (HOST_R_BAD);
90
91	return (copy_hostent(he, hptr, HOST_R_COPY));
92#endif
93}
94
95/*%
96 *	These assume a single context is in operation per thread.
97 *	If this is not the case we will need to call irs directly
98 *	rather than through the base functions.
99 */
100
101HOST_R_RETURN
102gethostent_r(struct hostent *hptr, HOST_R_ARGS) {
103	struct hostent *he = gethostent();
104#ifdef HOST_R_SETANSWER
105	int n = 0;
106#endif
107
108#ifdef HOST_R_ERRNO
109	HOST_R_ERRNO;
110#endif
111
112#ifdef HOST_R_SETANSWER
113	if (he == NULL || (n = copy_hostent(he, hptr, HOST_R_COPY)) != 0)
114		*answerp = NULL;
115	else
116		*answerp = hptr;
117
118	return (n);
119#else
120	if (he == NULL)
121		return (HOST_R_BAD);
122
123	return (copy_hostent(he, hptr, HOST_R_COPY));
124#endif
125}
126
127HOST_R_SET_RETURN
128#ifdef HOST_R_ENT_ARGS
129sethostent_r(int stay_open, HOST_R_ENT_ARGS)
130#else
131sethostent_r(int stay_open)
132#endif
133{
134#ifdef HOST_R_ENT_ARGS
135	UNUSED(hdptr);
136#endif
137	sethostent(stay_open);
138#ifdef	HOST_R_SET_RESULT
139	return (HOST_R_SET_RESULT);
140#endif
141}
142
143HOST_R_END_RETURN
144#ifdef HOST_R_ENT_ARGS
145endhostent_r(HOST_R_ENT_ARGS)
146#else
147endhostent_r(void)
148#endif
149{
150#ifdef HOST_R_ENT_ARGS
151	UNUSED(hdptr);
152#endif
153	endhostent();
154	HOST_R_END_RESULT(HOST_R_OK);
155}
156
157/* Private */
158
159#ifndef HOSTENT_DATA
160static HOST_R_RETURN
161copy_hostent(struct hostent *he, struct hostent *hptr, HOST_R_COPY_ARGS) {
162	char *cp;
163	char **ptr;
164	int i, n;
165	int nptr, len;
166
167	/* Find out the amount of space required to store the answer. */
168	nptr = 2; /*%< NULL ptrs */
169	len = (char *)ALIGN(buf) - buf;
170	for (i = 0; he->h_addr_list[i]; i++, nptr++) {
171		len += he->h_length;
172	}
173	for (i = 0; he->h_aliases[i]; i++, nptr++) {
174		len += strlen(he->h_aliases[i]) + 1;
175	}
176	len += strlen(he->h_name) + 1;
177	len += nptr * sizeof(char*);
178
179	if (len > buflen) {
180		errno = ERANGE;
181		return (HOST_R_BAD);
182	}
183
184	/* copy address size and type */
185	hptr->h_addrtype = he->h_addrtype;
186	n = hptr->h_length = he->h_length;
187
188	ptr = (char **)ALIGN(buf);
189	cp = (char *)ALIGN(buf) + nptr * sizeof(char *);
190
191	/* copy address list */
192	hptr->h_addr_list = ptr;
193	for (i = 0; he->h_addr_list[i]; i++ , ptr++) {
194		memcpy(cp, he->h_addr_list[i], n);
195		hptr->h_addr_list[i] = cp;
196		cp += n;
197	}
198	hptr->h_addr_list[i] = NULL;
199	ptr++;
200
201	/* copy official name */
202	n = strlen(he->h_name) + 1;
203	strcpy(cp, he->h_name);
204	hptr->h_name = cp;
205	cp += n;
206
207	/* copy aliases */
208	hptr->h_aliases = ptr;
209	for (i = 0 ; he->h_aliases[i]; i++) {
210		n = strlen(he->h_aliases[i]) + 1;
211		strcpy(cp, he->h_aliases[i]);
212		hptr->h_aliases[i] = cp;
213		cp += n;
214	}
215	hptr->h_aliases[i] = NULL;
216
217	return (HOST_R_OK);
218}
219#else /* !HOSTENT_DATA */
220static int
221copy_hostent(struct hostent *he, struct hostent *hptr, HOST_R_COPY_ARGS) {
222	char *cp, *eob;
223	int i, n;
224
225	/* copy address size and type */
226	hptr->h_addrtype = he->h_addrtype;
227	n = hptr->h_length = he->h_length;
228
229	/* copy up to first 35 addresses */
230	i = 0;
231	cp = hdptr->hostbuf;
232	eob = hdptr->hostbuf + sizeof(hdptr->hostbuf);
233	hptr->h_addr_list = hdptr->h_addr_ptrs;
234	while (he->h_addr_list[i] && i < (_MAXADDRS)) {
235		if (n < (eob - cp)) {
236			memcpy(cp, he->h_addr_list[i], n);
237			hptr->h_addr_list[i] = cp;
238			cp += n;
239		} else {
240			break;
241		}
242		i++;
243	}
244	hptr->h_addr_list[i] = NULL;
245
246	/* copy official name */
247	if ((n = strlen(he->h_name) + 1) < (eob - cp)) {
248		strcpy(cp, he->h_name);
249		hptr->h_name = cp;
250		cp += n;
251	} else {
252		return (-1);
253	}
254
255	/* copy aliases */
256	i = 0;
257	hptr->h_aliases = hdptr->host_aliases;
258	while (he->h_aliases[i] && i < (_MAXALIASES-1)) {
259		if ((n = strlen(he->h_aliases[i]) + 1) < (eob - cp)) {
260			strcpy(cp, he->h_aliases[i]);
261			hptr->h_aliases[i] = cp;
262			cp += n;
263		} else {
264			break;
265		}
266		i++;
267	}
268	hptr->h_aliases[i] = NULL;
269
270	return (HOST_R_OK);
271}
272#endif /* !HOSTENT_DATA */
273#else /* HOST_R_RETURN */
274	static int gethostent_r_unknown_system = 0;
275#endif /* HOST_R_RETURN */
276#endif /* !defined(_REENTRANT) || !defined(DO_PTHREADS) */
277/*! \file */
278