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