gethostby_door.c revision 1219:f89f56c2d9ac
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License").  You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22
23/*
24 * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
25 * Use is subject to license terms.
26 */
27
28#pragma ident	"%Z%%M%	%I%	%E% SMI"
29
30#include "mt.h"
31#include <pwd.h>
32#include <strings.h>
33#include <sys/mman.h>
34#include <sys/door.h>
35#include <errno.h>
36#include <fcntl.h>
37#include <synch.h>
38#include <getxby_door.h>
39#include "nss.h"
40
41#ifdef PIC
42
43static struct hostent *process_gethost(struct hostent *, char *, int, int *,
44    nsc_data_t *);
45
46struct hostent *
47_door_gethostbyname_r(const char *name, struct hostent *result, char *buffer,
48	int buflen, int *h_errnop)
49{
50
51	/*
52	 * allocate space on the stack for the nscd to return
53	 * host and host alias information
54	 */
55	union {
56		nsc_data_t 	s_d;
57		char		s_b[8192];
58	} space;
59	nsc_data_t	*sptr;
60	int		ndata;
61	int		adata;
62	struct	hostent *resptr = NULL;
63
64	if ((name == NULL) ||
65	    (strlen(name) >= (sizeof (space) - sizeof (nsc_data_t)))) {
66		errno = ERANGE;
67		if (h_errnop)
68			*h_errnop = HOST_NOT_FOUND;
69		return (NULL);
70	}
71
72	adata = (sizeof (nsc_call_t) + strlen(name) + 1);
73	ndata = sizeof (space);
74	space.s_d.nsc_call.nsc_callnumber = GETHOSTBYNAME;
75	(void) strcpy(space.s_d.nsc_call.nsc_u.name, name);
76	sptr = &space.s_d;
77
78	switch (_nsc_trydoorcall(&sptr, &ndata, &adata)) {
79	    case SUCCESS:	/* positive cache hit */
80		break;
81	    case NOTFOUND:	/* negative cache hit */
82		if (h_errnop)
83		    *h_errnop = space.s_d.nsc_ret.nsc_errno;
84		return (NULL);
85	    default:
86		return ((struct hostent *)_switch_gethostbyname_r(name,
87		    result, buffer, buflen, h_errnop));
88	}
89	resptr = process_gethost(result, buffer, buflen, h_errnop, sptr);
90
91	/*
92	 * check if doors realloced buffer underneath of us....
93	 * munmap or suffer a memory leak
94	 */
95
96	if (sptr != &space.s_d) {
97		munmap((char *)sptr, ndata); /* return memory */
98	}
99
100	return (resptr);
101}
102
103struct hostent *
104_door_gethostbyaddr_r(const char *addr, int length, int type,
105	struct hostent *result, char *buffer, int buflen, int *h_errnop)
106{
107	/*
108	 * allocate space on the stack for the nscd to return
109	 * host and host alias information
110	 */
111	union {
112		nsc_data_t 	s_d;
113		char		s_b[8192];
114	} space;
115	nsc_data_t 	*sptr;
116	int		ndata;
117	int		adata;
118	struct	hostent *resptr = NULL;
119
120	if (addr == NULL) {
121		if (h_errnop)
122			*h_errnop = HOST_NOT_FOUND;
123		return (NULL);
124	}
125
126	ndata = sizeof (space);
127	adata = length + sizeof (nsc_call_t) + 1;
128	sptr = &space.s_d;
129
130	space.s_d.nsc_call.nsc_callnumber = GETHOSTBYADDR;
131	space.s_d.nsc_call.nsc_u.addr.a_type = type;
132	space.s_d.nsc_call.nsc_u.addr.a_length = length;
133	(void) memcpy(space.s_d.nsc_call.nsc_u.addr.a_data, addr, length);
134
135	switch (_nsc_trydoorcall(&sptr, &ndata, &adata)) {
136	    case SUCCESS:	/* positive cache hit */
137		break;
138	    case NOTFOUND:	/* negative cache hit */
139		if (h_errnop)
140		    *h_errnop = space.s_d.nsc_ret.nsc_errno;
141		return (NULL);
142	    default:
143		return ((struct hostent *)_switch_gethostbyaddr_r(addr,
144		    length, type, result, buffer, buflen, h_errnop));
145	}
146
147	resptr = process_gethost(result, buffer, buflen, h_errnop, sptr);
148
149	/*
150	 * check if doors realloced buffer underneath of us....
151	 * munmap it or suffer a memory leak
152	 */
153
154	if (sptr != &space.s_d) {
155		munmap((char *)sptr, ndata); /* return memory */
156	}
157
158	return (resptr);
159
160}
161
162#if !defined(_LP64)
163
164static struct hostent *
165process_gethost(struct hostent *result, char *buffer, int buflen,
166	int *h_errnop, nsc_data_t *sptr)
167{
168	int i;
169
170	char *fixed;
171
172	fixed = (char *)(((int)buffer +3) & ~3);
173	buflen -= fixed - buffer;
174	buffer = fixed;
175
176	if (buflen + sizeof (struct hostent)
177	    < sptr->nsc_ret.nsc_bufferbytesused) {
178		/*
179		 * no enough space allocated by user
180		 */
181		errno = ERANGE;
182		if (h_errnop)
183			*h_errnop = HOST_NOT_FOUND;
184		return (NULL);
185	}
186
187	(void) memcpy(buffer,
188	    sptr->nsc_ret.nsc_u.buff + sizeof (struct hostent),
189	    sptr->nsc_ret.nsc_bufferbytesused - sizeof (struct hostent));
190
191	sptr->nsc_ret.nsc_u.hst.h_name += (int)buffer;
192	sptr->nsc_ret.nsc_u.hst.h_aliases =
193	    (char **)((char *)sptr->nsc_ret.nsc_u.hst.h_aliases + (int)buffer);
194	sptr->nsc_ret.nsc_u.hst.h_addr_list =
195	    (char **)((char *)sptr->nsc_ret.nsc_u.hst.h_addr_list +
196	    (int)buffer);
197	for (i = 0; sptr->nsc_ret.nsc_u.hst.h_aliases[i]; i++) {
198		sptr->nsc_ret.nsc_u.hst.h_aliases[i] += (int)buffer;
199	}
200	for (i = 0; sptr->nsc_ret.nsc_u.hst.h_addr_list[i]; i++) {
201		sptr->nsc_ret.nsc_u.hst.h_addr_list[i] += (int)buffer;
202	}
203
204	*result = sptr->nsc_ret.nsc_u.hst;
205
206	return (result);
207}
208
209#else /* _LP64 */
210
211#define	RNDUP(buf, n) (((uintptr_t)buf + n - 1l) & ~(n - 1l))
212
213static struct hostent *
214process_gethost(struct hostent *result, char *buffer, int buflen,
215	int *h_errnop, nsc_data_t *sptr)
216{
217	char *fixed;
218	char *dest;
219	char *start;
220	char **aliaseslist;
221	char **addrlist;
222	int *alias;
223	int *address;
224	size_t strs;
225	int numaliases;
226	int numaddrs;
227	int i;
228
229	fixed = (char *)RNDUP(buffer, sizeof (char *));
230	buflen -= fixed - buffer;
231	buffer = fixed;
232
233	if (buflen < 0) {
234		/* no enough space allocated by user */
235		errno = ERANGE;
236		if (h_errnop)
237			*h_errnop = HOST_NOT_FOUND;
238		return (NULL);
239	}
240
241	/* find out whether the user has provided sufficient space */
242
243	start = sptr->nsc_ret.nsc_u.buff + sizeof (struct hostent32);
244	strs = 1 + strlen(sptr->nsc_ret.nsc_u.hst.h_name + start);
245	alias = (int *)(start + sptr->nsc_ret.nsc_u.hst.h_aliases);
246	for (numaliases = 0; alias[numaliases]; numaliases++)
247	    strs += 1 + strlen(start + alias[numaliases]);
248	strs = RNDUP(strs, sizeof (int));
249	strs += sizeof (char *) * (numaliases + 1);
250	address = (int *)(start + sptr->nsc_ret.nsc_u.hst.h_addr_list);
251	for (numaddrs = 0; address[numaddrs]; numaddrs++)
252	    strs += RNDUP(sptr->nsc_ret.nsc_u.hst.h_length, sizeof (int));
253	strs += sizeof (char *) * (numaddrs + 1);
254
255	if (buflen < strs) {
256
257		/* no enough space allocated by user */
258
259		errno = ERANGE;
260		if (h_errnop)
261			*h_errnop = HOST_NOT_FOUND;
262		return (NULL);
263	}
264
265
266	/*
267	 * allocat the h_aliases list and the h_addr_list first to align 'em.
268	 */
269
270	dest = buffer;
271	aliaseslist = (char **)dest;
272	dest += sizeof (char *) * (numaliases + 1);
273	addrlist = (char **)dest;
274	dest += sizeof (char *) * (numaddrs + 1);
275
276	/* fill out h_name */
277
278	start = sptr->nsc_ret.nsc_u.buff + sizeof (struct hostent32);
279	(void) strcpy(dest, sptr->nsc_ret.nsc_u.hst.h_name + start);
280	strs = 1 + strlen(sptr->nsc_ret.nsc_u.hst.h_name + start);
281	result->h_name = dest;
282	dest += strs;
283
284	/*
285	 * fill out the h_aliases list
286	 */
287	for (i = 0; i < numaliases; i++) {
288		alias = (int *)(start + sptr->nsc_ret.nsc_u.hst.h_aliases);
289		(void) strcpy(dest, start + alias[i]);
290		strs = 1 + strlen(start + alias[i]);
291		aliaseslist[i] = dest;
292		dest += strs;
293	}
294	aliaseslist[i] = 0;	/* null term ptr chain */
295
296	result->h_aliases = aliaseslist;
297
298	/*
299	 * fill out the h_addr list
300	 */
301
302	dest = (char *)RNDUP(dest, sizeof (int));
303
304	for (i = 0; i < numaddrs; i++) {
305		address = (int *)(start + sptr->nsc_ret.nsc_u.hst.h_addr_list);
306		(void) memcpy(dest, start + address[i],
307		    sptr->nsc_ret.nsc_u.hst.h_length);
308		strs = sptr->nsc_ret.nsc_u.hst.h_length;
309		addrlist[i] = dest;
310		dest += strs;
311		dest = (char *)RNDUP(dest, sizeof (int));
312	}
313
314	addrlist[i] = 0;	/* null term ptr chain */
315
316	result->h_addr_list = addrlist;
317
318	result->h_length = sptr->nsc_ret.nsc_u.hst.h_length;
319	result->h_addrtype = sptr->nsc_ret.nsc_u.hst.h_addrtype;
320
321	return (result);
322}
323#endif /* _LP64 */
324#endif /* PIC */
325