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