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