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