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