xref: /netbsd-src/external/bsd/libbind/dist/irs/gethostent_r.c (revision 5bbd2a12505d72a8177929a37b5cee489d0a1cfd)
1 /*	$NetBSD: gethostent_r.c,v 1.1.1.2 2012/09/09 16:07:57 christos Exp $	*/
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)
21 static 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 
39 static HOST_R_RETURN
40 copy_hostent(struct hostent *, struct hostent *, HOST_R_COPY_ARGS);
41 
42 HOST_R_RETURN
gethostbyname_r(const char * name,struct hostent * hptr,HOST_R_ARGS)43 gethostbyname_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 
68 HOST_R_RETURN
gethostbyaddr_r(const char * addr,int len,int type,struct hostent * hptr,HOST_R_ARGS)69 gethostbyaddr_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 
101 HOST_R_RETURN
gethostent_r(struct hostent * hptr,HOST_R_ARGS)102 gethostent_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 
127 HOST_R_SET_RETURN
128 #ifdef HOST_R_ENT_ARGS
sethostent_r(int stay_open,HOST_R_ENT_ARGS)129 sethostent_r(int stay_open, HOST_R_ENT_ARGS)
130 #else
131 sethostent_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 
143 HOST_R_END_RETURN
144 #ifdef HOST_R_ENT_ARGS
endhostent_r(HOST_R_ENT_ARGS)145 endhostent_r(HOST_R_ENT_ARGS)
146 #else
147 endhostent_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
160 static HOST_R_RETURN
copy_hostent(struct hostent * he,struct hostent * hptr,HOST_R_COPY_ARGS)161 copy_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 */
220 static int
copy_hostent(struct hostent * he,struct hostent * hptr,HOST_R_COPY_ARGS)221 copy_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