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