xref: /titanic_51/usr/src/uts/common/idmap/idmap_kapi.c (revision 0cd13cbfb4270b840b4bd22ec5f673b2b6a2c02b)
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 (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*
28  * Windows to Solaris Identity Mapping kernel API
29  * This module provides an API to map Windows SIDs to
30  * Solaris UID and GIDs.
31  */
32 
33 #pragma ident	"%Z%%M%	%I%	%E% SMI"
34 
35 #include <sys/types.h>
36 #include <sys/ksynch.h>
37 #include <sys/door.h>
38 #include <rpc/rpc_msg.h>
39 #include <rpc/xdr.h>
40 #include <rpc/auth.h>
41 #include <rpc/rpc_sztypes.h>
42 #ifdef	DEBUG
43 #include <sys/cmn_err.h>
44 #endif	/* DEBUG */
45 #include <sys/proc.h>
46 #include <sys/sunddi.h>
47 #include <sys/param.h>
48 #include <sys/atomic.h>
49 #include <sys/sysmacros.h>
50 #include <sys/disp.h>
51 #include <sys/kidmap.h>
52 #include <sys/zone.h>
53 #include "idmap_prot.h"
54 #include "kidmap_priv.h"
55 
56 
57 /*
58  * Defined types
59  */
60 
61 
62 /*
63  * This structure holds pointers for the
64  * batch mapping results.
65  */
66 typedef struct idmap_get_res {
67 	idmap_id_type	idtype;
68 	uid_t		*uid;
69 	gid_t		*gid;
70 	uid_t		*pid;
71 	int		*is_user;
72 	const char	**sid_prefix;
73 	uint32_t	*rid;
74 	idmap_stat	*stat;
75 } idmap_get_res;
76 
77 /* Batch mapping handle structure */
78 struct idmap_get_handle {
79 	struct idmap_zone_specific *zs;
80 	int 		mapping_num;
81 	int 		mapping_size;
82 	idmap_mapping	*mapping;
83 	idmap_get_res	*result;
84 };
85 
86 
87 /* Zone specific data */
88 typedef struct idmap_zone_specific {
89 	kmutex_t	zone_mutex;
90 	idmap_cache_t	cache;
91 	door_handle_t 	door_handle;
92 	int		door_valid;
93 	uint32_t	message_id;
94 } idmap_zone_specific_t;
95 
96 
97 
98 /*
99  * Module global data
100  */
101 
102 static kmutex_t		idmap_zone_mutex;
103 static zone_key_t	idmap_zone_key;
104 
105 
106 /*
107  * Local function definitions
108  */
109 
110 
111 static int
112 kidmap_rpc_call(idmap_zone_specific_t *zs, uint32_t op,
113 		xdrproc_t xdr_args, caddr_t args,
114 		xdrproc_t xdr_res, caddr_t res);
115 
116 static int
117 kidmap_call_door(idmap_zone_specific_t *zs, door_arg_t *arg);
118 
119 static idmap_zone_specific_t *
120 idmap_get_zone_specific(zone_t *zone);
121 
122 
123 
124 int
125 idmap_reg_dh(zone_t *zone, door_handle_t dh)
126 {
127 	idmap_zone_specific_t *zs;
128 
129 	zs = idmap_get_zone_specific(zone);
130 
131 	mutex_enter(&zs->zone_mutex);
132 
133 	if (zs->door_valid)
134 		door_ki_rele(zs->door_handle);
135 
136 	zs->door_handle = dh;
137 	zs->door_valid = 1;
138 
139 	mutex_exit(&zs->zone_mutex);
140 
141 	return (0);
142 }
143 
144 /*
145  * idmap_unreg_dh
146  *
147  * This routine is called by system call idmap_unreg().
148  * idmap_unreg() calls door_ki_rele() on the supplied
149  * door handle after this routine returns. We only
150  * need to perform one door release on zs->door_handle
151  */
152 int
153 idmap_unreg_dh(zone_t *zone, door_handle_t dh)
154 {
155 	idmap_zone_specific_t *zs;
156 
157 	zs = idmap_get_zone_specific(zone);
158 
159 	kidmap_cache_purge(&zs->cache);
160 
161 	mutex_enter(&zs->zone_mutex);
162 
163 	if (!zs->door_valid) {
164 		mutex_exit(&zs->zone_mutex);
165 		return (EINVAL);
166 	}
167 
168 	if (zs->door_handle != dh) {
169 		mutex_exit(&zs->zone_mutex);
170 		return (EINVAL);
171 	}
172 
173 	door_ki_rele(zs->door_handle);
174 
175 	zs->door_valid = 0;
176 	mutex_exit(&zs->zone_mutex);
177 
178 	return (0);
179 }
180 
181 
182 static int
183 kidmap_call_door(idmap_zone_specific_t *zs, door_arg_t *arg)
184 {
185 	door_handle_t dh;
186 	int status = 0;
187 
188 	mutex_enter(&zs->zone_mutex);
189 	if (!zs->door_valid) {
190 		mutex_exit(&zs->zone_mutex);
191 		return (-1);
192 	}
193 	dh = zs->door_handle;
194 	door_ki_hold(dh);
195 	mutex_exit(&zs->zone_mutex);
196 
197 	status = door_ki_upcall(dh, arg);
198 
199 #ifdef	DEBUG
200 	if (status != 0)
201 		cmn_err(CE_WARN, "idmap: Door call failed %d\n", status);
202 #endif	/* DEBUG */
203 
204 	door_ki_rele(dh);
205 
206 	if (status == EBADF) {
207 		/*
208 		 * If we get EBADF we will most likely not get an
209 		 * idmap_unreg_dh().
210 		 */
211 		mutex_enter(&zs->zone_mutex);
212 		if (zs->door_valid) {
213 			zs->door_valid = 0;
214 			door_ki_rele(zs->door_handle);
215 		}
216 		mutex_exit(&zs->zone_mutex);
217 	}
218 
219 	return (status);
220 }
221 
222 
223 static idmap_zone_specific_t *
224 idmap_get_zone_specific(zone_t *zone)
225 {
226 	idmap_zone_specific_t *zs;
227 
228 	ASSERT(zone != NULL);
229 
230 	zs = zone_getspecific(idmap_zone_key, zone);
231 	if (zs != NULL)
232 		return (zs);
233 
234 	mutex_enter(&idmap_zone_mutex);
235 	zs = zone_getspecific(idmap_zone_key, zone);
236 	if (zs == NULL) {
237 		zs = kmem_zalloc(sizeof (idmap_zone_specific_t), KM_SLEEP);
238 		mutex_init(&zs->zone_mutex, NULL, MUTEX_DEFAULT, NULL);
239 		kidmap_cache_create(&zs->cache);
240 		(void) zone_setspecific(idmap_zone_key, zone, zs);
241 		mutex_exit(&idmap_zone_mutex);
242 		return (zs);
243 	}
244 	mutex_exit(&idmap_zone_mutex);
245 
246 	return (zs);
247 }
248 
249 
250 static void
251 /* ARGSUSED */
252 idmap_zone_destroy(zoneid_t zone_id, void *arg)
253 {
254 	idmap_zone_specific_t *zs = arg;
255 	if (zs != NULL) {
256 		kidmap_cache_delete(&zs->cache);
257 		if (zs->door_valid) {
258 			door_ki_rele(zs->door_handle);
259 		}
260 		mutex_destroy(&zs->zone_mutex);
261 		kmem_free(zs, sizeof (idmap_zone_specific_t));
262 	}
263 }
264 
265 
266 int
267 kidmap_start(void)
268 {
269 	mutex_init(&idmap_zone_mutex, NULL, MUTEX_DEFAULT, NULL);
270 	zone_key_create(&idmap_zone_key, NULL, NULL, idmap_zone_destroy);
271 	kidmap_sid_prefix_store_init();
272 
273 	return (0);
274 }
275 
276 
277 int
278 kidmap_stop(void)
279 {
280 	return (EBUSY);
281 }
282 
283 
284 /*
285  * idmap_get_door
286  *
287  * This is called by the system call allocids() to get the door for the
288  * given zone.
289  */
290 door_handle_t
291 idmap_get_door(zone_t *zone)
292 {
293 	door_handle_t dh = NULL;
294 	idmap_zone_specific_t *zs;
295 
296 	zs = idmap_get_zone_specific(zone);
297 
298 	mutex_enter(&zs->zone_mutex);
299 	if (zs->door_valid) {
300 		dh = zs->door_handle;
301 		door_ki_hold(dh);
302 	}
303 	mutex_exit(&zs->zone_mutex);
304 	return (dh);
305 }
306 
307 
308 /*
309  * idmap_purge_cache
310  *
311  * This is called by the system call allocids() to purge the cache for the
312  * given zone.
313  */
314 void
315 idmap_purge_cache(zone_t *zone)
316 {
317 	idmap_zone_specific_t *zs;
318 
319 	zs = idmap_get_zone_specific(zone);
320 
321 	kidmap_cache_purge(&zs->cache);
322 }
323 
324 
325 
326 
327 /*
328  * Given Domain SID and RID, get UID
329  *
330  * Input:
331  * sid_prefix	- Domain SID in canonical form
332  * rid	- RID
333  *
334  * Output:
335  * uid  - POSIX UID if return == IDMAP_SUCCESS
336  *
337  * Return:
338  * Success return IDMAP_SUCCESS else IDMAP error
339  */
340 idmap_stat
341 kidmap_getuidbysid(zone_t *zone, const char *sid_prefix, uint32_t rid,
342 		uid_t *uid)
343 {
344 	idmap_zone_specific_t	*zs;
345 	idmap_mapping_batch	args;
346 	idmap_mapping		mapping;
347 	idmap_ids_res		results;
348 	uint32_t		op = IDMAP_GET_MAPPED_IDS;
349 	const char		*new_sid_prefix;
350 	idmap_stat		status;
351 
352 	if (sid_prefix == NULL || uid == NULL)
353 		return (IDMAP_ERR_ARG);
354 
355 	zs = idmap_get_zone_specific(zone);
356 
357 	if (kidmap_cache_lookup_uidbysid(&zs->cache, sid_prefix, rid, uid)
358 	    == IDMAP_SUCCESS)
359 		return (IDMAP_SUCCESS);
360 
361 	bzero(&mapping, sizeof (idmap_mapping));
362 	mapping.id1.idtype = IDMAP_SID;
363 	mapping.id1.idmap_id_u.sid.prefix = (char *)sid_prefix;
364 	mapping.id1.idmap_id_u.sid.rid = rid;
365 	mapping.id2.idtype = IDMAP_UID;
366 
367 	bzero(&results, sizeof (idmap_ids_res));
368 
369 	args.idmap_mapping_batch_len = 1;
370 	args.idmap_mapping_batch_val = &mapping;
371 
372 	if (kidmap_rpc_call(zs, op, xdr_idmap_mapping_batch,
373 	    (caddr_t)&args, xdr_idmap_ids_res,
374 	    (caddr_t)&results) == 0) {
375 		/* Door call succeded */
376 		if (results.ids.ids_len >= 1 &&
377 		    results.ids.ids_val[0].id.idtype == IDMAP_UID) {
378 			status = results.ids.ids_val[0].retcode;
379 			*uid = results.ids.ids_val[0].id.idmap_id_u.uid;
380 			if (status == IDMAP_SUCCESS) {
381 				new_sid_prefix = kidmap_find_sid_prefix(
382 				    sid_prefix);
383 				kidmap_cache_add_uidbysid(&zs->cache,
384 				    new_sid_prefix, rid, *uid);
385 			}
386 		} else {
387 			status = IDMAP_ERR_NOMAPPING;
388 			*uid = UID_NOBODY;
389 		}
390 		xdr_free(xdr_idmap_ids_res, (char *)&results);
391 	} else {
392 		/* Door call failed */
393 		status = IDMAP_ERR_NOMAPPING;
394 		*uid = UID_NOBODY;
395 	}
396 	return (status);
397 }
398 
399 
400 /*
401  * Given Domain SID and RID, get GID
402  *
403  * Input:
404  * sid_prefix	- Domain SID in canonical form
405  * rid	- RID
406  *
407  * Output:
408  * gid  - POSIX UID if return == IDMAP_SUCCESS
409  *
410  * Return:
411  * Success return IDMAP_SUCCESS else IDMAP error
412  */
413 idmap_stat
414 kidmap_getgidbysid(zone_t *zone, const char *sid_prefix, uint32_t rid,
415 		gid_t *gid)
416 {
417 	idmap_zone_specific_t	*zs;
418 	idmap_mapping_batch	args;
419 	idmap_mapping		mapping;
420 	idmap_ids_res		results;
421 	uint32_t		op = IDMAP_GET_MAPPED_IDS;
422 	const char		*new_sid_prefix;
423 	idmap_stat		status;
424 
425 	if (sid_prefix == NULL || gid == NULL)
426 		return (IDMAP_ERR_ARG);
427 
428 	zs = idmap_get_zone_specific(zone);
429 
430 	if (kidmap_cache_lookup_gidbysid(&zs->cache, sid_prefix, rid, gid)
431 	    == IDMAP_SUCCESS)
432 		return (IDMAP_SUCCESS);
433 
434 	bzero(&mapping, sizeof (idmap_mapping));
435 	mapping.id1.idtype = IDMAP_SID;
436 	mapping.id1.idmap_id_u.sid.prefix = (char *)sid_prefix;
437 	mapping.id1.idmap_id_u.sid.rid = rid;
438 	mapping.id2.idtype = IDMAP_GID;
439 
440 	bzero(&results, sizeof (idmap_ids_res));
441 
442 	args.idmap_mapping_batch_len = 1;
443 	args.idmap_mapping_batch_val = &mapping;
444 
445 	if (kidmap_rpc_call(zs, op, xdr_idmap_mapping_batch,
446 	    (caddr_t)&args, xdr_idmap_ids_res,
447 	    (caddr_t)&results) == 0) {
448 		/* Door call succeded */
449 		if (results.ids.ids_len >= 1 &&
450 		    results.ids.ids_val[0].id.idtype == IDMAP_GID) {
451 			status = results.ids.ids_val[0].retcode;
452 			*gid = results.ids.ids_val[0].id.idmap_id_u.gid;
453 			if (status == IDMAP_SUCCESS) {
454 				new_sid_prefix = kidmap_find_sid_prefix(
455 				    sid_prefix);
456 				kidmap_cache_add_gidbysid(&zs->cache,
457 				    new_sid_prefix, rid, *gid);
458 			}
459 		} else {
460 			status = IDMAP_ERR_NOMAPPING;
461 			*gid = GID_NOBODY;
462 		}
463 		xdr_free(xdr_idmap_ids_res, (char *)&results);
464 	} else {
465 		/* Door call failed */
466 		status = IDMAP_ERR_NOMAPPING;
467 		*gid = GID_NOBODY;
468 	}
469 	return (status);
470 }
471 
472 /*
473  * Given Domain SID and RID, get Posix ID
474  *
475  * Input:
476  * sid_prefix	- Domain SID in canonical form
477  * rid	- RID
478  *
479  * Output:
480  * pid  - POSIX ID if return == IDMAP_SUCCESS
481  * is_user - 1 == UID, 0 == GID  if return == IDMAP_SUCCESS
482  *
483  * Return:
484  * Success return IDMAP_SUCCESS else IDMAP error
485  */
486 idmap_stat
487 kidmap_getpidbysid(zone_t *zone, const char *sid_prefix, uint32_t rid,
488 		uid_t *pid, int *is_user)
489 {
490 	idmap_zone_specific_t	*zs;
491 	idmap_mapping_batch	args;
492 	idmap_mapping		mapping;
493 	idmap_ids_res		results;
494 	uint32_t		op = IDMAP_GET_MAPPED_IDS;
495 	const char		*new_sid_prefix;
496 	idmap_stat		status;
497 
498 	if (sid_prefix == NULL || pid == NULL || is_user == NULL)
499 		return (IDMAP_ERR_ARG);
500 
501 	zs = idmap_get_zone_specific(zone);
502 
503 	if (kidmap_cache_lookup_pidbysid(&zs->cache, sid_prefix, rid, pid,
504 	    is_user) == IDMAP_SUCCESS)
505 		return (IDMAP_SUCCESS);
506 
507 	bzero(&mapping, sizeof (idmap_mapping));
508 	mapping.id1.idtype = IDMAP_SID;
509 	mapping.id1.idmap_id_u.sid.prefix = (char *)sid_prefix;
510 	mapping.id1.idmap_id_u.sid.rid = rid;
511 	mapping.id2.idtype = IDMAP_POSIXID;
512 
513 	bzero(&results, sizeof (idmap_ids_res));
514 
515 	args.idmap_mapping_batch_len = 1;
516 	args.idmap_mapping_batch_val = &mapping;
517 
518 	if (kidmap_rpc_call(zs, op, xdr_idmap_mapping_batch,
519 	    (caddr_t)&args, xdr_idmap_ids_res,
520 	    (caddr_t)&results) == 0) {
521 		/* Door call succeded */
522 		if (results.ids.ids_len >= 1 && (
523 		    results.ids.ids_val[0].id.idtype == IDMAP_UID ||
524 		    results.ids.ids_val[0].id.idtype == IDMAP_GID)) {
525 			status = results.ids.ids_val[0].retcode;
526 			if (results.ids.ids_val[0].id.idtype == IDMAP_UID) {
527 				*is_user = 1;
528 				*pid = results.ids.ids_val[0].id.idmap_id_u.uid;
529 			} else {
530 				*is_user = 0;
531 				*pid = results.ids.ids_val[0].id.idmap_id_u.gid;
532 			}
533 			if (status == IDMAP_SUCCESS) {
534 				new_sid_prefix = kidmap_find_sid_prefix(
535 				    sid_prefix);
536 				kidmap_cache_add_pidbysid(&zs->cache,
537 				    new_sid_prefix, rid, *pid,
538 				    *is_user);
539 			}
540 		} else {
541 			status = IDMAP_ERR_NOMAPPING;
542 			*is_user = 1;
543 			*pid = UID_NOBODY;
544 		}
545 		xdr_free(xdr_idmap_ids_res, (char *)&results);
546 	} else {
547 		/* Door call failed */
548 		status = IDMAP_ERR_NOMAPPING;
549 		*is_user = 1;
550 		*pid = UID_NOBODY;
551 	}
552 	return (status);
553 }
554 
555 
556 /*
557  * Given UID, get Domain SID and RID
558  *
559  * Input:
560  * uid - Posix UID
561  *
562  * Output:
563  * sid_prefix	- Domain SID if return == IDMAP_SUCCESS
564  * rid	- RID if return == IDMAP_SUCCESS
565  *
566  * Return:
567  * Success return IDMAP_SUCCESS else IDMAP error
568  */
569 idmap_stat
570 kidmap_getsidbyuid(zone_t *zone, uid_t uid, const char **sid_prefix,
571 		uint32_t *rid)
572 {
573 	idmap_zone_specific_t	*zs;
574 	idmap_mapping_batch	args;
575 	idmap_mapping		mapping;
576 	idmap_ids_res		results;
577 	uint32_t		op = IDMAP_GET_MAPPED_IDS;
578 	idmap_stat		status;
579 	time_t			entry_ttl;
580 	idmap_id		*id;
581 
582 	if (sid_prefix == NULL || rid == NULL)
583 		return (IDMAP_ERR_ARG);
584 
585 	zs = idmap_get_zone_specific(zone);
586 
587 	if (kidmap_cache_lookup_sidbyuid(&zs->cache, sid_prefix, rid, uid)
588 	    == IDMAP_SUCCESS) {
589 		return (IDMAP_SUCCESS);
590 	}
591 
592 	bzero(&mapping, sizeof (idmap_mapping));
593 	mapping.id1.idtype = IDMAP_UID;
594 	mapping.id1.idmap_id_u.uid = uid;
595 	mapping.id2.idtype = IDMAP_SID;
596 
597 	bzero(&results, sizeof (idmap_ids_res));
598 
599 	args.idmap_mapping_batch_len = 1;
600 	args.idmap_mapping_batch_val = &mapping;
601 
602 	if (kidmap_rpc_call(zs, op, xdr_idmap_mapping_batch,
603 	    (caddr_t)&args, xdr_idmap_ids_res,
604 	    (caddr_t)&results) == 0) {
605 		/* Door call succeded */
606 		if (results.ids.ids_len >= 1 &&
607 		    (results.ids.ids_val[0].id.idtype == IDMAP_SID ||
608 		    results.ids.ids_val[0].id.idtype == IDMAP_USID ||
609 		    results.ids.ids_val[0].id.idtype == IDMAP_GSID)) {
610 			status = results.ids.ids_val[0].retcode;
611 			id = &results.ids.ids_val[0].id;
612 			*sid_prefix = kidmap_find_sid_prefix(
613 			    id->idmap_id_u.sid.prefix);
614 			*rid = id->idmap_id_u.sid.rid;
615 			if (status == IDMAP_SUCCESS) {
616 				kidmap_cache_add_sidbyuid(&zs->cache,
617 				    *sid_prefix, *rid, uid);
618 			}
619 		} else {
620 			status = IDMAP_ERR_NOMAPPING;
621 			*rid = 0;
622 			*sid_prefix = NULL;
623 		}
624 		xdr_free(xdr_idmap_ids_res, (char *)&results);
625 	} else {
626 		/* Door call failed */
627 		status = IDMAP_ERR_NOMAPPING;
628 		*rid = 0;
629 		*sid_prefix = NULL;
630 	}
631 	return (status);
632 }
633 
634 
635 /*
636  * Given GID, get Domain SID and RID
637  *
638  * Input:
639  * gid - Posix GID
640  *
641  * Output:
642  * sid_prefix	- Domain SID if return == IDMAP_SUCCESS
643  * rid	- RID if return == IDMAP_SUCCESS
644  *
645  * Return:
646  * Success return IDMAP_SUCCESS else IDMAP error
647  */
648 idmap_stat
649 kidmap_getsidbygid(zone_t *zone, gid_t gid, const char **sid_prefix,
650 		uint32_t *rid)
651 {
652 	idmap_zone_specific_t	*zs;
653 	idmap_mapping_batch	args;
654 	idmap_mapping		mapping;
655 	idmap_ids_res		results;
656 	uint32_t		op = IDMAP_GET_MAPPED_IDS;
657 	idmap_stat		status;
658 	idmap_id		*id;
659 
660 	if (sid_prefix == NULL || rid == NULL)
661 		return (IDMAP_ERR_ARG);
662 
663 	zs = idmap_get_zone_specific(zone);
664 
665 	if (kidmap_cache_lookup_sidbygid(&zs->cache, sid_prefix, rid, gid)
666 	    == IDMAP_SUCCESS) {
667 		return (IDMAP_SUCCESS);
668 	}
669 
670 	bzero(&mapping, sizeof (idmap_mapping));
671 	mapping.id1.idtype = IDMAP_GID;
672 	mapping.id1.idmap_id_u.uid = gid;
673 	mapping.id2.idtype = IDMAP_SID;
674 
675 	bzero(&results, sizeof (idmap_ids_res));
676 
677 	args.idmap_mapping_batch_len = 1;
678 	args.idmap_mapping_batch_val = &mapping;
679 
680 	if (kidmap_rpc_call(zs, op, xdr_idmap_mapping_batch,
681 	    (caddr_t)&args, xdr_idmap_ids_res,
682 	    (caddr_t)&results) == 0) {
683 		/* Door call succeded */
684 		if (results.ids.ids_len >= 1 &&
685 		    (results.ids.ids_val[0].id.idtype == IDMAP_SID ||
686 		    results.ids.ids_val[0].id.idtype == IDMAP_USID ||
687 		    results.ids.ids_val[0].id.idtype == IDMAP_GSID)) {
688 			status = results.ids.ids_val[0].retcode;
689 			id = &results.ids.ids_val[0].id;
690 			*sid_prefix = kidmap_find_sid_prefix(
691 			    id->idmap_id_u.sid.prefix);
692 			*rid = id->idmap_id_u.sid.rid;
693 			if (status == IDMAP_SUCCESS) {
694 				kidmap_cache_add_sidbygid(&zs->cache,
695 				    *sid_prefix, *rid, gid);
696 			}
697 		} else {
698 			status = IDMAP_ERR_NOMAPPING;
699 			*rid = 0;
700 			*sid_prefix = NULL;
701 		}
702 		xdr_free(xdr_idmap_ids_res, (char *)&results);
703 	} else {
704 		/* Door call failed */
705 		status = IDMAP_ERR_NOMAPPING;
706 		*rid = 0;
707 		*sid_prefix = NULL;
708 	}
709 	return (status);
710 }
711 
712 /*
713  * Create handle to get SID to UID/GID mapping entries
714  *
715  * Input:
716  * 	none
717  * Return:
718  *	get_handle
719  *
720  */
721 idmap_get_handle_t *
722 kidmap_get_create(zone_t *zone)
723 {
724 	idmap_zone_specific_t	*zs;
725 	idmap_get_handle_t	*handle;
726 #define	INIT_MAPPING_SIZE	32
727 
728 	zs = idmap_get_zone_specific(zone);
729 
730 	handle = kmem_zalloc(sizeof (idmap_get_handle_t), KM_SLEEP);
731 
732 	handle->mapping = kmem_zalloc((sizeof (idmap_mapping)) *
733 	    INIT_MAPPING_SIZE, KM_SLEEP);
734 
735 	handle->result = kmem_zalloc((sizeof (idmap_get_res)) *
736 	    INIT_MAPPING_SIZE, KM_SLEEP);
737 	handle->mapping_size = INIT_MAPPING_SIZE;
738 	handle->zs = zs;
739 
740 	return (handle);
741 }
742 
743 /*
744  * Internal routine to extend a "get_handle"
745  */
746 static void
747 kidmap_get_extend(idmap_get_handle_t *get_handle)
748 {
749 	idmap_mapping *mapping;
750 	idmap_get_res *result;
751 	int new_size = get_handle->mapping_size + INIT_MAPPING_SIZE;
752 
753 	mapping = kmem_zalloc((sizeof (idmap_mapping)) *
754 	    new_size, KM_SLEEP);
755 	(void) memcpy(mapping, get_handle->mapping,
756 	    (sizeof (idmap_mapping)) * get_handle->mapping_size);
757 
758 	result = kmem_zalloc((sizeof (idmap_get_res)) *
759 	    new_size, KM_SLEEP);
760 	(void) memcpy(result, get_handle->result,
761 	    (sizeof (idmap_get_res)) * get_handle->mapping_size);
762 
763 	kmem_free(get_handle->mapping,
764 	    (sizeof (idmap_mapping)) * get_handle->mapping_size);
765 	get_handle->mapping = mapping;
766 
767 	kmem_free(get_handle->result,
768 	    (sizeof (idmap_get_res)) * get_handle->mapping_size);
769 	get_handle->result = result;
770 
771 	get_handle->mapping_size = new_size;
772 }
773 
774 
775 /*
776  * Given Domain SID and RID, get UID
777  *
778  * Input:
779  * sid_prefix	- Domain SID in canonical form
780  * rid	- RID
781  *
782  * Output:
783  * stat - status of the get request
784  * uid  - POSIX UID if stat == IDMAP_SUCCESS
785  *
786  * Note: The output parameters will be set by idmap_get_mappings()
787  */
788 idmap_stat
789 kidmap_batch_getuidbysid(idmap_get_handle_t *get_handle, const char *sid_prefix,
790 			uint32_t rid, uid_t *uid, idmap_stat *stat)
791 {
792 	idmap_mapping	*mapping;
793 	idmap_get_res 	*result;
794 
795 	if (get_handle == NULL || sid_prefix == NULL ||
796 	    uid == NULL || stat == NULL)
797 		return (IDMAP_ERR_ARG);
798 
799 	if (kidmap_cache_lookup_uidbysid(&get_handle->zs->cache, sid_prefix,
800 	    rid, uid) == IDMAP_SUCCESS) {
801 		*stat = IDMAP_SUCCESS;
802 		return (IDMAP_SUCCESS);
803 	}
804 
805 	if (get_handle->mapping_num >= get_handle->mapping_size)
806 		kidmap_get_extend(get_handle);
807 
808 	mapping = &get_handle->mapping[get_handle->mapping_num];
809 	mapping->flag = 0;
810 	mapping->id1.idtype = IDMAP_SID;
811 	mapping->id1.idmap_id_u.sid.prefix = (char *)sid_prefix;
812 	mapping->id1.idmap_id_u.sid.rid = rid;
813 	mapping->id2.idtype = IDMAP_UID;
814 
815 	result = &get_handle->result[get_handle->mapping_num];
816 	result->idtype = IDMAP_UID;
817 	result->uid = uid;
818 	result->gid = NULL;
819 	result->pid = NULL;
820 	result->sid_prefix = NULL;
821 	result->rid = NULL;
822 	result->is_user = NULL;
823 	result->stat = stat;
824 
825 	get_handle->mapping_num++;
826 
827 	return (IDMAP_SUCCESS);
828 }
829 
830 
831 /*
832  * Given Domain SID and RID, get GID
833  *
834  * Input:
835  * sid_prefix	- Domain SID in canonical form
836  * rid	- RID
837  *
838  * Output:
839  * stat - status of the get request
840  * gid  - POSIX GID if stat == IDMAP_SUCCESS
841  *
842  * Note: The output parameters will be set by idmap_get_mappings()
843  */
844 idmap_stat
845 kidmap_batch_getgidbysid(idmap_get_handle_t *get_handle, const char *sid_prefix,
846 			uint32_t rid, uid_t *gid, idmap_stat *stat)
847 {
848 	idmap_mapping	*mapping;
849 	idmap_get_res 	*result;
850 
851 	if (get_handle == NULL || sid_prefix == NULL ||
852 	    gid == NULL || stat == NULL)
853 		return (IDMAP_ERR_ARG);
854 
855 	if (kidmap_cache_lookup_gidbysid(&get_handle->zs->cache, sid_prefix,
856 	    rid, gid) == IDMAP_SUCCESS) {
857 		*stat = IDMAP_SUCCESS;
858 		return (IDMAP_SUCCESS);
859 	}
860 
861 	if (get_handle->mapping_num >= get_handle->mapping_size)
862 		kidmap_get_extend(get_handle);
863 
864 	mapping = &get_handle->mapping[get_handle->mapping_num];
865 	mapping->flag = 0;
866 	mapping->id1.idtype = IDMAP_SID;
867 	mapping->id1.idmap_id_u.sid.prefix = (char *)sid_prefix;
868 	mapping->id1.idmap_id_u.sid.rid = rid;
869 	mapping->id2.idtype = IDMAP_GID;
870 
871 	result = &get_handle->result[get_handle->mapping_num];
872 	result->idtype = IDMAP_GID;
873 	result->uid = NULL;
874 	result->gid = gid;
875 	result->pid = NULL;
876 	result->sid_prefix = NULL;
877 	result->rid = NULL;
878 	result->is_user = NULL;
879 	result->stat = stat;
880 
881 	get_handle->mapping_num++;
882 
883 	return (IDMAP_SUCCESS);
884 }
885 
886 
887 /*
888  * Given Domain SID and RID, get Posix ID
889  *
890  * Input:
891  * sid_prefix	- Domain SID in canonical form
892  * rid	- RID
893  *
894  * Output:
895  * stat    - status of the get request
896  * is_user - user or group
897  * pid     - POSIX UID if stat == IDMAP_SUCCESS and is_user == 1
898  *           POSIX GID if stat == IDMAP_SUCCESS and is_user == 0
899  *
900  * Note: The output parameters will be set by idmap_get_mappings()
901  */
902 idmap_stat
903 kidmap_batch_getpidbysid(idmap_get_handle_t *get_handle, const char *sid_prefix,
904 		uint32_t rid, uid_t *pid, int *is_user, idmap_stat *stat)
905 {
906 	idmap_mapping	*mapping;
907 	idmap_get_res 	*result;
908 
909 	if (get_handle == NULL || sid_prefix == NULL || pid == NULL ||
910 	    is_user == NULL || stat == NULL)
911 		return (IDMAP_ERR_ARG);
912 
913 	if (kidmap_cache_lookup_pidbysid(&get_handle->zs->cache, sid_prefix,
914 	    rid, pid, is_user) == IDMAP_SUCCESS) {
915 		*stat = IDMAP_SUCCESS;
916 		return (IDMAP_SUCCESS);
917 	}
918 
919 
920 	if (get_handle->mapping_num >= get_handle->mapping_size)
921 		kidmap_get_extend(get_handle);
922 
923 	mapping = &get_handle->mapping[get_handle->mapping_num];
924 	mapping->flag = 0;
925 	mapping->id1.idtype = IDMAP_SID;
926 	mapping->id1.idmap_id_u.sid.prefix = (char *)sid_prefix;
927 	mapping->id1.idmap_id_u.sid.rid = rid;
928 	mapping->id2.idtype = IDMAP_POSIXID;
929 
930 	result = &get_handle->result[get_handle->mapping_num];
931 	result->idtype = IDMAP_POSIXID;
932 	result->uid = NULL;
933 	result->gid = NULL;
934 	result->pid = pid;
935 	result->sid_prefix = NULL;
936 	result->rid = NULL;
937 	result->is_user = is_user;
938 	result->stat = stat;
939 
940 	get_handle->mapping_num++;
941 
942 	return (IDMAP_SUCCESS);
943 }
944 
945 
946 /*
947  * Given UID, get SID and RID
948  *
949  * Input:
950  * uid  - POSIX UID
951  *
952  * Output:
953  * stat - status of the get request
954  * sid  - SID in canonical form (if stat == IDMAP_SUCCESS)
955  * rid	- RID (if stat == IDMAP_SUCCESS)
956  *
957  * Note: The output parameters will be set by idmap_get_mappings()
958  */
959 idmap_stat
960 kidmap_batch_getsidbyuid(idmap_get_handle_t *get_handle, uid_t uid,
961 		const char **sid_prefix, uint32_t *rid, idmap_stat *stat)
962 {
963 	idmap_mapping	*mapping;
964 	idmap_get_res 	*result;
965 
966 	if (get_handle == NULL || sid_prefix == NULL ||
967 	    rid == NULL || stat == NULL)
968 		return (IDMAP_ERR_ARG);
969 
970 	if (kidmap_cache_lookup_sidbyuid(&get_handle->zs->cache,
971 	    sid_prefix, rid, uid) == IDMAP_SUCCESS) {
972 		*stat = IDMAP_SUCCESS;
973 		return (IDMAP_SUCCESS);
974 	}
975 
976 	if (get_handle->mapping_num >= get_handle->mapping_size)
977 		kidmap_get_extend(get_handle);
978 
979 	mapping = &get_handle->mapping[get_handle->mapping_num];
980 	mapping->flag = 0;
981 	mapping->id1.idtype = IDMAP_UID;
982 	mapping->id1.idmap_id_u.uid = uid;
983 	mapping->id2.idtype = IDMAP_SID;
984 
985 	result = &get_handle->result[get_handle->mapping_num];
986 	result->idtype = IDMAP_SID;
987 	result->uid = NULL;
988 	result->gid = NULL;
989 	result->pid = NULL;
990 	result->sid_prefix = sid_prefix;
991 	result->rid = rid;
992 	result->is_user = NULL;
993 	result->stat = stat;
994 
995 	get_handle->mapping_num++;
996 
997 	return (IDMAP_SUCCESS);
998 }
999 
1000 
1001 /*
1002  * Given GID, get SID and RID
1003  *
1004  * Input:
1005  * gid  - POSIX GID
1006  *
1007  * Output:
1008  * stat - status of the get request
1009  * sid  - SID in canonical form (if stat == IDMAP_SUCCESS)
1010  * rid	- RID (if stat == IDMAP_SUCCESS)
1011  *
1012  * Note: The output parameters will be set by idmap_get_mappings()
1013  */
1014 idmap_stat
1015 kidmap_batch_getsidbygid(idmap_get_handle_t *get_handle, gid_t gid,
1016 		const char **sid_prefix, uint32_t *rid, idmap_stat *stat)
1017 {
1018 	idmap_mapping	*mapping;
1019 	idmap_get_res 	*result;
1020 
1021 	if (get_handle == NULL || sid_prefix == NULL ||
1022 	    rid == NULL || stat == NULL)
1023 		return (IDMAP_ERR_ARG);
1024 
1025 	if (kidmap_cache_lookup_sidbygid(&get_handle->zs->cache,
1026 	    sid_prefix, rid, gid) == IDMAP_SUCCESS) {
1027 		*stat = IDMAP_SUCCESS;
1028 		return (IDMAP_SUCCESS);
1029 	}
1030 
1031 	if (get_handle->mapping_num >= get_handle->mapping_size)
1032 		kidmap_get_extend(get_handle);
1033 
1034 	mapping = &get_handle->mapping[get_handle->mapping_num];
1035 	mapping->flag = 0;
1036 	mapping->id1.idtype = IDMAP_GID;
1037 	mapping->id1.idmap_id_u.gid = gid;
1038 	mapping->id2.idtype = IDMAP_SID;
1039 
1040 	result = &get_handle->result[get_handle->mapping_num];
1041 	result->idtype = IDMAP_SID;
1042 	result->uid = NULL;
1043 	result->gid = NULL;
1044 	result->pid = NULL;
1045 	result->sid_prefix = sid_prefix;
1046 	result->rid = rid;
1047 	result->is_user = NULL;
1048 	result->stat = stat;
1049 
1050 	get_handle->mapping_num++;
1051 
1052 	return (IDMAP_SUCCESS);
1053 }
1054 
1055 
1056 /*
1057  * Process the batched "get mapping" requests. The results (i.e.
1058  * status and identity) will be available in the data areas
1059  * provided by individual requests.
1060  *
1061  * If the door call fails the status IDMAP_ERR_NOMAPPING is
1062  * return and the UID or UID result is set to "nobody"
1063  */
1064 
1065 idmap_stat
1066 kidmap_get_mappings(idmap_get_handle_t *get_handle)
1067 {
1068 	idmap_mapping_batch	args;
1069 	idmap_ids_res		results;
1070 	uint32_t		op = IDMAP_GET_MAPPED_IDS;
1071 	idmap_mapping		*mapping;
1072 	idmap_get_res		*result;
1073 	idmap_id		*id;
1074 	int			status;
1075 	int			i;
1076 	const char		*sid_prefix;
1077 	int			is_user;
1078 	idmap_cache_t		*cache;
1079 
1080 	if (get_handle == NULL)
1081 		return (IDMAP_ERR_ARG);
1082 
1083 	if (get_handle->mapping_num == 0)
1084 		return (IDMAP_SUCCESS);
1085 	cache = &get_handle->zs->cache;
1086 
1087 	bzero(&results, sizeof (idmap_ids_res));
1088 
1089 	args.idmap_mapping_batch_len = get_handle->mapping_num;
1090 	args.idmap_mapping_batch_val = get_handle->mapping;
1091 
1092 	if (kidmap_rpc_call(get_handle->zs, op, xdr_idmap_mapping_batch,
1093 	    (caddr_t)&args, xdr_idmap_ids_res,
1094 	    (caddr_t)&results) == 0) {
1095 		/* Door call succeded */
1096 		status = IDMAP_SUCCESS;
1097 		for (i = 0; i < get_handle->mapping_num; i++) {
1098 			mapping = &get_handle->mapping[i];
1099 			result =  &get_handle->result[i];
1100 
1101 			if (i > results.ids.ids_len) {
1102 				*result->stat =	IDMAP_ERR_NOMAPPING;
1103 				if (result->uid)
1104 					*result->uid = UID_NOBODY;
1105 				if (result->gid)
1106 					*result->gid = GID_NOBODY;
1107 				if (result->pid)
1108 					*result->pid = UID_NOBODY;
1109 				if (result->is_user)
1110 					*result->is_user = 1;
1111 				if (result->sid_prefix)
1112 					*result->sid_prefix = NULL;
1113 				if (result->rid)
1114 					*result->rid = 0;
1115 				continue;
1116 			}
1117 			*result->stat = results.ids.ids_val[i].retcode;
1118 
1119 			id = &results.ids.ids_val[i].id;
1120 			switch (id->idtype) {
1121 			case IDMAP_UID:
1122 				if (result->uid)
1123 					*result->uid = id->idmap_id_u.uid;
1124 				if (result->pid)
1125 					*result->pid = id->idmap_id_u.uid;
1126 				if (result->is_user)
1127 					*result->is_user = 1;
1128 				sid_prefix = kidmap_find_sid_prefix(
1129 				    mapping->id1.idmap_id_u.sid.prefix);
1130 				if (*result->stat == IDMAP_SUCCESS &&
1131 				    result->uid)
1132 					kidmap_cache_add_uidbysid(
1133 					    cache,
1134 					    sid_prefix,
1135 					    mapping->id1.idmap_id_u.sid.rid,
1136 					    id->idmap_id_u.uid);
1137 				else if (*result->stat == IDMAP_SUCCESS &&
1138 				    result->pid)
1139 					kidmap_cache_add_uidbysid(
1140 					    cache,
1141 					    sid_prefix,
1142 					    mapping->id1.idmap_id_u.sid.rid,
1143 					    id->idmap_id_u.uid);
1144 				break;
1145 
1146 			case IDMAP_GID:
1147 				if (result->gid)
1148 					*result->gid = id->idmap_id_u.gid;
1149 				if (result->pid)
1150 					*result->pid = id->idmap_id_u.gid;
1151 				if (result->is_user)
1152 					*result->is_user = 0;
1153 				sid_prefix = kidmap_find_sid_prefix(
1154 				    mapping->id1.idmap_id_u.sid.prefix);
1155 				if (*result->stat == IDMAP_SUCCESS &&
1156 				    result->gid)
1157 					kidmap_cache_add_gidbysid(
1158 					    cache,
1159 					    sid_prefix,
1160 					    mapping->id1.idmap_id_u.sid.rid,
1161 					    id->idmap_id_u.gid);
1162 				else if (*result->stat == IDMAP_SUCCESS &&
1163 				    result->pid)
1164 					kidmap_cache_add_gidbysid(
1165 					    cache,
1166 					    sid_prefix,
1167 					    mapping->id1.idmap_id_u.sid.rid,
1168 					    id->idmap_id_u.gid);
1169 				break;
1170 
1171 			case IDMAP_SID:
1172 			case IDMAP_USID:
1173 			case IDMAP_GSID:
1174 				sid_prefix = kidmap_find_sid_prefix(
1175 				    id->idmap_id_u.sid.prefix);
1176 				if (result->sid_prefix && result->rid) {
1177 					*result->sid_prefix = sid_prefix;
1178 					*result->rid = id->idmap_id_u.sid.rid;
1179 				}
1180 				if (*result->stat == IDMAP_SUCCESS &&
1181 				    mapping->id1.idtype == IDMAP_UID)
1182 					kidmap_cache_add_sidbyuid(
1183 					    cache,
1184 					    sid_prefix,
1185 					    id->idmap_id_u.sid.rid,
1186 					    mapping->id1.idmap_id_u.uid);
1187 				else if (*result->stat == IDMAP_SUCCESS &&
1188 				    mapping->id1.idtype == IDMAP_GID)
1189 					kidmap_cache_add_sidbygid(
1190 					    cache,
1191 					    sid_prefix,
1192 					    id->idmap_id_u.sid.rid,
1193 					    mapping->id1.idmap_id_u.gid);
1194 				break;
1195 
1196 			default:
1197 				*result->stat = IDMAP_ERR_NORESULT;
1198 				if (result->uid)
1199 					*result->uid = UID_NOBODY;
1200 				if (result->gid)
1201 					*result->gid = GID_NOBODY;
1202 				if (result->pid)
1203 					*result->pid = UID_NOBODY;
1204 				if (result->is_user)
1205 					*result->is_user = 1;
1206 				if (result->sid_prefix)
1207 					*result->sid_prefix = NULL;
1208 				if (result->rid)
1209 					*result->rid = 0;
1210 				break;
1211 			}
1212 		}
1213 		xdr_free(xdr_idmap_ids_res, (char *)&results);
1214 	} else {
1215 		/* Door call failed */
1216 		status = IDMAP_ERR_NOMAPPING;
1217 		for (i = 0; i < get_handle->mapping_num; i++) {
1218 			result =  &get_handle->result[i];
1219 
1220 			*result->stat = IDMAP_ERR_NOMAPPING;
1221 			if (result->uid)
1222 				*result->uid = UID_NOBODY;
1223 			if (result->gid)
1224 				*result->gid = GID_NOBODY;
1225 			if (result->pid)
1226 				*result->pid = UID_NOBODY;
1227 			if (result->is_user)
1228 				*result->is_user = 1;
1229 			if (result->sid_prefix)
1230 				*result->sid_prefix = NULL;
1231 			if (result->rid)
1232 				*result->rid = 0;
1233 		}
1234 	}
1235 
1236 	/* Reset get_handle for new resquests */
1237 	get_handle->mapping_num = 0;
1238 	return (status);
1239 }
1240 
1241 
1242 /*
1243  * Destroy the "get mapping" handle
1244  */
1245 void
1246 kidmap_get_destroy(idmap_get_handle_t *get_handle)
1247 {
1248 	if (get_handle == NULL)
1249 		return;
1250 
1251 	kmem_free(get_handle->mapping,
1252 	    (sizeof (idmap_mapping)) * get_handle->mapping_size);
1253 	get_handle->mapping = NULL;
1254 
1255 	kmem_free(get_handle->result,
1256 	    (sizeof (idmap_get_res)) * get_handle->mapping_size);
1257 	get_handle->result = NULL;
1258 
1259 	kmem_free(get_handle, sizeof (idmap_get_handle_t));
1260 }
1261 
1262 
1263 static int
1264 kidmap_rpc_call(idmap_zone_specific_t *zs, uint32_t op, xdrproc_t xdr_args,
1265 		caddr_t args, xdrproc_t xdr_res, caddr_t res)
1266 {
1267 	XDR		xdr_ctx;
1268 	struct	rpc_msg reply_msg;
1269 	char		*inbuf_ptr = NULL;
1270 	size_t		inbuf_size = 4096;
1271 	char		*outbuf_ptr = NULL;
1272 	size_t 		outbuf_size = 4096;
1273 	size_t		size;
1274 	int		status = 0;
1275 	door_arg_t	params;
1276 	int 		retry = 0;
1277 	struct rpc_msg	call_msg;
1278 
1279 	params.rbuf = NULL;
1280 	params.rsize = 0;
1281 
1282 retry:
1283 	inbuf_ptr = kmem_alloc(inbuf_size, KM_SLEEP);
1284 	outbuf_ptr = kmem_alloc(outbuf_size, KM_SLEEP);
1285 
1286 	xdrmem_create(&xdr_ctx, inbuf_ptr, inbuf_size, XDR_ENCODE);
1287 
1288 	call_msg.rm_call.cb_prog = IDMAP_PROG;
1289 	call_msg.rm_call.cb_vers = IDMAP_V1;
1290 	call_msg.rm_xid = atomic_inc_32_nv(&zs->message_id);
1291 
1292 	if (!xdr_callhdr(&xdr_ctx, &call_msg)) {
1293 #ifdef	DEBUG
1294 		cmn_err(CE_WARN, "idmap: xdr encoding header error");
1295 #endif	/* DEBUG */
1296 		status = -1;
1297 		goto exit;
1298 	}
1299 
1300 	if (!xdr_uint32(&xdr_ctx, &op) ||
1301 	    /* Auth none */
1302 	    !xdr_opaque_auth(&xdr_ctx, &_null_auth) ||
1303 	    !xdr_opaque_auth(&xdr_ctx, &_null_auth) ||
1304 	    /* RPC args */
1305 	    !xdr_args(&xdr_ctx, args)) {
1306 #ifdef	DEBUG
1307 		cmn_err(CE_WARN, "idmap: xdr encoding error");
1308 #endif	/* DEBUG */
1309 		if (retry > 2) {
1310 			status = -1;
1311 			goto exit;
1312 		}
1313 		retry++;
1314 		if (inbuf_ptr) {
1315 			kmem_free(inbuf_ptr, inbuf_size);
1316 			inbuf_ptr = NULL;
1317 		}
1318 		if (outbuf_ptr) {
1319 			kmem_free(outbuf_ptr, outbuf_size);
1320 			outbuf_ptr = NULL;
1321 		}
1322 		if ((size = xdr_sizeof(xdr_args, args)) == 0) {
1323 #ifdef	DEBUG
1324 			cmn_err(CE_WARN, "idmap: xdr_sizeof error");
1325 #endif	/* DEBUG */
1326 			status = -1;
1327 			goto exit;
1328 		}
1329 		inbuf_size = size + 1024;
1330 		outbuf_size = size + 1024;
1331 		goto retry;
1332 	}
1333 
1334 	params.data_ptr = inbuf_ptr;
1335 	params.data_size = XDR_GETPOS(&xdr_ctx);
1336 	params.desc_ptr = NULL;
1337 	params.desc_num = 0;
1338 	params.rbuf = outbuf_ptr;
1339 	params.rsize = outbuf_size;
1340 
1341 	if (kidmap_call_door(zs, &params) != 0) {
1342 		status = -1;
1343 		goto exit;
1344 	}
1345 
1346 	reply_msg.acpted_rply.ar_verf = _null_auth;
1347 	reply_msg.acpted_rply.ar_results.where = res;
1348 	reply_msg.acpted_rply.ar_results.proc = xdr_res;
1349 	xdrmem_create(&xdr_ctx, params.data_ptr, params.data_size, XDR_DECODE);
1350 	if (xdr_replymsg(&xdr_ctx, &reply_msg)) {
1351 		if (reply_msg.rm_reply.rp_stat != MSG_ACCEPTED ||
1352 		    reply_msg.rm_reply.rp_acpt.ar_stat != SUCCESS) {
1353 			status = -1;
1354 			goto exit;
1355 		}
1356 	} else {
1357 #ifdef	DEBUG
1358 		cmn_err(CE_WARN, "idmap: xdr decoding reply message error");
1359 #endif	/* DEBUG */
1360 		status = -1;
1361 	}
1362 
1363 exit:
1364 	if (outbuf_ptr != params.rbuf && params.rbuf != NULL)
1365 		kmem_free(params.rbuf, params.rsize);
1366 	if (inbuf_ptr)
1367 		kmem_free(inbuf_ptr, inbuf_size);
1368 	if (outbuf_ptr)
1369 		kmem_free(outbuf_ptr, outbuf_size);
1370 	return (status);
1371 }
1372