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