xref: /illumos-gate/usr/src/common/nvpair/nvpair.c (revision 48bbca816818409505a6e214d0911fda44e622e3)
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 	if (name_sz >= 1ULL << (sizeof (nvp->nvp_name_sz) * NBBY - 1))
913 		return (EINVAL);
914 
915 	nvp_sz = NVP_SIZE_CALC(name_sz, value_sz);
916 
917 	if ((nvp = nvp_buf_alloc(nvl, nvp_sz)) == NULL)
918 		return (ENOMEM);
919 
920 	ASSERT(nvp->nvp_size == nvp_sz);
921 	nvp->nvp_name_sz = name_sz;
922 	nvp->nvp_value_elem = nelem;
923 	nvp->nvp_type = type;
924 	bcopy(name, NVP_NAME(nvp), name_sz);
925 
926 	switch (type) {
927 	case DATA_TYPE_BOOLEAN:
928 		break;
929 	case DATA_TYPE_STRING_ARRAY: {
930 		char *const *strs = data;
931 		char *buf = NVP_VALUE(nvp);
932 		char **cstrs = (void *)buf;
933 
934 		/* skip pre-allocated space for pointer array */
935 		buf += nelem * sizeof (uint64_t);
936 		for (i = 0; i < nelem; i++) {
937 			int slen = strlen(strs[i]) + 1;
938 			bcopy(strs[i], buf, slen);
939 			cstrs[i] = buf;
940 			buf += slen;
941 		}
942 		break;
943 	}
944 	case DATA_TYPE_NVLIST: {
945 		nvlist_t *nnvl = EMBEDDED_NVL(nvp);
946 		nvlist_t *onvl = (nvlist_t *)data;
947 
948 		if ((err = nvlist_copy_embedded(nvl, onvl, nnvl)) != 0) {
949 			nvp_buf_free(nvl, nvp);
950 			return (err);
951 		}
952 		break;
953 	}
954 	case DATA_TYPE_NVLIST_ARRAY: {
955 		nvlist_t **onvlp = (nvlist_t **)data;
956 		nvlist_t **nvlp = EMBEDDED_NVL_ARRAY(nvp);
957 		nvlist_t *embedded = (nvlist_t *)
958 		    ((uintptr_t)nvlp + nelem * sizeof (uint64_t));
959 
960 		for (i = 0; i < nelem; i++) {
961 			if ((err = nvlist_copy_embedded(nvl,
962 			    onvlp[i], embedded)) != 0) {
963 				/*
964 				 * Free any successfully created lists
965 				 */
966 				nvpair_free(nvp);
967 				nvp_buf_free(nvl, nvp);
968 				return (err);
969 			}
970 
971 			nvlp[i] = embedded++;
972 		}
973 		break;
974 	}
975 	default:
976 		bcopy(data, NVP_VALUE(nvp), value_sz);
977 	}
978 
979 	/* if unique name, remove before add */
980 	if (nvl->nvl_nvflag & NV_UNIQUE_NAME)
981 		(void) nvlist_remove_all(nvl, name);
982 	else if (nvl->nvl_nvflag & NV_UNIQUE_NAME_TYPE)
983 		(void) nvlist_remove(nvl, name, type);
984 
985 	nvp_buf_link(nvl, nvp);
986 
987 	return (0);
988 }
989 
990 int
991 nvlist_add_boolean(nvlist_t *nvl, const char *name)
992 {
993 	return (nvlist_add_common(nvl, name, DATA_TYPE_BOOLEAN, 0, NULL));
994 }
995 
996 int
997 nvlist_add_boolean_value(nvlist_t *nvl, const char *name, boolean_t val)
998 {
999 	return (nvlist_add_common(nvl, name, DATA_TYPE_BOOLEAN_VALUE, 1, &val));
1000 }
1001 
1002 int
1003 nvlist_add_byte(nvlist_t *nvl, const char *name, uchar_t val)
1004 {
1005 	return (nvlist_add_common(nvl, name, DATA_TYPE_BYTE, 1, &val));
1006 }
1007 
1008 int
1009 nvlist_add_int8(nvlist_t *nvl, const char *name, int8_t val)
1010 {
1011 	return (nvlist_add_common(nvl, name, DATA_TYPE_INT8, 1, &val));
1012 }
1013 
1014 int
1015 nvlist_add_uint8(nvlist_t *nvl, const char *name, uint8_t val)
1016 {
1017 	return (nvlist_add_common(nvl, name, DATA_TYPE_UINT8, 1, &val));
1018 }
1019 
1020 int
1021 nvlist_add_int16(nvlist_t *nvl, const char *name, int16_t val)
1022 {
1023 	return (nvlist_add_common(nvl, name, DATA_TYPE_INT16, 1, &val));
1024 }
1025 
1026 int
1027 nvlist_add_uint16(nvlist_t *nvl, const char *name, uint16_t val)
1028 {
1029 	return (nvlist_add_common(nvl, name, DATA_TYPE_UINT16, 1, &val));
1030 }
1031 
1032 int
1033 nvlist_add_int32(nvlist_t *nvl, const char *name, int32_t val)
1034 {
1035 	return (nvlist_add_common(nvl, name, DATA_TYPE_INT32, 1, &val));
1036 }
1037 
1038 int
1039 nvlist_add_uint32(nvlist_t *nvl, const char *name, uint32_t val)
1040 {
1041 	return (nvlist_add_common(nvl, name, DATA_TYPE_UINT32, 1, &val));
1042 }
1043 
1044 int
1045 nvlist_add_int64(nvlist_t *nvl, const char *name, int64_t val)
1046 {
1047 	return (nvlist_add_common(nvl, name, DATA_TYPE_INT64, 1, &val));
1048 }
1049 
1050 int
1051 nvlist_add_uint64(nvlist_t *nvl, const char *name, uint64_t val)
1052 {
1053 	return (nvlist_add_common(nvl, name, DATA_TYPE_UINT64, 1, &val));
1054 }
1055 
1056 #if !defined(_KERNEL)
1057 int
1058 nvlist_add_double(nvlist_t *nvl, const char *name, double val)
1059 {
1060 	return (nvlist_add_common(nvl, name, DATA_TYPE_DOUBLE, 1, &val));
1061 }
1062 #endif
1063 
1064 int
1065 nvlist_add_string(nvlist_t *nvl, const char *name, const char *val)
1066 {
1067 	return (nvlist_add_common(nvl, name, DATA_TYPE_STRING, 1, (void *)val));
1068 }
1069 
1070 int
1071 nvlist_add_boolean_array(nvlist_t *nvl, const char *name,
1072     boolean_t *a, uint_t n)
1073 {
1074 	return (nvlist_add_common(nvl, name, DATA_TYPE_BOOLEAN_ARRAY, n, a));
1075 }
1076 
1077 int
1078 nvlist_add_byte_array(nvlist_t *nvl, const char *name, uchar_t *a, uint_t n)
1079 {
1080 	return (nvlist_add_common(nvl, name, DATA_TYPE_BYTE_ARRAY, n, a));
1081 }
1082 
1083 int
1084 nvlist_add_int8_array(nvlist_t *nvl, const char *name, int8_t *a, uint_t n)
1085 {
1086 	return (nvlist_add_common(nvl, name, DATA_TYPE_INT8_ARRAY, n, a));
1087 }
1088 
1089 int
1090 nvlist_add_uint8_array(nvlist_t *nvl, const char *name, uint8_t *a, uint_t n)
1091 {
1092 	return (nvlist_add_common(nvl, name, DATA_TYPE_UINT8_ARRAY, n, a));
1093 }
1094 
1095 int
1096 nvlist_add_int16_array(nvlist_t *nvl, const char *name, int16_t *a, uint_t n)
1097 {
1098 	return (nvlist_add_common(nvl, name, DATA_TYPE_INT16_ARRAY, n, a));
1099 }
1100 
1101 int
1102 nvlist_add_uint16_array(nvlist_t *nvl, const char *name, uint16_t *a, uint_t n)
1103 {
1104 	return (nvlist_add_common(nvl, name, DATA_TYPE_UINT16_ARRAY, n, a));
1105 }
1106 
1107 int
1108 nvlist_add_int32_array(nvlist_t *nvl, const char *name, int32_t *a, uint_t n)
1109 {
1110 	return (nvlist_add_common(nvl, name, DATA_TYPE_INT32_ARRAY, n, a));
1111 }
1112 
1113 int
1114 nvlist_add_uint32_array(nvlist_t *nvl, const char *name, uint32_t *a, uint_t n)
1115 {
1116 	return (nvlist_add_common(nvl, name, DATA_TYPE_UINT32_ARRAY, n, a));
1117 }
1118 
1119 int
1120 nvlist_add_int64_array(nvlist_t *nvl, const char *name, int64_t *a, uint_t n)
1121 {
1122 	return (nvlist_add_common(nvl, name, DATA_TYPE_INT64_ARRAY, n, a));
1123 }
1124 
1125 int
1126 nvlist_add_uint64_array(nvlist_t *nvl, const char *name, uint64_t *a, uint_t n)
1127 {
1128 	return (nvlist_add_common(nvl, name, DATA_TYPE_UINT64_ARRAY, n, a));
1129 }
1130 
1131 int
1132 nvlist_add_string_array(nvlist_t *nvl, const char *name,
1133     char *const *a, uint_t n)
1134 {
1135 	return (nvlist_add_common(nvl, name, DATA_TYPE_STRING_ARRAY, n, a));
1136 }
1137 
1138 int
1139 nvlist_add_hrtime(nvlist_t *nvl, const char *name, hrtime_t val)
1140 {
1141 	return (nvlist_add_common(nvl, name, DATA_TYPE_HRTIME, 1, &val));
1142 }
1143 
1144 int
1145 nvlist_add_nvlist(nvlist_t *nvl, const char *name, nvlist_t *val)
1146 {
1147 	return (nvlist_add_common(nvl, name, DATA_TYPE_NVLIST, 1, val));
1148 }
1149 
1150 int
1151 nvlist_add_nvlist_array(nvlist_t *nvl, const char *name, nvlist_t **a, uint_t n)
1152 {
1153 	return (nvlist_add_common(nvl, name, DATA_TYPE_NVLIST_ARRAY, n, a));
1154 }
1155 
1156 /* reading name-value pairs */
1157 nvpair_t *
1158 nvlist_next_nvpair(nvlist_t *nvl, nvpair_t *nvp)
1159 {
1160 	nvpriv_t *priv;
1161 	i_nvp_t *curr;
1162 
1163 	if (nvl == NULL ||
1164 	    (priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL)
1165 		return (NULL);
1166 
1167 	curr = NVPAIR2I_NVP(nvp);
1168 
1169 	/*
1170 	 * Ensure that nvp is a valid nvpair on this nvlist.
1171 	 * NB: nvp_curr is used only as a hint so that we don't always
1172 	 * have to walk the list to determine if nvp is still on the list.
1173 	 */
1174 	if (nvp == NULL)
1175 		curr = priv->nvp_list;
1176 	else if (priv->nvp_curr == curr || nvlist_contains_nvp(nvl, nvp))
1177 		curr = curr->nvi_next;
1178 	else
1179 		curr = NULL;
1180 
1181 	priv->nvp_curr = curr;
1182 
1183 	return (curr != NULL ? &curr->nvi_nvp : NULL);
1184 }
1185 
1186 nvpair_t *
1187 nvlist_prev_nvpair(nvlist_t *nvl, nvpair_t *nvp)
1188 {
1189 	nvpriv_t *priv;
1190 	i_nvp_t *curr;
1191 
1192 	if (nvl == NULL ||
1193 	    (priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL)
1194 		return (NULL);
1195 
1196 	curr = NVPAIR2I_NVP(nvp);
1197 
1198 	if (nvp == NULL)
1199 		curr = priv->nvp_last;
1200 	else if (priv->nvp_curr == curr || nvlist_contains_nvp(nvl, nvp))
1201 		curr = curr->nvi_prev;
1202 	else
1203 		curr = NULL;
1204 
1205 	priv->nvp_curr = curr;
1206 
1207 	return (curr != NULL ? &curr->nvi_nvp : NULL);
1208 }
1209 
1210 boolean_t
1211 nvlist_empty(nvlist_t *nvl)
1212 {
1213 	nvpriv_t *priv;
1214 
1215 	if (nvl == NULL ||
1216 	    (priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL)
1217 		return (B_TRUE);
1218 
1219 	return (priv->nvp_list == NULL);
1220 }
1221 
1222 char *
1223 nvpair_name(nvpair_t *nvp)
1224 {
1225 	return (NVP_NAME(nvp));
1226 }
1227 
1228 data_type_t
1229 nvpair_type(nvpair_t *nvp)
1230 {
1231 	return (NVP_TYPE(nvp));
1232 }
1233 
1234 int
1235 nvpair_type_is_array(nvpair_t *nvp)
1236 {
1237 	data_type_t type = NVP_TYPE(nvp);
1238 
1239 	if ((type == DATA_TYPE_BYTE_ARRAY) ||
1240 	    (type == DATA_TYPE_INT8_ARRAY) ||
1241 	    (type == DATA_TYPE_UINT8_ARRAY) ||
1242 	    (type == DATA_TYPE_INT16_ARRAY) ||
1243 	    (type == DATA_TYPE_UINT16_ARRAY) ||
1244 	    (type == DATA_TYPE_INT32_ARRAY) ||
1245 	    (type == DATA_TYPE_UINT32_ARRAY) ||
1246 	    (type == DATA_TYPE_INT64_ARRAY) ||
1247 	    (type == DATA_TYPE_UINT64_ARRAY) ||
1248 	    (type == DATA_TYPE_BOOLEAN_ARRAY) ||
1249 	    (type == DATA_TYPE_STRING_ARRAY) ||
1250 	    (type == DATA_TYPE_NVLIST_ARRAY))
1251 		return (1);
1252 	return (0);
1253 
1254 }
1255 
1256 static int
1257 nvpair_value_common(nvpair_t *nvp, data_type_t type, uint_t *nelem, void *data)
1258 {
1259 	if (nvp == NULL || nvpair_type(nvp) != type)
1260 		return (EINVAL);
1261 
1262 	/*
1263 	 * For non-array types, we copy the data.
1264 	 * For array types (including string), we set a pointer.
1265 	 */
1266 	switch (type) {
1267 	case DATA_TYPE_BOOLEAN:
1268 		if (nelem != NULL)
1269 			*nelem = 0;
1270 		break;
1271 
1272 	case DATA_TYPE_BOOLEAN_VALUE:
1273 	case DATA_TYPE_BYTE:
1274 	case DATA_TYPE_INT8:
1275 	case DATA_TYPE_UINT8:
1276 	case DATA_TYPE_INT16:
1277 	case DATA_TYPE_UINT16:
1278 	case DATA_TYPE_INT32:
1279 	case DATA_TYPE_UINT32:
1280 	case DATA_TYPE_INT64:
1281 	case DATA_TYPE_UINT64:
1282 	case DATA_TYPE_HRTIME:
1283 #if !defined(_KERNEL)
1284 	case DATA_TYPE_DOUBLE:
1285 #endif
1286 		if (data == NULL)
1287 			return (EINVAL);
1288 		bcopy(NVP_VALUE(nvp), data,
1289 		    (size_t)i_get_value_size(type, NULL, 1));
1290 		if (nelem != NULL)
1291 			*nelem = 1;
1292 		break;
1293 
1294 	case DATA_TYPE_NVLIST:
1295 	case DATA_TYPE_STRING:
1296 		if (data == NULL)
1297 			return (EINVAL);
1298 		*(void **)data = (void *)NVP_VALUE(nvp);
1299 		if (nelem != NULL)
1300 			*nelem = 1;
1301 		break;
1302 
1303 	case DATA_TYPE_BOOLEAN_ARRAY:
1304 	case DATA_TYPE_BYTE_ARRAY:
1305 	case DATA_TYPE_INT8_ARRAY:
1306 	case DATA_TYPE_UINT8_ARRAY:
1307 	case DATA_TYPE_INT16_ARRAY:
1308 	case DATA_TYPE_UINT16_ARRAY:
1309 	case DATA_TYPE_INT32_ARRAY:
1310 	case DATA_TYPE_UINT32_ARRAY:
1311 	case DATA_TYPE_INT64_ARRAY:
1312 	case DATA_TYPE_UINT64_ARRAY:
1313 	case DATA_TYPE_STRING_ARRAY:
1314 	case DATA_TYPE_NVLIST_ARRAY:
1315 		if (nelem == NULL || data == NULL)
1316 			return (EINVAL);
1317 		if ((*nelem = NVP_NELEM(nvp)) != 0)
1318 			*(void **)data = (void *)NVP_VALUE(nvp);
1319 		else
1320 			*(void **)data = NULL;
1321 		break;
1322 
1323 	default:
1324 		return (ENOTSUP);
1325 	}
1326 
1327 	return (0);
1328 }
1329 
1330 static int
1331 nvlist_lookup_common(nvlist_t *nvl, const char *name, data_type_t type,
1332     uint_t *nelem, void *data)
1333 {
1334 	nvpriv_t *priv;
1335 	nvpair_t *nvp;
1336 	i_nvp_t *curr;
1337 
1338 	if (name == NULL || nvl == NULL ||
1339 	    (priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL)
1340 		return (EINVAL);
1341 
1342 	if (!(nvl->nvl_nvflag & (NV_UNIQUE_NAME | NV_UNIQUE_NAME_TYPE)))
1343 		return (ENOTSUP);
1344 
1345 	for (curr = priv->nvp_list; curr != NULL; curr = curr->nvi_next) {
1346 		nvp = &curr->nvi_nvp;
1347 
1348 		if (strcmp(name, NVP_NAME(nvp)) == 0 && NVP_TYPE(nvp) == type)
1349 			return (nvpair_value_common(nvp, type, nelem, data));
1350 	}
1351 
1352 	return (ENOENT);
1353 }
1354 
1355 int
1356 nvlist_lookup_boolean(nvlist_t *nvl, const char *name)
1357 {
1358 	return (nvlist_lookup_common(nvl, name, DATA_TYPE_BOOLEAN, NULL, NULL));
1359 }
1360 
1361 int
1362 nvlist_lookup_boolean_value(nvlist_t *nvl, const char *name, boolean_t *val)
1363 {
1364 	return (nvlist_lookup_common(nvl, name,
1365 	    DATA_TYPE_BOOLEAN_VALUE, NULL, val));
1366 }
1367 
1368 int
1369 nvlist_lookup_byte(nvlist_t *nvl, const char *name, uchar_t *val)
1370 {
1371 	return (nvlist_lookup_common(nvl, name, DATA_TYPE_BYTE, NULL, val));
1372 }
1373 
1374 int
1375 nvlist_lookup_int8(nvlist_t *nvl, const char *name, int8_t *val)
1376 {
1377 	return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT8, NULL, val));
1378 }
1379 
1380 int
1381 nvlist_lookup_uint8(nvlist_t *nvl, const char *name, uint8_t *val)
1382 {
1383 	return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT8, NULL, val));
1384 }
1385 
1386 int
1387 nvlist_lookup_int16(nvlist_t *nvl, const char *name, int16_t *val)
1388 {
1389 	return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT16, NULL, val));
1390 }
1391 
1392 int
1393 nvlist_lookup_uint16(nvlist_t *nvl, const char *name, uint16_t *val)
1394 {
1395 	return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT16, NULL, val));
1396 }
1397 
1398 int
1399 nvlist_lookup_int32(nvlist_t *nvl, const char *name, int32_t *val)
1400 {
1401 	return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT32, NULL, val));
1402 }
1403 
1404 int
1405 nvlist_lookup_uint32(nvlist_t *nvl, const char *name, uint32_t *val)
1406 {
1407 	return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT32, NULL, val));
1408 }
1409 
1410 int
1411 nvlist_lookup_int64(nvlist_t *nvl, const char *name, int64_t *val)
1412 {
1413 	return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT64, NULL, val));
1414 }
1415 
1416 int
1417 nvlist_lookup_uint64(nvlist_t *nvl, const char *name, uint64_t *val)
1418 {
1419 	return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT64, NULL, val));
1420 }
1421 
1422 #if !defined(_KERNEL)
1423 int
1424 nvlist_lookup_double(nvlist_t *nvl, const char *name, double *val)
1425 {
1426 	return (nvlist_lookup_common(nvl, name, DATA_TYPE_DOUBLE, NULL, val));
1427 }
1428 #endif
1429 
1430 int
1431 nvlist_lookup_string(nvlist_t *nvl, const char *name, char **val)
1432 {
1433 	return (nvlist_lookup_common(nvl, name, DATA_TYPE_STRING, NULL, val));
1434 }
1435 
1436 int
1437 nvlist_lookup_nvlist(nvlist_t *nvl, const char *name, nvlist_t **val)
1438 {
1439 	return (nvlist_lookup_common(nvl, name, DATA_TYPE_NVLIST, NULL, val));
1440 }
1441 
1442 int
1443 nvlist_lookup_boolean_array(nvlist_t *nvl, const char *name,
1444     boolean_t **a, uint_t *n)
1445 {
1446 	return (nvlist_lookup_common(nvl, name,
1447 	    DATA_TYPE_BOOLEAN_ARRAY, n, a));
1448 }
1449 
1450 int
1451 nvlist_lookup_byte_array(nvlist_t *nvl, const char *name,
1452     uchar_t **a, uint_t *n)
1453 {
1454 	return (nvlist_lookup_common(nvl, name, DATA_TYPE_BYTE_ARRAY, n, a));
1455 }
1456 
1457 int
1458 nvlist_lookup_int8_array(nvlist_t *nvl, const char *name, int8_t **a, uint_t *n)
1459 {
1460 	return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT8_ARRAY, n, a));
1461 }
1462 
1463 int
1464 nvlist_lookup_uint8_array(nvlist_t *nvl, const char *name,
1465     uint8_t **a, uint_t *n)
1466 {
1467 	return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT8_ARRAY, n, a));
1468 }
1469 
1470 int
1471 nvlist_lookup_int16_array(nvlist_t *nvl, const char *name,
1472     int16_t **a, uint_t *n)
1473 {
1474 	return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT16_ARRAY, n, a));
1475 }
1476 
1477 int
1478 nvlist_lookup_uint16_array(nvlist_t *nvl, const char *name,
1479     uint16_t **a, uint_t *n)
1480 {
1481 	return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT16_ARRAY, n, a));
1482 }
1483 
1484 int
1485 nvlist_lookup_int32_array(nvlist_t *nvl, const char *name,
1486     int32_t **a, uint_t *n)
1487 {
1488 	return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT32_ARRAY, n, a));
1489 }
1490 
1491 int
1492 nvlist_lookup_uint32_array(nvlist_t *nvl, const char *name,
1493     uint32_t **a, uint_t *n)
1494 {
1495 	return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT32_ARRAY, n, a));
1496 }
1497 
1498 int
1499 nvlist_lookup_int64_array(nvlist_t *nvl, const char *name,
1500     int64_t **a, uint_t *n)
1501 {
1502 	return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT64_ARRAY, n, a));
1503 }
1504 
1505 int
1506 nvlist_lookup_uint64_array(nvlist_t *nvl, const char *name,
1507     uint64_t **a, uint_t *n)
1508 {
1509 	return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT64_ARRAY, n, a));
1510 }
1511 
1512 int
1513 nvlist_lookup_string_array(nvlist_t *nvl, const char *name,
1514     char ***a, uint_t *n)
1515 {
1516 	return (nvlist_lookup_common(nvl, name, DATA_TYPE_STRING_ARRAY, n, a));
1517 }
1518 
1519 int
1520 nvlist_lookup_nvlist_array(nvlist_t *nvl, const char *name,
1521     nvlist_t ***a, uint_t *n)
1522 {
1523 	return (nvlist_lookup_common(nvl, name, DATA_TYPE_NVLIST_ARRAY, n, a));
1524 }
1525 
1526 int
1527 nvlist_lookup_hrtime(nvlist_t *nvl, const char *name, hrtime_t *val)
1528 {
1529 	return (nvlist_lookup_common(nvl, name, DATA_TYPE_HRTIME, NULL, val));
1530 }
1531 
1532 int
1533 nvlist_lookup_pairs(nvlist_t *nvl, int flag, ...)
1534 {
1535 	va_list ap;
1536 	char *name;
1537 	int noentok = (flag & NV_FLAG_NOENTOK ? 1 : 0);
1538 	int ret = 0;
1539 
1540 	va_start(ap, flag);
1541 	while (ret == 0 && (name = va_arg(ap, char *)) != NULL) {
1542 		data_type_t type;
1543 		void *val;
1544 		uint_t *nelem;
1545 
1546 		switch (type = va_arg(ap, data_type_t)) {
1547 		case DATA_TYPE_BOOLEAN:
1548 			ret = nvlist_lookup_common(nvl, name, type, NULL, NULL);
1549 			break;
1550 
1551 		case DATA_TYPE_BOOLEAN_VALUE:
1552 		case DATA_TYPE_BYTE:
1553 		case DATA_TYPE_INT8:
1554 		case DATA_TYPE_UINT8:
1555 		case DATA_TYPE_INT16:
1556 		case DATA_TYPE_UINT16:
1557 		case DATA_TYPE_INT32:
1558 		case DATA_TYPE_UINT32:
1559 		case DATA_TYPE_INT64:
1560 		case DATA_TYPE_UINT64:
1561 		case DATA_TYPE_HRTIME:
1562 		case DATA_TYPE_STRING:
1563 		case DATA_TYPE_NVLIST:
1564 #if !defined(_KERNEL)
1565 		case DATA_TYPE_DOUBLE:
1566 #endif
1567 			val = va_arg(ap, void *);
1568 			ret = nvlist_lookup_common(nvl, name, type, NULL, val);
1569 			break;
1570 
1571 		case DATA_TYPE_BYTE_ARRAY:
1572 		case DATA_TYPE_BOOLEAN_ARRAY:
1573 		case DATA_TYPE_INT8_ARRAY:
1574 		case DATA_TYPE_UINT8_ARRAY:
1575 		case DATA_TYPE_INT16_ARRAY:
1576 		case DATA_TYPE_UINT16_ARRAY:
1577 		case DATA_TYPE_INT32_ARRAY:
1578 		case DATA_TYPE_UINT32_ARRAY:
1579 		case DATA_TYPE_INT64_ARRAY:
1580 		case DATA_TYPE_UINT64_ARRAY:
1581 		case DATA_TYPE_STRING_ARRAY:
1582 		case DATA_TYPE_NVLIST_ARRAY:
1583 			val = va_arg(ap, void *);
1584 			nelem = va_arg(ap, uint_t *);
1585 			ret = nvlist_lookup_common(nvl, name, type, nelem, val);
1586 			break;
1587 
1588 		default:
1589 			ret = EINVAL;
1590 		}
1591 
1592 		if (ret == ENOENT && noentok)
1593 			ret = 0;
1594 	}
1595 	va_end(ap);
1596 
1597 	return (ret);
1598 }
1599 
1600 /*
1601  * Find the 'name'ed nvpair in the nvlist 'nvl'. If 'name' found, the function
1602  * returns zero and a pointer to the matching nvpair is returned in '*ret'
1603  * (given 'ret' is non-NULL). If 'sep' is specified then 'name' will penitrate
1604  * multiple levels of embedded nvlists, with 'sep' as the separator. As an
1605  * example, if sep is '.', name might look like: "a" or "a.b" or "a.c[3]" or
1606  * "a.d[3].e[1]".  This matches the C syntax for array embed (for convience,
1607  * code also supports "a.d[3]e[1]" syntax).
1608  *
1609  * If 'ip' is non-NULL and the last name component is an array, return the
1610  * value of the "...[index]" array index in *ip. For an array reference that
1611  * is not indexed, *ip will be returned as -1. If there is a syntax error in
1612  * 'name', and 'ep' is non-NULL then *ep will be set to point to the location
1613  * inside the 'name' string where the syntax error was detected.
1614  */
1615 static int
1616 nvlist_lookup_nvpair_ei_sep(nvlist_t *nvl, const char *name, const char sep,
1617     nvpair_t **ret, int *ip, char **ep)
1618 {
1619 	nvpair_t	*nvp;
1620 	const char	*np;
1621 	char		*sepp;
1622 	char		*idxp, *idxep;
1623 	nvlist_t	**nva;
1624 	long		idx;
1625 	int		n;
1626 
1627 	if (ip)
1628 		*ip = -1;			/* not indexed */
1629 	if (ep)
1630 		*ep = NULL;
1631 
1632 	if ((nvl == NULL) || (name == NULL))
1633 		return (EINVAL);
1634 
1635 	sepp = NULL;
1636 	idx = 0;
1637 	/* step through components of name */
1638 	for (np = name; np && *np; np = sepp) {
1639 		/* ensure unique names */
1640 		if (!(nvl->nvl_nvflag & NV_UNIQUE_NAME))
1641 			return (ENOTSUP);
1642 
1643 		/* skip white space */
1644 		skip_whitespace(np);
1645 		if (*np == 0)
1646 			break;
1647 
1648 		/* set 'sepp' to end of current component 'np' */
1649 		if (sep)
1650 			sepp = strchr(np, sep);
1651 		else
1652 			sepp = NULL;
1653 
1654 		/* find start of next "[ index ]..." */
1655 		idxp = strchr(np, '[');
1656 
1657 		/* if sepp comes first, set idxp to NULL */
1658 		if (sepp && idxp && (sepp < idxp))
1659 			idxp = NULL;
1660 
1661 		/*
1662 		 * At this point 'idxp' is set if there is an index
1663 		 * expected for the current component.
1664 		 */
1665 		if (idxp) {
1666 			/* set 'n' to length of current 'np' name component */
1667 			n = idxp++ - np;
1668 
1669 			/* keep sepp up to date for *ep use as we advance */
1670 			skip_whitespace(idxp);
1671 			sepp = idxp;
1672 
1673 			/* determine the index value */
1674 #if defined(_KERNEL) && !defined(_BOOT)
1675 			if (ddi_strtol(idxp, &idxep, 0, &idx))
1676 				goto fail;
1677 #else
1678 			idx = strtol(idxp, &idxep, 0);
1679 #endif
1680 			if (idxep == idxp)
1681 				goto fail;
1682 
1683 			/* keep sepp up to date for *ep use as we advance */
1684 			sepp = idxep;
1685 
1686 			/* skip white space index value and check for ']' */
1687 			skip_whitespace(sepp);
1688 			if (*sepp++ != ']')
1689 				goto fail;
1690 
1691 			/* for embedded arrays, support C syntax: "a[1].b" */
1692 			skip_whitespace(sepp);
1693 			if (sep && (*sepp == sep))
1694 				sepp++;
1695 		} else if (sepp) {
1696 			n = sepp++ - np;
1697 		} else {
1698 			n = strlen(np);
1699 		}
1700 
1701 		/* trim trailing whitespace by reducing length of 'np' */
1702 		if (n == 0)
1703 			goto fail;
1704 		for (n--; (np[n] == ' ') || (np[n] == '\t'); n--)
1705 			;
1706 		n++;
1707 
1708 		/* skip whitespace, and set sepp to NULL if complete */
1709 		if (sepp) {
1710 			skip_whitespace(sepp);
1711 			if (*sepp == 0)
1712 				sepp = NULL;
1713 		}
1714 
1715 		/*
1716 		 * At this point:
1717 		 * o  'n' is the length of current 'np' component.
1718 		 * o  'idxp' is set if there was an index, and value 'idx'.
1719 		 * o  'sepp' is set to the beginning of the next component,
1720 		 *    and set to NULL if we have no more components.
1721 		 *
1722 		 * Search for nvpair with matching component name.
1723 		 */
1724 		for (nvp = nvlist_next_nvpair(nvl, NULL); nvp != NULL;
1725 		    nvp = nvlist_next_nvpair(nvl, nvp)) {
1726 
1727 			/* continue if no match on name */
1728 			if (strncmp(np, nvpair_name(nvp), n) ||
1729 			    (strlen(nvpair_name(nvp)) != n))
1730 				continue;
1731 
1732 			/* if indexed, verify type is array oriented */
1733 			if (idxp && !nvpair_type_is_array(nvp))
1734 				goto fail;
1735 
1736 			/*
1737 			 * Full match found, return nvp and idx if this
1738 			 * was the last component.
1739 			 */
1740 			if (sepp == NULL) {
1741 				if (ret)
1742 					*ret = nvp;
1743 				if (ip && idxp)
1744 					*ip = (int)idx;	/* return index */
1745 				return (0);		/* found */
1746 			}
1747 
1748 			/*
1749 			 * More components: current match must be
1750 			 * of DATA_TYPE_NVLIST or DATA_TYPE_NVLIST_ARRAY
1751 			 * to support going deeper.
1752 			 */
1753 			if (nvpair_type(nvp) == DATA_TYPE_NVLIST) {
1754 				nvl = EMBEDDED_NVL(nvp);
1755 				break;
1756 			} else if (nvpair_type(nvp) == DATA_TYPE_NVLIST_ARRAY) {
1757 				(void) nvpair_value_nvlist_array(nvp,
1758 				    &nva, (uint_t *)&n);
1759 				if ((n < 0) || (idx >= n))
1760 					goto fail;
1761 				nvl = nva[idx];
1762 				break;
1763 			}
1764 
1765 			/* type does not support more levels */
1766 			goto fail;
1767 		}
1768 		if (nvp == NULL)
1769 			goto fail;		/* 'name' not found */
1770 
1771 		/* search for match of next component in embedded 'nvl' list */
1772 	}
1773 
1774 fail:	if (ep && sepp)
1775 		*ep = sepp;
1776 	return (EINVAL);
1777 }
1778 
1779 /*
1780  * Return pointer to nvpair with specified 'name'.
1781  */
1782 int
1783 nvlist_lookup_nvpair(nvlist_t *nvl, const char *name, nvpair_t **ret)
1784 {
1785 	return (nvlist_lookup_nvpair_ei_sep(nvl, name, 0, ret, NULL, NULL));
1786 }
1787 
1788 /*
1789  * Determine if named nvpair exists in nvlist (use embedded separator of '.'
1790  * and return array index).  See nvlist_lookup_nvpair_ei_sep for more detailed
1791  * description.
1792  */
1793 int nvlist_lookup_nvpair_embedded_index(nvlist_t *nvl,
1794     const char *name, nvpair_t **ret, int *ip, char **ep)
1795 {
1796 	return (nvlist_lookup_nvpair_ei_sep(nvl, name, '.', ret, ip, ep));
1797 }
1798 
1799 boolean_t
1800 nvlist_exists(nvlist_t *nvl, const char *name)
1801 {
1802 	nvpriv_t *priv;
1803 	nvpair_t *nvp;
1804 	i_nvp_t *curr;
1805 
1806 	if (name == NULL || nvl == NULL ||
1807 	    (priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL)
1808 		return (B_FALSE);
1809 
1810 	for (curr = priv->nvp_list; curr != NULL; curr = curr->nvi_next) {
1811 		nvp = &curr->nvi_nvp;
1812 
1813 		if (strcmp(name, NVP_NAME(nvp)) == 0)
1814 			return (B_TRUE);
1815 	}
1816 
1817 	return (B_FALSE);
1818 }
1819 
1820 int
1821 nvpair_value_boolean_value(nvpair_t *nvp, boolean_t *val)
1822 {
1823 	return (nvpair_value_common(nvp, DATA_TYPE_BOOLEAN_VALUE, NULL, val));
1824 }
1825 
1826 int
1827 nvpair_value_byte(nvpair_t *nvp, uchar_t *val)
1828 {
1829 	return (nvpair_value_common(nvp, DATA_TYPE_BYTE, NULL, val));
1830 }
1831 
1832 int
1833 nvpair_value_int8(nvpair_t *nvp, int8_t *val)
1834 {
1835 	return (nvpair_value_common(nvp, DATA_TYPE_INT8, NULL, val));
1836 }
1837 
1838 int
1839 nvpair_value_uint8(nvpair_t *nvp, uint8_t *val)
1840 {
1841 	return (nvpair_value_common(nvp, DATA_TYPE_UINT8, NULL, val));
1842 }
1843 
1844 int
1845 nvpair_value_int16(nvpair_t *nvp, int16_t *val)
1846 {
1847 	return (nvpair_value_common(nvp, DATA_TYPE_INT16, NULL, val));
1848 }
1849 
1850 int
1851 nvpair_value_uint16(nvpair_t *nvp, uint16_t *val)
1852 {
1853 	return (nvpair_value_common(nvp, DATA_TYPE_UINT16, NULL, val));
1854 }
1855 
1856 int
1857 nvpair_value_int32(nvpair_t *nvp, int32_t *val)
1858 {
1859 	return (nvpair_value_common(nvp, DATA_TYPE_INT32, NULL, val));
1860 }
1861 
1862 int
1863 nvpair_value_uint32(nvpair_t *nvp, uint32_t *val)
1864 {
1865 	return (nvpair_value_common(nvp, DATA_TYPE_UINT32, NULL, val));
1866 }
1867 
1868 int
1869 nvpair_value_int64(nvpair_t *nvp, int64_t *val)
1870 {
1871 	return (nvpair_value_common(nvp, DATA_TYPE_INT64, NULL, val));
1872 }
1873 
1874 int
1875 nvpair_value_uint64(nvpair_t *nvp, uint64_t *val)
1876 {
1877 	return (nvpair_value_common(nvp, DATA_TYPE_UINT64, NULL, val));
1878 }
1879 
1880 #if !defined(_KERNEL)
1881 int
1882 nvpair_value_double(nvpair_t *nvp, double *val)
1883 {
1884 	return (nvpair_value_common(nvp, DATA_TYPE_DOUBLE, NULL, val));
1885 }
1886 #endif
1887 
1888 int
1889 nvpair_value_string(nvpair_t *nvp, char **val)
1890 {
1891 	return (nvpair_value_common(nvp, DATA_TYPE_STRING, NULL, val));
1892 }
1893 
1894 int
1895 nvpair_value_nvlist(nvpair_t *nvp, nvlist_t **val)
1896 {
1897 	return (nvpair_value_common(nvp, DATA_TYPE_NVLIST, NULL, val));
1898 }
1899 
1900 int
1901 nvpair_value_boolean_array(nvpair_t *nvp, boolean_t **val, uint_t *nelem)
1902 {
1903 	return (nvpair_value_common(nvp, DATA_TYPE_BOOLEAN_ARRAY, nelem, val));
1904 }
1905 
1906 int
1907 nvpair_value_byte_array(nvpair_t *nvp, uchar_t **val, uint_t *nelem)
1908 {
1909 	return (nvpair_value_common(nvp, DATA_TYPE_BYTE_ARRAY, nelem, val));
1910 }
1911 
1912 int
1913 nvpair_value_int8_array(nvpair_t *nvp, int8_t **val, uint_t *nelem)
1914 {
1915 	return (nvpair_value_common(nvp, DATA_TYPE_INT8_ARRAY, nelem, val));
1916 }
1917 
1918 int
1919 nvpair_value_uint8_array(nvpair_t *nvp, uint8_t **val, uint_t *nelem)
1920 {
1921 	return (nvpair_value_common(nvp, DATA_TYPE_UINT8_ARRAY, nelem, val));
1922 }
1923 
1924 int
1925 nvpair_value_int16_array(nvpair_t *nvp, int16_t **val, uint_t *nelem)
1926 {
1927 	return (nvpair_value_common(nvp, DATA_TYPE_INT16_ARRAY, nelem, val));
1928 }
1929 
1930 int
1931 nvpair_value_uint16_array(nvpair_t *nvp, uint16_t **val, uint_t *nelem)
1932 {
1933 	return (nvpair_value_common(nvp, DATA_TYPE_UINT16_ARRAY, nelem, val));
1934 }
1935 
1936 int
1937 nvpair_value_int32_array(nvpair_t *nvp, int32_t **val, uint_t *nelem)
1938 {
1939 	return (nvpair_value_common(nvp, DATA_TYPE_INT32_ARRAY, nelem, val));
1940 }
1941 
1942 int
1943 nvpair_value_uint32_array(nvpair_t *nvp, uint32_t **val, uint_t *nelem)
1944 {
1945 	return (nvpair_value_common(nvp, DATA_TYPE_UINT32_ARRAY, nelem, val));
1946 }
1947 
1948 int
1949 nvpair_value_int64_array(nvpair_t *nvp, int64_t **val, uint_t *nelem)
1950 {
1951 	return (nvpair_value_common(nvp, DATA_TYPE_INT64_ARRAY, nelem, val));
1952 }
1953 
1954 int
1955 nvpair_value_uint64_array(nvpair_t *nvp, uint64_t **val, uint_t *nelem)
1956 {
1957 	return (nvpair_value_common(nvp, DATA_TYPE_UINT64_ARRAY, nelem, val));
1958 }
1959 
1960 int
1961 nvpair_value_string_array(nvpair_t *nvp, char ***val, uint_t *nelem)
1962 {
1963 	return (nvpair_value_common(nvp, DATA_TYPE_STRING_ARRAY, nelem, val));
1964 }
1965 
1966 int
1967 nvpair_value_nvlist_array(nvpair_t *nvp, nvlist_t ***val, uint_t *nelem)
1968 {
1969 	return (nvpair_value_common(nvp, DATA_TYPE_NVLIST_ARRAY, nelem, val));
1970 }
1971 
1972 int
1973 nvpair_value_hrtime(nvpair_t *nvp, hrtime_t *val)
1974 {
1975 	return (nvpair_value_common(nvp, DATA_TYPE_HRTIME, NULL, val));
1976 }
1977 
1978 /*
1979  * Add specified pair to the list.
1980  */
1981 int
1982 nvlist_add_nvpair(nvlist_t *nvl, nvpair_t *nvp)
1983 {
1984 	if (nvl == NULL || nvp == NULL)
1985 		return (EINVAL);
1986 
1987 	return (nvlist_add_common(nvl, NVP_NAME(nvp), NVP_TYPE(nvp),
1988 	    NVP_NELEM(nvp), NVP_VALUE(nvp)));
1989 }
1990 
1991 /*
1992  * Merge the supplied nvlists and put the result in dst.
1993  * The merged list will contain all names specified in both lists,
1994  * the values are taken from nvl in the case of duplicates.
1995  * Return 0 on success.
1996  */
1997 /*ARGSUSED*/
1998 int
1999 nvlist_merge(nvlist_t *dst, nvlist_t *nvl, int flag)
2000 {
2001 	if (nvl == NULL || dst == NULL)
2002 		return (EINVAL);
2003 
2004 	if (dst != nvl)
2005 		return (nvlist_copy_pairs(nvl, dst));
2006 
2007 	return (0);
2008 }
2009 
2010 /*
2011  * Encoding related routines
2012  */
2013 #define	NVS_OP_ENCODE	0
2014 #define	NVS_OP_DECODE	1
2015 #define	NVS_OP_GETSIZE	2
2016 
2017 typedef struct nvs_ops nvs_ops_t;
2018 
2019 typedef struct {
2020 	int		nvs_op;
2021 	const nvs_ops_t	*nvs_ops;
2022 	void		*nvs_private;
2023 	nvpriv_t	*nvs_priv;
2024 	int		nvs_recursion;
2025 } nvstream_t;
2026 
2027 /*
2028  * nvs operations are:
2029  *   - nvs_nvlist
2030  *     encoding / decoding of a nvlist header (nvlist_t)
2031  *     calculates the size used for header and end detection
2032  *
2033  *   - nvs_nvpair
2034  *     responsible for the first part of encoding / decoding of an nvpair
2035  *     calculates the decoded size of an nvpair
2036  *
2037  *   - nvs_nvp_op
2038  *     second part of encoding / decoding of an nvpair
2039  *
2040  *   - nvs_nvp_size
2041  *     calculates the encoding size of an nvpair
2042  *
2043  *   - nvs_nvl_fini
2044  *     encodes the end detection mark (zeros).
2045  */
2046 struct nvs_ops {
2047 	int (*nvs_nvlist)(nvstream_t *, nvlist_t *, size_t *);
2048 	int (*nvs_nvpair)(nvstream_t *, nvpair_t *, size_t *);
2049 	int (*nvs_nvp_op)(nvstream_t *, nvpair_t *);
2050 	int (*nvs_nvp_size)(nvstream_t *, nvpair_t *, size_t *);
2051 	int (*nvs_nvl_fini)(nvstream_t *);
2052 };
2053 
2054 typedef struct {
2055 	char	nvh_encoding;	/* nvs encoding method */
2056 	char	nvh_endian;	/* nvs endian */
2057 	char	nvh_reserved1;	/* reserved for future use */
2058 	char	nvh_reserved2;	/* reserved for future use */
2059 } nvs_header_t;
2060 
2061 static int
2062 nvs_encode_pairs(nvstream_t *nvs, nvlist_t *nvl)
2063 {
2064 	nvpriv_t *priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv;
2065 	i_nvp_t *curr;
2066 
2067 	/*
2068 	 * Walk nvpair in list and encode each nvpair
2069 	 */
2070 	for (curr = priv->nvp_list; curr != NULL; curr = curr->nvi_next)
2071 		if (nvs->nvs_ops->nvs_nvpair(nvs, &curr->nvi_nvp, NULL) != 0)
2072 			return (EFAULT);
2073 
2074 	return (nvs->nvs_ops->nvs_nvl_fini(nvs));
2075 }
2076 
2077 static int
2078 nvs_decode_pairs(nvstream_t *nvs, nvlist_t *nvl)
2079 {
2080 	nvpair_t *nvp;
2081 	size_t nvsize;
2082 	int err;
2083 
2084 	/*
2085 	 * Get decoded size of next pair in stream, alloc
2086 	 * memory for nvpair_t, then decode the nvpair
2087 	 */
2088 	while ((err = nvs->nvs_ops->nvs_nvpair(nvs, NULL, &nvsize)) == 0) {
2089 		if (nvsize == 0) /* end of list */
2090 			break;
2091 
2092 		/* make sure len makes sense */
2093 		if (nvsize < NVP_SIZE_CALC(1, 0))
2094 			return (EFAULT);
2095 
2096 		if ((nvp = nvp_buf_alloc(nvl, nvsize)) == NULL)
2097 			return (ENOMEM);
2098 
2099 		if ((err = nvs->nvs_ops->nvs_nvp_op(nvs, nvp)) != 0) {
2100 			nvp_buf_free(nvl, nvp);
2101 			return (err);
2102 		}
2103 
2104 		if (i_validate_nvpair(nvp) != 0) {
2105 			nvpair_free(nvp);
2106 			nvp_buf_free(nvl, nvp);
2107 			return (EFAULT);
2108 		}
2109 
2110 		nvp_buf_link(nvl, nvp);
2111 	}
2112 	return (err);
2113 }
2114 
2115 static int
2116 nvs_getsize_pairs(nvstream_t *nvs, nvlist_t *nvl, size_t *buflen)
2117 {
2118 	nvpriv_t *priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv;
2119 	i_nvp_t *curr;
2120 	uint64_t nvsize = *buflen;
2121 	size_t size;
2122 
2123 	/*
2124 	 * Get encoded size of nvpairs in nvlist
2125 	 */
2126 	for (curr = priv->nvp_list; curr != NULL; curr = curr->nvi_next) {
2127 		if (nvs->nvs_ops->nvs_nvp_size(nvs, &curr->nvi_nvp, &size) != 0)
2128 			return (EINVAL);
2129 
2130 		if ((nvsize += size) > INT32_MAX)
2131 			return (EINVAL);
2132 	}
2133 
2134 	*buflen = nvsize;
2135 	return (0);
2136 }
2137 
2138 static int
2139 nvs_operation(nvstream_t *nvs, nvlist_t *nvl, size_t *buflen)
2140 {
2141 	int err;
2142 
2143 	if (nvl->nvl_priv == 0)
2144 		return (EFAULT);
2145 
2146 	/*
2147 	 * Perform the operation, starting with header, then each nvpair
2148 	 */
2149 	if ((err = nvs->nvs_ops->nvs_nvlist(nvs, nvl, buflen)) != 0)
2150 		return (err);
2151 
2152 	switch (nvs->nvs_op) {
2153 	case NVS_OP_ENCODE:
2154 		err = nvs_encode_pairs(nvs, nvl);
2155 		break;
2156 
2157 	case NVS_OP_DECODE:
2158 		err = nvs_decode_pairs(nvs, nvl);
2159 		break;
2160 
2161 	case NVS_OP_GETSIZE:
2162 		err = nvs_getsize_pairs(nvs, nvl, buflen);
2163 		break;
2164 
2165 	default:
2166 		err = EINVAL;
2167 	}
2168 
2169 	return (err);
2170 }
2171 
2172 static int
2173 nvs_embedded(nvstream_t *nvs, nvlist_t *embedded)
2174 {
2175 	switch (nvs->nvs_op) {
2176 	case NVS_OP_ENCODE: {
2177 		int err;
2178 
2179 		if (nvs->nvs_recursion >= nvpair_max_recursion)
2180 			return (EINVAL);
2181 		nvs->nvs_recursion++;
2182 		err = nvs_operation(nvs, embedded, NULL);
2183 		nvs->nvs_recursion--;
2184 		return (err);
2185 	}
2186 	case NVS_OP_DECODE: {
2187 		nvpriv_t *priv;
2188 		int err;
2189 
2190 		if (embedded->nvl_version != NV_VERSION)
2191 			return (ENOTSUP);
2192 
2193 		if ((priv = nv_priv_alloc_embedded(nvs->nvs_priv)) == NULL)
2194 			return (ENOMEM);
2195 
2196 		nvlist_init(embedded, embedded->nvl_nvflag, priv);
2197 
2198 		if (nvs->nvs_recursion >= nvpair_max_recursion)
2199 			return (EINVAL);
2200 		nvs->nvs_recursion++;
2201 		if ((err = nvs_operation(nvs, embedded, NULL)) != 0)
2202 			nvlist_free(embedded);
2203 		nvs->nvs_recursion--;
2204 		return (err);
2205 	}
2206 	default:
2207 		break;
2208 	}
2209 
2210 	return (EINVAL);
2211 }
2212 
2213 static int
2214 nvs_embedded_nvl_array(nvstream_t *nvs, nvpair_t *nvp, size_t *size)
2215 {
2216 	size_t nelem = NVP_NELEM(nvp);
2217 	nvlist_t **nvlp = EMBEDDED_NVL_ARRAY(nvp);
2218 	int i;
2219 
2220 	switch (nvs->nvs_op) {
2221 	case NVS_OP_ENCODE:
2222 		for (i = 0; i < nelem; i++)
2223 			if (nvs_embedded(nvs, nvlp[i]) != 0)
2224 				return (EFAULT);
2225 		break;
2226 
2227 	case NVS_OP_DECODE: {
2228 		size_t len = nelem * sizeof (uint64_t);
2229 		nvlist_t *embedded = (nvlist_t *)((uintptr_t)nvlp + len);
2230 
2231 		bzero(nvlp, len);	/* don't trust packed data */
2232 		for (i = 0; i < nelem; i++) {
2233 			if (nvs_embedded(nvs, embedded) != 0) {
2234 				nvpair_free(nvp);
2235 				return (EFAULT);
2236 			}
2237 
2238 			nvlp[i] = embedded++;
2239 		}
2240 		break;
2241 	}
2242 	case NVS_OP_GETSIZE: {
2243 		uint64_t nvsize = 0;
2244 
2245 		for (i = 0; i < nelem; i++) {
2246 			size_t nvp_sz = 0;
2247 
2248 			if (nvs_operation(nvs, nvlp[i], &nvp_sz) != 0)
2249 				return (EINVAL);
2250 
2251 			if ((nvsize += nvp_sz) > INT32_MAX)
2252 				return (EINVAL);
2253 		}
2254 
2255 		*size = nvsize;
2256 		break;
2257 	}
2258 	default:
2259 		return (EINVAL);
2260 	}
2261 
2262 	return (0);
2263 }
2264 
2265 static int nvs_native(nvstream_t *, nvlist_t *, char *, size_t *);
2266 static int nvs_xdr(nvstream_t *, nvlist_t *, char *, size_t *);
2267 
2268 /*
2269  * Common routine for nvlist operations:
2270  * encode, decode, getsize (encoded size).
2271  */
2272 static int
2273 nvlist_common(nvlist_t *nvl, char *buf, size_t *buflen, int encoding,
2274     int nvs_op)
2275 {
2276 	int err = 0;
2277 	nvstream_t nvs;
2278 	int nvl_endian;
2279 #ifdef	_LITTLE_ENDIAN
2280 	int host_endian = 1;
2281 #else
2282 	int host_endian = 0;
2283 #endif	/* _LITTLE_ENDIAN */
2284 	nvs_header_t *nvh = (void *)buf;
2285 
2286 	if (buflen == NULL || nvl == NULL ||
2287 	    (nvs.nvs_priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL)
2288 		return (EINVAL);
2289 
2290 	nvs.nvs_op = nvs_op;
2291 	nvs.nvs_recursion = 0;
2292 
2293 	/*
2294 	 * For NVS_OP_ENCODE and NVS_OP_DECODE make sure an nvlist and
2295 	 * a buffer is allocated.  The first 4 bytes in the buffer are
2296 	 * used for encoding method and host endian.
2297 	 */
2298 	switch (nvs_op) {
2299 	case NVS_OP_ENCODE:
2300 		if (buf == NULL || *buflen < sizeof (nvs_header_t))
2301 			return (EINVAL);
2302 
2303 		nvh->nvh_encoding = encoding;
2304 		nvh->nvh_endian = nvl_endian = host_endian;
2305 		nvh->nvh_reserved1 = 0;
2306 		nvh->nvh_reserved2 = 0;
2307 		break;
2308 
2309 	case NVS_OP_DECODE:
2310 		if (buf == NULL || *buflen < sizeof (nvs_header_t))
2311 			return (EINVAL);
2312 
2313 		/* get method of encoding from first byte */
2314 		encoding = nvh->nvh_encoding;
2315 		nvl_endian = nvh->nvh_endian;
2316 		break;
2317 
2318 	case NVS_OP_GETSIZE:
2319 		nvl_endian = host_endian;
2320 
2321 		/*
2322 		 * add the size for encoding
2323 		 */
2324 		*buflen = sizeof (nvs_header_t);
2325 		break;
2326 
2327 	default:
2328 		return (ENOTSUP);
2329 	}
2330 
2331 	/*
2332 	 * Create an nvstream with proper encoding method
2333 	 */
2334 	switch (encoding) {
2335 	case NV_ENCODE_NATIVE:
2336 		/*
2337 		 * check endianness, in case we are unpacking
2338 		 * from a file
2339 		 */
2340 		if (nvl_endian != host_endian)
2341 			return (ENOTSUP);
2342 		err = nvs_native(&nvs, nvl, buf, buflen);
2343 		break;
2344 	case NV_ENCODE_XDR:
2345 		err = nvs_xdr(&nvs, nvl, buf, buflen);
2346 		break;
2347 	default:
2348 		err = ENOTSUP;
2349 		break;
2350 	}
2351 
2352 	return (err);
2353 }
2354 
2355 int
2356 nvlist_size(nvlist_t *nvl, size_t *size, int encoding)
2357 {
2358 	return (nvlist_common(nvl, NULL, size, encoding, NVS_OP_GETSIZE));
2359 }
2360 
2361 /*
2362  * Pack nvlist into contiguous memory
2363  */
2364 /*ARGSUSED1*/
2365 int
2366 nvlist_pack(nvlist_t *nvl, char **bufp, size_t *buflen, int encoding,
2367     int kmflag)
2368 {
2369 #if defined(_KERNEL) && !defined(_BOOT)
2370 	return (nvlist_xpack(nvl, bufp, buflen, encoding,
2371 	    (kmflag == KM_SLEEP ? nv_alloc_sleep : nv_alloc_nosleep)));
2372 #else
2373 	return (nvlist_xpack(nvl, bufp, buflen, encoding, nv_alloc_nosleep));
2374 #endif
2375 }
2376 
2377 int
2378 nvlist_xpack(nvlist_t *nvl, char **bufp, size_t *buflen, int encoding,
2379     nv_alloc_t *nva)
2380 {
2381 	nvpriv_t nvpriv;
2382 	size_t alloc_size;
2383 	char *buf;
2384 	int err;
2385 
2386 	if (nva == NULL || nvl == NULL || bufp == NULL || buflen == NULL)
2387 		return (EINVAL);
2388 
2389 	if (*bufp != NULL)
2390 		return (nvlist_common(nvl, *bufp, buflen, encoding,
2391 		    NVS_OP_ENCODE));
2392 
2393 	/*
2394 	 * Here is a difficult situation:
2395 	 * 1. The nvlist has fixed allocator properties.
2396 	 *    All other nvlist routines (like nvlist_add_*, ...) use
2397 	 *    these properties.
2398 	 * 2. When using nvlist_pack() the user can specify their own
2399 	 *    allocator properties (e.g. by using KM_NOSLEEP).
2400 	 *
2401 	 * We use the user specified properties (2). A clearer solution
2402 	 * will be to remove the kmflag from nvlist_pack(), but we will
2403 	 * not change the interface.
2404 	 */
2405 	nv_priv_init(&nvpriv, nva, 0);
2406 
2407 	if ((err = nvlist_size(nvl, &alloc_size, encoding)))
2408 		return (err);
2409 
2410 	if ((buf = nv_mem_zalloc(&nvpriv, alloc_size)) == NULL)
2411 		return (ENOMEM);
2412 
2413 	if ((err = nvlist_common(nvl, buf, &alloc_size, encoding,
2414 	    NVS_OP_ENCODE)) != 0) {
2415 		nv_mem_free(&nvpriv, buf, alloc_size);
2416 	} else {
2417 		*buflen = alloc_size;
2418 		*bufp = buf;
2419 	}
2420 
2421 	return (err);
2422 }
2423 
2424 /*
2425  * Unpack buf into an nvlist_t
2426  */
2427 /*ARGSUSED1*/
2428 int
2429 nvlist_unpack(char *buf, size_t buflen, nvlist_t **nvlp, int kmflag)
2430 {
2431 #if defined(_KERNEL) && !defined(_BOOT)
2432 	return (nvlist_xunpack(buf, buflen, nvlp,
2433 	    (kmflag == KM_SLEEP ? nv_alloc_sleep : nv_alloc_nosleep)));
2434 #else
2435 	return (nvlist_xunpack(buf, buflen, nvlp, nv_alloc_nosleep));
2436 #endif
2437 }
2438 
2439 int
2440 nvlist_xunpack(char *buf, size_t buflen, nvlist_t **nvlp, nv_alloc_t *nva)
2441 {
2442 	nvlist_t *nvl;
2443 	int err;
2444 
2445 	if (nvlp == NULL)
2446 		return (EINVAL);
2447 
2448 	if ((err = nvlist_xalloc(&nvl, 0, nva)) != 0)
2449 		return (err);
2450 
2451 	if ((err = nvlist_common(nvl, buf, &buflen, 0, NVS_OP_DECODE)) != 0)
2452 		nvlist_free(nvl);
2453 	else
2454 		*nvlp = nvl;
2455 
2456 	return (err);
2457 }
2458 
2459 /*
2460  * Native encoding functions
2461  */
2462 typedef struct {
2463 	/*
2464 	 * This structure is used when decoding a packed nvpair in
2465 	 * the native format.  n_base points to a buffer containing the
2466 	 * packed nvpair.  n_end is a pointer to the end of the buffer.
2467 	 * (n_end actually points to the first byte past the end of the
2468 	 * buffer.)  n_curr is a pointer that lies between n_base and n_end.
2469 	 * It points to the current data that we are decoding.
2470 	 * The amount of data left in the buffer is equal to n_end - n_curr.
2471 	 * n_flag is used to recognize a packed embedded list.
2472 	 */
2473 	caddr_t n_base;
2474 	caddr_t n_end;
2475 	caddr_t n_curr;
2476 	uint_t  n_flag;
2477 } nvs_native_t;
2478 
2479 static int
2480 nvs_native_create(nvstream_t *nvs, nvs_native_t *native, char *buf,
2481     size_t buflen)
2482 {
2483 	switch (nvs->nvs_op) {
2484 	case NVS_OP_ENCODE:
2485 	case NVS_OP_DECODE:
2486 		nvs->nvs_private = native;
2487 		native->n_curr = native->n_base = buf;
2488 		native->n_end = buf + buflen;
2489 		native->n_flag = 0;
2490 		return (0);
2491 
2492 	case NVS_OP_GETSIZE:
2493 		nvs->nvs_private = native;
2494 		native->n_curr = native->n_base = native->n_end = NULL;
2495 		native->n_flag = 0;
2496 		return (0);
2497 	default:
2498 		return (EINVAL);
2499 	}
2500 }
2501 
2502 /*ARGSUSED*/
2503 static void
2504 nvs_native_destroy(nvstream_t *nvs)
2505 {
2506 }
2507 
2508 static int
2509 native_cp(nvstream_t *nvs, void *buf, size_t size)
2510 {
2511 	nvs_native_t *native = (nvs_native_t *)nvs->nvs_private;
2512 
2513 	if (native->n_curr + size > native->n_end)
2514 		return (EFAULT);
2515 
2516 	/*
2517 	 * The bcopy() below eliminates alignment requirement
2518 	 * on the buffer (stream) and is preferred over direct access.
2519 	 */
2520 	switch (nvs->nvs_op) {
2521 	case NVS_OP_ENCODE:
2522 		bcopy(buf, native->n_curr, size);
2523 		break;
2524 	case NVS_OP_DECODE:
2525 		bcopy(native->n_curr, buf, size);
2526 		break;
2527 	default:
2528 		return (EINVAL);
2529 	}
2530 
2531 	native->n_curr += size;
2532 	return (0);
2533 }
2534 
2535 /*
2536  * operate on nvlist_t header
2537  */
2538 static int
2539 nvs_native_nvlist(nvstream_t *nvs, nvlist_t *nvl, size_t *size)
2540 {
2541 	nvs_native_t *native = nvs->nvs_private;
2542 
2543 	switch (nvs->nvs_op) {
2544 	case NVS_OP_ENCODE:
2545 	case NVS_OP_DECODE:
2546 		if (native->n_flag)
2547 			return (0);	/* packed embedded list */
2548 
2549 		native->n_flag = 1;
2550 
2551 		/* copy version and nvflag of the nvlist_t */
2552 		if (native_cp(nvs, &nvl->nvl_version, sizeof (int32_t)) != 0 ||
2553 		    native_cp(nvs, &nvl->nvl_nvflag, sizeof (int32_t)) != 0)
2554 			return (EFAULT);
2555 
2556 		return (0);
2557 
2558 	case NVS_OP_GETSIZE:
2559 		/*
2560 		 * if calculate for packed embedded list
2561 		 * 	4 for end of the embedded list
2562 		 * else
2563 		 * 	2 * sizeof (int32_t) for nvl_version and nvl_nvflag
2564 		 * 	and 4 for end of the entire list
2565 		 */
2566 		if (native->n_flag) {
2567 			*size += 4;
2568 		} else {
2569 			native->n_flag = 1;
2570 			*size += 2 * sizeof (int32_t) + 4;
2571 		}
2572 
2573 		return (0);
2574 
2575 	default:
2576 		return (EINVAL);
2577 	}
2578 }
2579 
2580 static int
2581 nvs_native_nvl_fini(nvstream_t *nvs)
2582 {
2583 	if (nvs->nvs_op == NVS_OP_ENCODE) {
2584 		nvs_native_t *native = (nvs_native_t *)nvs->nvs_private;
2585 		/*
2586 		 * Add 4 zero bytes at end of nvlist. They are used
2587 		 * for end detection by the decode routine.
2588 		 */
2589 		if (native->n_curr + sizeof (int) > native->n_end)
2590 			return (EFAULT);
2591 
2592 		bzero(native->n_curr, sizeof (int));
2593 		native->n_curr += sizeof (int);
2594 	}
2595 
2596 	return (0);
2597 }
2598 
2599 static int
2600 nvpair_native_embedded(nvstream_t *nvs, nvpair_t *nvp)
2601 {
2602 	if (nvs->nvs_op == NVS_OP_ENCODE) {
2603 		nvs_native_t *native = (nvs_native_t *)nvs->nvs_private;
2604 		nvlist_t *packed = (void *)
2605 		    (native->n_curr - nvp->nvp_size + NVP_VALOFF(nvp));
2606 		/*
2607 		 * Null out the pointer that is meaningless in the packed
2608 		 * structure. The address may not be aligned, so we have
2609 		 * to use bzero.
2610 		 */
2611 		bzero(&packed->nvl_priv, sizeof (packed->nvl_priv));
2612 	}
2613 
2614 	return (nvs_embedded(nvs, EMBEDDED_NVL(nvp)));
2615 }
2616 
2617 static int
2618 nvpair_native_embedded_array(nvstream_t *nvs, nvpair_t *nvp)
2619 {
2620 	if (nvs->nvs_op == NVS_OP_ENCODE) {
2621 		nvs_native_t *native = (nvs_native_t *)nvs->nvs_private;
2622 		char *value = native->n_curr - nvp->nvp_size + NVP_VALOFF(nvp);
2623 		size_t len = NVP_NELEM(nvp) * sizeof (uint64_t);
2624 		nvlist_t *packed = (nvlist_t *)((uintptr_t)value + len);
2625 		int i;
2626 		/*
2627 		 * Null out pointers that are meaningless in the packed
2628 		 * structure. The addresses may not be aligned, so we have
2629 		 * to use bzero.
2630 		 */
2631 		bzero(value, len);
2632 
2633 		for (i = 0; i < NVP_NELEM(nvp); i++, packed++)
2634 			/*
2635 			 * Null out the pointer that is meaningless in the
2636 			 * packed structure. The address may not be aligned,
2637 			 * so we have to use bzero.
2638 			 */
2639 			bzero(&packed->nvl_priv, sizeof (packed->nvl_priv));
2640 	}
2641 
2642 	return (nvs_embedded_nvl_array(nvs, nvp, NULL));
2643 }
2644 
2645 static void
2646 nvpair_native_string_array(nvstream_t *nvs, nvpair_t *nvp)
2647 {
2648 	switch (nvs->nvs_op) {
2649 	case NVS_OP_ENCODE: {
2650 		nvs_native_t *native = (nvs_native_t *)nvs->nvs_private;
2651 		uint64_t *strp = (void *)
2652 		    (native->n_curr - nvp->nvp_size + NVP_VALOFF(nvp));
2653 		/*
2654 		 * Null out pointers that are meaningless in the packed
2655 		 * structure. The addresses may not be aligned, so we have
2656 		 * to use bzero.
2657 		 */
2658 		bzero(strp, NVP_NELEM(nvp) * sizeof (uint64_t));
2659 		break;
2660 	}
2661 	case NVS_OP_DECODE: {
2662 		char **strp = (void *)NVP_VALUE(nvp);
2663 		char *buf = ((char *)strp + NVP_NELEM(nvp) * sizeof (uint64_t));
2664 		int i;
2665 
2666 		for (i = 0; i < NVP_NELEM(nvp); i++) {
2667 			strp[i] = buf;
2668 			buf += strlen(buf) + 1;
2669 		}
2670 		break;
2671 	}
2672 	}
2673 }
2674 
2675 static int
2676 nvs_native_nvp_op(nvstream_t *nvs, nvpair_t *nvp)
2677 {
2678 	data_type_t type;
2679 	int value_sz;
2680 	int ret = 0;
2681 
2682 	/*
2683 	 * We do the initial bcopy of the data before we look at
2684 	 * the nvpair type, because when we're decoding, we won't
2685 	 * have the correct values for the pair until we do the bcopy.
2686 	 */
2687 	switch (nvs->nvs_op) {
2688 	case NVS_OP_ENCODE:
2689 	case NVS_OP_DECODE:
2690 		if (native_cp(nvs, nvp, nvp->nvp_size) != 0)
2691 			return (EFAULT);
2692 		break;
2693 	default:
2694 		return (EINVAL);
2695 	}
2696 
2697 	/* verify nvp_name_sz, check the name string length */
2698 	if (i_validate_nvpair_name(nvp) != 0)
2699 		return (EFAULT);
2700 
2701 	type = NVP_TYPE(nvp);
2702 
2703 	/*
2704 	 * Verify type and nelem and get the value size.
2705 	 * In case of data types DATA_TYPE_STRING and DATA_TYPE_STRING_ARRAY
2706 	 * is the size of the string(s) excluded.
2707 	 */
2708 	if ((value_sz = i_get_value_size(type, NULL, NVP_NELEM(nvp))) < 0)
2709 		return (EFAULT);
2710 
2711 	if (NVP_SIZE_CALC(nvp->nvp_name_sz, value_sz) > nvp->nvp_size)
2712 		return (EFAULT);
2713 
2714 	switch (type) {
2715 	case DATA_TYPE_NVLIST:
2716 		ret = nvpair_native_embedded(nvs, nvp);
2717 		break;
2718 	case DATA_TYPE_NVLIST_ARRAY:
2719 		ret = nvpair_native_embedded_array(nvs, nvp);
2720 		break;
2721 	case DATA_TYPE_STRING_ARRAY:
2722 		nvpair_native_string_array(nvs, nvp);
2723 		break;
2724 	default:
2725 		break;
2726 	}
2727 
2728 	return (ret);
2729 }
2730 
2731 static int
2732 nvs_native_nvp_size(nvstream_t *nvs, nvpair_t *nvp, size_t *size)
2733 {
2734 	uint64_t nvp_sz = nvp->nvp_size;
2735 
2736 	switch (NVP_TYPE(nvp)) {
2737 	case DATA_TYPE_NVLIST: {
2738 		size_t nvsize = 0;
2739 
2740 		if (nvs_operation(nvs, EMBEDDED_NVL(nvp), &nvsize) != 0)
2741 			return (EINVAL);
2742 
2743 		nvp_sz += nvsize;
2744 		break;
2745 	}
2746 	case DATA_TYPE_NVLIST_ARRAY: {
2747 		size_t nvsize;
2748 
2749 		if (nvs_embedded_nvl_array(nvs, nvp, &nvsize) != 0)
2750 			return (EINVAL);
2751 
2752 		nvp_sz += nvsize;
2753 		break;
2754 	}
2755 	default:
2756 		break;
2757 	}
2758 
2759 	if (nvp_sz > INT32_MAX)
2760 		return (EINVAL);
2761 
2762 	*size = nvp_sz;
2763 
2764 	return (0);
2765 }
2766 
2767 static int
2768 nvs_native_nvpair(nvstream_t *nvs, nvpair_t *nvp, size_t *size)
2769 {
2770 	switch (nvs->nvs_op) {
2771 	case NVS_OP_ENCODE:
2772 		return (nvs_native_nvp_op(nvs, nvp));
2773 
2774 	case NVS_OP_DECODE: {
2775 		nvs_native_t *native = (nvs_native_t *)nvs->nvs_private;
2776 		int32_t decode_len;
2777 
2778 		/* try to read the size value from the stream */
2779 		if (native->n_curr + sizeof (int32_t) > native->n_end)
2780 			return (EFAULT);
2781 		bcopy(native->n_curr, &decode_len, sizeof (int32_t));
2782 
2783 		/* sanity check the size value */
2784 		if (decode_len < 0 ||
2785 		    decode_len > native->n_end - native->n_curr)
2786 			return (EFAULT);
2787 
2788 		*size = decode_len;
2789 
2790 		/*
2791 		 * If at the end of the stream then move the cursor
2792 		 * forward, otherwise nvpair_native_op() will read
2793 		 * the entire nvpair at the same cursor position.
2794 		 */
2795 		if (*size == 0)
2796 			native->n_curr += sizeof (int32_t);
2797 		break;
2798 	}
2799 
2800 	default:
2801 		return (EINVAL);
2802 	}
2803 
2804 	return (0);
2805 }
2806 
2807 static const nvs_ops_t nvs_native_ops = {
2808 	nvs_native_nvlist,
2809 	nvs_native_nvpair,
2810 	nvs_native_nvp_op,
2811 	nvs_native_nvp_size,
2812 	nvs_native_nvl_fini
2813 };
2814 
2815 static int
2816 nvs_native(nvstream_t *nvs, nvlist_t *nvl, char *buf, size_t *buflen)
2817 {
2818 	nvs_native_t native;
2819 	int err;
2820 
2821 	nvs->nvs_ops = &nvs_native_ops;
2822 
2823 	if ((err = nvs_native_create(nvs, &native, buf + sizeof (nvs_header_t),
2824 	    *buflen - sizeof (nvs_header_t))) != 0)
2825 		return (err);
2826 
2827 	err = nvs_operation(nvs, nvl, buflen);
2828 
2829 	nvs_native_destroy(nvs);
2830 
2831 	return (err);
2832 }
2833 
2834 /*
2835  * XDR encoding functions
2836  *
2837  * An xdr packed nvlist is encoded as:
2838  *
2839  *  - encoding methode and host endian (4 bytes)
2840  *  - nvl_version (4 bytes)
2841  *  - nvl_nvflag (4 bytes)
2842  *
2843  *  - encoded nvpairs, the format of one xdr encoded nvpair is:
2844  *	- encoded size of the nvpair (4 bytes)
2845  *	- decoded size of the nvpair (4 bytes)
2846  *	- name string, (4 + sizeof(NV_ALIGN4(string))
2847  *	  a string is coded as size (4 bytes) and data
2848  *	- data type (4 bytes)
2849  *	- number of elements in the nvpair (4 bytes)
2850  *	- data
2851  *
2852  *  - 2 zero's for end of the entire list (8 bytes)
2853  */
2854 static int
2855 nvs_xdr_create(nvstream_t *nvs, XDR *xdr, char *buf, size_t buflen)
2856 {
2857 	/* xdr data must be 4 byte aligned */
2858 	if ((ulong_t)buf % 4 != 0)
2859 		return (EFAULT);
2860 
2861 	switch (nvs->nvs_op) {
2862 	case NVS_OP_ENCODE:
2863 		xdrmem_create(xdr, buf, (uint_t)buflen, XDR_ENCODE);
2864 		nvs->nvs_private = xdr;
2865 		return (0);
2866 	case NVS_OP_DECODE:
2867 		xdrmem_create(xdr, buf, (uint_t)buflen, XDR_DECODE);
2868 		nvs->nvs_private = xdr;
2869 		return (0);
2870 	case NVS_OP_GETSIZE:
2871 		nvs->nvs_private = NULL;
2872 		return (0);
2873 	default:
2874 		return (EINVAL);
2875 	}
2876 }
2877 
2878 static void
2879 nvs_xdr_destroy(nvstream_t *nvs)
2880 {
2881 	switch (nvs->nvs_op) {
2882 	case NVS_OP_ENCODE:
2883 	case NVS_OP_DECODE:
2884 		xdr_destroy((XDR *)nvs->nvs_private);
2885 		break;
2886 	default:
2887 		break;
2888 	}
2889 }
2890 
2891 static int
2892 nvs_xdr_nvlist(nvstream_t *nvs, nvlist_t *nvl, size_t *size)
2893 {
2894 	switch (nvs->nvs_op) {
2895 	case NVS_OP_ENCODE:
2896 	case NVS_OP_DECODE: {
2897 		XDR 	*xdr = nvs->nvs_private;
2898 
2899 		if (!xdr_int(xdr, &nvl->nvl_version) ||
2900 		    !xdr_u_int(xdr, &nvl->nvl_nvflag))
2901 			return (EFAULT);
2902 		break;
2903 	}
2904 	case NVS_OP_GETSIZE: {
2905 		/*
2906 		 * 2 * 4 for nvl_version + nvl_nvflag
2907 		 * and 8 for end of the entire list
2908 		 */
2909 		*size += 2 * 4 + 8;
2910 		break;
2911 	}
2912 	default:
2913 		return (EINVAL);
2914 	}
2915 	return (0);
2916 }
2917 
2918 static int
2919 nvs_xdr_nvl_fini(nvstream_t *nvs)
2920 {
2921 	if (nvs->nvs_op == NVS_OP_ENCODE) {
2922 		XDR *xdr = nvs->nvs_private;
2923 		int zero = 0;
2924 
2925 		if (!xdr_int(xdr, &zero) || !xdr_int(xdr, &zero))
2926 			return (EFAULT);
2927 	}
2928 
2929 	return (0);
2930 }
2931 
2932 /*
2933  * The format of xdr encoded nvpair is:
2934  * encode_size, decode_size, name string, data type, nelem, data
2935  */
2936 static int
2937 nvs_xdr_nvp_op(nvstream_t *nvs, nvpair_t *nvp)
2938 {
2939 	data_type_t type;
2940 	char	*buf;
2941 	char	*buf_end = (char *)nvp + nvp->nvp_size;
2942 	int	value_sz;
2943 	uint_t	nelem, buflen;
2944 	bool_t	ret = FALSE;
2945 	XDR	*xdr = nvs->nvs_private;
2946 
2947 	ASSERT(xdr != NULL && nvp != NULL);
2948 
2949 	/* name string */
2950 	if ((buf = NVP_NAME(nvp)) >= buf_end)
2951 		return (EFAULT);
2952 	buflen = buf_end - buf;
2953 
2954 	if (!xdr_string(xdr, &buf, buflen - 1))
2955 		return (EFAULT);
2956 	nvp->nvp_name_sz = strlen(buf) + 1;
2957 
2958 	/* type and nelem */
2959 	if (!xdr_int(xdr, (int *)&nvp->nvp_type) ||
2960 	    !xdr_int(xdr, &nvp->nvp_value_elem))
2961 		return (EFAULT);
2962 
2963 	type = NVP_TYPE(nvp);
2964 	nelem = nvp->nvp_value_elem;
2965 
2966 	/*
2967 	 * Verify type and nelem and get the value size.
2968 	 * In case of data types DATA_TYPE_STRING and DATA_TYPE_STRING_ARRAY
2969 	 * is the size of the string(s) excluded.
2970 	 */
2971 	if ((value_sz = i_get_value_size(type, NULL, nelem)) < 0)
2972 		return (EFAULT);
2973 
2974 	/* if there is no data to extract then return */
2975 	if (nelem == 0)
2976 		return (0);
2977 
2978 	/* value */
2979 	if ((buf = NVP_VALUE(nvp)) >= buf_end)
2980 		return (EFAULT);
2981 	buflen = buf_end - buf;
2982 
2983 	if (buflen < value_sz)
2984 		return (EFAULT);
2985 
2986 	switch (type) {
2987 	case DATA_TYPE_NVLIST:
2988 		if (nvs_embedded(nvs, (void *)buf) == 0)
2989 			return (0);
2990 		break;
2991 
2992 	case DATA_TYPE_NVLIST_ARRAY:
2993 		if (nvs_embedded_nvl_array(nvs, nvp, NULL) == 0)
2994 			return (0);
2995 		break;
2996 
2997 	case DATA_TYPE_BOOLEAN:
2998 		ret = TRUE;
2999 		break;
3000 
3001 	case DATA_TYPE_BYTE:
3002 	case DATA_TYPE_INT8:
3003 	case DATA_TYPE_UINT8:
3004 		ret = xdr_char(xdr, buf);
3005 		break;
3006 
3007 	case DATA_TYPE_INT16:
3008 		ret = xdr_short(xdr, (void *)buf);
3009 		break;
3010 
3011 	case DATA_TYPE_UINT16:
3012 		ret = xdr_u_short(xdr, (void *)buf);
3013 		break;
3014 
3015 	case DATA_TYPE_BOOLEAN_VALUE:
3016 	case DATA_TYPE_INT32:
3017 		ret = xdr_int(xdr, (void *)buf);
3018 		break;
3019 
3020 	case DATA_TYPE_UINT32:
3021 		ret = xdr_u_int(xdr, (void *)buf);
3022 		break;
3023 
3024 	case DATA_TYPE_INT64:
3025 		ret = xdr_longlong_t(xdr, (void *)buf);
3026 		break;
3027 
3028 	case DATA_TYPE_UINT64:
3029 		ret = xdr_u_longlong_t(xdr, (void *)buf);
3030 		break;
3031 
3032 	case DATA_TYPE_HRTIME:
3033 		/*
3034 		 * NOTE: must expose the definition of hrtime_t here
3035 		 */
3036 		ret = xdr_longlong_t(xdr, (void *)buf);
3037 		break;
3038 #if !defined(_KERNEL)
3039 	case DATA_TYPE_DOUBLE:
3040 		ret = xdr_double(xdr, (void *)buf);
3041 		break;
3042 #endif
3043 	case DATA_TYPE_STRING:
3044 		ret = xdr_string(xdr, &buf, buflen - 1);
3045 		break;
3046 
3047 	case DATA_TYPE_BYTE_ARRAY:
3048 		ret = xdr_opaque(xdr, buf, nelem);
3049 		break;
3050 
3051 	case DATA_TYPE_INT8_ARRAY:
3052 	case DATA_TYPE_UINT8_ARRAY:
3053 		ret = xdr_array(xdr, &buf, &nelem, buflen, sizeof (int8_t),
3054 		    (xdrproc_t)xdr_char);
3055 		break;
3056 
3057 	case DATA_TYPE_INT16_ARRAY:
3058 		ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (int16_t),
3059 		    sizeof (int16_t), (xdrproc_t)xdr_short);
3060 		break;
3061 
3062 	case DATA_TYPE_UINT16_ARRAY:
3063 		ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (uint16_t),
3064 		    sizeof (uint16_t), (xdrproc_t)xdr_u_short);
3065 		break;
3066 
3067 	case DATA_TYPE_BOOLEAN_ARRAY:
3068 	case DATA_TYPE_INT32_ARRAY:
3069 		ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (int32_t),
3070 		    sizeof (int32_t), (xdrproc_t)xdr_int);
3071 		break;
3072 
3073 	case DATA_TYPE_UINT32_ARRAY:
3074 		ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (uint32_t),
3075 		    sizeof (uint32_t), (xdrproc_t)xdr_u_int);
3076 		break;
3077 
3078 	case DATA_TYPE_INT64_ARRAY:
3079 		ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (int64_t),
3080 		    sizeof (int64_t), (xdrproc_t)xdr_longlong_t);
3081 		break;
3082 
3083 	case DATA_TYPE_UINT64_ARRAY:
3084 		ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (uint64_t),
3085 		    sizeof (uint64_t), (xdrproc_t)xdr_u_longlong_t);
3086 		break;
3087 
3088 	case DATA_TYPE_STRING_ARRAY: {
3089 		size_t len = nelem * sizeof (uint64_t);
3090 		char **strp = (void *)buf;
3091 		int i;
3092 
3093 		if (nvs->nvs_op == NVS_OP_DECODE)
3094 			bzero(buf, len);	/* don't trust packed data */
3095 
3096 		for (i = 0; i < nelem; i++) {
3097 			if (buflen <= len)
3098 				return (EFAULT);
3099 
3100 			buf += len;
3101 			buflen -= len;
3102 
3103 			if (xdr_string(xdr, &buf, buflen - 1) != TRUE)
3104 				return (EFAULT);
3105 
3106 			if (nvs->nvs_op == NVS_OP_DECODE)
3107 				strp[i] = buf;
3108 			len = strlen(buf) + 1;
3109 		}
3110 		ret = TRUE;
3111 		break;
3112 	}
3113 	default:
3114 		break;
3115 	}
3116 
3117 	return (ret == TRUE ? 0 : EFAULT);
3118 }
3119 
3120 static int
3121 nvs_xdr_nvp_size(nvstream_t *nvs, nvpair_t *nvp, size_t *size)
3122 {
3123 	data_type_t type = NVP_TYPE(nvp);
3124 	/*
3125 	 * encode_size + decode_size + name string size + data type + nelem
3126 	 * where name string size = 4 + NV_ALIGN4(strlen(NVP_NAME(nvp)))
3127 	 */
3128 	uint64_t nvp_sz = 4 + 4 + 4 + NV_ALIGN4(strlen(NVP_NAME(nvp))) + 4 + 4;
3129 
3130 	switch (type) {
3131 	case DATA_TYPE_BOOLEAN:
3132 		break;
3133 
3134 	case DATA_TYPE_BOOLEAN_VALUE:
3135 	case DATA_TYPE_BYTE:
3136 	case DATA_TYPE_INT8:
3137 	case DATA_TYPE_UINT8:
3138 	case DATA_TYPE_INT16:
3139 	case DATA_TYPE_UINT16:
3140 	case DATA_TYPE_INT32:
3141 	case DATA_TYPE_UINT32:
3142 		nvp_sz += 4;	/* 4 is the minimum xdr unit */
3143 		break;
3144 
3145 	case DATA_TYPE_INT64:
3146 	case DATA_TYPE_UINT64:
3147 	case DATA_TYPE_HRTIME:
3148 #if !defined(_KERNEL)
3149 	case DATA_TYPE_DOUBLE:
3150 #endif
3151 		nvp_sz += 8;
3152 		break;
3153 
3154 	case DATA_TYPE_STRING:
3155 		nvp_sz += 4 + NV_ALIGN4(strlen((char *)NVP_VALUE(nvp)));
3156 		break;
3157 
3158 	case DATA_TYPE_BYTE_ARRAY:
3159 		nvp_sz += NV_ALIGN4(NVP_NELEM(nvp));
3160 		break;
3161 
3162 	case DATA_TYPE_BOOLEAN_ARRAY:
3163 	case DATA_TYPE_INT8_ARRAY:
3164 	case DATA_TYPE_UINT8_ARRAY:
3165 	case DATA_TYPE_INT16_ARRAY:
3166 	case DATA_TYPE_UINT16_ARRAY:
3167 	case DATA_TYPE_INT32_ARRAY:
3168 	case DATA_TYPE_UINT32_ARRAY:
3169 		nvp_sz += 4 + 4 * (uint64_t)NVP_NELEM(nvp);
3170 		break;
3171 
3172 	case DATA_TYPE_INT64_ARRAY:
3173 	case DATA_TYPE_UINT64_ARRAY:
3174 		nvp_sz += 4 + 8 * (uint64_t)NVP_NELEM(nvp);
3175 		break;
3176 
3177 	case DATA_TYPE_STRING_ARRAY: {
3178 		int i;
3179 		char **strs = (void *)NVP_VALUE(nvp);
3180 
3181 		for (i = 0; i < NVP_NELEM(nvp); i++)
3182 			nvp_sz += 4 + NV_ALIGN4(strlen(strs[i]));
3183 
3184 		break;
3185 	}
3186 
3187 	case DATA_TYPE_NVLIST:
3188 	case DATA_TYPE_NVLIST_ARRAY: {
3189 		size_t nvsize = 0;
3190 		int old_nvs_op = nvs->nvs_op;
3191 		int err;
3192 
3193 		nvs->nvs_op = NVS_OP_GETSIZE;
3194 		if (type == DATA_TYPE_NVLIST)
3195 			err = nvs_operation(nvs, EMBEDDED_NVL(nvp), &nvsize);
3196 		else
3197 			err = nvs_embedded_nvl_array(nvs, nvp, &nvsize);
3198 		nvs->nvs_op = old_nvs_op;
3199 
3200 		if (err != 0)
3201 			return (EINVAL);
3202 
3203 		nvp_sz += nvsize;
3204 		break;
3205 	}
3206 
3207 	default:
3208 		return (EINVAL);
3209 	}
3210 
3211 	if (nvp_sz > INT32_MAX)
3212 		return (EINVAL);
3213 
3214 	*size = nvp_sz;
3215 
3216 	return (0);
3217 }
3218 
3219 
3220 /*
3221  * The NVS_XDR_MAX_LEN macro takes a packed xdr buffer of size x and estimates
3222  * the largest nvpair that could be encoded in the buffer.
3223  *
3224  * See comments above nvpair_xdr_op() for the format of xdr encoding.
3225  * The size of a xdr packed nvpair without any data is 5 words.
3226  *
3227  * Using the size of the data directly as an estimate would be ok
3228  * in all cases except one.  If the data type is of DATA_TYPE_STRING_ARRAY
3229  * then the actual nvpair has space for an array of pointers to index
3230  * the strings.  These pointers are not encoded into the packed xdr buffer.
3231  *
3232  * If the data is of type DATA_TYPE_STRING_ARRAY and all the strings are
3233  * of length 0, then each string is endcoded in xdr format as a single word.
3234  * Therefore when expanded to an nvpair there will be 2.25 word used for
3235  * each string.  (a int64_t allocated for pointer usage, and a single char
3236  * for the null termination.)
3237  *
3238  * This is the calculation performed by the NVS_XDR_MAX_LEN macro.
3239  */
3240 #define	NVS_XDR_HDR_LEN		((size_t)(5 * 4))
3241 #define	NVS_XDR_DATA_LEN(y)	(((size_t)(y) <= NVS_XDR_HDR_LEN) ? \
3242 					0 : ((size_t)(y) - NVS_XDR_HDR_LEN))
3243 #define	NVS_XDR_MAX_LEN(x)	(NVP_SIZE_CALC(1, 0) + \
3244 					(NVS_XDR_DATA_LEN(x) * 2) + \
3245 					NV_ALIGN4((NVS_XDR_DATA_LEN(x) / 4)))
3246 
3247 static int
3248 nvs_xdr_nvpair(nvstream_t *nvs, nvpair_t *nvp, size_t *size)
3249 {
3250 	XDR 	*xdr = nvs->nvs_private;
3251 	int32_t	encode_len, decode_len;
3252 
3253 	switch (nvs->nvs_op) {
3254 	case NVS_OP_ENCODE: {
3255 		size_t nvsize;
3256 
3257 		if (nvs_xdr_nvp_size(nvs, nvp, &nvsize) != 0)
3258 			return (EFAULT);
3259 
3260 		decode_len = nvp->nvp_size;
3261 		encode_len = nvsize;
3262 		if (!xdr_int(xdr, &encode_len) || !xdr_int(xdr, &decode_len))
3263 			return (EFAULT);
3264 
3265 		return (nvs_xdr_nvp_op(nvs, nvp));
3266 	}
3267 	case NVS_OP_DECODE: {
3268 		struct xdr_bytesrec bytesrec;
3269 
3270 		/* get the encode and decode size */
3271 		if (!xdr_int(xdr, &encode_len) || !xdr_int(xdr, &decode_len))
3272 			return (EFAULT);
3273 		*size = decode_len;
3274 
3275 		/* are we at the end of the stream? */
3276 		if (*size == 0)
3277 			return (0);
3278 
3279 		/* sanity check the size parameter */
3280 		if (!xdr_control(xdr, XDR_GET_BYTES_AVAIL, &bytesrec))
3281 			return (EFAULT);
3282 
3283 		if (*size > NVS_XDR_MAX_LEN(bytesrec.xc_num_avail))
3284 			return (EFAULT);
3285 		break;
3286 	}
3287 
3288 	default:
3289 		return (EINVAL);
3290 	}
3291 	return (0);
3292 }
3293 
3294 static const struct nvs_ops nvs_xdr_ops = {
3295 	nvs_xdr_nvlist,
3296 	nvs_xdr_nvpair,
3297 	nvs_xdr_nvp_op,
3298 	nvs_xdr_nvp_size,
3299 	nvs_xdr_nvl_fini
3300 };
3301 
3302 static int
3303 nvs_xdr(nvstream_t *nvs, nvlist_t *nvl, char *buf, size_t *buflen)
3304 {
3305 	XDR xdr;
3306 	int err;
3307 
3308 	nvs->nvs_ops = &nvs_xdr_ops;
3309 
3310 	if ((err = nvs_xdr_create(nvs, &xdr, buf + sizeof (nvs_header_t),
3311 	    *buflen - sizeof (nvs_header_t))) != 0)
3312 		return (err);
3313 
3314 	err = nvs_operation(nvs, nvl, buflen);
3315 
3316 	nvs_xdr_destroy(nvs);
3317 
3318 	return (err);
3319 }
3320