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