Home | History | Annotate | Line # | Download | only in nvpair
nvpair.c revision 1.1.1.2.12.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.12.1   tls 	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