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