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