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