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