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