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