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