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