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