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