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