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