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