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