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