Home | History | Annotate | Download | only in nvpair
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 
     22 /*
     23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
     24  * Use is subject to license terms.
     25  */
     26 
     27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
     28 
     29 #include <sys/stropts.h>
     30 #include <sys/debug.h>
     31 #include <sys/isa_defs.h>
     32 #include <sys/int_limits.h>
     33 #include <sys/nvpair.h>
     34 #include <sys/nvpair_impl.h>
     35 #include <rpc/types.h>
     36 #include <rpc/xdr.h>
     37 
     38 #if defined(_KERNEL) && !defined(_BOOT)
     39 #include <sys/varargs.h>
     40 #include <sys/ddi.h>
     41 #include <sys/sunddi.h>
     42 #else
     43 #include <stdarg.h>
     44 #include <stdlib.h>
     45 #include <string.h>
     46 #include <strings.h>
     47 #endif
     48 
     49 #ifndef	offsetof
     50 #define	offsetof(s, m)		((size_t)(&(((s *)0)->m)))
     51 #endif
     52 #define	skip_whitespace(p)	while ((*(p) == ' ') || (*(p) == '\t')) p++
     53 
     54 /*
     55  * nvpair.c - Provides kernel & userland interfaces for manipulating
     56  *	name-value pairs.
     57  *
     58  * Overview Diagram
     59  *
     60  *  +--------------+
     61  *  |  nvlist_t    |
     62  *  |--------------|
     63  *  | nvl_version  |
     64  *  | nvl_nvflag   |
     65  *  | nvl_priv    -+-+
     66  *  | nvl_flag     | |
     67  *  | nvl_pad      | |
     68  *  +--------------+ |
     69  *                   V
     70  *      +--------------+      last i_nvp in list
     71  *      | nvpriv_t     |  +--------------------->
     72  *      |--------------|  |
     73  *   +--+- nvp_list    |  |   +------------+
     74  *   |  |  nvp_last   -+--+   + nv_alloc_t |
     75  *   |  |  nvp_curr    |      |------------|
     76  *   |  |  nvp_nva    -+----> | nva_ops    |
     77  *   |  |  nvp_stat    |      | nva_arg    |
     78  *   |  +--------------+      +------------+
     79  *   |
     80  *   +-------+
     81  *           V
     82  *   +---------------------+      +-------------------+
     83  *   |  i_nvp_t            |  +-->|  i_nvp_t          |  +-->
     84  *   |---------------------|  |   |-------------------|  |
     85  *   | nvi_next           -+--+   | nvi_next         -+--+
     86  *   | nvi_prev (NULL)     | <----+ nvi_prev          |
     87  *   | . . . . . . . . . . |      | . . . . . . . . . |
     88  *   | nvp (nvpair_t)      |      | nvp (nvpair_t)    |
     89  *   |  - nvp_size         |      |  - nvp_size       |
     90  *   |  - nvp_name_sz      |      |  - nvp_name_sz    |
     91  *   |  - nvp_value_elem   |      |  - nvp_value_elem |
     92  *   |  - nvp_type         |      |  - nvp_type       |
     93  *   |  - data ...         |      |  - data ...       |
     94  *   +---------------------+      +-------------------+
     95  *
     96  *
     97  *
     98  *   +---------------------+              +---------------------+
     99  *   |  i_nvp_t            |  +-->    +-->|  i_nvp_t (last)     |
    100  *   |---------------------|  |       |   |---------------------|
    101  *   |  nvi_next          -+--+ ... --+   | nvi_next (NULL)     |
    102  * <-+- nvi_prev           |<-- ...  <----+ nvi_prev            |
    103  *   | . . . . . . . . .   |              | . . . . . . . . .   |
    104  *   | nvp (nvpair_t)      |              | nvp (nvpair_t)      |
    105  *   |  - nvp_size         |              |  - nvp_size         |
    106  *   |  - nvp_name_sz      |              |  - nvp_name_sz      |
    107  *   |  - nvp_value_elem   |              |  - nvp_value_elem   |
    108  *   |  - DATA_TYPE_NVLIST |              |  - nvp_type         |
    109  *   |  - data (embedded)  |              |  - data ...         |
    110  *   |    nvlist name      |              +---------------------+
    111  *   |  +--------------+   |
    112  *   |  |  nvlist_t    |   |
    113  *   |  |--------------|   |
    114  *   |  | nvl_version  |   |
    115  *   |  | nvl_nvflag   |   |
    116  *   |  | nvl_priv   --+---+---->
    117  *   |  | nvl_flag     |   |
    118  *   |  | nvl_pad      |   |
    119  *   |  +--------------+   |
    120  *   +---------------------+
    121  *
    122  *
    123  * N.B. nvpair_t may be aligned on 4 byte boundary, so +4 will
    124  * allow value to be aligned on 8 byte boundary
    125  *
    126  * name_len is the length of the name string including the null terminator
    127  * so it must be >= 1
    128  */
    129 #define	NVP_SIZE_CALC(name_len, data_len) \
    130 	(NV_ALIGN((sizeof (nvpair_t)) + name_len) + NV_ALIGN(data_len))
    131 
    132 static int i_get_value_size(data_type_t type, const void *data, uint_t nelem);
    133 static int nvlist_add_common(nvlist_t *nvl, const char *name, data_type_t type,
    134     uint_t nelem, const void *data);
    135 
    136 #define	NV_STAT_EMBEDDED	0x1
    137 #define	EMBEDDED_NVL(nvp)	((nvlist_t *)(void *)NVP_VALUE(nvp))
    138 #define	EMBEDDED_NVL_ARRAY(nvp)	((nvlist_t **)(void *)NVP_VALUE(nvp))
    139 
    140 #define	NVP_VALOFF(nvp)	(NV_ALIGN(sizeof (nvpair_t) + (nvp)->nvp_name_sz))
    141 #define	NVPAIR2I_NVP(nvp) \
    142 	((i_nvp_t *)((size_t)(nvp) - offsetof(i_nvp_t, nvi_nvp)))
    143 
    144 
    145 int
    146 nv_alloc_init(nv_alloc_t *nva, const nv_alloc_ops_t *nvo, /* args */ ...)
    147 {
    148 	va_list valist;
    149 	int err = 0;
    150 
    151 	nva->nva_ops = nvo;
    152 	nva->nva_arg = NULL;
    153 
    154 	va_start(valist, nvo);
    155 	if (nva->nva_ops->nv_ao_init != NULL)
    156 		err = nva->nva_ops->nv_ao_init(nva, valist);
    157 	va_end(valist);
    158 
    159 	return (err);
    160 }
    161 
    162 void
    163 nv_alloc_reset(nv_alloc_t *nva)
    164 {
    165 	if (nva->nva_ops->nv_ao_reset != NULL)
    166 		nva->nva_ops->nv_ao_reset(nva);
    167 }
    168 
    169 void
    170 nv_alloc_fini(nv_alloc_t *nva)
    171 {
    172 	if (nva->nva_ops->nv_ao_fini != NULL)
    173 		nva->nva_ops->nv_ao_fini(nva);
    174 }
    175 
    176 nv_alloc_t *
    177 nvlist_lookup_nv_alloc(nvlist_t *nvl)
    178 {
    179 	nvpriv_t *priv;
    180 
    181 	if (nvl == NULL ||
    182 	    (priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL)
    183 		return (NULL);
    184 
    185 	return (priv->nvp_nva);
    186 }
    187 
    188 static void *
    189 nv_mem_zalloc(nvpriv_t *nvp, size_t size)
    190 {
    191 	nv_alloc_t *nva = nvp->nvp_nva;
    192 	void *buf;
    193 
    194 	if ((buf = nva->nva_ops->nv_ao_alloc(nva, size)) != NULL)
    195 		bzero(buf, size);
    196 
    197 	return (buf);
    198 }
    199 
    200 static void
    201 nv_mem_free(nvpriv_t *nvp, void *buf, size_t size)
    202 {
    203 	nv_alloc_t *nva = nvp->nvp_nva;
    204 
    205 	nva->nva_ops->nv_ao_free(nva, buf, size);
    206 }
    207 
    208 static void
    209 nv_priv_init(nvpriv_t *priv, nv_alloc_t *nva, uint32_t stat)
    210 {
    211 	bzero(priv, sizeof (nvpriv_t));
    212 
    213 	priv->nvp_nva = nva;
    214 	priv->nvp_stat = stat;
    215 }
    216 
    217 static nvpriv_t *
    218 nv_priv_alloc(nv_alloc_t *nva)
    219 {
    220 	nvpriv_t *priv;
    221 
    222 	/*
    223 	 * nv_mem_alloc() cannot called here because it needs the priv
    224 	 * argument.
    225 	 */
    226 	if ((priv = nva->nva_ops->nv_ao_alloc(nva, sizeof (nvpriv_t))) == NULL)
    227 		return (NULL);
    228 
    229 	nv_priv_init(priv, nva, 0);
    230 
    231 	return (priv);
    232 }
    233 
    234 /*
    235  * Embedded lists need their own nvpriv_t's.  We create a new
    236  * nvpriv_t using the parameters and allocator from the parent
    237  * list's nvpriv_t.
    238  */
    239 static nvpriv_t *
    240 nv_priv_alloc_embedded(nvpriv_t *priv)
    241 {
    242 	nvpriv_t *emb_priv;
    243 
    244 	if ((emb_priv = nv_mem_zalloc(priv, sizeof (nvpriv_t))) == NULL)
    245 		return (NULL);
    246 
    247 	nv_priv_init(emb_priv, priv->nvp_nva, NV_STAT_EMBEDDED);
    248 
    249 	return (emb_priv);
    250 }
    251 
    252 static void
    253 nvlist_init(nvlist_t *nvl, uint32_t nvflag, nvpriv_t *priv)
    254 {
    255 	nvl->nvl_version = NV_VERSION;
    256 	nvl->nvl_nvflag = nvflag & (NV_UNIQUE_NAME|NV_UNIQUE_NAME_TYPE);
    257 	nvl->nvl_priv = (uint64_t)(uintptr_t)priv;
    258 	nvl->nvl_flag = 0;
    259 	nvl->nvl_pad = 0;
    260 }
    261 
    262 /*
    263  * nvlist_alloc - Allocate nvlist.
    264  */
    265 /*ARGSUSED1*/
    266 int
    267 nvlist_alloc(nvlist_t **nvlp, uint_t nvflag, int kmflag)
    268 {
    269 #if defined(_KERNEL) && !defined(_BOOT)
    270 	return (nvlist_xalloc(nvlp, nvflag,
    271 	    (kmflag == KM_SLEEP ? nv_alloc_sleep : nv_alloc_nosleep)));
    272 #else
    273 	return (nvlist_xalloc(nvlp, nvflag, nv_alloc_nosleep));
    274 #endif
    275 }
    276 
    277 int
    278 nvlist_xalloc(nvlist_t **nvlp, uint_t nvflag, nv_alloc_t *nva)
    279 {
    280 	nvpriv_t *priv;
    281 
    282 	if (nvlp == NULL || nva == NULL)
    283 		return (EINVAL);
    284 
    285 	if ((priv = nv_priv_alloc(nva)) == NULL)
    286 		return (ENOMEM);
    287 
    288 	if ((*nvlp = nv_mem_zalloc(priv,
    289 	    NV_ALIGN(sizeof (nvlist_t)))) == NULL) {
    290 		nv_mem_free(priv, priv, sizeof (nvpriv_t));
    291 		return (ENOMEM);
    292 	}
    293 
    294 	nvlist_init(*nvlp, nvflag, priv);
    295 
    296 	return (0);
    297 }
    298 
    299 /*
    300  * nvp_buf_alloc - Allocate i_nvp_t for storing a new nv pair.
    301  */
    302 static nvpair_t *
    303 nvp_buf_alloc(nvlist_t *nvl, size_t len)
    304 {
    305 	nvpriv_t *priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv;
    306 	i_nvp_t *buf;
    307 	nvpair_t *nvp;
    308 	size_t nvsize;
    309 
    310 	/*
    311 	 * Allocate the buffer
    312 	 */
    313 	nvsize = len + offsetof(i_nvp_t, nvi_nvp);
    314 
    315 	if ((buf = nv_mem_zalloc(priv, nvsize)) == NULL)
    316 		return (NULL);
    317 
    318 	nvp = &buf->nvi_nvp;
    319 	nvp->nvp_size = len;
    320 
    321 	return (nvp);
    322 }
    323 
    324 /*
    325  * nvp_buf_free - de-Allocate an i_nvp_t.
    326  */
    327 static void
    328 nvp_buf_free(nvlist_t *nvl, nvpair_t *nvp)
    329 {
    330 	nvpriv_t *priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv;
    331 	size_t nvsize = nvp->nvp_size + offsetof(i_nvp_t, nvi_nvp);
    332 
    333 	nv_mem_free(priv, NVPAIR2I_NVP(nvp), nvsize);
    334 }
    335 
    336 /*
    337  * nvp_buf_link - link a new nv pair into the nvlist.
    338  */
    339 static void
    340 nvp_buf_link(nvlist_t *nvl, nvpair_t *nvp)
    341 {
    342 	nvpriv_t *priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv;
    343 	i_nvp_t *curr = NVPAIR2I_NVP(nvp);
    344 
    345 	/* Put element at end of nvlist */
    346 	if (priv->nvp_list == NULL) {
    347 		priv->nvp_list = priv->nvp_last = curr;
    348 	} else {
    349 		curr->nvi_prev = priv->nvp_last;
    350 		priv->nvp_last->nvi_next = curr;
    351 		priv->nvp_last = curr;
    352 	}
    353 }
    354 
    355 /*
    356  * nvp_buf_unlink - unlink an removed nvpair out of the nvlist.
    357  */
    358 static void
    359 nvp_buf_unlink(nvlist_t *nvl, nvpair_t *nvp)
    360 {
    361 	nvpriv_t *priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv;
    362 	i_nvp_t *curr = NVPAIR2I_NVP(nvp);
    363 
    364 	/*
    365 	 * protect nvlist_next_nvpair() against walking on freed memory.
    366 	 */
    367 	if (priv->nvp_curr == curr)
    368 		priv->nvp_curr = curr->nvi_next;
    369 
    370 	if (curr == priv->nvp_list)
    371 		priv->nvp_list = curr->nvi_next;
    372 	else
    373 		curr->nvi_prev->nvi_next = curr->nvi_next;
    374 
    375 	if (curr == priv->nvp_last)
    376 		priv->nvp_last = curr->nvi_prev;
    377 	else
    378 		curr->nvi_next->nvi_prev = curr->nvi_prev;
    379 }
    380 
    381 /*
    382  * take a nvpair type and number of elements and make sure the are valid
    383  */
    384 static int
    385 i_validate_type_nelem(data_type_t type, uint_t nelem)
    386 {
    387 	switch (type) {
    388 	case DATA_TYPE_BOOLEAN:
    389 		if (nelem != 0)
    390 			return (EINVAL);
    391 		break;
    392 	case DATA_TYPE_BOOLEAN_VALUE:
    393 	case DATA_TYPE_BYTE:
    394 	case DATA_TYPE_INT8:
    395 	case DATA_TYPE_UINT8:
    396 	case DATA_TYPE_INT16:
    397 	case DATA_TYPE_UINT16:
    398 	case DATA_TYPE_INT32:
    399 	case DATA_TYPE_UINT32:
    400 	case DATA_TYPE_INT64:
    401 	case DATA_TYPE_UINT64:
    402 	case DATA_TYPE_STRING:
    403 	case DATA_TYPE_HRTIME:
    404 	case DATA_TYPE_NVLIST:
    405 #if !defined(_KERNEL)
    406 	case DATA_TYPE_DOUBLE:
    407 #endif
    408 		if (nelem != 1)
    409 			return (EINVAL);
    410 		break;
    411 	case DATA_TYPE_BOOLEAN_ARRAY:
    412 	case DATA_TYPE_BYTE_ARRAY:
    413 	case DATA_TYPE_INT8_ARRAY:
    414 	case DATA_TYPE_UINT8_ARRAY:
    415 	case DATA_TYPE_INT16_ARRAY:
    416 	case DATA_TYPE_UINT16_ARRAY:
    417 	case DATA_TYPE_INT32_ARRAY:
    418 	case DATA_TYPE_UINT32_ARRAY:
    419 	case DATA_TYPE_INT64_ARRAY:
    420 	case DATA_TYPE_UINT64_ARRAY:
    421 	case DATA_TYPE_STRING_ARRAY:
    422 	case DATA_TYPE_NVLIST_ARRAY:
    423 		/* we allow arrays with 0 elements */
    424 		break;
    425 	default:
    426 		return (EINVAL);
    427 	}
    428 	return (0);
    429 }
    430 
    431 /*
    432  * Verify nvp_name_sz and check the name string length.
    433  */
    434 static int
    435 i_validate_nvpair_name(nvpair_t *nvp)
    436 {
    437 	if ((nvp->nvp_name_sz <= 0) ||
    438 	    (nvp->nvp_size < NVP_SIZE_CALC(nvp->nvp_name_sz, 0)))
    439 		return (EFAULT);
    440 
    441 	/* verify the name string, make sure its terminated */
    442 	if (NVP_NAME(nvp)[nvp->nvp_name_sz - 1] != '\0')
    443 		return (EFAULT);
    444 
    445 	return (strlen(NVP_NAME(nvp)) == nvp->nvp_name_sz - 1 ? 0 : EFAULT);
    446 }
    447 
    448 static int
    449 i_validate_nvpair_value(data_type_t type, uint_t nelem, const void *data)
    450 {
    451 	switch (type) {
    452 	case DATA_TYPE_BOOLEAN_VALUE:
    453 		if (*(boolean_t *)data != B_TRUE &&
    454 		    *(boolean_t *)data != B_FALSE)
    455 			return (EINVAL);
    456 		break;
    457 	case DATA_TYPE_BOOLEAN_ARRAY: {
    458 		int i;
    459 
    460 		for (i = 0; i < nelem; i++)
    461 			if (((boolean_t *)data)[i] != B_TRUE &&
    462 			    ((boolean_t *)data)[i] != B_FALSE)
    463 				return (EINVAL);
    464 		break;
    465 	}
    466 	default:
    467 		break;
    468 	}
    469 
    470 	return (0);
    471 }
    472 
    473 /*
    474  * This function takes a pointer to what should be a nvpair and it's size
    475  * and then verifies that all the nvpair fields make sense and can be
    476  * trusted.  This function is used when decoding packed nvpairs.
    477  */
    478 static int
    479 i_validate_nvpair(nvpair_t *nvp)
    480 {
    481 	data_type_t type = NVP_TYPE(nvp);
    482 	int size1, size2;
    483 
    484 	/* verify nvp_name_sz, check the name string length */
    485 	if (i_validate_nvpair_name(nvp) != 0)
    486 		return (EFAULT);
    487 
    488 	if (i_validate_nvpair_value(type, NVP_NELEM(nvp), NVP_VALUE(nvp)) != 0)
    489 		return (EFAULT);
    490 
    491 	/*
    492 	 * verify nvp_type, nvp_value_elem, and also possibly
    493 	 * verify string values and get the value size.
    494 	 */
    495 	size2 = i_get_value_size(type, NVP_VALUE(nvp), NVP_NELEM(nvp));
    496 	size1 = nvp->nvp_size - NVP_VALOFF(nvp);
    497 	if (size2 < 0 || size1 != NV_ALIGN(size2))
    498 		return (EFAULT);
    499 
    500 	return (0);
    501 }
    502 
    503 static int
    504 nvlist_copy_pairs(nvlist_t *snvl, nvlist_t *dnvl)
    505 {
    506 	nvpriv_t *priv;
    507 	i_nvp_t *curr;
    508 
    509 	if ((priv = (nvpriv_t *)(uintptr_t)snvl->nvl_priv) == NULL)
    510 		return (EINVAL);
    511 
    512 	for (curr = priv->nvp_list; curr != NULL; curr = curr->nvi_next) {
    513 		nvpair_t *nvp = &curr->nvi_nvp;
    514 		int err;
    515 
    516 		if ((err = nvlist_add_common(dnvl, NVP_NAME(nvp), NVP_TYPE(nvp),
    517 		    NVP_NELEM(nvp), NVP_VALUE(nvp))) != 0)
    518 			return (err);
    519 	}
    520 
    521 	return (0);
    522 }
    523 
    524 /*
    525  * Frees all memory allocated for an nvpair (like embedded lists) with
    526  * the exception of the nvpair buffer itself.
    527  */
    528 static void
    529 nvpair_free(nvpair_t *nvp)
    530 {
    531 	switch (NVP_TYPE(nvp)) {
    532 	case DATA_TYPE_NVLIST:
    533 		nvlist_free(EMBEDDED_NVL(nvp));
    534 		break;
    535 	case DATA_TYPE_NVLIST_ARRAY: {
    536 		nvlist_t **nvlp = EMBEDDED_NVL_ARRAY(nvp);
    537 		int i;
    538 
    539 		for (i = 0; i < NVP_NELEM(nvp); i++)
    540 			if (nvlp[i] != NULL)
    541 				nvlist_free(nvlp[i]);
    542 		break;
    543 	}
    544 	default:
    545 		break;
    546 	}
    547 }
    548 
    549 /*
    550  * nvlist_free - free an unpacked nvlist
    551  */
    552 void
    553 nvlist_free(nvlist_t *nvl)
    554 {
    555 	nvpriv_t *priv;
    556 	i_nvp_t *curr;
    557 
    558 	if (nvl == NULL ||
    559 	    (priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL)
    560 		return;
    561 
    562 	/*
    563 	 * Unpacked nvlist are linked through i_nvp_t
    564 	 */
    565 	curr = priv->nvp_list;
    566 	while (curr != NULL) {
    567 		nvpair_t *nvp = &curr->nvi_nvp;
    568 		curr = curr->nvi_next;
    569 
    570 		nvpair_free(nvp);
    571 		nvp_buf_free(nvl, nvp);
    572 	}
    573 
    574 	if (!(priv->nvp_stat & NV_STAT_EMBEDDED))
    575 		nv_mem_free(priv, nvl, NV_ALIGN(sizeof (nvlist_t)));
    576 	else
    577 		nvl->nvl_priv = 0;
    578 
    579 	nv_mem_free(priv, priv, sizeof (nvpriv_t));
    580 }
    581 
    582 static int
    583 nvlist_contains_nvp(nvlist_t *nvl, nvpair_t *nvp)
    584 {
    585 	nvpriv_t *priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv;
    586 	i_nvp_t *curr;
    587 
    588 	if (nvp == NULL)
    589 		return (0);
    590 
    591 	for (curr = priv->nvp_list; curr != NULL; curr = curr->nvi_next)
    592 		if (&curr->nvi_nvp == nvp)
    593 			return (1);
    594 
    595 	return (0);
    596 }
    597 
    598 /*
    599  * Make a copy of nvlist
    600  */
    601 /*ARGSUSED1*/
    602 int
    603 nvlist_dup(nvlist_t *nvl, nvlist_t **nvlp, int kmflag)
    604 {
    605 #if defined(_KERNEL) && !defined(_BOOT)
    606 	return (nvlist_xdup(nvl, nvlp,
    607 	    (kmflag == KM_SLEEP ? nv_alloc_sleep : nv_alloc_nosleep)));
    608 #else
    609 	return (nvlist_xdup(nvl, nvlp, nv_alloc_nosleep));
    610 #endif
    611 }
    612 
    613 int
    614 nvlist_xdup(nvlist_t *nvl, nvlist_t **nvlp, nv_alloc_t *nva)
    615 {
    616 	int err;
    617 	nvlist_t *ret;
    618 
    619 	if (nvl == NULL || nvlp == NULL)
    620 		return (EINVAL);
    621 
    622 	if ((err = nvlist_xalloc(&ret, nvl->nvl_nvflag, nva)) != 0)
    623 		return (err);
    624 
    625 	if ((err = nvlist_copy_pairs(nvl, ret)) != 0)
    626 		nvlist_free(ret);
    627 	else
    628 		*nvlp = ret;
    629 
    630 	return (err);
    631 }
    632 
    633 /*
    634  * Remove all with matching name
    635  */
    636 int
    637 nvlist_remove_all(nvlist_t *nvl, const char *name)
    638 {
    639 	nvpriv_t *priv;
    640 	i_nvp_t *curr;
    641 	int error = ENOENT;
    642 
    643 	if (nvl == NULL || name == NULL ||
    644 	    (priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL)
    645 		return (EINVAL);
    646 
    647 	curr = priv->nvp_list;
    648 	while (curr != NULL) {
    649 		nvpair_t *nvp = &curr->nvi_nvp;
    650 
    651 		curr = curr->nvi_next;
    652 		if (strcmp(name, NVP_NAME(nvp)) != 0)
    653 			continue;
    654 
    655 		nvp_buf_unlink(nvl, nvp);
    656 		nvpair_free(nvp);
    657 		nvp_buf_free(nvl, nvp);
    658 
    659 		error = 0;
    660 	}
    661 
    662 	return (error);
    663 }
    664 
    665 /*
    666  * Remove first one with matching name and type
    667  */
    668 int
    669 nvlist_remove(nvlist_t *nvl, const char *name, data_type_t type)
    670 {
    671 	nvpriv_t *priv;
    672 	i_nvp_t *curr;
    673 
    674 	if (nvl == NULL || name == NULL ||
    675 	    (priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL)
    676 		return (EINVAL);
    677 
    678 	curr = priv->nvp_list;
    679 	while (curr != NULL) {
    680 		nvpair_t *nvp = &curr->nvi_nvp;
    681 
    682 		if (strcmp(name, NVP_NAME(nvp)) == 0 && NVP_TYPE(nvp) == type) {
    683 			nvp_buf_unlink(nvl, nvp);
    684 			nvpair_free(nvp);
    685 			nvp_buf_free(nvl, nvp);
    686 
    687 			return (0);
    688 		}
    689 		curr = curr->nvi_next;
    690 	}
    691 
    692 	return (ENOENT);
    693 }
    694 
    695 /*
    696  * This function calculates the size of an nvpair value.
    697  *
    698  * The data argument controls the behavior in case of the data types
    699  * 	DATA_TYPE_STRING    	and
    700  *	DATA_TYPE_STRING_ARRAY
    701  * Is data == NULL then the size of the string(s) is excluded.
    702  */
    703 static int
    704 i_get_value_size(data_type_t type, const void *data, uint_t nelem)
    705 {
    706 	uint64_t value_sz;
    707 
    708 	if (i_validate_type_nelem(type, nelem) != 0)
    709 		return (-1);
    710 
    711 	/* Calculate required size for holding value */
    712 	switch (type) {
    713 	case DATA_TYPE_BOOLEAN:
    714 		value_sz = 0;
    715 		break;
    716 	case DATA_TYPE_BOOLEAN_VALUE:
    717 		value_sz = sizeof (boolean_t);
    718 		break;
    719 	case DATA_TYPE_BYTE:
    720 		value_sz = sizeof (uchar_t);
    721 		break;
    722 	case DATA_TYPE_INT8:
    723 		value_sz = sizeof (int8_t);
    724 		break;
    725 	case DATA_TYPE_UINT8:
    726 		value_sz = sizeof (uint8_t);
    727 		break;
    728 	case DATA_TYPE_INT16:
    729 		value_sz = sizeof (int16_t);
    730 		break;
    731 	case DATA_TYPE_UINT16:
    732 		value_sz = sizeof (uint16_t);
    733 		break;
    734 	case DATA_TYPE_INT32:
    735 		value_sz = sizeof (int32_t);
    736 		break;
    737 	case DATA_TYPE_UINT32:
    738 		value_sz = sizeof (uint32_t);
    739 		break;
    740 	case DATA_TYPE_INT64:
    741 		value_sz = sizeof (int64_t);
    742 		break;
    743 	case DATA_TYPE_UINT64:
    744 		value_sz = sizeof (uint64_t);
    745 		break;
    746 #if !defined(_KERNEL)
    747 	case DATA_TYPE_DOUBLE:
    748 		value_sz = sizeof (double);
    749 		break;
    750 #endif
    751 	case DATA_TYPE_STRING:
    752 		if (data == NULL)
    753 			value_sz = 0;
    754 		else
    755 			value_sz = strlen(data) + 1;
    756 		break;
    757 	case DATA_TYPE_BOOLEAN_ARRAY:
    758 		value_sz = (uint64_t)nelem * sizeof (boolean_t);
    759 		break;
    760 	case DATA_TYPE_BYTE_ARRAY:
    761 		value_sz = (uint64_t)nelem * sizeof (uchar_t);
    762 		break;
    763 	case DATA_TYPE_INT8_ARRAY:
    764 		value_sz = (uint64_t)nelem * sizeof (int8_t);
    765 		break;
    766 	case DATA_TYPE_UINT8_ARRAY:
    767 		value_sz = (uint64_t)nelem * sizeof (uint8_t);
    768 		break;
    769 	case DATA_TYPE_INT16_ARRAY:
    770 		value_sz = (uint64_t)nelem * sizeof (int16_t);
    771 		break;
    772 	case DATA_TYPE_UINT16_ARRAY:
    773 		value_sz = (uint64_t)nelem * sizeof (uint16_t);
    774 		break;
    775 	case DATA_TYPE_INT32_ARRAY:
    776 		value_sz = (uint64_t)nelem * sizeof (int32_t);
    777 		break;
    778 	case DATA_TYPE_UINT32_ARRAY:
    779 		value_sz = (uint64_t)nelem * sizeof (uint32_t);
    780 		break;
    781 	case DATA_TYPE_INT64_ARRAY:
    782 		value_sz = (uint64_t)nelem * sizeof (int64_t);
    783 		break;
    784 	case DATA_TYPE_UINT64_ARRAY:
    785 		value_sz = (uint64_t)nelem * sizeof (uint64_t);
    786 		break;
    787 	case DATA_TYPE_STRING_ARRAY:
    788 		value_sz = (uint64_t)nelem * sizeof (uint64_t);
    789 
    790 		if (data != NULL) {
    791 			char *const *strs = data;
    792 			uint_t i;
    793 
    794 			/* no alignment requirement for strings */
    795 			for (i = 0; i < nelem; i++) {
    796 				if (strs[i] == NULL)
    797 					return (-1);
    798 				value_sz += strlen(strs[i]) + 1;
    799 			}
    800 		}
    801 		break;
    802 	case DATA_TYPE_HRTIME:
    803 		value_sz = sizeof (hrtime_t);
    804 		break;
    805 	case DATA_TYPE_NVLIST:
    806 		value_sz = NV_ALIGN(sizeof (nvlist_t));
    807 		break;
    808 	case DATA_TYPE_NVLIST_ARRAY:
    809 		value_sz = (uint64_t)nelem * sizeof (uint64_t) +
    810 		    (uint64_t)nelem * NV_ALIGN(sizeof (nvlist_t));
    811 		break;
    812 	default:
    813 		return (-1);
    814 	}
    815 
    816 	return (value_sz > INT32_MAX ? -1 : (int)value_sz);
    817 }
    818 
    819 static int
    820 nvlist_copy_embedded(nvlist_t *nvl, nvlist_t *onvl, nvlist_t *emb_nvl)
    821 {
    822 	nvpriv_t *priv;
    823 	int err;
    824 
    825 	if ((priv = nv_priv_alloc_embedded((nvpriv_t *)(uintptr_t)
    826 	    nvl->nvl_priv)) == NULL)
    827 		return (ENOMEM);
    828 
    829 	nvlist_init(emb_nvl, onvl->nvl_nvflag, priv);
    830 
    831 	if ((err = nvlist_copy_pairs(onvl, emb_nvl)) != 0) {
    832 		nvlist_free(emb_nvl);
    833 		emb_nvl->nvl_priv = 0;
    834 	}
    835 
    836 	return (err);
    837 }
    838 
    839 /*
    840  * nvlist_add_common - Add new <name,value> pair to nvlist
    841  */
    842 static int
    843 nvlist_add_common(nvlist_t *nvl, const char *name,
    844     data_type_t type, uint_t nelem, const void *data)
    845 {
    846 	nvpair_t *nvp;
    847 	uint_t i;
    848 
    849 	int nvp_sz, name_sz, value_sz;
    850 	int err = 0;
    851 
    852 	if (name == NULL || nvl == NULL || nvl->nvl_priv == 0)
    853 		return (EINVAL);
    854 
    855 	if (nelem != 0 && data == NULL)
    856 		return (EINVAL);
    857 
    858 	/*
    859 	 * Verify type and nelem and get the value size.
    860 	 * In case of data types DATA_TYPE_STRING and DATA_TYPE_STRING_ARRAY
    861 	 * is the size of the string(s) included.
    862 	 */
    863 	if ((value_sz = i_get_value_size(type, data, nelem)) < 0)
    864 		return (EINVAL);
    865 
    866 	if (i_validate_nvpair_value(type, nelem, data) != 0)
    867 		return (EINVAL);
    868 
    869 	/*
    870 	 * If we're adding an nvlist or nvlist array, ensure that we are not
    871 	 * adding the input nvlist to itself, which would cause recursion,
    872 	 * and ensure that no NULL nvlist pointers are present.
    873 	 */
    874 	switch (type) {
    875 	case DATA_TYPE_NVLIST:
    876 		if (data == nvl || data == NULL)
    877 			return (EINVAL);
    878 		break;
    879 	case DATA_TYPE_NVLIST_ARRAY: {
    880 		nvlist_t **onvlp = (nvlist_t **)data;
    881 		for (i = 0; i < nelem; i++) {
    882 			if (onvlp[i] == nvl || onvlp[i] == NULL)
    883 				return (EINVAL);
    884 		}
    885 		break;
    886 	}
    887 	default:
    888 		break;
    889 	}
    890 
    891 	/* calculate sizes of the nvpair elements and the nvpair itself */
    892 	name_sz = strlen(name) + 1;
    893 
    894 	nvp_sz = NVP_SIZE_CALC(name_sz, value_sz);
    895 
    896 	if ((nvp = nvp_buf_alloc(nvl, nvp_sz)) == NULL)
    897 		return (ENOMEM);
    898 
    899 	ASSERT(nvp->nvp_size == nvp_sz);
    900 	nvp->nvp_name_sz = name_sz;
    901 	nvp->nvp_value_elem = nelem;
    902 	nvp->nvp_type = type;
    903 	bcopy(name, NVP_NAME(nvp), name_sz);
    904 
    905 	switch (type) {
    906 	case DATA_TYPE_BOOLEAN:
    907 		break;
    908 	case DATA_TYPE_STRING_ARRAY: {
    909 		char *const *strs = data;
    910 		char *buf = NVP_VALUE(nvp);
    911 		char **cstrs = (void *)buf;
    912 
    913 		/* skip pre-allocated space for pointer array */
    914 		buf += nelem * sizeof (uint64_t);
    915 		for (i = 0; i < nelem; i++) {
    916 			int slen = strlen(strs[i]) + 1;
    917 			bcopy(strs[i], buf, slen);
    918 			cstrs[i] = buf;
    919 			buf += slen;
    920 		}
    921 		break;
    922 	}
    923 	case DATA_TYPE_NVLIST: {
    924 		nvlist_t *nnvl = EMBEDDED_NVL(nvp);
    925 		nvlist_t *onvl = (nvlist_t *)data;
    926 
    927 		if ((err = nvlist_copy_embedded(nvl, onvl, nnvl)) != 0) {
    928 			nvp_buf_free(nvl, nvp);
    929 			return (err);
    930 		}
    931 		break;
    932 	}
    933 	case DATA_TYPE_NVLIST_ARRAY: {
    934 		nvlist_t **onvlp = (nvlist_t **)data;
    935 		nvlist_t **nvlp = EMBEDDED_NVL_ARRAY(nvp);
    936 		nvlist_t *embedded = (nvlist_t *)
    937 		    ((uintptr_t)nvlp + nelem * sizeof (uint64_t));
    938 
    939 		for (i = 0; i < nelem; i++) {
    940 			if ((err = nvlist_copy_embedded(nvl,
    941 			    onvlp[i], embedded)) != 0) {
    942 				/*
    943 				 * Free any successfully created lists
    944 				 */
    945 				nvpair_free(nvp);
    946 				nvp_buf_free(nvl, nvp);
    947 				return (err);
    948 			}
    949 
    950 			nvlp[i] = embedded++;
    951 		}
    952 		break;
    953 	}
    954 	default:
    955 		bcopy(data, NVP_VALUE(nvp), value_sz);
    956 	}
    957 
    958 	/* if unique name, remove before add */
    959 	if (nvl->nvl_nvflag & NV_UNIQUE_NAME)
    960 		(void) nvlist_remove_all(nvl, name);
    961 	else if (nvl->nvl_nvflag & NV_UNIQUE_NAME_TYPE)
    962 		(void) nvlist_remove(nvl, name, type);
    963 
    964 	nvp_buf_link(nvl, nvp);
    965 
    966 	return (0);
    967 }
    968 
    969 int
    970 nvlist_add_boolean(nvlist_t *nvl, const char *name)
    971 {
    972 	return (nvlist_add_common(nvl, name, DATA_TYPE_BOOLEAN, 0, NULL));
    973 }
    974 
    975 int
    976 nvlist_add_boolean_value(nvlist_t *nvl, const char *name, boolean_t val)
    977 {
    978 	return (nvlist_add_common(nvl, name, DATA_TYPE_BOOLEAN_VALUE, 1, &val));
    979 }
    980 
    981 int
    982 nvlist_add_byte(nvlist_t *nvl, const char *name, uchar_t val)
    983 {
    984 	return (nvlist_add_common(nvl, name, DATA_TYPE_BYTE, 1, &val));
    985 }
    986 
    987 int
    988 nvlist_add_int8(nvlist_t *nvl, const char *name, int8_t val)
    989 {
    990 	return (nvlist_add_common(nvl, name, DATA_TYPE_INT8, 1, &val));
    991 }
    992 
    993 int
    994 nvlist_add_uint8(nvlist_t *nvl, const char *name, uint8_t val)
    995 {
    996 	return (nvlist_add_common(nvl, name, DATA_TYPE_UINT8, 1, &val));
    997 }
    998 
    999 int
   1000 nvlist_add_int16(nvlist_t *nvl, const char *name, int16_t val)
   1001 {
   1002 	return (nvlist_add_common(nvl, name, DATA_TYPE_INT16, 1, &val));
   1003 }
   1004 
   1005 int
   1006 nvlist_add_uint16(nvlist_t *nvl, const char *name, uint16_t val)
   1007 {
   1008 	return (nvlist_add_common(nvl, name, DATA_TYPE_UINT16, 1, &val));
   1009 }
   1010 
   1011 int
   1012 nvlist_add_int32(nvlist_t *nvl, const char *name, int32_t val)
   1013 {
   1014 	return (nvlist_add_common(nvl, name, DATA_TYPE_INT32, 1, &val));
   1015 }
   1016 
   1017 int
   1018 nvlist_add_uint32(nvlist_t *nvl, const char *name, uint32_t val)
   1019 {
   1020 	return (nvlist_add_common(nvl, name, DATA_TYPE_UINT32, 1, &val));
   1021 }
   1022 
   1023 int
   1024 nvlist_add_int64(nvlist_t *nvl, const char *name, int64_t val)
   1025 {
   1026 	return (nvlist_add_common(nvl, name, DATA_TYPE_INT64, 1, &val));
   1027 }
   1028 
   1029 int
   1030 nvlist_add_uint64(nvlist_t *nvl, const char *name, uint64_t val)
   1031 {
   1032 	return (nvlist_add_common(nvl, name, DATA_TYPE_UINT64, 1, &val));
   1033 }
   1034 
   1035 #if !defined(_KERNEL)
   1036 int
   1037 nvlist_add_double(nvlist_t *nvl, const char *name, double val)
   1038 {
   1039 	return (nvlist_add_common(nvl, name, DATA_TYPE_DOUBLE, 1, &val));
   1040 }
   1041 #endif
   1042 
   1043 int
   1044 nvlist_add_string(nvlist_t *nvl, const char *name, const char *val)
   1045 {
   1046 	return (nvlist_add_common(nvl, name, DATA_TYPE_STRING, 1, (void *)val));
   1047 }
   1048 
   1049 int
   1050 nvlist_add_boolean_array(nvlist_t *nvl, const char *name,
   1051     boolean_t *a, uint_t n)
   1052 {
   1053 	return (nvlist_add_common(nvl, name, DATA_TYPE_BOOLEAN_ARRAY, n, a));
   1054 }
   1055 
   1056 int
   1057 nvlist_add_byte_array(nvlist_t *nvl, const char *name, uchar_t *a, uint_t n)
   1058 {
   1059 	return (nvlist_add_common(nvl, name, DATA_TYPE_BYTE_ARRAY, n, a));
   1060 }
   1061 
   1062 int
   1063 nvlist_add_int8_array(nvlist_t *nvl, const char *name, int8_t *a, uint_t n)
   1064 {
   1065 	return (nvlist_add_common(nvl, name, DATA_TYPE_INT8_ARRAY, n, a));
   1066 }
   1067 
   1068 int
   1069 nvlist_add_uint8_array(nvlist_t *nvl, const char *name, uint8_t *a, uint_t n)
   1070 {
   1071 	return (nvlist_add_common(nvl, name, DATA_TYPE_UINT8_ARRAY, n, a));
   1072 }
   1073 
   1074 int
   1075 nvlist_add_int16_array(nvlist_t *nvl, const char *name, int16_t *a, uint_t n)
   1076 {
   1077 	return (nvlist_add_common(nvl, name, DATA_TYPE_INT16_ARRAY, n, a));
   1078 }
   1079 
   1080 int
   1081 nvlist_add_uint16_array(nvlist_t *nvl, const char *name, uint16_t *a, uint_t n)
   1082 {
   1083 	return (nvlist_add_common(nvl, name, DATA_TYPE_UINT16_ARRAY, n, a));
   1084 }
   1085 
   1086 int
   1087 nvlist_add_int32_array(nvlist_t *nvl, const char *name, int32_t *a, uint_t n)
   1088 {
   1089 	return (nvlist_add_common(nvl, name, DATA_TYPE_INT32_ARRAY, n, a));
   1090 }
   1091 
   1092 int
   1093 nvlist_add_uint32_array(nvlist_t *nvl, const char *name, uint32_t *a, uint_t n)
   1094 {
   1095 	return (nvlist_add_common(nvl, name, DATA_TYPE_UINT32_ARRAY, n, a));
   1096 }
   1097 
   1098 int
   1099 nvlist_add_int64_array(nvlist_t *nvl, const char *name, int64_t *a, uint_t n)
   1100 {
   1101 	return (nvlist_add_common(nvl, name, DATA_TYPE_INT64_ARRAY, n, a));
   1102 }
   1103 
   1104 int
   1105 nvlist_add_uint64_array(nvlist_t *nvl, const char *name, uint64_t *a, uint_t n)
   1106 {
   1107 	return (nvlist_add_common(nvl, name, DATA_TYPE_UINT64_ARRAY, n, a));
   1108 }
   1109 
   1110 in