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