xref: /titanic_44/usr/src/lib/libnsl/nss/getipnodeby_door.c (revision 8eea8e29cc4374d1ee24c25a07f45af132db3499)
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  * Copyright 1998-2003 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <pwd.h>
30 #include <strings.h>
31 #include <sys/mman.h>
32 #include <sys/door.h>
33 #include <errno.h>
34 #include <fcntl.h>
35 #include <synch.h>
36 #include <getxby_door.h>
37 #include <nss_dbdefs.h>
38 #include "nss.h"
39 
40 #ifdef PIC
41 
42 static struct hostent *__process_getipnode(struct hostent *, char *, int, int *,
43     nsc_data_t *);
44 
45 struct hostent *
46 _door_getipnodebyname_r(const char *name, struct hostent *result, char *buffer,
47 	int buflen, int af_family, int flags, int *h_errnop)
48 {
49 
50 	/*
51 	 * allocate space on the stack for the nscd to return
52 	 * host and host alias information
53 	 */
54 	union {
55 		nsc_data_t 	s_d;
56 		char		s_b[8192];
57 	} space;
58 	nsc_data_t	*sptr;
59 	int		ndata;
60 	int		adata;
61 	struct	hostent *resptr = NULL;
62 
63 	if ((name == (const char *)NULL) ||
64 	    (strlen(name) >= (sizeof (space) - sizeof (nsc_data_t)
65 					- 2 * sizeof (int)))) {
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 + 2 * sizeof (int));
73 	ndata = sizeof (space);
74 	space.s_d.nsc_call.nsc_callnumber = GETIPNODEBYNAME;
75 	space.s_d.nsc_call.nsc_u.ipnode.af_family = af_family;
76 	space.s_d.nsc_call.nsc_u.ipnode.flags = flags;
77 	strcpy(space.s_d.nsc_call.nsc_u.ipnode.name, name);
78 	sptr = &space.s_d;
79 
80 	switch (_nsc_trydoorcall(&sptr, &ndata, &adata)) {
81 	    case SUCCESS:	/* positive cache hit */
82 		break;
83 	    case NOTFOUND:	/* negative cache hit */
84 		if (h_errnop)
85 		    *h_errnop = space.s_d.nsc_ret.nsc_errno;
86 		return (NULL);
87 	    default:
88 		return ((struct hostent *)_switch_getipnodebyname_r(name,
89 		    result, buffer, buflen, af_family, flags, h_errnop));
90 	}
91 	resptr = __process_getipnode(result, buffer, buflen, h_errnop, sptr);
92 
93 	/*
94 	 * check if doors realloced buffer underneath of us....
95 	 * munmap or suffer a memory leak
96 	 */
97 
98 	if (sptr != &space.s_d) {
99 		munmap((char *)sptr, ndata); /* return memory */
100 	}
101 
102 	return (resptr);
103 }
104 
105 struct hostent *
106 _door_getipnodebyaddr_r(const char *addr, int length, int type,
107 	struct hostent *result, char *buffer, int buflen, int *h_errnop)
108 {
109 	/*
110 	 * allocate space on the stack for the nscd to return
111 	 * host and host alias information
112 	 */
113 	union {
114 		nsc_data_t 	s_d;
115 		char		s_b[8192];
116 	} space;
117 	nsc_data_t 	*sptr;
118 	int		ndata;
119 	int		adata;
120 	struct	hostent *resptr = NULL;
121 
122 	if (addr == (const char *)NULL) {
123 		if (h_errnop)
124 			*h_errnop = HOST_NOT_FOUND;
125 		return (NULL);
126 	}
127 
128 	ndata = sizeof (space);
129 	adata = length + sizeof (nsc_call_t) + 1;
130 	sptr = &space.s_d;
131 
132 	space.s_d.nsc_call.nsc_callnumber = GETIPNODEBYADDR;
133 	space.s_d.nsc_call.nsc_u.addr.a_type = type;
134 	space.s_d.nsc_call.nsc_u.addr.a_length = length;
135 	memcpy(space.s_d.nsc_call.nsc_u.addr.a_data, addr, length);
136 
137 	switch (_nsc_trydoorcall(&sptr, &ndata, &adata)) {
138 	    case SUCCESS:	/* positive cache hit */
139 		break;
140 	    case NOTFOUND:	/* negative cache hit */
141 		if (h_errnop)
142 		    *h_errnop = space.s_d.nsc_ret.nsc_errno;
143 		return (NULL);
144 	    default:
145 		return ((struct hostent *)_switch_getipnodebyaddr_r(addr,
146 		    length, type, result, buffer, buflen, h_errnop));
147 	}
148 
149 	resptr = __process_getipnode(result, buffer, buflen, h_errnop, sptr);
150 
151 	/*
152 	 * check if doors realloced buffer underneath of us....
153 	 * munmap it or suffer a memory leak
154 	 */
155 
156 	if (sptr != &space.s_d) {
157 		munmap((char *)sptr, ndata); /* return memory */
158 	}
159 
160 	return (resptr);
161 }
162 
163 #if !defined(_LP64)
164 
165 static struct hostent *
166 __process_getipnode(struct hostent *result, char *buffer, int buflen,
167 	int *h_errnop, nsc_data_t *sptr)
168 {
169 	int i;
170 
171 	char *fixed;
172 
173 	fixed = (char *)ROUND_UP((int)buffer, sizeof (char *));
174 	buflen -= fixed - buffer;
175 	buffer = fixed;
176 
177 	if (buflen + sizeof (struct hostent)
178 	    < sptr->nsc_ret.nsc_bufferbytesused) {
179 		/*
180 		 * no enough space allocated by user
181 		 */
182 		errno = ERANGE;
183 		if (h_errnop)
184 			*h_errnop = HOST_NOT_FOUND;
185 		return (NULL);
186 	}
187 
188 	memcpy(buffer, 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 static struct hostent *
212 __process_getipnode(struct hostent *result, char *buffer, int buflen,
213 	int *h_errnop, nsc_data_t *sptr)
214 {
215 	char *fixed;
216 	char *dest;
217 	char *start;
218 	char **aliaseslist;
219 	char **addrlist;
220 	int *alias;
221 	int *address;
222 	size_t strs;
223 	int numaliases;
224 	int numaddrs;
225 	int i;
226 
227 	fixed = (char *)ROUND_UP(buffer, sizeof (char *));
228 	buflen -= fixed - buffer;
229 	buffer = fixed;
230 	if (buflen < 0) {
231 		/* no enough space allocated by user */
232 		errno = ERANGE;
233 		if (h_errnop)
234 			*h_errnop = HOST_NOT_FOUND;
235 		return (NULL);
236 	}
237 
238 	/*
239 	 * find out whether the user has provided sufficient space
240 	 */
241 	start = sptr->nsc_ret.nsc_u.buff + sizeof (struct hostent32);
242 	/*
243 	 * Length of hostname + null
244 	 */
245 	strs = 1 + strlen(sptr->nsc_ret.nsc_u.hst.h_name + start);
246 	/*
247 	 * length of all aliases + null
248 	 */
249 	alias = (int *)(start + sptr->nsc_ret.nsc_u.hst.h_aliases);
250 	for (numaliases = 0; alias[numaliases]; numaliases++)
251 	    strs += 1 + strlen(start + alias[numaliases]);
252 	/*
253 	 * Realign on word boundary
254 	 */
255 	strs = ROUND_UP(strs, sizeof (char *));
256 	/*
257 	 * Count the array of pointers to all aliases + null pointer
258 	 */
259 	strs += sizeof (char *) * (numaliases + 1);
260 	/*
261 	 * length of all addresses + null. Also, account for word alignment.
262 	 */
263 	address = (int *)(start + sptr->nsc_ret.nsc_u.hst.h_addr_list);
264 	for (numaddrs = 0; address[numaddrs]; numaddrs++) {
265 		strs += sptr->nsc_ret.nsc_u.hst.h_length;
266 		strs = ROUND_UP(strs, sizeof (char *));
267 	}
268 	/*
269 	 * Count the array of pointers to all addresses + null pointer
270 	 */
271 	strs += sizeof (char *) * (numaddrs + 1);
272 
273 	if (buflen < strs) {
274 
275 		/* no enough space allocated by user */
276 
277 		errno = ERANGE;
278 		if (h_errnop)
279 			*h_errnop = HOST_NOT_FOUND;
280 		return (NULL);
281 	}
282 
283 	/*
284 	 * allocat the h_aliases list and the h_addr_list first to align 'em.
285 	 */
286 	dest = buffer;
287 	aliaseslist = (char **)dest;
288 	dest += sizeof (char *) * (numaliases + 1);
289 	addrlist = (char **)dest;
290 	dest += sizeof (char *) * (numaddrs + 1);
291 	/*
292 	 * fill out h_name
293 	 */
294 	start = sptr->nsc_ret.nsc_u.buff + sizeof (struct hostent32);
295 	strcpy(dest, sptr->nsc_ret.nsc_u.hst.h_name + start);
296 	strs = 1 + strlen(sptr->nsc_ret.nsc_u.hst.h_name + start);
297 	result->h_name = dest;
298 	dest += strs;
299 	/*
300 	 * fill out the h_aliases list
301 	 */
302 	alias = (int *)(start + sptr->nsc_ret.nsc_u.hst.h_aliases);
303 	for (i = 0; i < numaliases; i++) {
304 		strcpy(dest, start + alias[i]);
305 		aliaseslist[i] = dest;
306 		dest += 1 + strlen(start + alias[i]);
307 	}
308 	aliaseslist[i] = 0;	/* null term ptr chain */
309 	result->h_aliases = aliaseslist;
310 
311 	/*
312 	 * fill out the h_addr list
313 	 */
314 	dest = (char *)ROUND_UP(dest, sizeof (char *));
315 	address = (int *)(start + sptr->nsc_ret.nsc_u.hst.h_addr_list);
316 	for (i = 0; i < numaddrs; i++) {
317 		memcpy(dest, start + address[i],
318 		    sptr->nsc_ret.nsc_u.hst.h_length);
319 		addrlist[i] = dest;
320 		dest += sptr->nsc_ret.nsc_u.hst.h_length;
321 		dest = (char *)ROUND_UP(dest, sizeof (char *));
322 	}
323 
324 	addrlist[i] = 0;	/* null term ptr chain */
325 
326 	result->h_addr_list = addrlist;
327 
328 	result->h_length = sptr->nsc_ret.nsc_u.hst.h_length;
329 	result->h_addrtype = sptr->nsc_ret.nsc_u.hst.h_addrtype;
330 
331 	return (result);
332 }
333 #endif /* _LP64 */
334 
335 #endif /* PIC */
336