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