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