xref: /illumos-gate/usr/src/common/nvpair/nvpair.c (revision 8c69cc8fbe729fa7b091e901c4b50508ccc6bb33)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
24  * Copyright (c) 2015, 2017 by Delphix. All rights reserved.
25  */
26 
27 #include <sys/stropts.h>
28 #include <sys/debug.h>
29 #include <sys/isa_defs.h>
30 #include <sys/int_limits.h>
31 #include <sys/nvpair.h>
32 #include <sys/nvpair_impl.h>
33 #include <rpc/types.h>
34 #include <rpc/xdr.h>
35 
36 #if defined(_KERNEL) && !defined(_BOOT)
37 #include <sys/varargs.h>
38 #include <sys/ddi.h>
39 #include <sys/sunddi.h>
40 #include <sys/sysmacros.h>
41 #else
42 #include <stdarg.h>
43 #include <stdlib.h>
44 #include <string.h>
45 #include <strings.h>
46 #include <stddef.h>
47 #endif
48 
49 #define	skip_whitespace(p)	while ((*(p) == ' ') || (*(p) == '\t')) p++
50 
51 /*
52  * nvpair.c - Provides kernel & userland interfaces for manipulating
53  *	name-value pairs.
54  *
55  * Overview Diagram
56  *
57  *  +--------------+
58  *  |  nvlist_t    |
59  *  |--------------|
60  *  | nvl_version  |
61  *  | nvl_nvflag   |
62  *  | nvl_priv    -+-+
63  *  | nvl_flag     | |
64  *  | nvl_pad      | |
65  *  +--------------+ |
66  *                   V
67  *      +--------------+      last i_nvp in list
68  *      | nvpriv_t     |  +--------------------->
69  *      |--------------|  |
70  *   +--+- nvp_list    |  |   +------------+
71  *   |  |  nvp_last   -+--+   + nv_alloc_t |
72  *   |  |  nvp_curr    |      |------------|
73  *   |  |  nvp_nva    -+----> | nva_ops    |
74  *   |  |  nvp_stat    |      | nva_arg    |
75  *   |  +--------------+      +------------+
76  *   |
77  *   +-------+
78  *           V
79  *   +---------------------+      +-------------------+
80  *   |  i_nvp_t            |  +-->|  i_nvp_t          |  +-->
81  *   |---------------------|  |   |-------------------|  |
82  *   | nvi_next           -+--+   | nvi_next         -+--+
83  *   | nvi_prev (NULL)     | <----+ nvi_prev          |
84  *   | . . . . . . . . . . |      | . . . . . . . . . |
85  *   | nvp (nvpair_t)      |      | nvp (nvpair_t)    |
86  *   |  - nvp_size         |      |  - nvp_size       |
87  *   |  - nvp_name_sz      |      |  - nvp_name_sz    |
88  *   |  - nvp_value_elem   |      |  - nvp_value_elem |
89  *   |  - nvp_type         |      |  - nvp_type       |
90  *   |  - data ...         |      |  - data ...       |
91  *   +---------------------+      +-------------------+
92  *
93  *
94  *
95  *   +---------------------+              +---------------------+
96  *   |  i_nvp_t            |  +-->    +-->|  i_nvp_t (last)     |
97  *   |---------------------|  |       |   |---------------------|
98  *   |  nvi_next          -+--+ ... --+   | nvi_next (NULL)     |
99  * <-+- nvi_prev           |<-- ...  <----+ nvi_prev            |
100  *   | . . . . . . . . .   |              | . . . . . . . . .   |
101  *   | nvp (nvpair_t)      |              | nvp (nvpair_t)      |
102  *   |  - nvp_size         |              |  - nvp_size         |
103  *   |  - nvp_name_sz      |              |  - nvp_name_sz      |
104  *   |  - nvp_value_elem   |              |  - nvp_value_elem   |
105  *   |  - DATA_TYPE_NVLIST |              |  - nvp_type         |
106  *   |  - data (embedded)  |              |  - data ...         |
107  *   |    nvlist name      |              +---------------------+
108  *   |  +--------------+   |
109  *   |  |  nvlist_t    |   |
110  *   |  |--------------|   |
111  *   |  | nvl_version  |   |
112  *   |  | nvl_nvflag   |   |
113  *   |  | nvl_priv   --+---+---->
114  *   |  | nvl_flag     |   |
115  *   |  | nvl_pad      |   |
116  *   |  +--------------+   |
117  *   +---------------------+
118  *
119  *
120  * N.B. nvpair_t may be aligned on 4 byte boundary, so +4 will
121  * allow value to be aligned on 8 byte boundary
122  *
123  * name_len is the length of the name string including the null terminator
124  * so it must be >= 1
125  */
126 #define	NVP_SIZE_CALC(name_len, data_len) \
127 	(NV_ALIGN((sizeof (nvpair_t)) + name_len) + NV_ALIGN(data_len))
128 
129 static int i_get_value_size(data_type_t type, const void *data, uint_t nelem);
130 static int nvlist_add_common(nvlist_t *nvl, const char *name, data_type_t type,
131     uint_t nelem, const void *data);
132 
133 #define	NV_STAT_EMBEDDED	0x1
134 #define	EMBEDDED_NVL(nvp)	((nvlist_t *)(void *)NVP_VALUE(nvp))
135 #define	EMBEDDED_NVL_ARRAY(nvp)	((nvlist_t **)(void *)NVP_VALUE(nvp))
136 
137 #define	NVP_VALOFF(nvp)	(NV_ALIGN(sizeof (nvpair_t) + (nvp)->nvp_name_sz))
138 #define	NVPAIR2I_NVP(nvp) \
139 	((i_nvp_t *)((size_t)(nvp) - offsetof(i_nvp_t, nvi_nvp)))
140 
141 #ifdef _KERNEL
142 int nvpair_max_recursion = 20;
143 #else
144 int nvpair_max_recursion = 100;
145 #endif
146 
147 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 			nvlist_free(embedded);
2200 			return (EINVAL);
2201 		}
2202 		nvs->nvs_recursion++;
2203 		if ((err = nvs_operation(nvs, embedded, NULL)) != 0)
2204 			nvlist_free(embedded);
2205 		nvs->nvs_recursion--;
2206 		return (err);
2207 	}
2208 	default:
2209 		break;
2210 	}
2211 
2212 	return (EINVAL);
2213 }
2214 
2215 static int
2216 nvs_embedded_nvl_array(nvstream_t *nvs, nvpair_t *nvp, size_t *size)
2217 {
2218 	size_t nelem = NVP_NELEM(nvp);
2219 	nvlist_t **nvlp = EMBEDDED_NVL_ARRAY(nvp);
2220 	int i;
2221 
2222 	switch (nvs->nvs_op) {
2223 	case NVS_OP_ENCODE:
2224 		for (i = 0; i < nelem; i++)
2225 			if (nvs_embedded(nvs, nvlp[i]) != 0)
2226 				return (EFAULT);
2227 		break;
2228 
2229 	case NVS_OP_DECODE: {
2230 		size_t len = nelem * sizeof (uint64_t);
2231 		nvlist_t *embedded = (nvlist_t *)((uintptr_t)nvlp + len);
2232 
2233 		bzero(nvlp, len);	/* don't trust packed data */
2234 		for (i = 0; i < nelem; i++) {
2235 			if (nvs_embedded(nvs, embedded) != 0) {
2236 				nvpair_free(nvp);
2237 				return (EFAULT);
2238 			}
2239 
2240 			nvlp[i] = embedded++;
2241 		}
2242 		break;
2243 	}
2244 	case NVS_OP_GETSIZE: {
2245 		uint64_t nvsize = 0;
2246 
2247 		for (i = 0; i < nelem; i++) {
2248 			size_t nvp_sz = 0;
2249 
2250 			if (nvs_operation(nvs, nvlp[i], &nvp_sz) != 0)
2251 				return (EINVAL);
2252 
2253 			if ((nvsize += nvp_sz) > INT32_MAX)
2254 				return (EINVAL);
2255 		}
2256 
2257 		*size = nvsize;
2258 		break;
2259 	}
2260 	default:
2261 		return (EINVAL);
2262 	}
2263 
2264 	return (0);
2265 }
2266 
2267 static int nvs_native(nvstream_t *, nvlist_t *, char *, size_t *);
2268 static int nvs_xdr(nvstream_t *, nvlist_t *, char *, size_t *);
2269 
2270 /*
2271  * Common routine for nvlist operations:
2272  * encode, decode, getsize (encoded size).
2273  */
2274 static int
2275 nvlist_common(nvlist_t *nvl, char *buf, size_t *buflen, int encoding,
2276     int nvs_op)
2277 {
2278 	int err = 0;
2279 	nvstream_t nvs;
2280 	int nvl_endian;
2281 #ifdef	_LITTLE_ENDIAN
2282 	int host_endian = 1;
2283 #else
2284 	int host_endian = 0;
2285 #endif	/* _LITTLE_ENDIAN */
2286 	nvs_header_t *nvh = (void *)buf;
2287 
2288 	if (buflen == NULL || nvl == NULL ||
2289 	    (nvs.nvs_priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL)
2290 		return (EINVAL);
2291 
2292 	nvs.nvs_op = nvs_op;
2293 	nvs.nvs_recursion = 0;
2294 
2295 	/*
2296 	 * For NVS_OP_ENCODE and NVS_OP_DECODE make sure an nvlist and
2297 	 * a buffer is allocated.  The first 4 bytes in the buffer are
2298 	 * used for encoding method and host endian.
2299 	 */
2300 	switch (nvs_op) {
2301 	case NVS_OP_ENCODE:
2302 		if (buf == NULL || *buflen < sizeof (nvs_header_t))
2303 			return (EINVAL);
2304 
2305 		nvh->nvh_encoding = encoding;
2306 		nvh->nvh_endian = nvl_endian = host_endian;
2307 		nvh->nvh_reserved1 = 0;
2308 		nvh->nvh_reserved2 = 0;
2309 		break;
2310 
2311 	case NVS_OP_DECODE:
2312 		if (buf == NULL || *buflen < sizeof (nvs_header_t))
2313 			return (EINVAL);
2314 
2315 		/* get method of encoding from first byte */
2316 		encoding = nvh->nvh_encoding;
2317 		nvl_endian = nvh->nvh_endian;
2318 		break;
2319 
2320 	case NVS_OP_GETSIZE:
2321 		nvl_endian = host_endian;
2322 
2323 		/*
2324 		 * add the size for encoding
2325 		 */
2326 		*buflen = sizeof (nvs_header_t);
2327 		break;
2328 
2329 	default:
2330 		return (ENOTSUP);
2331 	}
2332 
2333 	/*
2334 	 * Create an nvstream with proper encoding method
2335 	 */
2336 	switch (encoding) {
2337 	case NV_ENCODE_NATIVE:
2338 		/*
2339 		 * check endianness, in case we are unpacking
2340 		 * from a file
2341 		 */
2342 		if (nvl_endian != host_endian)
2343 			return (ENOTSUP);
2344 		err = nvs_native(&nvs, nvl, buf, buflen);
2345 		break;
2346 	case NV_ENCODE_XDR:
2347 		err = nvs_xdr(&nvs, nvl, buf, buflen);
2348 		break;
2349 	default:
2350 		err = ENOTSUP;
2351 		break;
2352 	}
2353 
2354 	return (err);
2355 }
2356 
2357 int
2358 nvlist_size(nvlist_t *nvl, size_t *size, int encoding)
2359 {
2360 	return (nvlist_common(nvl, NULL, size, encoding, NVS_OP_GETSIZE));
2361 }
2362 
2363 /*
2364  * Pack nvlist into contiguous memory
2365  */
2366 /*ARGSUSED1*/
2367 int
2368 nvlist_pack(nvlist_t *nvl, char **bufp, size_t *buflen, int encoding,
2369     int kmflag)
2370 {
2371 #if defined(_KERNEL) && !defined(_BOOT)
2372 	return (nvlist_xpack(nvl, bufp, buflen, encoding,
2373 	    (kmflag == KM_SLEEP ? nv_alloc_sleep : nv_alloc_nosleep)));
2374 #else
2375 	return (nvlist_xpack(nvl, bufp, buflen, encoding, nv_alloc_nosleep));
2376 #endif
2377 }
2378 
2379 int
2380 nvlist_xpack(nvlist_t *nvl, char **bufp, size_t *buflen, int encoding,
2381     nv_alloc_t *nva)
2382 {
2383 	nvpriv_t nvpriv;
2384 	size_t alloc_size;
2385 	char *buf;
2386 	int err;
2387 
2388 	if (nva == NULL || nvl == NULL || bufp == NULL || buflen == NULL)
2389 		return (EINVAL);
2390 
2391 	if (*bufp != NULL)
2392 		return (nvlist_common(nvl, *bufp, buflen, encoding,
2393 		    NVS_OP_ENCODE));
2394 
2395 	/*
2396 	 * Here is a difficult situation:
2397 	 * 1. The nvlist has fixed allocator properties.
2398 	 *    All other nvlist routines (like nvlist_add_*, ...) use
2399 	 *    these properties.
2400 	 * 2. When using nvlist_pack() the user can specify their own
2401 	 *    allocator properties (e.g. by using KM_NOSLEEP).
2402 	 *
2403 	 * We use the user specified properties (2). A clearer solution
2404 	 * will be to remove the kmflag from nvlist_pack(), but we will
2405 	 * not change the interface.
2406 	 */
2407 	nv_priv_init(&nvpriv, nva, 0);
2408 
2409 	if ((err = nvlist_size(nvl, &alloc_size, encoding)))
2410 		return (err);
2411 
2412 	if ((buf = nv_mem_zalloc(&nvpriv, alloc_size)) == NULL)
2413 		return (ENOMEM);
2414 
2415 	if ((err = nvlist_common(nvl, buf, &alloc_size, encoding,
2416 	    NVS_OP_ENCODE)) != 0) {
2417 		nv_mem_free(&nvpriv, buf, alloc_size);
2418 	} else {
2419 		*buflen = alloc_size;
2420 		*bufp = buf;
2421 	}
2422 
2423 	return (err);
2424 }
2425 
2426 /*
2427  * Unpack buf into an nvlist_t
2428  */
2429 /*ARGSUSED1*/
2430 int
2431 nvlist_unpack(char *buf, size_t buflen, nvlist_t **nvlp, int kmflag)
2432 {
2433 #if defined(_KERNEL) && !defined(_BOOT)
2434 	return (nvlist_xunpack(buf, buflen, nvlp,
2435 	    (kmflag == KM_SLEEP ? nv_alloc_sleep : nv_alloc_nosleep)));
2436 #else
2437 	return (nvlist_xunpack(buf, buflen, nvlp, nv_alloc_nosleep));
2438 #endif
2439 }
2440 
2441 int
2442 nvlist_xunpack(char *buf, size_t buflen, nvlist_t **nvlp, nv_alloc_t *nva)
2443 {
2444 	nvlist_t *nvl;
2445 	int err;
2446 
2447 	if (nvlp == NULL)
2448 		return (EINVAL);
2449 
2450 	if ((err = nvlist_xalloc(&nvl, 0, nva)) != 0)
2451 		return (err);
2452 
2453 	if ((err = nvlist_common(nvl, buf, &buflen, 0, NVS_OP_DECODE)) != 0)
2454 		nvlist_free(nvl);
2455 	else
2456 		*nvlp = nvl;
2457 
2458 	return (err);
2459 }
2460 
2461 /*
2462  * Native encoding functions
2463  */
2464 typedef struct {
2465 	/*
2466 	 * This structure is used when decoding a packed nvpair in
2467 	 * the native format.  n_base points to a buffer containing the
2468 	 * packed nvpair.  n_end is a pointer to the end of the buffer.
2469 	 * (n_end actually points to the first byte past the end of the
2470 	 * buffer.)  n_curr is a pointer that lies between n_base and n_end.
2471 	 * It points to the current data that we are decoding.
2472 	 * The amount of data left in the buffer is equal to n_end - n_curr.
2473 	 * n_flag is used to recognize a packed embedded list.
2474 	 */
2475 	caddr_t n_base;
2476 	caddr_t n_end;
2477 	caddr_t n_curr;
2478 	uint_t  n_flag;
2479 } nvs_native_t;
2480 
2481 static int
2482 nvs_native_create(nvstream_t *nvs, nvs_native_t *native, char *buf,
2483     size_t buflen)
2484 {
2485 	switch (nvs->nvs_op) {
2486 	case NVS_OP_ENCODE:
2487 	case NVS_OP_DECODE:
2488 		nvs->nvs_private = native;
2489 		native->n_curr = native->n_base = buf;
2490 		native->n_end = buf + buflen;
2491 		native->n_flag = 0;
2492 		return (0);
2493 
2494 	case NVS_OP_GETSIZE:
2495 		nvs->nvs_private = native;
2496 		native->n_curr = native->n_base = native->n_end = NULL;
2497 		native->n_flag = 0;
2498 		return (0);
2499 	default:
2500 		return (EINVAL);
2501 	}
2502 }
2503 
2504 /*ARGSUSED*/
2505 static void
2506 nvs_native_destroy(nvstream_t *nvs)
2507 {
2508 }
2509 
2510 static int
2511 native_cp(nvstream_t *nvs, void *buf, size_t size)
2512 {
2513 	nvs_native_t *native = (nvs_native_t *)nvs->nvs_private;
2514 
2515 	if (native->n_curr + size > native->n_end)
2516 		return (EFAULT);
2517 
2518 	/*
2519 	 * The bcopy() below eliminates alignment requirement
2520 	 * on the buffer (stream) and is preferred over direct access.
2521 	 */
2522 	switch (nvs->nvs_op) {
2523 	case NVS_OP_ENCODE:
2524 		bcopy(buf, native->n_curr, size);
2525 		break;
2526 	case NVS_OP_DECODE:
2527 		bcopy(native->n_curr, buf, size);
2528 		break;
2529 	default:
2530 		return (EINVAL);
2531 	}
2532 
2533 	native->n_curr += size;
2534 	return (0);
2535 }
2536 
2537 /*
2538  * operate on nvlist_t header
2539  */
2540 static int
2541 nvs_native_nvlist(nvstream_t *nvs, nvlist_t *nvl, size_t *size)
2542 {
2543 	nvs_native_t *native = nvs->nvs_private;
2544 
2545 	switch (nvs->nvs_op) {
2546 	case NVS_OP_ENCODE:
2547 	case NVS_OP_DECODE:
2548 		if (native->n_flag)
2549 			return (0);	/* packed embedded list */
2550 
2551 		native->n_flag = 1;
2552 
2553 		/* copy version and nvflag of the nvlist_t */
2554 		if (native_cp(nvs, &nvl->nvl_version, sizeof (int32_t)) != 0 ||
2555 		    native_cp(nvs, &nvl->nvl_nvflag, sizeof (int32_t)) != 0)
2556 			return (EFAULT);
2557 
2558 		return (0);
2559 
2560 	case NVS_OP_GETSIZE:
2561 		/*
2562 		 * if calculate for packed embedded list
2563 		 * 	4 for end of the embedded list
2564 		 * else
2565 		 * 	2 * sizeof (int32_t) for nvl_version and nvl_nvflag
2566 		 * 	and 4 for end of the entire list
2567 		 */
2568 		if (native->n_flag) {
2569 			*size += 4;
2570 		} else {
2571 			native->n_flag = 1;
2572 			*size += 2 * sizeof (int32_t) + 4;
2573 		}
2574 
2575 		return (0);
2576 
2577 	default:
2578 		return (EINVAL);
2579 	}
2580 }
2581 
2582 static int
2583 nvs_native_nvl_fini(nvstream_t *nvs)
2584 {
2585 	if (nvs->nvs_op == NVS_OP_ENCODE) {
2586 		nvs_native_t *native = (nvs_native_t *)nvs->nvs_private;
2587 		/*
2588 		 * Add 4 zero bytes at end of nvlist. They are used
2589 		 * for end detection by the decode routine.
2590 		 */
2591 		if (native->n_curr + sizeof (int) > native->n_end)
2592 			return (EFAULT);
2593 
2594 		bzero(native->n_curr, sizeof (int));
2595 		native->n_curr += sizeof (int);
2596 	}
2597 
2598 	return (0);
2599 }
2600 
2601 static int
2602 nvpair_native_embedded(nvstream_t *nvs, nvpair_t *nvp)
2603 {
2604 	if (nvs->nvs_op == NVS_OP_ENCODE) {
2605 		nvs_native_t *native = (nvs_native_t *)nvs->nvs_private;
2606 		nvlist_t *packed = (void *)
2607 		    (native->n_curr - nvp->nvp_size + NVP_VALOFF(nvp));
2608 		/*
2609 		 * Null out the pointer that is meaningless in the packed
2610 		 * structure. The address may not be aligned, so we have
2611 		 * to use bzero.
2612 		 */
2613 		bzero(&packed->nvl_priv, sizeof (packed->nvl_priv));
2614 	}
2615 
2616 	return (nvs_embedded(nvs, EMBEDDED_NVL(nvp)));
2617 }
2618 
2619 static int
2620 nvpair_native_embedded_array(nvstream_t *nvs, nvpair_t *nvp)
2621 {
2622 	if (nvs->nvs_op == NVS_OP_ENCODE) {
2623 		nvs_native_t *native = (nvs_native_t *)nvs->nvs_private;
2624 		char *value = native->n_curr - nvp->nvp_size + NVP_VALOFF(nvp);
2625 		size_t len = NVP_NELEM(nvp) * sizeof (uint64_t);
2626 		nvlist_t *packed = (nvlist_t *)((uintptr_t)value + len);
2627 		int i;
2628 		/*
2629 		 * Null out pointers that are meaningless in the packed
2630 		 * structure. The addresses may not be aligned, so we have
2631 		 * to use bzero.
2632 		 */
2633 		bzero(value, len);
2634 
2635 		for (i = 0; i < NVP_NELEM(nvp); i++, packed++)
2636 			/*
2637 			 * Null out the pointer that is meaningless in the
2638 			 * packed structure. The address may not be aligned,
2639 			 * so we have to use bzero.
2640 			 */
2641 			bzero(&packed->nvl_priv, sizeof (packed->nvl_priv));
2642 	}
2643 
2644 	return (nvs_embedded_nvl_array(nvs, nvp, NULL));
2645 }
2646 
2647 static void
2648 nvpair_native_string_array(nvstream_t *nvs, nvpair_t *nvp)
2649 {
2650 	switch (nvs->nvs_op) {
2651 	case NVS_OP_ENCODE: {
2652 		nvs_native_t *native = (nvs_native_t *)nvs->nvs_private;
2653 		uint64_t *strp = (void *)
2654 		    (native->n_curr - nvp->nvp_size + NVP_VALOFF(nvp));
2655 		/*
2656 		 * Null out pointers that are meaningless in the packed
2657 		 * structure. The addresses may not be aligned, so we have
2658 		 * to use bzero.
2659 		 */
2660 		bzero(strp, NVP_NELEM(nvp) * sizeof (uint64_t));
2661 		break;
2662 	}
2663 	case NVS_OP_DECODE: {
2664 		char **strp = (void *)NVP_VALUE(nvp);
2665 		char *buf = ((char *)strp + NVP_NELEM(nvp) * sizeof (uint64_t));
2666 		int i;
2667 
2668 		for (i = 0; i < NVP_NELEM(nvp); i++) {
2669 			strp[i] = buf;
2670 			buf += strlen(buf) + 1;
2671 		}
2672 		break;
2673 	}
2674 	}
2675 }
2676 
2677 static int
2678 nvs_native_nvp_op(nvstream_t *nvs, nvpair_t *nvp)
2679 {
2680 	data_type_t type;
2681 	int value_sz;
2682 	int ret = 0;
2683 
2684 	/*
2685 	 * We do the initial bcopy of the data before we look at
2686 	 * the nvpair type, because when we're decoding, we won't
2687 	 * have the correct values for the pair until we do the bcopy.
2688 	 */
2689 	switch (nvs->nvs_op) {
2690 	case NVS_OP_ENCODE:
2691 	case NVS_OP_DECODE:
2692 		if (native_cp(nvs, nvp, nvp->nvp_size) != 0)
2693 			return (EFAULT);
2694 		break;
2695 	default:
2696 		return (EINVAL);
2697 	}
2698 
2699 	/* verify nvp_name_sz, check the name string length */
2700 	if (i_validate_nvpair_name(nvp) != 0)
2701 		return (EFAULT);
2702 
2703 	type = NVP_TYPE(nvp);
2704 
2705 	/*
2706 	 * Verify type and nelem and get the value size.
2707 	 * In case of data types DATA_TYPE_STRING and DATA_TYPE_STRING_ARRAY
2708 	 * is the size of the string(s) excluded.
2709 	 */
2710 	if ((value_sz = i_get_value_size(type, NULL, NVP_NELEM(nvp))) < 0)
2711 		return (EFAULT);
2712 
2713 	if (NVP_SIZE_CALC(nvp->nvp_name_sz, value_sz) > nvp->nvp_size)
2714 		return (EFAULT);
2715 
2716 	switch (type) {
2717 	case DATA_TYPE_NVLIST:
2718 		ret = nvpair_native_embedded(nvs, nvp);
2719 		break;
2720 	case DATA_TYPE_NVLIST_ARRAY:
2721 		ret = nvpair_native_embedded_array(nvs, nvp);
2722 		break;
2723 	case DATA_TYPE_STRING_ARRAY:
2724 		nvpair_native_string_array(nvs, nvp);
2725 		break;
2726 	default:
2727 		break;
2728 	}
2729 
2730 	return (ret);
2731 }
2732 
2733 static int
2734 nvs_native_nvp_size(nvstream_t *nvs, nvpair_t *nvp, size_t *size)
2735 {
2736 	uint64_t nvp_sz = nvp->nvp_size;
2737 
2738 	switch (NVP_TYPE(nvp)) {
2739 	case DATA_TYPE_NVLIST: {
2740 		size_t nvsize = 0;
2741 
2742 		if (nvs_operation(nvs, EMBEDDED_NVL(nvp), &nvsize) != 0)
2743 			return (EINVAL);
2744 
2745 		nvp_sz += nvsize;
2746 		break;
2747 	}
2748 	case DATA_TYPE_NVLIST_ARRAY: {
2749 		size_t nvsize;
2750 
2751 		if (nvs_embedded_nvl_array(nvs, nvp, &nvsize) != 0)
2752 			return (EINVAL);
2753 
2754 		nvp_sz += nvsize;
2755 		break;
2756 	}
2757 	default:
2758 		break;
2759 	}
2760 
2761 	if (nvp_sz > INT32_MAX)
2762 		return (EINVAL);
2763 
2764 	*size = nvp_sz;
2765 
2766 	return (0);
2767 }
2768 
2769 static int
2770 nvs_native_nvpair(nvstream_t *nvs, nvpair_t *nvp, size_t *size)
2771 {
2772 	switch (nvs->nvs_op) {
2773 	case NVS_OP_ENCODE:
2774 		return (nvs_native_nvp_op(nvs, nvp));
2775 
2776 	case NVS_OP_DECODE: {
2777 		nvs_native_t *native = (nvs_native_t *)nvs->nvs_private;
2778 		int32_t decode_len;
2779 
2780 		/* try to read the size value from the stream */
2781 		if (native->n_curr + sizeof (int32_t) > native->n_end)
2782 			return (EFAULT);
2783 		bcopy(native->n_curr, &decode_len, sizeof (int32_t));
2784 
2785 		/* sanity check the size value */
2786 		if (decode_len < 0 ||
2787 		    decode_len > native->n_end - native->n_curr)
2788 			return (EFAULT);
2789 
2790 		*size = decode_len;
2791 
2792 		/*
2793 		 * If at the end of the stream then move the cursor
2794 		 * forward, otherwise nvpair_native_op() will read
2795 		 * the entire nvpair at the same cursor position.
2796 		 */
2797 		if (*size == 0)
2798 			native->n_curr += sizeof (int32_t);
2799 		break;
2800 	}
2801 
2802 	default:
2803 		return (EINVAL);
2804 	}
2805 
2806 	return (0);
2807 }
2808 
2809 static const nvs_ops_t nvs_native_ops = {
2810 	nvs_native_nvlist,
2811 	nvs_native_nvpair,
2812 	nvs_native_nvp_op,
2813 	nvs_native_nvp_size,
2814 	nvs_native_nvl_fini
2815 };
2816 
2817 static int
2818 nvs_native(nvstream_t *nvs, nvlist_t *nvl, char *buf, size_t *buflen)
2819 {
2820 	nvs_native_t native;
2821 	int err;
2822 
2823 	nvs->nvs_ops = &nvs_native_ops;
2824 
2825 	if ((err = nvs_native_create(nvs, &native, buf + sizeof (nvs_header_t),
2826 	    *buflen - sizeof (nvs_header_t))) != 0)
2827 		return (err);
2828 
2829 	err = nvs_operation(nvs, nvl, buflen);
2830 
2831 	nvs_native_destroy(nvs);
2832 
2833 	return (err);
2834 }
2835 
2836 /*
2837  * XDR encoding functions
2838  *
2839  * An xdr packed nvlist is encoded as:
2840  *
2841  *  - encoding methode and host endian (4 bytes)
2842  *  - nvl_version (4 bytes)
2843  *  - nvl_nvflag (4 bytes)
2844  *
2845  *  - encoded nvpairs, the format of one xdr encoded nvpair is:
2846  *	- encoded size of the nvpair (4 bytes)
2847  *	- decoded size of the nvpair (4 bytes)
2848  *	- name string, (4 + sizeof(NV_ALIGN4(string))
2849  *	  a string is coded as size (4 bytes) and data
2850  *	- data type (4 bytes)
2851  *	- number of elements in the nvpair (4 bytes)
2852  *	- data
2853  *
2854  *  - 2 zero's for end of the entire list (8 bytes)
2855  */
2856 static int
2857 nvs_xdr_create(nvstream_t *nvs, XDR *xdr, char *buf, size_t buflen)
2858 {
2859 	/* xdr data must be 4 byte aligned */
2860 	if ((ulong_t)buf % 4 != 0)
2861 		return (EFAULT);
2862 
2863 	switch (nvs->nvs_op) {
2864 	case NVS_OP_ENCODE:
2865 		xdrmem_create(xdr, buf, (uint_t)buflen, XDR_ENCODE);
2866 		nvs->nvs_private = xdr;
2867 		return (0);
2868 	case NVS_OP_DECODE:
2869 		xdrmem_create(xdr, buf, (uint_t)buflen, XDR_DECODE);
2870 		nvs->nvs_private = xdr;
2871 		return (0);
2872 	case NVS_OP_GETSIZE:
2873 		nvs->nvs_private = NULL;
2874 		return (0);
2875 	default:
2876 		return (EINVAL);
2877 	}
2878 }
2879 
2880 static void
2881 nvs_xdr_destroy(nvstream_t *nvs)
2882 {
2883 	switch (nvs->nvs_op) {
2884 	case NVS_OP_ENCODE:
2885 	case NVS_OP_DECODE:
2886 		xdr_destroy((XDR *)nvs->nvs_private);
2887 		break;
2888 	default:
2889 		break;
2890 	}
2891 }
2892 
2893 static int
2894 nvs_xdr_nvlist(nvstream_t *nvs, nvlist_t *nvl, size_t *size)
2895 {
2896 	switch (nvs->nvs_op) {
2897 	case NVS_OP_ENCODE:
2898 	case NVS_OP_DECODE: {
2899 		XDR 	*xdr = nvs->nvs_private;
2900 
2901 		if (!xdr_int(xdr, &nvl->nvl_version) ||
2902 		    !xdr_u_int(xdr, &nvl->nvl_nvflag))
2903 			return (EFAULT);
2904 		break;
2905 	}
2906 	case NVS_OP_GETSIZE: {
2907 		/*
2908 		 * 2 * 4 for nvl_version + nvl_nvflag
2909 		 * and 8 for end of the entire list
2910 		 */
2911 		*size += 2 * 4 + 8;
2912 		break;
2913 	}
2914 	default:
2915 		return (EINVAL);
2916 	}
2917 	return (0);
2918 }
2919 
2920 static int
2921 nvs_xdr_nvl_fini(nvstream_t *nvs)
2922 {
2923 	if (nvs->nvs_op == NVS_OP_ENCODE) {
2924 		XDR *xdr = nvs->nvs_private;
2925 		int zero = 0;
2926 
2927 		if (!xdr_int(xdr, &zero) || !xdr_int(xdr, &zero))
2928 			return (EFAULT);
2929 	}
2930 
2931 	return (0);
2932 }
2933 
2934 /*
2935  * The format of xdr encoded nvpair is:
2936  * encode_size, decode_size, name string, data type, nelem, data
2937  */
2938 static int
2939 nvs_xdr_nvp_op(nvstream_t *nvs, nvpair_t *nvp)
2940 {
2941 	data_type_t type;
2942 	char	*buf;
2943 	char	*buf_end = (char *)nvp + nvp->nvp_size;
2944 	int	value_sz;
2945 	uint_t	nelem, buflen;
2946 	bool_t	ret = FALSE;
2947 	XDR	*xdr = nvs->nvs_private;
2948 
2949 	ASSERT(xdr != NULL && nvp != NULL);
2950 
2951 	/* name string */
2952 	if ((buf = NVP_NAME(nvp)) >= buf_end)
2953 		return (EFAULT);
2954 	buflen = buf_end - buf;
2955 
2956 	if (!xdr_string(xdr, &buf, buflen - 1))
2957 		return (EFAULT);
2958 	nvp->nvp_name_sz = strlen(buf) + 1;
2959 
2960 	/* type and nelem */
2961 	if (!xdr_int(xdr, (int *)&nvp->nvp_type) ||
2962 	    !xdr_int(xdr, &nvp->nvp_value_elem))
2963 		return (EFAULT);
2964 
2965 	type = NVP_TYPE(nvp);
2966 	nelem = nvp->nvp_value_elem;
2967 
2968 	/*
2969 	 * Verify type and nelem and get the value size.
2970 	 * In case of data types DATA_TYPE_STRING and DATA_TYPE_STRING_ARRAY
2971 	 * is the size of the string(s) excluded.
2972 	 */
2973 	if ((value_sz = i_get_value_size(type, NULL, nelem)) < 0)
2974 		return (EFAULT);
2975 
2976 	/* if there is no data to extract then return */
2977 	if (nelem == 0)
2978 		return (0);
2979 
2980 	/* value */
2981 	if ((buf = NVP_VALUE(nvp)) >= buf_end)
2982 		return (EFAULT);
2983 	buflen = buf_end - buf;
2984 
2985 	if (buflen < value_sz)
2986 		return (EFAULT);
2987 
2988 	switch (type) {
2989 	case DATA_TYPE_NVLIST:
2990 		if (nvs_embedded(nvs, (void *)buf) == 0)
2991 			return (0);
2992 		break;
2993 
2994 	case DATA_TYPE_NVLIST_ARRAY:
2995 		if (nvs_embedded_nvl_array(nvs, nvp, NULL) == 0)
2996 			return (0);
2997 		break;
2998 
2999 	case DATA_TYPE_BOOLEAN:
3000 		ret = TRUE;
3001 		break;
3002 
3003 	case DATA_TYPE_BYTE:
3004 	case DATA_TYPE_INT8:
3005 	case DATA_TYPE_UINT8:
3006 		ret = xdr_char(xdr, buf);
3007 		break;
3008 
3009 	case DATA_TYPE_INT16:
3010 		ret = xdr_short(xdr, (void *)buf);
3011 		break;
3012 
3013 	case DATA_TYPE_UINT16:
3014 		ret = xdr_u_short(xdr, (void *)buf);
3015 		break;
3016 
3017 	case DATA_TYPE_BOOLEAN_VALUE:
3018 	case DATA_TYPE_INT32:
3019 		ret = xdr_int(xdr, (void *)buf);
3020 		break;
3021 
3022 	case DATA_TYPE_UINT32:
3023 		ret = xdr_u_int(xdr, (void *)buf);
3024 		break;
3025 
3026 	case DATA_TYPE_INT64:
3027 		ret = xdr_longlong_t(xdr, (void *)buf);
3028 		break;
3029 
3030 	case DATA_TYPE_UINT64:
3031 		ret = xdr_u_longlong_t(xdr, (void *)buf);
3032 		break;
3033 
3034 	case DATA_TYPE_HRTIME:
3035 		/*
3036 		 * NOTE: must expose the definition of hrtime_t here
3037 		 */
3038 		ret = xdr_longlong_t(xdr, (void *)buf);
3039 		break;
3040 #if !defined(_KERNEL)
3041 	case DATA_TYPE_DOUBLE:
3042 		ret = xdr_double(xdr, (void *)buf);
3043 		break;
3044 #endif
3045 	case DATA_TYPE_STRING:
3046 		ret = xdr_string(xdr, &buf, buflen - 1);
3047 		break;
3048 
3049 	case DATA_TYPE_BYTE_ARRAY:
3050 		ret = xdr_opaque(xdr, buf, nelem);
3051 		break;
3052 
3053 	case DATA_TYPE_INT8_ARRAY:
3054 	case DATA_TYPE_UINT8_ARRAY:
3055 		ret = xdr_array(xdr, &buf, &nelem, buflen, sizeof (int8_t),
3056 		    (xdrproc_t)xdr_char);
3057 		break;
3058 
3059 	case DATA_TYPE_INT16_ARRAY:
3060 		ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (int16_t),
3061 		    sizeof (int16_t), (xdrproc_t)xdr_short);
3062 		break;
3063 
3064 	case DATA_TYPE_UINT16_ARRAY:
3065 		ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (uint16_t),
3066 		    sizeof (uint16_t), (xdrproc_t)xdr_u_short);
3067 		break;
3068 
3069 	case DATA_TYPE_BOOLEAN_ARRAY:
3070 	case DATA_TYPE_INT32_ARRAY:
3071 		ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (int32_t),
3072 		    sizeof (int32_t), (xdrproc_t)xdr_int);
3073 		break;
3074 
3075 	case DATA_TYPE_UINT32_ARRAY:
3076 		ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (uint32_t),
3077 		    sizeof (uint32_t), (xdrproc_t)xdr_u_int);
3078 		break;
3079 
3080 	case DATA_TYPE_INT64_ARRAY:
3081 		ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (int64_t),
3082 		    sizeof (int64_t), (xdrproc_t)xdr_longlong_t);
3083 		break;
3084 
3085 	case DATA_TYPE_UINT64_ARRAY:
3086 		ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (uint64_t),
3087 		    sizeof (uint64_t), (xdrproc_t)xdr_u_longlong_t);
3088 		break;
3089 
3090 	case DATA_TYPE_STRING_ARRAY: {
3091 		size_t len = nelem * sizeof (uint64_t);
3092 		char **strp = (void *)buf;
3093 		int i;
3094 
3095 		if (nvs->nvs_op == NVS_OP_DECODE)
3096 			bzero(buf, len);	/* don't trust packed data */
3097 
3098 		for (i = 0; i < nelem; i++) {
3099 			if (buflen <= len)
3100 				return (EFAULT);
3101 
3102 			buf += len;
3103 			buflen -= len;
3104 
3105 			if (xdr_string(xdr, &buf, buflen - 1) != TRUE)
3106 				return (EFAULT);
3107 
3108 			if (nvs->nvs_op == NVS_OP_DECODE)
3109 				strp[i] = buf;
3110 			len = strlen(buf) + 1;
3111 		}
3112 		ret = TRUE;
3113 		break;
3114 	}
3115 	default:
3116 		break;
3117 	}
3118 
3119 	return (ret == TRUE ? 0 : EFAULT);
3120 }
3121 
3122 static int
3123 nvs_xdr_nvp_size(nvstream_t *nvs, nvpair_t *nvp, size_t *size)
3124 {
3125 	data_type_t type = NVP_TYPE(nvp);
3126 	/*
3127 	 * encode_size + decode_size + name string size + data type + nelem
3128 	 * where name string size = 4 + NV_ALIGN4(strlen(NVP_NAME(nvp)))
3129 	 */
3130 	uint64_t nvp_sz = 4 + 4 + 4 + NV_ALIGN4(strlen(NVP_NAME(nvp))) + 4 + 4;
3131 
3132 	switch (type) {
3133 	case DATA_TYPE_BOOLEAN:
3134 		break;
3135 
3136 	case DATA_TYPE_BOOLEAN_VALUE:
3137 	case DATA_TYPE_BYTE:
3138 	case DATA_TYPE_INT8:
3139 	case DATA_TYPE_UINT8:
3140 	case DATA_TYPE_INT16:
3141 	case DATA_TYPE_UINT16:
3142 	case DATA_TYPE_INT32:
3143 	case DATA_TYPE_UINT32:
3144 		nvp_sz += 4;	/* 4 is the minimum xdr unit */
3145 		break;
3146 
3147 	case DATA_TYPE_INT64:
3148 	case DATA_TYPE_UINT64:
3149 	case DATA_TYPE_HRTIME:
3150 #if !defined(_KERNEL)
3151 	case DATA_TYPE_DOUBLE:
3152 #endif
3153 		nvp_sz += 8;
3154 		break;
3155 
3156 	case DATA_TYPE_STRING:
3157 		nvp_sz += 4 + NV_ALIGN4(strlen((char *)NVP_VALUE(nvp)));
3158 		break;
3159 
3160 	case DATA_TYPE_BYTE_ARRAY:
3161 		nvp_sz += NV_ALIGN4(NVP_NELEM(nvp));
3162 		break;
3163 
3164 	case DATA_TYPE_BOOLEAN_ARRAY:
3165 	case DATA_TYPE_INT8_ARRAY:
3166 	case DATA_TYPE_UINT8_ARRAY:
3167 	case DATA_TYPE_INT16_ARRAY:
3168 	case DATA_TYPE_UINT16_ARRAY:
3169 	case DATA_TYPE_INT32_ARRAY:
3170 	case DATA_TYPE_UINT32_ARRAY:
3171 		nvp_sz += 4 + 4 * (uint64_t)NVP_NELEM(nvp);
3172 		break;
3173 
3174 	case DATA_TYPE_INT64_ARRAY:
3175 	case DATA_TYPE_UINT64_ARRAY:
3176 		nvp_sz += 4 + 8 * (uint64_t)NVP_NELEM(nvp);
3177 		break;
3178 
3179 	case DATA_TYPE_STRING_ARRAY: {
3180 		int i;
3181 		char **strs = (void *)NVP_VALUE(nvp);
3182 
3183 		for (i = 0; i < NVP_NELEM(nvp); i++)
3184 			nvp_sz += 4 + NV_ALIGN4(strlen(strs[i]));
3185 
3186 		break;
3187 	}
3188 
3189 	case DATA_TYPE_NVLIST:
3190 	case DATA_TYPE_NVLIST_ARRAY: {
3191 		size_t nvsize = 0;
3192 		int old_nvs_op = nvs->nvs_op;
3193 		int err;
3194 
3195 		nvs->nvs_op = NVS_OP_GETSIZE;
3196 		if (type == DATA_TYPE_NVLIST)
3197 			err = nvs_operation(nvs, EMBEDDED_NVL(nvp), &nvsize);
3198 		else
3199 			err = nvs_embedded_nvl_array(nvs, nvp, &nvsize);
3200 		nvs->nvs_op = old_nvs_op;
3201 
3202 		if (err != 0)
3203 			return (EINVAL);
3204 
3205 		nvp_sz += nvsize;
3206 		break;
3207 	}
3208 
3209 	default:
3210 		return (EINVAL);
3211 	}
3212 
3213 	if (nvp_sz > INT32_MAX)
3214 		return (EINVAL);
3215 
3216 	*size = nvp_sz;
3217 
3218 	return (0);
3219 }
3220 
3221 
3222 /*
3223  * The NVS_XDR_MAX_LEN macro takes a packed xdr buffer of size x and estimates
3224  * the largest nvpair that could be encoded in the buffer.
3225  *
3226  * See comments above nvpair_xdr_op() for the format of xdr encoding.
3227  * The size of a xdr packed nvpair without any data is 5 words.
3228  *
3229  * Using the size of the data directly as an estimate would be ok
3230  * in all cases except one.  If the data type is of DATA_TYPE_STRING_ARRAY
3231  * then the actual nvpair has space for an array of pointers to index
3232  * the strings.  These pointers are not encoded into the packed xdr buffer.
3233  *
3234  * If the data is of type DATA_TYPE_STRING_ARRAY and all the strings are
3235  * of length 0, then each string is endcoded in xdr format as a single word.
3236  * Therefore when expanded to an nvpair there will be 2.25 word used for
3237  * each string.  (a int64_t allocated for pointer usage, and a single char
3238  * for the null termination.)
3239  *
3240  * This is the calculation performed by the NVS_XDR_MAX_LEN macro.
3241  */
3242 #define	NVS_XDR_HDR_LEN		((size_t)(5 * 4))
3243 #define	NVS_XDR_DATA_LEN(y)	(((size_t)(y) <= NVS_XDR_HDR_LEN) ? \
3244 					0 : ((size_t)(y) - NVS_XDR_HDR_LEN))
3245 #define	NVS_XDR_MAX_LEN(x)	(NVP_SIZE_CALC(1, 0) + \
3246 					(NVS_XDR_DATA_LEN(x) * 2) + \
3247 					NV_ALIGN4((NVS_XDR_DATA_LEN(x) / 4)))
3248 
3249 static int
3250 nvs_xdr_nvpair(nvstream_t *nvs, nvpair_t *nvp, size_t *size)
3251 {
3252 	XDR 	*xdr = nvs->nvs_private;
3253 	int32_t	encode_len, decode_len;
3254 
3255 	switch (nvs->nvs_op) {
3256 	case NVS_OP_ENCODE: {
3257 		size_t nvsize;
3258 
3259 		if (nvs_xdr_nvp_size(nvs, nvp, &nvsize) != 0)
3260 			return (EFAULT);
3261 
3262 		decode_len = nvp->nvp_size;
3263 		encode_len = nvsize;
3264 		if (!xdr_int(xdr, &encode_len) || !xdr_int(xdr, &decode_len))
3265 			return (EFAULT);
3266 
3267 		return (nvs_xdr_nvp_op(nvs, nvp));
3268 	}
3269 	case NVS_OP_DECODE: {
3270 		struct xdr_bytesrec bytesrec;
3271 
3272 		/* get the encode and decode size */
3273 		if (!xdr_int(xdr, &encode_len) || !xdr_int(xdr, &decode_len))
3274 			return (EFAULT);
3275 		*size = decode_len;
3276 
3277 		/* are we at the end of the stream? */
3278 		if (*size == 0)
3279 			return (0);
3280 
3281 		/* sanity check the size parameter */
3282 		if (!xdr_control(xdr, XDR_GET_BYTES_AVAIL, &bytesrec))
3283 			return (EFAULT);
3284 
3285 		if (*size > NVS_XDR_MAX_LEN(bytesrec.xc_num_avail))
3286 			return (EFAULT);
3287 		break;
3288 	}
3289 
3290 	default:
3291 		return (EINVAL);
3292 	}
3293 	return (0);
3294 }
3295 
3296 static const struct nvs_ops nvs_xdr_ops = {
3297 	nvs_xdr_nvlist,
3298 	nvs_xdr_nvpair,
3299 	nvs_xdr_nvp_op,
3300 	nvs_xdr_nvp_size,
3301 	nvs_xdr_nvl_fini
3302 };
3303 
3304 static int
3305 nvs_xdr(nvstream_t *nvs, nvlist_t *nvl, char *buf, size_t *buflen)
3306 {
3307 	XDR xdr;
3308 	int err;
3309 
3310 	nvs->nvs_ops = &nvs_xdr_ops;
3311 
3312 	if ((err = nvs_xdr_create(nvs, &xdr, buf + sizeof (nvs_header_t),
3313 	    *buflen - sizeof (nvs_header_t))) != 0)
3314 		return (err);
3315 
3316 	err = nvs_operation(nvs, nvl, buflen);
3317 
3318 	nvs_xdr_destroy(nvs);
3319 
3320 	return (err);
3321 }
3322