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