Home | History | Annotate | Download | only in nvpair
      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 2007 Sun Microsystems, Inc.  All rights reserved.
     24  * Use is subject to license terms.
     25  */
     26 
     27 #pragma ident	"@(#)nvpair.c	1.22	07/10/29 SMI"
     28 
     29 #include <sys/stropts.h>
     30 #include <sys/debug.h>
     31 #include <sys/isa_defs.h>
     32 #include <sys/int_limits.h>
     33 #include <sys/nvpair.h>
     34 #include <sys/nvpair_impl.h>
     35 #include <rpc/types.h>
     36 #include <rpc/xdr.h>
     37 
     38 #if defined(_KERNEL) && !defined(_BOOT)
     39 #include <sys/varargs.h>
     40 #else
     41 #include <stdarg.h>
     42 #include <strings.h>
     43 #endif
     44 
     45 #ifndef	offsetof
     46 #define	offsetof(s, m)	((size_t)(&(((s *)0)->m)))
     47 #endif
     48 
     49 
     50 /*
     51  * nvpair.c - Provides kernel & userland interfaces for manipulating
     52  *	name-value pairs.
     53  *
     54  * Overview Diagram
     55  *
     56  *  +--------------+
     57  *  |  nvlist_t    |
     58  *  |--------------|
     59  *  | nvl_version  |
     60  *  | nvl_nvflag   |
     61  *  | nvl_priv    -+-+
     62  *  | nvl_flag     | |
     63  *  | nvl_pad      | |
     64  *  +--------------+ |
     65  *                   V
     66  *      +--------------+      last i_nvp in list
     67  *      | nvpriv_t     |  +--------------------->
     68  *      |--------------|  |
     69  *   +--+- nvp_list    |  |   +------------+
     70  *   |  |  nvp_last   -+--+   + nv_alloc_t |
     71  *   |  |  nvp_curr    |      |------------|
     72  *   |  |  nvp_nva    -+----> | nva_ops    |
     73  *   |  |  nvp_stat    |      | nva_arg    |
     74  *   |  +--------------+      +------------+
     75  *   |
     76  *   +-------+
     77  *           V
     78  *   +---------------------+      +-------------------+
     79  *   |  i_nvp_t            |  +-->|  i_nvp_t          |  +-->
     80  *   |---------------------|  |   |-------------------|  |
     81  *   | nvi_next           -+--+   | nvi_next         -+--+
     82  *   | nvi_prev (NULL)     | <----+ nvi_prev          |
     83  *   | . . . . . . . . . . |      | . . . . . . . . . |
     84  *   | nvp (nvpair_t)      |      | nvp (nvpair_t)    |
     85  *   |  - nvp_size         |      |  - nvp_size       |
     86  *   |  - nvp_name_sz      |      |  - nvp_name_sz    |
     87  *   |  - nvp_value_elem   |      |  - nvp_value_elem |
     88  *   |  - nvp_type         |      |  - nvp_type       |
     89  *   |  - data ...         |      |  - data ...       |
     90  *   +---------------------+      +-------------------+
     91  *
     92  *
     93  *
     94  *   +---------------------+              +---------------------+
     95  *   |  i_nvp_t            |  +-->    +-->|  i_nvp_t (last)     |
     96  *   |---------------------|  |       |   |---------------------|
     97  *   |  nvi_next          -+--+ ... --+   | nvi_next (NULL)     |
     98  * <-+- nvi_prev           |<-- ...  <----+ nvi_prev            |
     99  *   | . . . . . . . . .   |              | . . . . . . . . .   |
    100  *   | nvp (nvpair_t)      |              | nvp (nvpair_t)      |
    101  *   |  - nvp_size         |              |  - nvp_size         |
    102  *   |  - nvp_name_sz      |              |  - nvp_name_sz      |
    103  *   |  - nvp_value_elem   |              |  - nvp_value_elem   |
    104  *   |  - DATA_TYPE_NVLIST |              |  - nvp_type         |
    105  *   |  - data (embedded)  |              |  - data ...         |
    106  *   |    nvlist name      |              +---------------------+
    107  *   |  +--------------+   |
    108  *   |  |  nvlist_t    |   |
    109  *   |  |--------------|   |
    110  *   |  | nvl_version  |   |
    111  *   |  | nvl_nvflag   |   |
    112  *   |  | nvl_priv   --+---+---->
    113  *   |  | nvl_flag     |   |
    114  *   |  | nvl_pad      |   |
    115  *   |  +--------------+   |
    116  *   +---------------------+
    117  *
    118  *
    119  * N.B. nvpair_t may be aligned on 4 byte boundary, so +4 will
    120  * allow value to be aligned on 8 byte boundary
    121  *
    122  * name_len is the length of the name string including the null terminator
    123  * so it must be >= 1
    124  */
    125 #define	NVP_SIZE_CALC(name_len, data_len) \
    126 	(NV_ALIGN((sizeof (nvpair_t)) + name_len) + NV_ALIGN(data_len))
    127 
    128 static int i_get_value_size(data_type_t type, const void *data, uint_t nelem);
    129 static int nvlist_add_common(nvlist_t *nvl, const char *name, data_type_t type,
    130     uint_t nelem, const void *data);
    131 
    132 #define	NV_STAT_EMBEDDED	0x1
    133 #define	EMBEDDED_NVL(nvp)	((nvlist_t *)(void *)NVP_VALUE(nvp))
    134 #define	EMBEDDED_NVL_ARRAY(nvp)	((nvlist_t **)(void *)NVP_VALUE(nvp))
    135 
    136 #define	NVP_VALOFF(nvp)	(NV_ALIGN(sizeof (nvpair_t) + (nvp)->nvp_name_sz))
    137 #define	NVPAIR2I_NVP(nvp) \
    138 	((i_nvp_t *)((size_t)(nvp) - offsetof(i_nvp_t, nvi_nvp)))
    139 
    140 
    141 int
    142 nv_alloc_init(nv_alloc_t *nva, const nv_alloc_ops_t *nvo, /* args */ ...)
    143 {
    144 	va_list valist;
    145 	int err = 0;
    146 
    147 	nva->nva_ops = nvo;
    148 	nva->nva_arg = NULL;
    149 
    150 	va_start(valist, nvo);
    151 	if (nva->nva_ops->nv_ao_init != NULL)
    152 		err = nva->nva_ops->nv_ao_init(nva, valist);
    153 	va_end(valist);
    154 
    155 	return (err);
    156 }
    157 
    158 void
    159 nv_alloc_reset(nv_alloc_t *nva)
    160 {
    161 	if (nva->nva_ops->nv_ao_reset != NULL)
    162 		nva->nva_ops->nv_ao_reset(nva);
    163 }
    164 
    165 void
    166 nv_alloc_fini(nv_alloc_t *nva)
    167 {
    168 	if (nva->nva_ops->nv_ao_fini != NULL)
    169 		nva->nva_ops->nv_ao_fini(nva);
    170 }
    171 
    172 nv_alloc_t *
    173 nvlist_lookup_nv_alloc(nvlist_t *nvl)
    174 {
    175 	nvpriv_t *priv;
    176 
    177 	if (nvl == NULL ||
    178 	    (priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL)
    179 		return (NULL);
    180 
    181 	return (priv->nvp_nva);
    182 }
    183 
    184 static void *
    185 nv_mem_zalloc(nvpriv_t *nvp, size_t size)
    186 {
    187 	nv_alloc_t *nva = nvp->nvp_nva;
    188 	void *buf;
    189 
    190 	if ((buf = nva->nva_ops->nv_ao_alloc(nva, size)) != NULL)
    191 		bzero(buf, size);
    192 
    193 	return (buf);
    194 }
    195 
    196 static void
    197 nv_mem_free(nvpriv_t *nvp, void *buf, size_t size)
    198 {
    199 	nv_alloc_t *nva = nvp->nvp_nva;
    200 
    201 	nva->nva_ops->nv_ao_free(nva, buf, size);
    202 }
    203 
    204 static void
    205 nv_priv_init(nvpriv_t *priv, nv_alloc_t *nva, uint32_t stat)
    206 {
    207 	bzero(priv, sizeof (priv));
    208 
    209 	priv->nvp_nva = nva;
    210 	priv->nvp_stat = stat;
    211 }
    212 
    213 static nvpriv_t *
    214 nv_priv_alloc(nv_alloc_t *nva)
    215 {
    216 	nvpriv_t *priv;
    217 
    218 	/*
    219 	 * nv_mem_alloc() cannot called here because it needs the priv
    220 	 * argument.
    221 	 */
    222 	if ((priv = nva->nva_ops->nv_ao_alloc(nva, sizeof (nvpriv_t))) == NULL)
    223 		return (NULL);
    224 
    225 	nv_priv_init(priv, nva, 0);
    226 
    227 	return (priv);
    228 }
    229 
    230 /*
    231  * Embedded lists need their own nvpriv_t's.  We create a new
    232  * nvpriv_t using the parameters and allocator from the parent
    233  * list's nvpriv_t.
    234  */
    235 static nvpriv_t *
    236 nv_priv_alloc_embedded(nvpriv_t *priv)
    237 {
    238 	nvpriv_t *emb_priv;
    239 
    240 	if ((emb_priv = nv_mem_zalloc(priv, sizeof (nvpriv_t))) == NULL)
    241 		return (NULL);
    242 
    243 	nv_priv_init(emb_priv, priv->nvp_nva, NV_STAT_EMBEDDED);
    244 
    245 	return (emb_priv);
    246 }
    247 
    248 static void
    249 nvlist_init(nvlist_t *nvl, uint32_t nvflag, nvpriv_t *priv)
    250 {
    251 	nvl->nvl_version = NV_VERSION;
    252 	nvl->nvl_nvflag = nvflag & (NV_UNIQUE_NAME|NV_UNIQUE_NAME_TYPE);
    253 	nvl->nvl_priv = (uint64_t)(uintptr_t)priv;
    254 	nvl->nvl_flag = 0;
    255 	nvl->nvl_pad = 0;
    256 }
    257 
    258 /*
    259  * nvlist_alloc - Allocate nvlist.
    260  */
    261 /*ARGSUSED1*/
    262 int
    263 nvlist_alloc(nvlist_t **nvlp, uint_t nvflag, int kmflag)
    264 {
    265 #if defined(_KERNEL) && !defined(_BOOT)
    266 	return (nvlist_xalloc(nvlp, nvflag,
    267 	    (kmflag == KM_SLEEP ? nv_alloc_sleep : nv_alloc_nosleep)));
    268 #else
    269 	return (nvlist_xalloc(nvlp, nvflag, nv_alloc_nosleep));
    270 #endif
    271 }
    272 
    273 int
    274 nvlist_xalloc(nvlist_t **nvlp, uint_t nvflag, nv_alloc_t *nva)
    275 {
    276 	nvpriv_t *priv;
    277 
    278 	if (nvlp == NULL || nva == NULL)
    279 		return (EINVAL);
    280 
    281 	if ((priv = nv_priv_alloc(nva)) == NULL)
    282 		return (ENOMEM);
    283 
    284 	if ((*nvlp = nv_mem_zalloc(priv,
    285 	    NV_ALIGN(sizeof (nvlist_t)))) == NULL) {
    286 		nv_mem_free(priv, priv, sizeof (nvpriv_t));
    287 		return (ENOMEM);
    288 	}
    289 
    290 	nvlist_init(*nvlp, nvflag, priv);
    291 
    292 	return (0);
    293 }
    294 
    295 /*
    296  * nvp_buf_alloc - Allocate i_nvp_t for storing a new nv pair.
    297  */
    298 static nvpair_t *
    299 nvp_buf_alloc(nvlist_t *nvl, size_t len)
    300 {
    301 	nvpriv_t *priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv;
    302 	i_nvp_t *buf;
    303 	nvpair_t *nvp;
    304 	size_t nvsize;
    305 
    306 	/*
    307 	 * Allocate the buffer
    308 	 */
    309 	nvsize = len + offsetof(i_nvp_t, nvi_nvp);
    310 
    311 	if ((buf = nv_mem_zalloc(priv, nvsize)) == NULL)
    312 		return (NULL);
    313 
    314 	nvp = &buf->nvi_nvp;
    315 	nvp->nvp_size = len;
    316 
    317 	return (nvp);
    318 }
    319 
    320 /*
    321  * nvp_buf_free - de-Allocate an i_nvp_t.
    322  */
    323 static void
    324 nvp_buf_free(nvlist_t *nvl, nvpair_t *nvp)
    325 {
    326 	nvpriv_t *priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv;
    327 	size_t nvsize = nvp->nvp_size + offsetof(i_nvp_t, nvi_nvp);
    328 
    329 	nv_mem_free(priv, NVPAIR2I_NVP(nvp), nvsize);
    330 }
    331 
    332 /*
    333  * nvp_buf_link - link a new nv pair into the nvlist.
    334  */
    335 static void
    336 nvp_buf_link(nvlist_t *nvl, nvpair_t *nvp)
    337 {
    338 	nvpriv_t *priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv;
    339 	i_nvp_t *curr = NVPAIR2I_NVP(nvp);
    340 
    341 	/* Put element at end of nvlist */
    342 	if (priv->nvp_list == NULL) {
    343 		priv->nvp_list = priv->nvp_last = curr;
    344 	} else {
    345 		curr->nvi_prev = priv->nvp_last;
    346 		priv->nvp_last->nvi_next = curr;
    347 		priv->nvp_last = curr;
    348 	}
    349 }
    350 
    351 /*
    352  * nvp_buf_unlink - unlink an removed nvpair out of the nvlist.
    353  */
    354 static void
    355 nvp_buf_unlink(nvlist_t *nvl, nvpair_t *nvp)
    356 {
    357 	nvpriv_t *priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv;
    358 	i_nvp_t *curr = NVPAIR2I_NVP(nvp);
    359 
    360 	/*
    361 	 * protect nvlist_next_nvpair() against walking on freed memory.
    362 	 */
    363 	if (priv->nvp_curr == curr)
    364 		priv->nvp_curr = curr->nvi_next;
    365 
    366 	if (curr == priv->nvp_list)
    367 		priv->nvp_list = curr->nvi_next;
    368 	else
    369 		curr->nvi_prev->nvi_next = curr->nvi_next;
    370 
    371 	if (curr == priv->nvp_last)
    372 		priv->nvp_last = curr->nvi_prev;
    373 	else
    374 		curr->nvi_next->nvi_prev = curr->nvi_prev;
    375 }
    376 
    377 /*
    378  * take a nvpair type and number of elements and make sure the are valid
    379  */
    380 static int
    381 i_validate_type_nelem(data_type_t type, uint_t nelem)
    382 {
    383 	switch (type) {
    384 	case DATA_TYPE_BOOLEAN:
    385 		if (nelem != 0)
    386 			return (EINVAL);
    387 		break;
    388 	case DATA_TYPE_BOOLEAN_VALUE:
    389 	case DATA_TYPE_BYTE:
    390 	case DATA_TYPE_INT8:
    391 	case DATA_TYPE_UINT8:
    392 	case DATA_TYPE_INT16:
    393 	case DATA_TYPE_UINT16:
    394 	case DATA_TYPE_INT32:
    395 	case DATA_TYPE_UINT32:
    396 	case DATA_TYPE_INT64:
    397 	case DATA_TYPE_UINT64:
    398 	case DATA_TYPE_STRING:
    399 	case DATA_TYPE_HRTIME:
    400 	case DATA_TYPE_NVLIST:
    401 		if (nelem != 1)
    402 			return (EINVAL);
    403 		break;
    404 	case DATA_TYPE_BOOLEAN_ARRAY:
    405 	case DATA_TYPE_BYTE_ARRAY:
    406 	case DATA_TYPE_INT8_ARRAY:
    407 	case DATA_TYPE_UINT8_ARRAY:
    408 	case DATA_TYPE_INT16_ARRAY:
    409 	case DATA_TYPE_UINT16_ARRAY:
    410 	case DATA_TYPE_INT32_ARRAY:
    411 	case DATA_TYPE_UINT32_ARRAY:
    412 	case DATA_TYPE_INT64_ARRAY:
    413 	case DATA_TYPE_UINT64_ARRAY:
    414 	case DATA_TYPE_STRING_ARRAY:
    415 	case DATA_TYPE_NVLIST_ARRAY:
    416 		/* we allow arrays with 0 elements */
    417 		break;
    418 	default:
    419 		return (EINVAL);
    420 	}
    421 	return (0);
    422 }
    423 
    424 /*
    425  * Verify nvp_name_sz and check the name string length.
    426  */
    427 static int
    428 i_validate_nvpair_name(nvpair_t *nvp)
    429 {
    430 	if ((nvp->nvp_name_sz <= 0) ||
    431 	    (nvp->nvp_size < NVP_SIZE_CALC(nvp->nvp_name_sz, 0)))
    432 		return (EFAULT);
    433 
    434 	/* verify the name string, make sure its terminated */
    435 	if (NVP_NAME(nvp)[nvp->nvp_name_sz - 1] != '\0')
    436 		return (EFAULT);
    437 
    438 	return (strlen(NVP_NAME(nvp)) == nvp->nvp_name_sz - 1 ? 0 : EFAULT);
    439 }
    440 
    441 static int
    442 i_validate_nvpair_value(data_type_t type, uint_t nelem, const void *data)
    443 {
    444 	switch (type) {
    445 	case DATA_TYPE_BOOLEAN_VALUE:
    446 		if (*(boolean_t *)data != B_TRUE &&
    447 		    *(boolean_t *)data != B_FALSE)
    448 			return (EINVAL);
    449 		break;
    450 	case DATA_TYPE_BOOLEAN_ARRAY: {
    451 		int i;
    452 
    453 		for (i = 0; i < nelem; i++)
    454 			if (((boolean_t *)data)[i] != B_TRUE &&
    455 			    ((boolean_t *)data)[i] != B_FALSE)
    456 				return (EINVAL);
    457 		break;
    458 	}
    459 	default:
    460 		break;
    461 	}
    462 
    463 	return (0);
    464 }
    465 
    466 /*
    467  * This function takes a pointer to what should be a nvpair and it's size
    468  * and then verifies that all the nvpair fields make sense and can be
    469  * trusted.  This function is used when decoding packed nvpairs.
    470  */
    471 static int
    472 i_validate_nvpair(nvpair_t *nvp)
    473 {
    474 	data_type_t type = NVP_TYPE(nvp);
    475 	int size1, size2;
    476 
    477 	/* verify nvp_name_sz, check the name string length */
    478 	if (i_validate_nvpair_name(nvp) != 0)
    479 		return (EFAULT);
    480 
    481 	if (i_validate_nvpair_value(type, NVP_NELEM(nvp), NVP_VALUE(nvp)) != 0)
    482 		return (EFAULT);
    483 
    484 	/*
    485 	 * verify nvp_type, nvp_value_elem, and also possibly
    486 	 * verify string values and get the value size.
    487 	 */
    488 	size2 = i_get_value_size(type, NVP_VALUE(nvp), NVP_NELEM(nvp));
    489 	size1 = nvp->nvp_size - NVP_VALOFF(nvp);
    490 	if (size2 < 0 || size1 != NV_ALIGN(size2))
    491 		return (EFAULT);
    492 
    493 	return (0);
    494 }
    495 
    496 static int
    497 nvlist_copy_pairs(nvlist_t *snvl, nvlist_t *dnvl)
    498 {
    499 	nvpriv_t *priv;
    500 	i_nvp_t *curr;
    501 
    502 	if ((priv = (nvpriv_t *)(uintptr_t)snvl->nvl_priv) == NULL)
    503 		return (EINVAL);
    504 
    505 	for (curr = priv->nvp_list; curr != NULL; curr = curr->nvi_next) {
    506 		nvpair_t *nvp = &curr->nvi_nvp;
    507 		int err;
    508 
    509 		if ((err = nvlist_add_common(dnvl, NVP_NAME(nvp), NVP_TYPE(nvp),
    510 		    NVP_NELEM(nvp), NVP_VALUE(nvp))) != 0)
    511 			return (err);
    512 	}
    513 
    514 	return (0);
    515 }
    516 
    517 /*
    518  * Frees all memory allocated for an nvpair (like embedded lists) with
    519  * the exception of the nvpair buffer itself.
    520  */
    521 static void
    522 nvpair_free(nvpair_t *nvp)
    523 {
    524 	switch (NVP_TYPE(nvp)) {
    525 	case DATA_TYPE_NVLIST:
    526 		nvlist_free(EMBEDDED_NVL(nvp));
    527 		break;
    528 	case DATA_TYPE_NVLIST_ARRAY: {
    529 		nvlist_t **nvlp = EMBEDDED_NVL_ARRAY(nvp);
    530 		int i;
    531 
    532 		for (i = 0; i < NVP_NELEM(nvp); i++)
    533 			if (nvlp[i] != NULL)
    534 				nvlist_free(nvlp[i]);
    535 		break;
    536 	}
    537 	default:
    538 		break;
    539 	}
    540 }
    541 
    542 /*
    543  * nvlist_free - free an unpacked nvlist
    544  */
    545 void
    546 nvlist_free(nvlist_t *nvl)
    547 {
    548 	nvpriv_t *priv;
    549 	i_nvp_t *curr;
    550 
    551 	if (nvl == NULL ||
    552 	    (priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL)
    553 		return;
    554 
    555 	/*
    556 	 * Unpacked nvlist are linked through i_nvp_t
    557 	 */
    558 	curr = priv->nvp_list;
    559 	while (curr != NULL) {
    560 		nvpair_t *nvp = &curr->nvi_nvp;
    561 		curr = curr->nvi_next;
    562 
    563 		nvpair_free(nvp);
    564 		nvp_buf_free(nvl, nvp);
    565 	}
    566 
    567 	if (!(priv->nvp_stat & NV_STAT_EMBEDDED))
    568 		nv_mem_free(priv, nvl, NV_ALIGN(sizeof (nvlist_t)));
    569 	else
    570 		nvl->nvl_priv = 0;
    571 
    572 	nv_mem_free(priv, priv, sizeof (nvpriv_t));
    573 }
    574 
    575 static int
    576 nvlist_contains_nvp(nvlist_t *nvl, nvpair_t *nvp)
    577 {
    578 	nvpriv_t *priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv;
    579 	i_nvp_t *curr;
    580 
    581 	if (nvp == NULL)
    582 		return (0);
    583 
    584 	for (curr = priv->nvp_list; curr != NULL; curr = curr->nvi_next)
    585 		if (&curr->nvi_nvp == nvp)
    586 			return (1);
    587 
    588 	return (0);
    589 }
    590 
    591 /*
    592  * Make a copy of nvlist
    593  */
    594 /*ARGSUSED1*/
    595 int
    596 nvlist_dup(nvlist_t *nvl, nvlist_t **nvlp, int kmflag)
    597 {
    598 #if defined(_KERNEL) && !defined(_BOOT)
    599 	return (nvlist_xdup(nvl, nvlp,
    600 	    (kmflag == KM_SLEEP ? nv_alloc_sleep : nv_alloc_nosleep)));
    601 #else
    602 	return (nvlist_xdup(nvl, nvlp, nv_alloc_nosleep));
    603 #endif
    604 }
    605 
    606 int
    607 nvlist_xdup(nvlist_t *nvl, nvlist_t **nvlp, nv_alloc_t *nva)
    608 {
    609 	int err;
    610 	nvlist_t *ret;
    611 
    612 	if (nvl == NULL || nvlp == NULL)
    613 		return (EINVAL);
    614 
    615 	if ((err = nvlist_xalloc(&ret, nvl->nvl_nvflag, nva)) != 0)
    616 		return (err);
    617 
    618 	if ((err = nvlist_copy_pairs(nvl, ret)) != 0)
    619 		nvlist_free(ret);
    620 	else
    621 		*nvlp = ret;
    622 
    623 	return (err);
    624 }
    625 
    626 /*
    627  * Remove all with matching name
    628  */
    629 int
    630 nvlist_remove_all(nvlist_t *nvl, const char *name)
    631 {
    632 	nvpriv_t *priv;
    633 	i_nvp_t *curr;
    634 	int error = ENOENT;
    635 
    636 	if (nvl == NULL || name == NULL ||
    637 	    (priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL)
    638 		return (EINVAL);
    639 
    640 	curr = priv->nvp_list;
    641 	while (curr != NULL) {
    642 		nvpair_t *nvp = &curr->nvi_nvp;
    643 
    644 		curr = curr->nvi_next;
    645 		if (strcmp(name, NVP_NAME(nvp)) != 0)
    646 			continue;
    647 
    648 		nvp_buf_unlink(nvl, nvp);
    649 		nvpair_free(nvp);
    650 		nvp_buf_free(nvl, nvp);
    651 
    652 		error = 0;
    653 	}
    654 
    655 	return (error);
    656 }
    657 
    658 /*
    659  * Remove first one with matching name and type
    660  */
    661 int
    662 nvlist_remove(nvlist_t *nvl, const char *name, data_type_t type)
    663 {
    664 	nvpriv_t *priv;
    665 	i_nvp_t *curr;
    666 
    667 	if (nvl == NULL || name == NULL ||
    668 	    (priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL)
    669 		return (EINVAL);
    670 
    671 	curr = priv->nvp_list;
    672 	while (curr != NULL) {
    673 		nvpair_t *nvp = &curr->nvi_nvp;
    674 
    675 		if (strcmp(name, NVP_NAME(nvp)) == 0 && NVP_TYPE(nvp) == type) {
    676 			nvp_buf_unlink(nvl, nvp);
    677 			nvpair_free(nvp);
    678 			nvp_buf_free(nvl, nvp);
    679 
    680 			return (0);
    681 		}
    682 		curr = curr->nvi_next;
    683 	}
    684 
    685 	return (ENOENT);
    686 }
    687 
    688 /*
    689  * This function calculates the size of an nvpair value.
    690  *
    691  * The data argument controls the behavior in case of the data types
    692  * 	DATA_TYPE_STRING    	and
    693  *	DATA_TYPE_STRING_ARRAY
    694  * Is data == NULL then the size of the string(s) is excluded.
    695  */
    696 static int
    697 i_get_value_size(data_type_t type, const void *data, uint_t nelem)
    698 {
    699 	uint64_t value_sz;
    700 
    701 	if (i_validate_type_nelem(type, nelem) != 0)
    702 		return (-1);
    703 
    704 	/* Calculate required size for holding value */
    705 	switch (type) {
    706 	case DATA_TYPE_BOOLEAN:
    707 		value_sz = 0;
    708 		break;
    709 	case DATA_TYPE_BOOLEAN_VALUE:
    710 		value_sz = sizeof (boolean_t);
    711 		break;
    712 	case DATA_TYPE_BYTE:
    713 		value_sz = sizeof (uchar_t);
    714 		break;
    715 	case DATA_TYPE_INT8:
    716 		value_sz = sizeof (int8_t);
    717 		break;
    718 	case DATA_TYPE_UINT8:
    719 		value_sz = sizeof (uint8_t);
    720 		break;
    721 	case DATA_TYPE_INT16:
    722 		value_sz = sizeof (int16_t);
    723 		break;
    724 	case DATA_TYPE_UINT16:
    725 		value_sz = sizeof (uint16_t);
    726 		break;
    727 	case DATA_TYPE_INT32:
    728 		value_sz = sizeof (int32_t);
    729 		break;
    730 	case DATA_TYPE_UINT32:
    731 		value_sz = sizeof (uint32_t);
    732 		break;
    733 	case DATA_TYPE_INT64:
    734 		value_sz = sizeof (int64_t);
    735 		break;
    736 	case DATA_TYPE_UINT64:
    737 		value_sz = sizeof (uint64_t);
    738 		break;
    739 	case DATA_TYPE_STRING:
    740 		if (data == NULL)
    741 			value_sz = 0;
    742 		else
    743 			value_sz = strlen(data) + 1;
    744 		break;
    745 	case DATA_TYPE_BOOLEAN_ARRAY:
    746 		value_sz = (uint64_t)nelem * sizeof (boolean_t);
    747 		break;
    748 	case DATA_TYPE_BYTE_ARRAY:
    749 		value_sz = (uint64_t)nelem * sizeof (uchar_t);
    750 		break;
    751 	case DATA_TYPE_INT8_ARRAY:
    752 		value_sz = (uint64_t)nelem * sizeof (int8_t);
    753 		break;
    754 	case DATA_TYPE_UINT8_ARRAY:
    755 		value_sz = (uint64_t)nelem * sizeof (uint8_t);
    756 		break;
    757 	case DATA_TYPE_INT16_ARRAY:
    758 		value_sz = (uint64_t)nelem * sizeof (int16_t);
    759 		break;
    760 	case DATA_TYPE_UINT16_ARRAY:
    761 		value_sz = (uint64_t)nelem * sizeof (uint16_t);
    762 		break;
    763 	case DATA_TYPE_INT32_ARRAY:
    764 		value_sz = (uint64_t)nelem * sizeof (int32_t);
    765 		break;
    766 	case DATA_TYPE_UINT32_ARRAY:
    767 		value_sz = (uint64_t)nelem * sizeof (uint32_t);
    768 		break;
    769 	case DATA_TYPE_INT64_ARRAY:
    770 		value_sz = (uint64_t)nelem * sizeof (int64_t);
    771 		break;
    772 	case DATA_TYPE_UINT64_ARRAY:
    773 		value_sz = (uint64_t)nelem * sizeof (uint64_t);
    774 		break;
    775 	case DATA_TYPE_STRING_ARRAY:
    776 		value_sz = (uint64_t)nelem * sizeof (uint64_t);
    777 
    778 		if (data != NULL) {
    779 			char *const *strs = data;
    780 			uint_t i;
    781 
    782 			/* no alignment requirement for strings */
    783 			for (i = 0; i < nelem; i++) {
    784 				if (strs[i] == NULL)
    785 					return (-1);
    786 				value_sz += strlen(strs[i]) + 1;
    787 			}
    788 		}
    789 		break;
    790 	case DATA_TYPE_HRTIME:
    791 		value_sz = sizeof (hrtime_t);
    792 		break;
    793 	case DATA_TYPE_NVLIST:
    794 		value_sz = NV_ALIGN(sizeof (nvlist_t));
    795 		break;
    796 	case DATA_TYPE_NVLIST_ARRAY:
    797 		value_sz = (uint64_t)nelem * sizeof (uint64_t) +
    798 		    (uint64_t)nelem * NV_ALIGN(sizeof (nvlist_t));
    799 		break;
    800 	default:
    801 		return (-1);
    802 	}
    803 
    804 	return (value_sz > INT32_MAX ? -1 : (int)value_sz);
    805 }
    806 
    807 static int
    808 nvlist_copy_embedded(nvlist_t *nvl, nvlist_t *onvl, nvlist_t *emb_nvl)
    809 {
    810 	nvpriv_t *priv;
    811 	int err;
    812 
    813 	if ((priv = nv_priv_alloc_embedded((nvpriv_t *)(uintptr_t)
    814 	    nvl->nvl_priv)) == NULL)
    815 		return (ENOMEM);
    816 
    817 	nvlist_init(emb_nvl, onvl->nvl_nvflag, priv);
    818 
    819 	if ((err = nvlist_copy_pairs(onvl, emb_nvl)) != 0) {
    820 		nvlist_free(emb_nvl);
    821 		emb_nvl->nvl_priv = 0;
    822 	}
    823 
    824 	return (err);
    825 }
    826 
    827 /*
    828  * nvlist_add_common - Add new <name,value> pair to nvlist
    829  */
    830 static int
    831 nvlist_add_common(nvlist_t *nvl, const char *name,
    832     data_type_t type, uint_t nelem, const void *data)
    833 {
    834 	nvpair_t *nvp;
    835 	uint_t i;
    836 
    837 	int nvp_sz, name_sz, value_sz;
    838 	int err = 0;
    839 
    840 	if (name == NULL || nvl == NULL || nvl->nvl_priv == 0)
    841 		return (EINVAL);
    842 
    843 	if (nelem != 0 && data == NULL)
    844 		return (EINVAL);
    845 
    846 	/*
    847 	 * Verify type and nelem and get the value size.
    848 	 * In case of data types DATA_TYPE_STRING and DATA_TYPE_STRING_ARRAY
    849 	 * is the size of the string(s) included.
    850 	 */
    851 	if ((value_sz = i_get_value_size(type, data, nelem)) < 0)
    852 		return (EINVAL);
    853 
    854 	if (i_validate_nvpair_value(type, nelem, data) != 0)
    855 		return (EINVAL);
    856 
    857 	/*
    858 	 * If we're adding an nvlist or nvlist array, ensure that we are not
    859 	 * adding the input nvlist to itself, which would cause recursion,
    860 	 * and ensure that no NULL nvlist pointers are present.
    861 	 */
    862 	switch (type) {
    863 	case DATA_TYPE_NVLIST:
    864 		if (data == nvl || data == NULL)
    865 			return (EINVAL);
    866 		break;
    867 	case DATA_TYPE_NVLIST_ARRAY: {
    868 		nvlist_t **onvlp = (nvlist_t **)data;
    869 		for (i = 0; i < nelem; i++) {
    870 			if (onvlp[i] == nvl || onvlp[i] == NULL)
    871 				return (EINVAL);
    872 		}
    873 		break;
    874 	}
    875 	default:
    876 		break;
    877 	}
    878 
    879 	/* calculate sizes of the nvpair elements and the nvpair itself */
    880 	name_sz = strlen(name) + 1;
    881 
    882 	nvp_sz = NVP_SIZE_CALC(name_sz, value_sz);
    883 
    884 	if ((nvp = nvp_buf_alloc(nvl, nvp_sz)) == NULL)
    885 		return (ENOMEM);
    886 
    887 	ASSERT(nvp->nvp_size == nvp_sz);
    888 	nvp->nvp_name_sz = name_sz;
    889 	nvp->nvp_value_elem = nelem;
    890 	nvp->nvp_type = type;
    891 	bcopy(name, NVP_NAME(nvp), name_sz);
    892 
    893 	switch (type) {
    894 	case DATA_TYPE_BOOLEAN:
    895 		break;
    896 	case DATA_TYPE_STRING_ARRAY: {
    897 		char *const *strs = data;
    898 		char *buf = NVP_VALUE(nvp);
    899 		char **cstrs = (void *)buf;
    900 
    901 		/* skip pre-allocated space for pointer array */
    902 		buf += nelem * sizeof (uint64_t);
    903 		for (i = 0; i < nelem; i++) {
    904 			int slen = strlen(strs[i]) + 1;
    905 			bcopy(strs[i], buf, slen);
    906 			cstrs[i] = buf;
    907 			buf += slen;
    908 		}
    909 		break;
    910 	}
    911 	case DATA_TYPE_NVLIST: {
    912 		nvlist_t *nnvl = EMBEDDED_NVL(nvp);
    913 		nvlist_t *onvl = (nvlist_t *)data;
    914 
    915 		if ((err = nvlist_copy_embedded(nvl, onvl, nnvl)) != 0) {
    916 			nvp_buf_free(nvl, nvp);
    917 			return (err);
    918 		}
    919 		break;
    920 	}
    921 	case DATA_TYPE_NVLIST_ARRAY: {
    922 		nvlist_t **onvlp = (nvlist_t **)data;
    923 		nvlist_t **nvlp = EMBEDDED_NVL_ARRAY(nvp);
    924 		nvlist_t *embedded = (nvlist_t *)
    925 		    ((uintptr_t)nvlp + nelem * sizeof (uint64_t));
    926 
    927 		for (i = 0; i < nelem; i++) {
    928 			if ((err = nvlist_copy_embedded(nvl,
    929 			    onvlp[i], embedded)) != 0) {
    930 				/*
    931 				 * Free any successfully created lists
    932 				 */
    933 				nvpair_free(nvp);
    934 				nvp_buf_free(nvl, nvp);
    935 				return (err);
    936 			}
    937 
    938 			nvlp[i] = embedded++;
    939 		}
    940 		break;
    941 	}
    942 	default:
    943 		bcopy(data, NVP_VALUE(nvp), value_sz);
    944 	}
    945 
    946 	/* if unique name, remove before add */
    947 	if (nvl->nvl_nvflag & NV_UNIQUE_NAME)
    948 		(void) nvlist_remove_all(nvl, name);
    949 	else if (nvl->nvl_nvflag & NV_UNIQUE_NAME_TYPE)
    950 		(void) nvlist_remove(nvl, name, type);
    951 
    952 	nvp_buf_link(nvl, nvp);
    953 
    954 	return (0);
    955 }
    956 
    957 int
    958 nvlist_add_boolean(nvlist_t *nvl, const char *name)
    959 {
    960 	return (nvlist_add_common(nvl, name, DATA_TYPE_BOOLEAN, 0, NULL));
    961 }
    962 
    963 int
    964 nvlist_add_boolean_value(nvlist_t *nvl, const char *name, boolean_t val)
    965 {
    966 	return (nvlist_add_common(nvl, name, DATA_TYPE_BOOLEAN_VALUE, 1, &val));
    967 }
    968 
    969 int
    970 nvlist_add_byte(nvlist_t *nvl, const char *name, uchar_t val)
    971 {
    972 	return (nvlist_add_common(nvl, name, DATA_TYPE_BYTE, 1, &val));
    973 }
    974 
    975 int
    976 nvlist_add_int8(nvlist_t *nvl, const char *name, int8_t val)
    977 {
    978 	return (nvlist_add_common(nvl, name, DATA_TYPE_INT8, 1, &val));
    979 }
    980 
    981 int
    982 nvlist_add_uint8(nvlist_t *nvl, const char *name, uint8_t val)
    983 {
    984 	return (nvlist_add_common(nvl, name, DATA_TYPE_UINT8, 1, &val));
    985 }
    986 
    987 int
    988 nvlist_add_int16(nvlist_t *nvl, const char *name, int16_t val)
    989 {
    990 	return (nvlist_add_common(nvl, name, DATA_TYPE_INT16, 1, &val));
    991 }
    992 
    993 int
    994 nvlist_add_uint16(nvlist_t *nvl, const char *name, uint16_t val)
    995 {
    996 	return (nvlist_add_common(nvl, name, DATA_TYPE_UINT16, 1, &val));
    997 }
    998 
    999 int
   1000 nvlist_add_int32(nvlist_t *nvl, const char *name, int32_t val)
   1001 {
   1002 	return (nvlist_add_common(nvl, name, DATA_TYPE_INT32, 1, &val));
   1003 }
   1004 
   1005 int
   1006 nvlist_add_uint32(nvlist_t *nvl, const char *name, uint32_t val)
   1007 {
   1008 	return (nvlist_add_common(nvl, name, DATA_TYPE_UINT32, 1, &val));
   1009 }
   1010 
   1011 int
   1012 nvlist_add_int64(nvlist_t *nvl, const char *name, int64_t val)
   1013 {
   1014 	return (nvlist_add_common(nvl, name, DATA_TYPE_INT64, 1, &val));
   1015 }
   1016 
   1017 int
   1018 nvlist_add_uint64(nvlist_t *nvl, const char *name, uint64_t val)
   1019 {
   1020 	return (nvlist_add_common(nvl, name, DATA_TYPE_UINT64, 1, &val));
   1021 }
   1022 
   1023 int
   1024 nvlist_add_string(nvlist_t *nvl, const char *name, const char *val)
   1025 {
   1026 	return (nvlist_add_common(nvl, name, DATA_TYPE_STRING, 1, (void *)val));
   1027 }
   1028 
   1029 int
   1030 nvlist_add_boolean_array(nvlist_t *nvl, const char *name,
   1031     boolean_t *a, uint_t n)
   1032 {
   1033 	return (nvlist_add_common(nvl, name, DATA_TYPE_BOOLEAN_ARRAY, n, a));
   1034 }
   1035 
   1036 int
   1037 nvlist_add_byte_array(nvlist_t *nvl, const char *name, uchar_t *a, uint_t n)
   1038 {
   1039 	return (nvlist_add_common(nvl, name, DATA_TYPE_BYTE_ARRAY, n, a));
   1040 }
   1041 
   1042 int
   1043 nvlist_add_int8_array(nvlist_t *nvl, const char *name, int8_t *a, uint_t n)
   1044 {
   1045 	return (nvlist_add_common(nvl, name, DATA_TYPE_INT8_ARRAY, n, a));
   1046 }
   1047 
   1048 int
   1049 nvlist_add_uint8_array(nvlist_t *nvl, const char *name, uint8_t *a, uint_t n)
   1050 {
   1051 	return (nvlist_add_common(nvl, name, DATA_TYPE_UINT8_ARRAY, n, a));
   1052 }
   1053 
   1054 int
   1055 nvlist_add_int16_array(nvlist_t *nvl, const char *name, int16_t *a, uint_t n)
   1056 {
   1057 	return (nvlist_add_common(nvl, name, DATA_TYPE_INT16_ARRAY, n, a));
   1058 }
   1059 
   1060 int
   1061 nvlist_add_uint16_array(nvlist_t *nvl, const char *name, uint16_t *a, uint_t n)
   1062 {
   1063 	return (nvlist_add_common(nvl, name, DATA_TYPE_UINT16_ARRAY, n, a));
   1064 }
   1065 
   1066 int
   1067 nvlist_add_int32_array(nvlist_t *nvl, const char *name, int32_t *a, uint_t n)
   1068 {
   1069 	return (nvlist_add_common(nvl, name, DATA_TYPE_INT32_ARRAY, n, a));
   1070 }
   1071 
   1072 int
   1073 nvlist_add_uint32_array(nvlist_t *nvl, const char *name, uint32_t *a, uint_t n)
   1074 {
   1075 	return (nvlist_add_common(nvl, name, DATA_TYPE_UINT32_ARRAY, n, a));
   1076 }
   1077 
   1078 int
   1079 nvlist_add_int64_array(nvlist_t *nvl, const char *name, int64_t *a, uint_t n)
   1080 {
   1081 	return (nvlist_add_common(nvl, name, DATA_TYPE_INT64_ARRAY, n, a));
   1082 }
   1083 
   1084 int
   1085 nvlist_add_uint64_array(nvlist_t *nvl, const char *name, uint64_t *a, uint_t n)
   1086 {
   1087 	return (nvlist_add_common(nvl, name, DATA_TYPE_UINT64_ARRAY, n, a));
   1088 }
   1089 
   1090 int
   1091 nvlist_add_string_array(nvlist_t *nvl, const char *name,
   1092     char *const *a, uint_t n)
   1093 {
   1094 	return (nvlist_add_common(nvl, name, DATA_TYPE_STRING_ARRAY, n, a));
   1095 }
   1096 
   1097 int
   1098 nvlist_add_hrtime(nvlist_t *nvl, const char *name, hrtime_t val)
   1099 {
   1100 	return (nvlist_add_common(nvl, name, DATA_TYPE_HRTIME, 1, &val));
   1101 }
   1102 
   1103 int
   1104 nvlist_add_nvlist(nvlist_t *nvl, const char *name, nvlist_t *val)
   1105 {
   1106 	return (nvlist_add_common(nvl, name, DATA_TYPE_NVLIST, 1, val));
   1107 }
   1108 
   1109 int
   1110 nvlist_add_nvlist_array(nvlist_t *nvl, const char *name, nvlist_t **a, uint_t n)
   1111 {
   1112 	return (nvlist_add_common(nvl, name, DATA_TYPE_NVLIST_ARRAY, n, a));
   1113 }
   1114 
   1115 /* reading name-value pairs */
   1116 nvpair_t *
   1117 nvlist_next_nvpair(nvlist_t *nvl, nvpair_t *nvp)
   1118 {
   1119 	nvpriv_t *priv;
   1120 	i_nvp_t *curr;
   1121 
   1122 	if (nvl == NULL ||
   1123 	    (priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL)
   1124 		return (NULL);
   1125 
   1126 	curr = NVPAIR2I_NVP(nvp);
   1127 
   1128 	/*
   1129 	 * Ensure that nvp is a valid nvpair on this nvlist.
   1130 	 * NB: nvp_curr is used only as a hint so that we don't always
   1131 	 * have to walk the list to determine if nvp is still on the list.
   1132 	 */
   1133 	if (nvp == NULL)
   1134 		curr = priv->nvp_list;
   1135 	else if (priv->nvp_curr == curr || nvlist_contains_nvp(nvl, nvp))
   1136 		curr = curr->nvi_next;
   1137 	else
   1138 		curr = NULL;
   1139 
   1140 	priv->nvp_curr = curr;
   1141 
   1142 	return (curr != NULL ? &curr->nvi_nvp : NULL);
   1143 }
   1144 
   1145 char *
   1146 nvpair_name(nvpair_t *nvp)
   1147 {
   1148 	return (NVP_NAME(nvp));
   1149 }
   1150 
   1151 data_type_t
   1152 nvpair_type(nvpair_t *nvp)
   1153 {
   1154 	return (NVP_TYPE(nvp));
   1155 }
   1156 
   1157 static int
   1158 nvpair_value_common(nvpair_t *nvp, data_type_t type, uint_t *nelem, void *data)
   1159 {
   1160 	if (nvp == NULL || nvpair_type(nvp) != type)
   1161 		return (EINVAL);
   1162 
   1163 	/*
   1164 	 * For non-array types, we copy the data.
   1165 	 * For array types (including string), we set a pointer.
   1166 	 */
   1167 	switch (type) {
   1168 	case DATA_TYPE_BOOLEAN:
   1169 		if (nelem != NULL)
   1170 			*nelem = 0;
   1171 		break;
   1172 
   1173 	case DATA_TYPE_BOOLEAN_VALUE:
   1174 	case DATA_TYPE_BYTE:
   1175 	case DATA_TYPE_INT8:
   1176 	case DATA_TYPE_UINT8:
   1177 	case DATA_TYPE_INT16:
   1178 	case DATA_TYPE_UINT16:
   1179 	case DATA_TYPE_INT32:
   1180 	case DATA_TYPE_UINT32:
   1181 	case DATA_TYPE_INT64:
   1182 	case DATA_TYPE_UINT64:
   1183 	case DATA_TYPE_HRTIME:
   1184 		if (data == NULL)
   1185 			return (EINVAL);
   1186 		bcopy(NVP_VALUE(nvp), data,
   1187 		    (size_t)i_get_value_size(type, NULL, 1));
   1188 		if (nelem != NULL)
   1189 			*nelem = 1;
   1190 		break;
   1191 
   1192 	case DATA_TYPE_NVLIST:
   1193 	case DATA_TYPE_STRING:
   1194 		if (data == NULL)
   1195 			return (EINVAL);
   1196 		*(void **)data = (void *)NVP_VALUE(nvp);
   1197 		if (nelem != NULL)
   1198 			*nelem = 1;
   1199 		break;
   1200 
   1201 	case DATA_TYPE_BOOLEAN_ARRAY:
   1202 	case DATA_TYPE_BYTE_ARRAY:
   1203 	case DATA_TYPE_INT8_ARRAY:
   1204 	case DATA_TYPE_UINT8_ARRAY:
   1205 	case DATA_TYPE_INT16_ARRAY:
   1206 	case DATA_TYPE_UINT16_ARRAY:
   1207 	case DATA_TYPE_INT32_ARRAY:
   1208 	case DATA_TYPE_UINT32_ARRAY:
   1209 	case DATA_TYPE_INT64_ARRAY:
   1210 	case DATA_TYPE_UINT64_ARRAY:
   1211 	case DATA_TYPE_STRING_ARRAY:
   1212 	case DATA_TYPE_NVLIST_ARRAY:
   1213 		if (nelem == NULL || data == NULL)
   1214 			return (EINVAL);
   1215 		if ((*nelem = NVP_NELEM(nvp)) != 0)
   1216 			*(void **)data = (void *)NVP_VALUE(nvp);
   1217 		else
   1218 			*(void **)data = NULL;
   1219 		break;
   1220 
   1221 	default:
   1222 		return (ENOTSUP);
   1223 	}
   1224 
   1225 	return (0);
   1226 }
   1227 
   1228 static int
   1229 nvlist_lookup_common(nvlist_t *nvl, const char *name, data_type_t type,
   1230     uint_t *nelem, void *data)
   1231 {
   1232 	nvpriv_t *priv;
   1233 	nvpair_t *nvp;
   1234 	i_nvp_t *curr;
   1235 
   1236 	if (name == NULL || nvl == NULL ||
   1237 	    (priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL)
   1238 		return (EINVAL);
   1239 
   1240 	if (!(nvl->nvl_nvflag & (NV_UNIQUE_NAME | NV_UNIQUE_NAME_TYPE)))
   1241 		return (ENOTSUP);
   1242 
   1243 	for (curr = priv->nvp_list; curr != NULL; curr = curr->nvi_next) {
   1244 		nvp = &curr->nvi_nvp;
   1245 
   1246 		if (strcmp(name, NVP_NAME(nvp)) == 0 && NVP_TYPE(nvp) == type)
   1247 			return (nvpair_value_common(nvp, type, nelem, data));
   1248 	}
   1249 
   1250 	return (ENOENT);
   1251 }
   1252 
   1253 int
   1254 nvlist_lookup_boolean(nvlist_t *nvl, const char *name)
   1255 {
   1256 	return (nvlist_lookup_common(nvl, name, DATA_TYPE_BOOLEAN, NULL, NULL));
   1257 }
   1258 
   1259 int
   1260 nvlist_lookup_boolean_value(nvlist_t *nvl, const char *name, boolean_t *val)
   1261 {
   1262 	return (nvlist_lookup_common(nvl, name,
   1263 	    DATA_TYPE_BOOLEAN_VALUE, NULL, val));
   1264 }
   1265 
   1266 int
   1267 nvlist_lookup_byte(nvlist_t *nvl, const char *name, uchar_t *val)
   1268 {
   1269 	return (nvlist_lookup_common(nvl, name, DATA_TYPE_BYTE, NULL, val));
   1270 }
   1271 
   1272 int
   1273 nvlist_lookup_int8(nvlist_t *nvl, const char *name, int8_t *val)
   1274 {
   1275 	return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT8, NULL, val));
   1276 }
   1277 
   1278 int
   1279 nvlist_lookup_uint8(nvlist_t *nvl, const char *name, uint8_t *val)
   1280 {
   1281 	return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT8, NULL, val));
   1282 }
   1283 
   1284 int
   1285 nvlist_lookup_int16(nvlist_t *nvl, const char *name, int16_t *val)
   1286 {
   1287 	return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT16, NULL, val));
   1288 }
   1289 
   1290 int
   1291 nvlist_lookup_uint16(nvlist_t *nvl, const char *name, uint16_t *val)
   1292 {
   1293 	return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT16, NULL, val));
   1294 }
   1295 
   1296 int
   1297 nvlist_lookup_int32(nvlist_t *nvl, const char *name, int32_t *val)
   1298 {
   1299 	return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT32, NULL, val));
   1300 }
   1301 
   1302 int
   1303 nvlist_lookup_uint32(nvlist_t *nvl, const char *name, uint32_t *val)
   1304 {
   1305 	return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT32, NULL, val));
   1306 }
   1307 
   1308 int
   1309 nvlist_lookup_int64(nvlist_t *nvl, const char *name, int64_t *val)
   1310 {
   1311 	return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT64, NULL, val));
   1312 }
   1313 
   1314 int
   1315 nvlist_lookup_uint64(nvlist_t *nvl, const char *name, uint64_t *val)
   1316 {
   1317 	return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT64, NULL, val));
   1318 }
   1319 
   1320 int
   1321 nvlist_lookup_string(nvlist_t *nvl, const char *name, char **val)
   1322 {
   1323 	return (nvlist_lookup_common(nvl, name, DATA_TYPE_STRING, NULL, val));
   1324 }
   1325 
   1326 int
   1327 nvlist_lookup_nvlist(nvlist_t *nvl, const char *name, nvlist_t **val)
   1328 {
   1329 	return (nvlist_lookup_common(nvl, name, DATA_TYPE_NVLIST, NULL, val));
   1330 }
   1331 
   1332 int
   1333 nvlist_lookup_boolean_array(nvlist_t *nvl, const char *name,
   1334     boolean_t **a, uint_t *n)
   1335 {
   1336 	return (nvlist_lookup_common(nvl, name,
   1337 	    DATA_TYPE_BOOLEAN_ARRAY, n, a));
   1338 }
   1339 
   1340 int
   1341 nvlist_lookup_byte_array(nvlist_t *nvl, const char *name,
   1342     uchar_t **a, uint_t *n)
   1343 {
   1344 	return (nvlist_lookup_common(nvl, name, DATA_TYPE_BYTE_ARRAY, n, a));
   1345 }
   1346 
   1347 int
   1348 nvlist_lookup_int8_array(nvlist_t *nvl, const char *name, int8_t **a, uint_t *n)
   1349 {
   1350 	return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT8_ARRAY, n, a));
   1351 }
   1352 
   1353 int
   1354 nvlist_lookup_uint8_array(nvlist_t *nvl, const char *name,
   1355     uint8_t **a, uint_t *n)
   1356 {
   1357 	return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT8_ARRAY, n, a));
   1358 }
   1359 
   1360 int
   1361 nvlist_lookup_int16_array(nvlist_t *nvl, const char *name,
   1362     int16_t **a, uint_t *n)
   1363 {
   1364 	return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT16_ARRAY, n, a));
   1365 }
   1366 
   1367 int
   1368 nvlist_lookup_uint16_array(nvlist_t *nvl, const char *name,
   1369     uint16_t **a, uint_t *n)
   1370 {
   1371 	return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT16_ARRAY, n, a));
   1372 }
   1373 
   1374 int
   1375 nvlist_lookup_int32_array(nvlist_t *nvl, const char *name,
   1376     int32_t **a, uint_t *n)
   1377 {
   1378 	return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT32_ARRAY, n, a));
   1379 }
   1380 
   1381 int
   1382 nvlist_lookup_uint32_array(nvlist_t *nvl, const char *name,
   1383     uint32_t **a, uint_t *n)
   1384 {
   1385 	return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT32_ARRAY, n, a));
   1386 }
   1387 
   1388 int
   1389 nvlist_lookup_int64_array(nvlist_t *nvl, const char *name,
   1390     int64_t **a, uint_t *n)
   1391 {
   1392 	return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT64_ARRAY, n, a));
   1393 }
   1394 
   1395 int
   1396 nvlist_lookup_uint64_array(nvlist_t *nvl, const char *name,
   1397     uint64_t **a, uint_t *n)
   1398 {
   1399 	return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT64_ARRAY, n, a));
   1400 }
   1401 
   1402 int
   1403 nvlist_lookup_string_array(nvlist_t *nvl, const char *name,
   1404     char ***a, uint_t *n)
   1405 {
   1406 	return (nvlist_lookup_common(nvl, name, DATA_TYPE_STRING_ARRAY, n, a));
   1407 }
   1408 
   1409 int
   1410 nvlist_lookup_nvlist_array(nvlist_t *nvl, const char *name,
   1411     nvlist_t ***a, uint_t *n)
   1412 {
   1413 	return (nvlist_lookup_common(nvl, name, DATA_TYPE_NVLIST_ARRAY, n, a));
   1414 }
   1415 
   1416 int
   1417 nvlist_lookup_hrtime(nvlist_t *nvl, const char *name, hrtime_t *val)
   1418 {
   1419 	return (nvlist_lookup_common(nvl, name, DATA_TYPE_HRTIME, NULL, val));
   1420 }
   1421 
   1422 int
   1423 nvlist_lookup_pairs(nvlist_t *nvl, int flag, ...)
   1424 {
   1425 	va_list ap;
   1426 	char *name;
   1427 	int noentok = (flag & NV_FLAG_NOENTOK ? 1 : 0);
   1428 	int ret = 0;
   1429 
   1430 	va_start(ap, flag);
   1431 	while (ret == 0 && (name = va_arg(ap, char *)) != NULL) {
   1432 		data_type_t type;
   1433 		void *val;
   1434 		uint_t *nelem;
   1435 
   1436 		switch (type = va_arg(ap, data_type_t)) {
   1437 		case DATA_TYPE_BOOLEAN:
   1438 			ret = nvlist_lookup_common(nvl, name, type, NULL, NULL);
   1439 			break;
   1440 
   1441 		case DATA_TYPE_BOOLEAN_VALUE:
   1442 		case DATA_TYPE_BYTE:
   1443 		case DATA_TYPE_INT8:
   1444 		case DATA_TYPE_UINT8:
   1445 		case DATA_TYPE_INT16:
   1446 		case DATA_TYPE_UINT16:
   1447 		case DATA_TYPE_INT32:
   1448 		case DATA_TYPE_UINT32:
   1449 		case DATA_TYPE_INT64:
   1450 		case DATA_TYPE_UINT64:
   1451 		case DATA_TYPE_HRTIME:
   1452 		case DATA_TYPE_STRING:
   1453 		case DATA_TYPE_NVLIST:
   1454 			val = va_arg(ap, void *);
   1455 			ret = nvlist_lookup_common(nvl, name, type, NULL, val);
   1456 			break;
   1457 
   1458 		case DATA_TYPE_BYTE_ARRAY:
   1459 		case DATA_TYPE_BOOLEAN_ARRAY:
   1460 		case DATA_TYPE_INT8_ARRAY:
   1461 		case DATA_TYPE_UINT8_ARRAY:
   1462 		case DATA_TYPE_INT16_ARRAY:
   1463 		case DATA_TYPE_UINT16_ARRAY:
   1464 		case DATA_TYPE_INT32_ARRAY:
   1465 		case DATA_TYPE_UINT32_ARRAY:
   1466 		case DATA_TYPE_INT64_ARRAY:
   1467 		case DATA_TYPE_UINT64_ARRAY:
   1468 		case DATA_TYPE_STRING_ARRAY:
   1469 		case DATA_TYPE_NVLIST_ARRAY:
   1470 			val = va_arg(ap, void *);
   1471 			nelem = va_arg(ap, uint_t *);
   1472 			ret = nvlist_lookup_common(nvl, name, type, nelem, val);
   1473 			break;
   1474 
   1475 		default:
   1476 			ret = EINVAL;
   1477 		}
   1478 
   1479 		if (ret == ENOENT && noentok)
   1480 			ret = 0;
   1481 	}
   1482 	va_end(ap);
   1483 
   1484 	return (ret);
   1485 }
   1486 
   1487 int
   1488 nvlist_lookup_nvpair(nvlist_t *nvl, const char *name, nvpair_t **ret)
   1489 {
   1490 	nvpriv_t *priv;
   1491 	nvpair_t *nvp;
   1492 	i_nvp_t *curr;
   1493 
   1494 	if (name == NULL || nvl == NULL ||
   1495 	    (priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL)
   1496 		return (EINVAL);
   1497 
   1498 	if (!(nvl->nvl_nvflag & NV_UNIQUE_NAME))
   1499 		return (ENOTSUP);
   1500 
   1501 	for (curr = priv->nvp_list; curr != NULL; curr = curr->nvi_next) {
   1502 		nvp = &curr->nvi_nvp;
   1503 
   1504 		if (strcmp(name, NVP_NAME(nvp)) == 0) {
   1505 			*ret = nvp;
   1506 			return (0);
   1507 		}
   1508 	}
   1509 
   1510 	return (ENOENT);
   1511 }
   1512 
   1513 boolean_t
   1514 nvlist_exists(nvlist_t *nvl, const char *name)
   1515 {
   1516 	nvpriv_t *priv;
   1517 	nvpair_t *nvp;
   1518 	i_nvp_t *curr;
   1519 
   1520 	if (name == NULL || nvl == NULL ||
   1521 	    (priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL)
   1522 		return (B_FALSE);
   1523 
   1524 	for (curr = priv->nvp_list; curr != NULL; curr = curr->nvi_next) {
   1525 		nvp = &curr->nvi_nvp;
   1526 
   1527 		if (strcmp(name, NVP_NAME(nvp)) == 0)
   1528 			return (B_TRUE);
   1529 	}
   1530 
   1531 	return (B_FALSE);
   1532 }
   1533 
   1534 int
   1535 nvpair_value_boolean_value(nvpair_t *nvp, boolean_t *val)
   1536 {
   1537 	return (nvpair_value_common(nvp, DATA_TYPE_BOOLEAN_VALUE, NULL, val));
   1538 }
   1539 
   1540 int
   1541 nvpair_value_byte(nvpair_t *nvp, uchar_t *val)
   1542 {
   1543 	return (nvpair_value_common(nvp, DATA_TYPE_BYTE, NULL, val));
   1544 }
   1545 
   1546 int
   1547 nvpair_value_int8(nvpair_t *nvp, int8_t *val)
   1548 {
   1549 	return (nvpair_value_common(nvp, DATA_TYPE_INT8, NULL, val));
   1550 }
   1551 
   1552 int
   1553 nvpair_value_uint8(nvpair_t *nvp, uint8_t *val)
   1554 {
   1555 	return (nvpair_value_common(nvp, DATA_TYPE_UINT8, NULL, val));
   1556 }
   1557 
   1558 int
   1559 nvpair_value_int16(nvpair_t *nvp, int16_t *val)
   1560 {
   1561 	return (nvpair_value_common(nvp, DATA_TYPE_INT16, NULL, val));
   1562 }
   1563 
   1564 int
   1565 nvpair_value_uint16(nvpair_t *nvp, uint16_t *val)
   1566 {
   1567 	return (nvpair_value_common(nvp, DATA_TYPE_UINT16, NULL, val));
   1568 }
   1569 
   1570 int
   1571 nvpair_value_int32(nvpair_t *nvp, int32_t *val)
   1572 {
   1573 	return (nvpair_value_common(nvp, DATA_TYPE_INT32, NULL, val));
   1574 }
   1575 
   1576 int
   1577 nvpair_value_uint32(nvpair_t *nvp, uint32_t *val)
   1578 {
   1579 	return (nvpair_value_common(nvp, DATA_TYPE_UINT32, NULL, val));
   1580 }
   1581 
   1582 int
   1583 nvpair_value_int64(nvpair_t *nvp, int64_t *val)
   1584 {
   1585 	return (nvpair_value_common(nvp, DATA_TYPE_INT64, NULL, val));
   1586 }
   1587 
   1588 int
   1589 nvpair_value_uint64(nvpair_t *nvp, uint64_t *val)
   1590 {
   1591 	return (nvpair_value_common(nvp, DATA_TYPE_UINT64, NULL, val));
   1592 }
   1593 
   1594 int
   1595 nvpair_value_string(nvpair_t *nvp, char **val)
   1596 {
   1597 	return (nvpair_value_common(nvp, DATA_TYPE_STRING, NULL, val));
   1598 }
   1599 
   1600 int
   1601 nvpair_value_nvlist(nvpair_t *nvp, nvlist_t **val)
   1602 {
   1603 	return (nvpair_value_common(nvp, DATA_TYPE_NVLIST, NULL, val));
   1604 }
   1605 
   1606 int
   1607 nvpair_value_boolean_array(nvpair_t *nvp, boolean_t **val, uint_t *nelem)
   1608 {
   1609 	return (nvpair_value_common(nvp, DATA_TYPE_BOOLEAN_ARRAY, nelem, val));
   1610 }
   1611 
   1612 int
   1613 nvpair_value_byte_array(nvpair_t *nvp, uchar_t **val, uint_t *nelem)
   1614 {
   1615 	return (nvpair_value_common(nvp, DATA_TYPE_BYTE_ARRAY, nelem, val));
   1616 }
   1617 
   1618 int
   1619 nvpair_value_int8_array(nvpair_t *nvp, int8_t **val, uint_t *nelem)
   1620 {
   1621 	return (nvpair_value_common(nvp, DATA_TYPE_INT8_ARRAY, nelem, val));
   1622 }
   1623 
   1624 int
   1625 nvpair_value_uint8_array(nvpair_t *nvp, uint8_t **val, uint_t *nelem)
   1626 {
   1627 	return (nvpair_value_common(nvp, DATA_TYPE_UINT8_ARRAY, nelem, val));
   1628 }
   1629 
   1630 int
   1631 nvpair_value_int16_array(nvpair_t *nvp, int16_t **val, uint_t *nelem)
   1632 {
   1633 	return (nvpair_value_common(nvp, DATA_TYPE_INT16_ARRAY, nelem, val));
   1634 }
   1635 
   1636 int
   1637 nvpair_value_uint16_array(nvpair_t *nvp, uint16_t **val, uint_t *nelem)
   1638 {
   1639 	return (nvpair_value_common(nvp, DATA_TYPE_UINT16_ARRAY, nelem, val));
   1640 }
   1641 
   1642 int
   1643 nvpair_value_int32_array(nvpair_t *nvp, int32_t **val, uint_t *nelem)
   1644 {
   1645 	return (nvpair_value_common(nvp, DATA_TYPE_INT32_ARRAY, nelem, val));
   1646 }
   1647 
   1648 int
   1649 nvpair_value_uint32_array(nvpair_t *nvp, uint32_t **val, uint_t *nelem)
   1650 {
   1651 	return (nvpair_value_common(nvp, DATA_TYPE_UINT32_ARRAY, nelem, val));
   1652 }
   1653 
   1654 int
   1655 nvpair_value_int64_array(nvpair_t *nvp, int64_t **val, uint_t *nelem)
   1656 {
   1657 	return (nvpair_value_common(nvp, DATA_TYPE_INT64_ARRAY, nelem, val));
   1658 }
   1659 
   1660 int
   1661 nvpair_value_uint64_array(nvpair_t *nvp, uint64_t **val, uint_t *nelem)
   1662 {
   1663 	return (nvpair_value_common(nvp, DATA_TYPE_UINT64_ARRAY, nelem, val));
   1664 }
   1665 
   1666 int
   1667 nvpair_value_string_array(nvpair_t *nvp, char ***val, uint_t *nelem)
   1668 {
   1669 	return (nvpair_value_common(nvp, DATA_TYPE_STRING_ARRAY, nelem, val));
   1670 }
   1671 
   1672 int
   1673 nvpair_value_nvlist_array(nvpair_t *nvp, nvlist_t ***val, uint_t *nelem)
   1674 {
   1675 	return (nvpair_value_common(nvp, DATA_TYPE_NVLIST_ARRAY, nelem, val));
   1676 }
   1677 
   1678 int
   1679 nvpair_value_hrtime(nvpair_t *nvp, hrtime_t *val)
   1680 {
   1681 	return (nvpair_value_common(nvp, DATA_TYPE_HRTIME, NULL, val));
   1682 }
   1683 
   1684 /*
   1685  * Add specified pair to the list.
   1686  */
   1687 int
   1688 nvlist_add_nvpair(nvlist_t *nvl, nvpair_t *nvp)
   1689 {
   1690 	if (nvl == NULL || nvp == NULL)
   1691 		return (EINVAL);
   1692 
   1693 	return (nvlist_add_common(nvl, NVP_NAME(nvp), NVP_TYPE(nvp),
   1694 	    NVP_NELEM(nvp), NVP_VALUE(nvp)));
   1695 }
   1696 
   1697 /*
   1698  * Merge the supplied nvlists and put the result in dst.
   1699  * The merged list will contain all names specified in both lists,
   1700  * the values are taken from nvl in the case of duplicates.
   1701  * Return 0 on success.
   1702  */
   1703 /*ARGSUSED*/
   1704 int
   1705 nvlist_merge(nvlist_t *dst, nvlist_t *nvl, int flag)
   1706 {
   1707 	if (nvl == NULL || dst == NULL)
   1708 		return (EINVAL);
   1709 
   1710 	if (dst != nvl)
   1711 		return (nvlist_copy_pairs(nvl, dst));
   1712 
   1713 	return (0);
   1714 }
   1715 
   1716 /*
   1717  * Encoding related routines
   1718  */
   1719 #define	NVS_OP_ENCODE	0
   1720 #define	NVS_OP_DECODE	1
   1721 #define	NVS_OP_GETSIZE	2
   1722 
   1723 typedef struct nvs_ops nvs_ops_t;
   1724 
   1725 typedef struct {
   1726 	int		nvs_op;
   1727 	const nvs_ops_t	*nvs_ops;
   1728 	void		*nvs_private;
   1729 	nvpriv_t	*nvs_priv;
   1730 } nvstream_t;
   1731 
   1732 /*
   1733  * nvs operations are:
   1734  *   - nvs_nvlist
   1735  *     encoding / decoding of a nvlist header (nvlist_t)
   1736  *     calculates the size used for header and end detection
   1737  *
   1738  *   - nvs_nvpair
   1739  *     responsible for the first part of encoding / decoding of an nvpair
   1740  *     calculates the decoded size of an nvpair
   1741  *
   1742  *   - nvs_nvp_op
   1743  *     second part of encoding / decoding of an nvpair
   1744  *
   1745  *   - nvs_nvp_size
   1746  *     calculates the encoding size of an nvpair
   1747  *
   1748  *   - nvs_nvl_fini
   1749  *     encodes the end detection mark (zeros).
   1750  */
   1751 struct nvs_ops {
   1752 	int (*nvs_nvlist)(nvstream_t *, nvlist_t *, size_t *);
   1753 	int (*nvs_nvpair)(nvstream_t *, nvpair_t *, size_t *);
   1754 	int (*nvs_nvp_op)(nvstream_t *, nvpair_t *);
   1755 	int (*nvs_nvp_size)(nvstream_t *, nvpair_t *, size_t *);
   1756 	int (*nvs_nvl_fini)(nvstream_t *);
   1757 };
   1758 
   1759 typedef struct {
   1760 	char	nvh_encoding;	/* nvs encoding method */
   1761 	char	nvh_endian;	/* nvs endian */
   1762 	char	nvh_reserved1;	/* reserved for future use */
   1763 	char	nvh_reserved2;	/* reserved for future use */
   1764 } nvs_header_t;
   1765 
   1766 static int
   1767 nvs_encode_pairs(nvstream_t *nvs, nvlist_t *nvl)
   1768 {
   1769 	nvpriv_t *priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv;
   1770 	i_nvp_t *curr;
   1771 
   1772 	/*
   1773 	 * Walk nvpair in list and encode each nvpair
   1774 	 */
   1775 	for (curr = priv->nvp_list; curr != NULL; curr = curr->nvi_next)
   1776 		if (nvs->nvs_ops->nvs_nvpair(nvs, &curr->nvi_nvp, NULL) != 0)
   1777 			return (EFAULT);
   1778 
   1779 	return (nvs->nvs_ops->nvs_nvl_fini(nvs));
   1780 }
   1781 
   1782 static int
   1783 nvs_decode_pairs(nvstream_t *nvs, nvlist_t *nvl)
   1784 {
   1785 	nvpair_t *nvp;
   1786 	size_t nvsize;
   1787 	int err;
   1788 
   1789 	/*
   1790 	 * Get decoded size of next pair in stream, alloc
   1791 	 * memory for nvpair_t, then decode the nvpair
   1792 	 */
   1793 	while ((err = nvs->nvs_ops->nvs_nvpair(nvs, NULL, &nvsize)) == 0) {
   1794 		if (nvsize == 0) /* end of list */
   1795 			break;
   1796 
   1797 		/* make sure len makes sense */
   1798 		if (nvsize < NVP_SIZE_CALC(1, 0))
   1799 			return (EFAULT);
   1800 
   1801 		if ((nvp = nvp_buf_alloc(nvl, nvsize)) == NULL)
   1802 			return (ENOMEM);
   1803 
   1804 		if ((err = nvs->nvs_ops->nvs_nvp_op(nvs, nvp)) != 0) {
   1805 			nvp_buf_free(nvl, nvp);
   1806 			return (err);
   1807 		}
   1808 
   1809 		if (i_validate_nvpair(nvp) != 0) {
   1810 			nvpair_free(nvp);
   1811 			nvp_buf_free(nvl, nvp);
   1812 			return (EFAULT);
   1813 		}
   1814 
   1815 		nvp_buf_link(nvl, nvp);
   1816 	}
   1817 	return (err);
   1818 }
   1819 
   1820 static int
   1821 nvs_getsize_pairs(nvstream_t *nvs, nvlist_t *nvl, size_t *buflen)
   1822 {
   1823 	nvpriv_t *priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv;
   1824 	i_nvp_t *curr;
   1825 	uint64_t nvsize = *buflen;
   1826 	size_t size;
   1827 
   1828 	/*
   1829 	 * Get encoded size of nvpairs in nvlist
   1830 	 */
   1831 	for (curr = priv->nvp_list; curr != NULL; curr = curr->nvi_next) {
   1832 		if (nvs->nvs_ops->nvs_nvp_size(nvs, &curr->nvi_nvp, &size) != 0)
   1833 			return (EINVAL);
   1834 
   1835 		if ((nvsize += size) > INT32_MAX)
   1836 			return (EINVAL);
   1837 	}
   1838 
   1839 	*buflen = nvsize;
   1840 	return (0);
   1841 }
   1842 
   1843 static int
   1844 nvs_operation(nvstream_t *nvs, nvlist_t *nvl, size_t *buflen)
   1845 {
   1846 	int err;
   1847 
   1848 	if (nvl->nvl_priv == 0)
   1849 		return (EFAULT);
   1850 
   1851 	/*
   1852 	 * Perform the operation, starting with header, then each nvpair
   1853 	 */
   1854 	if ((err = nvs->nvs_ops->nvs_nvlist(nvs, nvl, buflen)) != 0)
   1855 		return (err);
   1856 
   1857 	switch (nvs->nvs_op) {
   1858 	case NVS_OP_ENCODE:
   1859 		err = nvs_encode_pairs(nvs, nvl);
   1860 		break;
   1861 
   1862 	case NVS_OP_DECODE:
   1863 		err = nvs_decode_pairs(nvs, nvl);
   1864 		break;
   1865 
   1866 	case NVS_OP_GETSIZE:
   1867 		err = nvs_getsize_pairs(nvs, nvl, buflen);
   1868 		break;
   1869 
   1870 	default:
   1871 		err = EINVAL;
   1872 	}
   1873 
   1874 	return (err);
   1875 }
   1876 
   1877 static int
   1878 nvs_embedded(nvstream_t *nvs, nvlist_t *embedded)
   1879 {
   1880 	switch (nvs->nvs_op) {
   1881 	case NVS_OP_ENCODE:
   1882 		return (nvs_operation(nvs, embedded, NULL));
   1883 
   1884 	case NVS_OP_DECODE: {
   1885 		nvpriv_t *priv;
   1886 		int err;
   1887 
   1888 		if (embedded->nvl_version != NV_VERSION)
   1889 			return (ENOTSUP);
   1890 
   1891 		if ((priv = nv_priv_alloc_embedded(nvs->nvs_priv)) == NULL)
   1892 			return (ENOMEM);
   1893 
   1894 		nvlist_init(embedded, embedded->nvl_nvflag, priv);
   1895 
   1896 		if ((err = nvs_operation(nvs, embedded, NULL)) != 0)
   1897 			nvlist_free(embedded);
   1898 		return (err);
   1899 	}
   1900 	default:
   1901 		break;
   1902 	}
   1903 
   1904 	return (EINVAL);
   1905 }
   1906 
   1907 static int
   1908 nvs_embedded_nvl_array(nvstream_t *nvs, nvpair_t *nvp, size_t *size)
   1909 {
   1910 	size_t nelem = NVP_NELEM(nvp);
   1911 	nvlist_t **nvlp = EMBEDDED_NVL_ARRAY(nvp);
   1912 	int i;
   1913 
   1914 	switch (nvs->nvs_op) {
   1915 	case NVS_OP_ENCODE:
   1916 		for (i = 0; i < nelem; i++)
   1917 			if (nvs_embedded(nvs, nvlp[i]) != 0)
   1918 				return (EFAULT);
   1919 		break;
   1920 
   1921 	case NVS_OP_DECODE: {
   1922 		size_t len = nelem * sizeof (uint64_t);
   1923 		nvlist_t *embedded = (nvlist_t *)((uintptr_t)nvlp + len);
   1924 
   1925 		bzero(nvlp, len);	/* don't trust packed data */
   1926 		for (i = 0; i < nelem; i++) {
   1927 			if (nvs_embedded(nvs, embedded) != 0) {
   1928 				nvpair_free(nvp);
   1929 				return (EFAULT);
   1930 			}
   1931 
   1932 			nvlp[i] = embedded++;
   1933 		}
   1934 		break;
   1935 	}
   1936 	case NVS_OP_GETSIZE: {
   1937 		uint64_t nvsize = 0;
   1938 
   1939 		for (i = 0; i < nelem; i++) {
   1940 			size_t nvp_sz = 0;
   1941 
   1942 			if (nvs_operation(nvs, nvlp[i], &nvp_sz) != 0)
   1943 				return (EINVAL);
   1944 
   1945 			if ((nvsize += nvp_sz) > INT32_MAX)
   1946 				return (EINVAL);
   1947 		}
   1948 
   1949 		*size = nvsize;
   1950 		break;
   1951 	}
   1952 	default:
   1953 		return (EINVAL);
   1954 	}
   1955 
   1956 	return (0);
   1957 }
   1958 
   1959 static int nvs_native(nvstream_t *, nvlist_t *, char *, size_t *);
   1960 static int nvs_xdr(nvstream_t *, nvlist_t *, char *, size_t *);
   1961 
   1962 /*
   1963  * Common routine for nvlist operations:
   1964  * encode, decode, getsize (encoded size).
   1965  */
   1966 static int
   1967 nvlist_common(nvlist_t *nvl, char *buf, size_t *buflen, int encoding,
   1968     int nvs_op)
   1969 {
   1970 	int err = 0;
   1971 	nvstream_t nvs;
   1972 	int nvl_endian;
   1973 #ifdef	_LITTLE_ENDIAN
   1974 	int host_endian = 1;
   1975 #else
   1976 	int host_endian = 0;
   1977 #endif	/* _LITTLE_ENDIAN */
   1978 	nvs_header_t *nvh = (void *)buf;
   1979 
   1980 	if (buflen == NULL || nvl == NULL ||
   1981 	    (nvs.nvs_priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL)
   1982 		return (EINVAL);
   1983 
   1984 	nvs.nvs_op = nvs_op;
   1985 
   1986 	/*
   1987 	 * For NVS_OP_ENCODE and NVS_OP_DECODE make sure an nvlist and
   1988 	 * a buffer is allocated.  The first 4 bytes in the buffer are
   1989 	 * used for encoding method and host endian.
   1990 	 */
   1991 	switch (nvs_op) {
   1992 	case NVS_OP_ENCODE:
   1993 		if (buf == NULL || *buflen < sizeof (nvs_header_t))
   1994 			return (EINVAL);
   1995 
   1996 		nvh->nvh_encoding = encoding;
   1997 		nvh->nvh_endian = nvl_endian = host_endian;
   1998 		nvh->nvh_reserved1 = 0;
   1999 		nvh->nvh_reserved2 = 0;
   2000 		break;
   2001 
   2002 	case NVS_OP_DECODE:
   2003 		if (buf == NULL || *buflen < sizeof (nvs_header_t))
   2004 			return (EINVAL);
   2005 
   2006 		/* get method of encoding from first byte */
   2007 		encoding = nvh->nvh_encoding;
   2008 		nvl_endian = nvh->nvh_endian;
   2009 		break;
   2010 
   2011 	case NVS_OP_GETSIZE:
   2012 		nvl_endian = host_endian;
   2013 
   2014 		/*
   2015 		 * add the size for encoding
   2016 		 */
   2017 		*buflen = sizeof (nvs_header_t);
   2018 		break;
   2019 
   2020 	default:
   2021 		return (ENOTSUP);
   2022 	}
   2023 
   2024 	/*
   2025 	 * Create an nvstream with proper encoding method
   2026 	 */
   2027 	switch (encoding) {
   2028 	case NV_ENCODE_NATIVE:
   2029 		/*
   2030 		 * check endianness, in case we are unpacking
   2031 		 * from a file
   2032 		 */
   2033 		if (nvl_endian != host_endian)
   2034 			return (ENOTSUP);
   2035 		err = nvs_native(&nvs, nvl, buf, buflen);
   2036 		break;
   2037 	case NV_ENCODE_XDR:
   2038 		err = nvs_xdr(&nvs, nvl, buf, buflen);
   2039 		break;
   2040 	default:
   2041 		err = ENOTSUP;
   2042 		break;
   2043 	}
   2044 
   2045 	return (err);
   2046 }
   2047 
   2048 int
   2049 nvlist_size(nvlist_t *nvl, size_t *size, int encoding)
   2050 {
   2051 	return (nvlist_common(nvl, NULL, size, encoding, NVS_OP_GETSIZE));
   2052 }
   2053 
   2054 /*
   2055  * Pack nvlist into contiguous memory
   2056  */
   2057 /*ARGSUSED1*/
   2058 int
   2059 nvlist_pack(nvlist_t *nvl, char **bufp, size_t *buflen, int encoding,
   2060     int kmflag)
   2061 {
   2062 #if defined(_KERNEL) && !defined(_BOOT)
   2063 	return (nvlist_xpack(nvl, bufp, buflen, encoding,
   2064 	    (kmflag == KM_SLEEP ? nv_alloc_sleep : nv_alloc_nosleep)));
   2065 #else
   2066 	return (nvlist_xpack(nvl, bufp, buflen, encoding, nv_alloc_nosleep));
   2067 #endif
   2068 }
   2069 
   2070 int
   2071 nvlist_xpack(nvlist_t *nvl, char **bufp, size_t *buflen, int encoding,
   2072     nv_alloc_t *nva)
   2073 {
   2074 	nvpriv_t nvpriv;
   2075 	size_t alloc_size;
   2076 	char *buf;
   2077 	int err;
   2078 
   2079 	if (nva == NULL || nvl == NULL || bufp == NULL || buflen == NULL)
   2080 		return (EINVAL);
   2081 
   2082 	if (*bufp != NULL)
   2083 		return (nvlist_common(nvl, *bufp, buflen, encoding,
   2084 		    NVS_OP_ENCODE));
   2085 
   2086 	/*
   2087 	 * Here is a difficult situation:
   2088 	 * 1. The nvlist has fixed allocator properties.
   2089 	 *    All other nvlist routines (like nvlist_add_*, ...) use
   2090 	 *    these properties.
   2091 	 * 2. When using nvlist_pack() the user can specify his own
   2092 	 *    allocator properties (e.g. by using KM_NOSLEEP).
   2093 	 *
   2094 	 * We use the user specified properties (2). A clearer solution
   2095 	 * will be to remove the kmflag from nvlist_pack(), but we will
   2096 	 * not change the interface.
   2097 	 */
   2098 	nv_priv_init(&nvpriv, nva, 0);
   2099 
   2100 	if (err = nvlist_size(nvl, &alloc_size, encoding))
   2101 		return (err);
   2102 
   2103 	if ((buf = nv_mem_zalloc(&nvpriv, alloc_size)) == NULL)
   2104 		return (ENOMEM);
   2105 
   2106 	if ((err = nvlist_common(nvl, buf, &alloc_size, encoding,
   2107 	    NVS_OP_ENCODE)) != 0) {
   2108 		nv_mem_free(&nvpriv, buf, alloc_size);
   2109 	} else {
   2110 		*buflen = alloc_size;
   2111 		*bufp = buf;
   2112 	}
   2113 
   2114 	return (err);
   2115 }
   2116 
   2117 /*
   2118  * Unpack buf into an nvlist_t
   2119  */
   2120 /*ARGSUSED1*/
   2121 int
   2122 nvlist_unpack(char *buf, size_t buflen, nvlist_t **nvlp, int kmflag)
   2123 {
   2124 #if defined(_KERNEL) && !defined(_BOOT)
   2125 	return (nvlist_xunpack(buf, buflen, nvlp,
   2126 	    (kmflag == KM_SLEEP ? nv_alloc_sleep : nv_alloc_nosleep)));
   2127 #else
   2128 	return (nvlist_xunpack(buf, buflen, nvlp, nv_alloc_nosleep));
   2129 #endif
   2130 }
   2131 
   2132 int
   2133 nvlist_xunpack(char *buf, size_t buflen, nvlist_t **nvlp, nv_alloc_t *nva)
   2134 {
   2135 	nvlist_t *nvl;
   2136 	int err;
   2137 
   2138 	if (nvlp == NULL)
   2139 		return (EINVAL);
   2140 
   2141 	if ((err = nvlist_xalloc(&nvl, 0, nva)) != 0)
   2142 		return (err);
   2143 
   2144 	if ((err = nvlist_common(nvl, buf, &buflen, 0, NVS_OP_DECODE)) != 0)
   2145 		nvlist_free(nvl);
   2146 	else
   2147 		*nvlp = nvl;
   2148 
   2149 	return (err);
   2150 }
   2151 
   2152 /*
   2153  * Native encoding functions
   2154  */
   2155 typedef struct {
   2156 	/*
   2157 	 * This structure is used when decoding a packed nvpair in
   2158 	 * the native format.  n_base points to a buffer containing the
   2159 	 * packed nvpair.  n_end is a pointer to the end of the buffer.
   2160 	 * (n_end actually points to the first byte past the end of the
   2161 	 * buffer.)  n_curr is a pointer that lies between n_base and n_end.
   2162 	 * It points to the current data that we are decoding.
   2163 	 * The amount of data left in the buffer is equal to n_end - n_curr.
   2164 	 * n_flag is used to recognize a packed embedded list.
   2165 	 */
   2166 	caddr_t n_base;
   2167 	caddr_t n_end;
   2168 	caddr_t n_curr;
   2169 	uint_t  n_flag;
   2170 } nvs_native_t;
   2171 
   2172 static int
   2173 nvs_native_create(nvstream_t *nvs, nvs_native_t *native, char *buf,
   2174     size_t buflen)
   2175 {
   2176 	switch (nvs->nvs_op) {
   2177 	case NVS_OP_ENCODE:
   2178 	case NVS_OP_DECODE:
   2179 		nvs->nvs_private = native;
   2180 		native->n_curr = native->n_base = buf;
   2181 		native->n_end = buf + buflen;
   2182 		native->n_flag = 0;
   2183 		return (0);
   2184 
   2185 	case NVS_OP_GETSIZE:
   2186 		nvs->nvs_private = native;
   2187 		native->n_curr = native->n_base = native->n_end = NULL;
   2188 		native->n_flag = 0;
   2189 		return (0);
   2190 	default:
   2191 		return (EINVAL);
   2192 	}
   2193 }
   2194 
   2195 /*ARGSUSED*/
   2196 static void
   2197 nvs_native_destroy(nvstream_t *nvs)
   2198 {
   2199 }
   2200 
   2201 static int
   2202 native_cp(nvstream_t *nvs, void *buf, size_t size)
   2203 {
   2204 	nvs_native_t *native = (nvs_native_t *)nvs->nvs_private;
   2205 
   2206 	if (native->n_curr + size > native->n_end)
   2207 		return (EFAULT);
   2208 
   2209 	/*
   2210 	 * The bcopy() below eliminates alignment requirement
   2211 	 * on the buffer (stream) and is preferred over direct access.
   2212 	 */
   2213 	switch (nvs->nvs_op) {
   2214 	case NVS_OP_ENCODE:
   2215 		bcopy(buf, native->n_curr, size);
   2216 		break;
   2217 	case NVS_OP_DECODE:
   2218 		bcopy(native->n_curr, buf, size);
   2219 		break;
   2220 	default:
   2221 		return (EINVAL);
   2222 	}
   2223 
   2224 	native->n_curr += size;
   2225 	return (0);
   2226 }
   2227 
   2228 /*
   2229  * operate on nvlist_t header
   2230  */
   2231 static int
   2232 nvs_native_nvlist(nvstream_t *nvs, nvlist_t *nvl, size_t *size)
   2233 {
   2234 	nvs_native_t *native = nvs->nvs_private;
   2235 
   2236 	switch (nvs->nvs_op) {
   2237 	case NVS_OP_ENCODE:
   2238 	case NVS_OP_DECODE:
   2239 		if (native->n_flag)
   2240 			return (0);	/* packed embedded list */
   2241 
   2242 		native->n_flag = 1;
   2243 
   2244 		/* copy version and nvflag of the nvlist_t */
   2245 		if (native_cp(nvs, &nvl->nvl_version, sizeof (int32_t)) != 0 ||
   2246 		    native_cp(nvs, &nvl->nvl_nvflag, sizeof (int32_t)) != 0)
   2247 			return (EFAULT);
   2248 
   2249 		return (0);
   2250 
   2251 	case NVS_OP_GETSIZE:
   2252 		/*
   2253 		 * if calculate for packed embedded list
   2254 		 * 	4 for end of the embedded list
   2255 		 * else
   2256 		 * 	2 * sizeof (int32_t) for nvl_version and nvl_nvflag
   2257 		 * 	and 4 for end of the entire list
   2258 		 */
   2259 		if (native->n_flag) {
   2260 			*size += 4;
   2261 		} else {
   2262 			native->n_flag = 1;
   2263 			*size += 2 * sizeof (int32_t) + 4;
   2264 		}
   2265 
   2266 		return (0);
   2267 
   2268 	default:
   2269 		return (EINVAL);
   2270 	}
   2271 }
   2272 
   2273 static int
   2274 nvs_native_nvl_fini(nvstream_t *nvs)
   2275 {
   2276 	if (nvs->nvs_op == NVS_OP_ENCODE) {
   2277 		nvs_native_t *native = (nvs_native_t *)nvs->nvs_private;
   2278 		/*
   2279 		 * Add 4 zero bytes at end of nvlist. They are used
   2280 		 * for end detection by the decode routine.
   2281 		 */
   2282 		if (native->n_curr + sizeof (int) > native->n_end)
   2283 			return (EFAULT);
   2284 
   2285 		bzero(native->n_curr, sizeof (int));
   2286 		native->n_curr += sizeof (int);
   2287 	}
   2288 
   2289 	return (0);
   2290 }
   2291 
   2292 static int
   2293 nvpair_native_embedded(nvstream_t *nvs, nvpair_t *nvp)
   2294 {
   2295 	if (nvs->nvs_op == NVS_OP_ENCODE) {
   2296 		nvs_native_t *native = (nvs_native_t *)nvs->nvs_private;
   2297 		nvlist_t *packed = (void *)
   2298 		    (native->n_curr - nvp->nvp_size + NVP_VALOFF(nvp));
   2299 		/*
   2300 		 * Null out the pointer that is meaningless in the packed
   2301 		 * structure. The address may not be aligned, so we have
   2302 		 * to use bzero.
   2303 		 */
   2304 		bzero(&packed->nvl_priv, sizeof (packed->nvl_priv));
   2305 	}
   2306 
   2307 	return (nvs_embedded(nvs, EMBEDDED_NVL(nvp)));
   2308 }
   2309 
   2310 static int
   2311 nvpair_native_embedded_array(nvstream_t *nvs, nvpair_t *nvp)
   2312 {
   2313 	if (nvs->nvs_op == NVS_OP_ENCODE) {
   2314 		nvs_native_t *native = (nvs_native_t *)nvs->nvs_private;
   2315 		char *value = native->n_curr - nvp->nvp_size + NVP_VALOFF(nvp);
   2316 		size_t len = NVP_NELEM(nvp) * sizeof (uint64_t);
   2317 		nvlist_t *packed = (nvlist_t *)((uintptr_t)value + len);
   2318 		int i;
   2319 		/*
   2320 		 * Null out pointers that are meaningless in the packed
   2321 		 * structure. The addresses may not be aligned, so we have
   2322 		 * to use bzero.
   2323 		 */
   2324 		bzero(value, len);
   2325 
   2326 		for (i = 0; i < NVP_NELEM(nvp); i++, packed++)
   2327 			/*
   2328 			 * Null out the pointer that is meaningless in the
   2329 			 * packed structure. The address may not be aligned,
   2330 			 * so we have to use bzero.
   2331 			 */
   2332 			bzero(&packed->nvl_priv, sizeof (packed->nvl_priv));
   2333 	}
   2334 
   2335 	return (nvs_embedded_nvl_array(nvs, nvp, NULL));
   2336 }
   2337 
   2338 static void
   2339 nvpair_native_string_array(nvstream_t *nvs, nvpair_t *nvp)
   2340 {
   2341 	switch (nvs->nvs_op) {
   2342 	case NVS_OP_ENCODE: {
   2343 		nvs_native_t *native = (nvs_native_t *)nvs->nvs_private;
   2344 		uint64_t *strp = (void *)
   2345 		    (native->n_curr - nvp->nvp_size + NVP_VALOFF(nvp));
   2346 		/*
   2347 		 * Null out pointers that are meaningless in the packed
   2348 		 * structure. The addresses may not be aligned, so we have
   2349 		 * to use bzero.
   2350 		 */
   2351 		bzero(strp, NVP_NELEM(nvp) * sizeof (uint64_t));
   2352 		break;
   2353 	}
   2354 	case NVS_OP_DECODE: {
   2355 		char **strp = (void *)NVP_VALUE(nvp);
   2356 		char *buf = ((char *)strp + NVP_NELEM(nvp) * sizeof (uint64_t));
   2357 		int i;
   2358 
   2359 		for (i = 0; i < NVP_NELEM(nvp); i++) {
   2360 			strp[i] = buf;
   2361 			buf += strlen(buf) + 1;
   2362 		}
   2363 		break;
   2364 	}
   2365 	}
   2366 }
   2367 
   2368 static int
   2369 nvs_native_nvp_op(nvstream_t *nvs, nvpair_t *nvp)
   2370 {
   2371 	data_type_t type;
   2372 	int value_sz;
   2373 	int ret = 0;
   2374 
   2375 	/*
   2376 	 * We do the initial bcopy of the data before we look at
   2377 	 * the nvpair type, because when we're decoding, we won't
   2378 	 * have the correct values for the pair until we do the bcopy.
   2379 	 */
   2380 	switch (nvs->nvs_op) {
   2381 	case NVS_OP_ENCODE:
   2382 	case NVS_OP_DECODE:
   2383 		if (native_cp(nvs, nvp, nvp->nvp_size) != 0)
   2384 			return (EFAULT);
   2385 		break;
   2386 	default:
   2387 		return (EINVAL);
   2388 	}
   2389 
   2390 	/* verify nvp_name_sz, check the name string length */
   2391 	if (i_validate_nvpair_name(nvp) != 0)
   2392 		return (EFAULT);
   2393 
   2394 	type = NVP_TYPE(nvp);
   2395 
   2396 	/*
   2397 	 * Verify type and nelem and get the value size.
   2398 	 * In case of data types DATA_TYPE_STRING and DATA_TYPE_STRING_ARRAY
   2399 	 * is the size of the string(s) excluded.
   2400 	 */
   2401 	if ((value_sz = i_get_value_size(type, NULL, NVP_NELEM(nvp))) < 0)
   2402 		return (EFAULT);
   2403 
   2404 	if (NVP_SIZE_CALC(nvp->nvp_name_sz, value_sz) > nvp->nvp_size)
   2405 		return (EFAULT);
   2406 
   2407 	switch (type) {
   2408 	case DATA_TYPE_NVLIST:
   2409 		ret = nvpair_native_embedded(nvs, nvp);
   2410 		break;
   2411 	case DATA_TYPE_NVLIST_ARRAY:
   2412 		ret = nvpair_native_embedded_array(nvs, nvp);
   2413 		break;
   2414 	case DATA_TYPE_STRING_ARRAY:
   2415 		nvpair_native_string_array(nvs, nvp);
   2416 		break;
   2417 	default:
   2418 		break;
   2419 	}
   2420 
   2421 	return (ret);
   2422 }
   2423 
   2424 static int
   2425 nvs_native_nvp_size(nvstream_t *nvs, nvpair_t *nvp, size_t *size)
   2426 {
   2427 	uint64_t nvp_sz = nvp->nvp_size;
   2428 
   2429 	switch (NVP_TYPE(nvp)) {
   2430 	case DATA_TYPE_NVLIST: {
   2431 		size_t nvsize = 0;
   2432 
   2433 		if (nvs_operation(nvs, EMBEDDED_NVL(nvp), &nvsize) != 0)
   2434 			return (EINVAL);
   2435 
   2436 		nvp_sz += nvsize;
   2437 		break;
   2438 	}
   2439 	case DATA_TYPE_NVLIST_ARRAY: {
   2440 		size_t nvsize;
   2441 
   2442 		if (nvs_embedded_nvl_array(nvs, nvp, &nvsize) != 0)
   2443 			return (EINVAL);
   2444 
   2445 		nvp_sz += nvsize;
   2446 		break;
   2447 	}
   2448 	default:
   2449 		break;
   2450 	}
   2451 
   2452 	if (nvp_sz > INT32_MAX)
   2453 		return (EINVAL);
   2454 
   2455 	*size = nvp_sz;
   2456 
   2457 	return (0);
   2458 }
   2459 
   2460 static int
   2461 nvs_native_nvpair(nvstream_t *nvs, nvpair_t *nvp, size_t *size)
   2462 {
   2463 	switch (nvs->nvs_op) {
   2464 	case NVS_OP_ENCODE:
   2465 		return (nvs_native_nvp_op(nvs, nvp));
   2466 
   2467 	case NVS_OP_DECODE: {
   2468 		nvs_native_t *native = (nvs_native_t *)nvs->nvs_private;
   2469 		int32_t decode_len;
   2470 
   2471 		/* try to read the size value from the stream */
   2472 		if (native->n_curr + sizeof (int32_t) > native->n_end)
   2473 			return (EFAULT);
   2474 		bcopy(native->n_curr, &decode_len, sizeof (int32_t));
   2475 
   2476 		/* sanity check the size value */
   2477 		if (decode_len < 0 ||
   2478 		    decode_len > native->n_end - native->n_curr)
   2479 			return (EFAULT);
   2480 
   2481 		*size = decode_len;
   2482 
   2483 		/*
   2484 		 * If at the end of the stream then move the cursor
   2485 		 * forward, otherwise nvpair_native_op() will read
   2486 		 * the entire nvpair at the same cursor position.
   2487 		 */
   2488 		if (*size == 0)
   2489 			native->n_curr += sizeof (int32_t);
   2490 		break;
   2491 	}
   2492 
   2493 	default:
   2494 		return (EINVAL);
   2495 	}
   2496 
   2497 	return (0);
   2498 }
   2499 
   2500 static const nvs_ops_t nvs_native_ops = {
   2501 	nvs_native_nvlist,
   2502 	nvs_native_nvpair,
   2503 	nvs_native_nvp_op,
   2504 	nvs_native_nvp_size,
   2505 	nvs_native_nvl_fini
   2506 };
   2507 
   2508 static int
   2509 nvs_native(nvstream_t *nvs, nvlist_t *nvl, char *buf, size_t *buflen)
   2510 {
   2511 	nvs_native_t native;
   2512 	int err;
   2513 
   2514 	nvs->nvs_ops = &nvs_native_ops;
   2515 
   2516 	if ((err = nvs_native_create(nvs, &native, buf + sizeof (nvs_header_t),
   2517 	    *buflen - sizeof (nvs_header_t))) != 0)
   2518 		return (err);
   2519 
   2520 	err = nvs_operation(nvs, nvl, buflen);
   2521 
   2522 	nvs_native_destroy(nvs);
   2523 
   2524 	return (err);
   2525 }
   2526 
   2527 /*
   2528  * XDR encoding functions
   2529  *
   2530  * An xdr packed nvlist is encoded as:
   2531  *
   2532  *  - encoding methode and host endian (4 bytes)
   2533  *  - nvl_version (4 bytes)
   2534  *  - nvl_nvflag (4 bytes)
   2535  *
   2536  *  - encoded nvpairs, the format of one xdr encoded nvpair is:
   2537  *	- encoded size of the nvpair (4 bytes)
   2538  *	- decoded size of the nvpair (4 bytes)
   2539  *	- name string, (4 + sizeof(NV_ALIGN4(string))
   2540  *	  a string is coded as size (4 bytes) and data
   2541  *	- data type (4 bytes)
   2542  *	- number of elements in the nvpair (4 bytes)
   2543  *	- data
   2544  *
   2545  *  - 2 zero's for end of the entire list (8 bytes)
   2546  */
   2547 static int
   2548 nvs_xdr_create(nvstream_t *nvs, XDR *xdr, char *buf, size_t buflen)
   2549 {
   2550 	/* xdr data must be 4 byte aligned */
   2551 	if ((ulong_t)buf % 4 != 0)
   2552 		return (EFAULT);
   2553 
   2554 	switch (nvs->nvs_op) {
   2555 	case NVS_OP_ENCODE:
   2556 		xdrmem_create(xdr, buf, (uint_t)buflen, XDR_ENCODE);
   2557 		nvs->nvs_private = xdr;
   2558 		return (0);
   2559 	case NVS_OP_DECODE:
   2560 		xdrmem_create(xdr, buf, (uint_t)buflen, XDR_DECODE);
   2561 		nvs->nvs_private = xdr;
   2562 		return (0);
   2563 	case NVS_OP_GETSIZE:
   2564 		nvs->nvs_private = NULL;
   2565 		return (0);
   2566 	default:
   2567 		return (EINVAL);
   2568 	}
   2569 }
   2570 
   2571 static void
   2572 nvs_xdr_destroy(nvstream_t *nvs)
   2573 {
   2574 	switch (nvs->nvs_op) {
   2575 	case NVS_OP_ENCODE:
   2576 	case NVS_OP_DECODE:
   2577 		xdr_destroy((XDR *)nvs->nvs_private);
   2578 		break;
   2579 	default:
   2580 		break;
   2581 	}
   2582 }
   2583 
   2584 static int
   2585 nvs_xdr_nvlist(nvstream_t *nvs, nvlist_t *nvl, size_t *size)
   2586 {
   2587 	switch (nvs->nvs_op) {
   2588 	case NVS_OP_ENCODE:
   2589 	case NVS_OP_DECODE: {
   2590 		XDR 	*xdr = nvs->nvs_private;
   2591 
   2592 		if (!xdr_int(xdr, &nvl->nvl_version) ||
   2593 		    !xdr_u_int(xdr, &nvl->nvl_nvflag))
   2594 			return (EFAULT);
   2595 		break;
   2596 	}
   2597 	case NVS_OP_GETSIZE: {
   2598 		/*
   2599 		 * 2 * 4 for nvl_version + nvl_nvflag
   2600 		 * and 8 for end of the entire list
   2601 		 */
   2602 		*size += 2 * 4 + 8;
   2603 		break;
   2604 	}
   2605 	default:
   2606 		return (EINVAL);
   2607 	}
   2608 	return (0);
   2609 }
   2610 
   2611 static int
   2612 nvs_xdr_nvl_fini(nvstream_t *nvs)
   2613 {
   2614 	if (nvs->nvs_op == NVS_OP_ENCODE) {
   2615 		XDR *xdr = nvs->nvs_private;
   2616 		int zero = 0;
   2617 
   2618 		if (!xdr_int(xdr, &zero) || !xdr_int(xdr, &zero))
   2619 			return (EFAULT);
   2620 	}
   2621 
   2622 	return (0);
   2623 }
   2624 
   2625 /*
   2626  * The format of xdr encoded nvpair is:
   2627  * encode_size, decode_size, name string, data type, nelem, data
   2628  */
   2629 static int
   2630 nvs_xdr_nvp_op(nvstream_t *nvs, nvpair_t *nvp)
   2631 {
   2632 	data_type_t type;
   2633 	char	*buf;
   2634 	char	*buf_end = (char *)nvp + nvp->nvp_size;
   2635 	int	value_sz;
   2636 	uint_t	nelem, buflen;
   2637 	bool_t	ret = FALSE;
   2638 	XDR	*xdr = nvs->nvs_private;
   2639 
   2640 	ASSERT(xdr != NULL && nvp != NULL);
   2641 
   2642 	/* name string */
   2643 	if ((buf = NVP_NAME(nvp)) >= buf_end)
   2644 		return (EFAULT);
   2645 	buflen = buf_end - buf;
   2646 
   2647 	if (!xdr_string(xdr, &buf, buflen - 1))
   2648 		return (EFAULT);
   2649 	nvp->nvp_name_sz = strlen(buf) + 1;
   2650 
   2651 	/* type and nelem */
   2652 	if (!xdr_int(xdr, (int *)&nvp->nvp_type) ||
   2653 	    !xdr_int(xdr, &nvp->nvp_value_elem))
   2654 		return (EFAULT);
   2655 
   2656 	type = NVP_TYPE(nvp);
   2657 	nelem = nvp->nvp_value_elem;
   2658 
   2659 	/*
   2660 	 * Verify type and nelem and get the value size.
   2661 	 * In case of data types DATA_TYPE_STRING and DATA_TYPE_STRING_ARRAY
   2662 	 * is the size of the string(s) excluded.
   2663 	 */
   2664 	if ((value_sz = i_get_value_size(type, NULL, nelem)) < 0)
   2665 		return (EFAULT);
   2666 
   2667 	/* if there is no data to extract then return */
   2668 	if (nelem == 0)
   2669 		return (0);
   2670 
   2671 	/* value */
   2672 	if ((buf = NVP_VALUE(nvp)) >= buf_end)
   2673 		return (EFAULT);
   2674 	buflen = buf_end - buf;
   2675 
   2676 	if (buflen < value_sz)
   2677 		return (EFAULT);
   2678 
   2679 	switch (type) {
   2680 	case DATA_TYPE_NVLIST:
   2681 		if (nvs_embedded(nvs, (void *)buf) == 0)
   2682 			return (0);
   2683 		break;
   2684 
   2685 	case DATA_TYPE_NVLIST_ARRAY:
   2686 		if (nvs_embedded_nvl_array(nvs, nvp, NULL) == 0)
   2687 			return (0);
   2688 		break;
   2689 
   2690 	case DATA_TYPE_BOOLEAN:
   2691 		ret = TRUE;
   2692 		break;
   2693 
   2694 	case DATA_TYPE_BYTE:
   2695 	case DATA_TYPE_INT8:
   2696 	case DATA_TYPE_UINT8:
   2697 		ret = xdr_char(xdr, buf);
   2698 		break;
   2699 
   2700 	case DATA_TYPE_INT16:
   2701 		ret = xdr_short(xdr, (void *)buf);
   2702 		break;
   2703 
   2704 	case DATA_TYPE_UINT16:
   2705 		ret = xdr_u_short(xdr, (void *)buf);
   2706 		break;
   2707 
   2708 	case DATA_TYPE_BOOLEAN_VALUE:
   2709 	case DATA_TYPE_INT32:
   2710 		ret = xdr_int(xdr, (void *)buf);
   2711 		break;
   2712 
   2713 	case DATA_TYPE_UINT32:
   2714 		ret = xdr_u_int(xdr, (void *)buf);
   2715 		break;
   2716 
   2717 	case DATA_TYPE_INT64:
   2718 		ret = xdr_longlong_t(xdr, (void *)buf);
   2719 		break;
   2720 
   2721 	case DATA_TYPE_UINT64:
   2722 		ret = xdr_u_longlong_t(xdr, (void *)buf);
   2723 		break;
   2724 
   2725 	case DATA_TYPE_HRTIME:
   2726 		/*
   2727 		 * NOTE: must expose the definition of hrtime_t here
   2728 		 */
   2729 		ret = xdr_longlong_t(xdr, (void *)buf);
   2730 		break;
   2731 
   2732 	case DATA_TYPE_STRING:
   2733 		ret = xdr_string(xdr, &buf, buflen - 1);
   2734 		break;
   2735 
   2736 	case DATA_TYPE_BYTE_ARRAY:
   2737 		ret = xdr_opaque(xdr, buf, nelem);
   2738 		break;
   2739 
   2740 	case DATA_TYPE_INT8_ARRAY:
   2741 	case DATA_TYPE_UINT8_ARRAY:
   2742 		ret = xdr_array(xdr, &buf, &nelem, buflen, sizeof (int8_t),
   2743 		    (xdrproc_t)xdr_char);
   2744 		break;
   2745 
   2746 	case DATA_TYPE_INT16_ARRAY:
   2747 		ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (int16_t),
   2748 		    sizeof (int16_t), (xdrproc_t)xdr_short);
   2749 		break;
   2750 
   2751 	case DATA_TYPE_UINT16_ARRAY:
   2752 		ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (uint16_t),
   2753 		    sizeof (uint16_t), (xdrproc_t)xdr_u_short);
   2754 		break;
   2755 
   2756 	case DATA_TYPE_BOOLEAN_ARRAY:
   2757 	case DATA_TYPE_INT32_ARRAY:
   2758 		ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (int32_t),
   2759 		    sizeof (int32_t), (xdrproc_t)xdr_int);
   2760 		break;
   2761 
   2762 	case DATA_TYPE_UINT32_ARRAY:
   2763 		ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (uint32_t),
   2764 		    sizeof (uint32_t), (xdrproc_t)xdr_u_int);
   2765 		break;
   2766 
   2767 	case DATA_TYPE_INT64_ARRAY:
   2768 		ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (int64_t),
   2769 		    sizeof (int64_t), (xdrproc_t)xdr_longlong_t);
   2770 		break;
   2771 
   2772 	case DATA_TYPE_UINT64_ARRAY:
   2773 		ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (uint64_t),
   2774 		    sizeof (uint64_t), (xdrproc_t)xdr_u_longlong_t);
   2775 		break;
   2776 
   2777 	case DATA_TYPE_STRING_ARRAY: {
   2778 		size_t len = nelem * sizeof (uint64_t);
   2779 		char **strp = (void *)buf;
   2780 		int i;
   2781 
   2782 		if (nvs->nvs_op == NVS_OP_DECODE)
   2783 			bzero(buf, len);	/* don't trust packed data */
   2784 
   2785 		for (i = 0; i < nelem; i++) {
   2786 			if (buflen <= len)
   2787 				return (EFAULT);
   2788 
   2789 			buf += len;
   2790 			buflen -= len;
   2791 
   2792 			if (xdr_string(xdr, &buf, buflen - 1) != TRUE)
   2793 				return (EFAULT);
   2794 
   2795 			if (nvs->nvs_op == NVS_OP_DECODE)
   2796 				strp[i] = buf;
   2797 			len = strlen(buf) + 1;
   2798 		}
   2799 		ret = TRUE;
   2800 		break;
   2801 	}
   2802 	default:
   2803 		break;
   2804 	}
   2805 
   2806 	return (ret == TRUE ? 0 : EFAULT);
   2807 }
   2808 
   2809 static int
   2810 nvs_xdr_nvp_size(nvstream_t *nvs, nvpair_t *nvp, size_t *size)
   2811 {
   2812 	data_type_t type = NVP_TYPE(nvp);
   2813 	/*
   2814 	 * encode_size + decode_size + name string size + data type + nelem
   2815 	 * where name string size = 4 + NV_ALIGN4(strlen(NVP_NAME(nvp)))
   2816 	 */
   2817 	uint64_t nvp_sz = 4 + 4 + 4 + NV_ALIGN4(strlen(NVP_NAME(nvp))) + 4 + 4;
   2818 
   2819 	switch (type) {
   2820 	case DATA_TYPE_BOOLEAN:
   2821 		break;
   2822 
   2823 	case DATA_TYPE_BOOLEAN_VALUE:
   2824 	case DATA_TYPE_BYTE:
   2825 	case DATA_TYPE_INT8:
   2826 	case DATA_TYPE_UINT8:
   2827 	case DATA_TYPE_INT16:
   2828 	case DATA_TYPE_UINT16:
   2829 	case DATA_TYPE_INT32:
   2830 	case DATA_TYPE_UINT32:
   2831 		nvp_sz += 4;	/* 4 is the minimum xdr unit */
   2832 		break;
   2833 
   2834 	case DATA_TYPE_INT64:
   2835 	case DATA_TYPE_UINT64:
   2836 	case DATA_TYPE_HRTIME:
   2837 		nvp_sz += 8;
   2838 		break;
   2839 
   2840 	case DATA_TYPE_STRING:
   2841 		nvp_sz += 4 + NV_ALIGN4(strlen((char *)NVP_VALUE(nvp)));
   2842 		break;
   2843 
   2844 	case DATA_TYPE_BYTE_ARRAY:
   2845 		nvp_sz += NV_ALIGN4(NVP_NELEM(nvp));
   2846 		break;
   2847 
   2848 	case DATA_TYPE_BOOLEAN_ARRAY:
   2849 	case DATA_TYPE_INT8_ARRAY:
   2850 	case DATA_TYPE_UINT8_ARRAY:
   2851 	case DATA_TYPE_INT16_ARRAY:
   2852 	case DATA_TYPE_UINT16_ARRAY:
   2853 	case DATA_TYPE_INT32_ARRAY:
   2854 	case DATA_TYPE_UINT32_ARRAY:
   2855 		nvp_sz += 4 + 4 * (uint64_t)NVP_NELEM(nvp);
   2856 		break;
   2857 
   2858 	case DATA_TYPE_INT64_ARRAY:
   2859 	case DATA_TYPE_UINT64_ARRAY:
   2860 		nvp_sz += 4 + 8 * (uint64_t)NVP_NELEM(nvp);
   2861 		break;
   2862 
   2863 	case DATA_TYPE_STRING_ARRAY: {
   2864 		int i;
   2865 		char **strs = (void *)NVP_VALUE(nvp);
   2866 
   2867 		for (i = 0; i < NVP_NELEM(nvp); i++)
   2868 			nvp_sz += 4 + NV_ALIGN4(strlen(strs[i]));
   2869 
   2870 		break;
   2871 	}
   2872 
   2873 	case DATA_TYPE_NVLIST:
   2874 	case DATA_TYPE_NVLIST_ARRAY: {
   2875 		size_t nvsize = 0;
   2876 		int old_nvs_op = nvs->nvs_op;
   2877 		int err;
   2878 
   2879 		nvs->nvs_op = NVS_OP_GETSIZE;
   2880 		if (type == DATA_TYPE_NVLIST)
   2881 			err = nvs_operation(nvs, EMBEDDED_NVL(nvp), &nvsize);
   2882 		else
   2883 			err = nvs_embedded_nvl_array(nvs, nvp, &nvsize);
   2884 		nvs->nvs_op = old_nvs_op;
   2885 
   2886 		if (err != 0)
   2887 			return (EINVAL);
   2888 
   2889 		nvp_sz += nvsize;
   2890 		break;
   2891 	}
   2892 
   2893 	default:
   2894 		return (EINVAL);
   2895 	}
   2896 
   2897 	if (nvp_sz > INT32_MAX)
   2898 		return (EINVAL);
   2899 
   2900 	*size = nvp_sz;
   2901 
   2902 	return (0);
   2903 }
   2904 
   2905 
   2906 /*
   2907  * The NVS_XDR_MAX_LEN macro takes a packed xdr buffer of size x and estimates
   2908  * the largest nvpair that could be encoded in the buffer.
   2909  *
   2910  * See comments above nvpair_xdr_op() for the format of xdr encoding.
   2911  * The size of a xdr packed nvpair without any data is 5 words.
   2912  *
   2913  * Using the size of the data directly as an estimate would be ok
   2914  * in all cases except one.  If the data type is of DATA_TYPE_STRING_ARRAY
   2915  * then the actual nvpair has space for an array of pointers to index
   2916  * the strings.  These pointers are not encoded into the packed xdr buffer.
   2917  *
   2918  * If the data is of type DATA_TYPE_STRING_ARRAY and all the strings are
   2919  * of length 0, then each string is endcoded in xdr format as a single word.
   2920  * Therefore when expanded to an nvpair there will be 2.25 word used for
   2921  * each string.  (a int64_t allocated for pointer usage, and a single char
   2922  * for the null termination.)
   2923  *
   2924  * This is the calculation performed by the NVS_XDR_MAX_LEN macro.
   2925  */
   2926 #define	NVS_XDR_HDR_LEN		((size_t)(5 * 4))
   2927 #define	NVS_XDR_DATA_LEN(y)	(((size_t)(y) <= NVS_XDR_HDR_LEN) ? \
   2928 					0 : ((size_t)(y) - NVS_XDR_HDR_LEN))
   2929 #define	NVS_XDR_MAX_LEN(x)	(NVP_SIZE_CALC(1, 0) + \
   2930 					(NVS_XDR_DATA_LEN(x) * 2) + \
   2931 					NV_ALIGN4((NVS_XDR_DATA_LEN(x) / 4)))
   2932 
   2933 static int
   2934 nvs_xdr_nvpair(nvstream_t *nvs, nvpair_t *nvp, size_t *size)
   2935 {
   2936 	XDR 	*xdr = nvs->nvs_private;
   2937 	int32_t	encode_len, decode_len;
   2938 
   2939 	switch (nvs->nvs_op) {
   2940 	case NVS_OP_ENCODE: {
   2941 		size_t nvsize;
   2942 
   2943 		if (nvs_xdr_nvp_size(nvs, nvp, &nvsize) != 0)
   2944 			return (EFAULT);
   2945 
   2946 		decode_len = nvp->nvp_size;
   2947 		encode_len = nvsize;
   2948 		if (!xdr_int(xdr, &encode_len) || !xdr_int(xdr, &decode_len))
   2949 			return (EFAULT);
   2950 
   2951 		return (nvs_xdr_nvp_op(nvs, nvp));
   2952 	}
   2953 	case NVS_OP_DECODE: {
   2954 		struct xdr_bytesrec bytesrec;
   2955 
   2956 		/* get the encode and decode size */
   2957 		if (!xdr_int(xdr, &encode_len) || !xdr_int(xdr, &decode_len))
   2958 			return (EFAULT);
   2959 		*size = decode_len;
   2960 
   2961 		/* are we at the end of the stream? */
   2962 		if (*size == 0)
   2963 			return (0);
   2964 
   2965 		/* sanity check the size parameter */
   2966 		if (!xdr_control(xdr, XDR_GET_BYTES_AVAIL, &bytesrec))
   2967 			return (EFAULT);
   2968 
   2969 		if (*size > NVS_XDR_MAX_LEN(bytesrec.xc_num_avail))
   2970 			return (EFAULT);
   2971 		break;
   2972 	}
   2973 
   2974 	default:
   2975 		return (EINVAL);
   2976 	}
   2977 	return (0);
   2978 }
   2979 
   2980 static const struct nvs_ops nvs_xdr_ops = {
   2981 	nvs_xdr_nvlist,
   2982 	nvs_xdr_nvpair,
   2983 	nvs_xdr_nvp_op,
   2984 	nvs_xdr_nvp_size,
   2985 	nvs_xdr_nvl_fini
   2986 };
   2987 
   2988 static int
   2989 nvs_xdr(nvstream_t *nvs, nvlist_t *nvl, char *buf, size_t *buflen)
   2990 {
   2991 	XDR xdr;
   2992 	int err;
   2993 
   2994 	nvs->nvs_ops = &nvs_xdr_ops;
   2995 
   2996 	if ((err = nvs_xdr_create(nvs, &xdr, buf + sizeof (nvs_header_t),
   2997 	    *buflen - sizeof (nvs_header_t))) != 0)
   2998 		return (err);
   2999 
   3000 	err = nvs_operation(nvs, nvl, buflen);
   3001 
   3002 	nvs_xdr_destroy(nvs);
   3003 
   3004 	return (err);
   3005 }
   3006