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