nvpair.c revision f6e214c7418f43af38bd8c3a557e3d0a1d311cfa
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			if (nvlp[i] != NULL)
544				nvlist_free(nvlp[i]);
545		break;
546	}
547	default:
548		break;
549	}
550}
551
552/*
553 * nvlist_free - free an unpacked nvlist
554 */
555void
556nvlist_free(nvlist_t *nvl)
557{
558	nvpriv_t *priv;
559	i_nvp_t *curr;
560
561	if (nvl == NULL ||
562	    (priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL)
563		return;
564
565	/*
566	 * Unpacked nvlist are linked through i_nvp_t
567	 */
568	curr = priv->nvp_list;
569	while (curr != NULL) {
570		nvpair_t *nvp = &curr->nvi_nvp;
571		curr = curr->nvi_next;
572
573		nvpair_free(nvp);
574		nvp_buf_free(nvl, nvp);
575	}
576
577	if (!(priv->nvp_stat & NV_STAT_EMBEDDED))
578		nv_mem_free(priv, nvl, NV_ALIGN(sizeof (nvlist_t)));
579	else
580		nvl->nvl_priv = 0;
581
582	nv_mem_free(priv, priv, sizeof (nvpriv_t));
583}
584
585static int
586nvlist_contains_nvp(nvlist_t *nvl, nvpair_t *nvp)
587{
588	nvpriv_t *priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv;
589	i_nvp_t *curr;
590
591	if (nvp == NULL)
592		return (0);
593
594	for (curr = priv->nvp_list; curr != NULL; curr = curr->nvi_next)
595		if (&curr->nvi_nvp == nvp)
596			return (1);
597
598	return (0);
599}
600
601/*
602 * Make a copy of nvlist
603 */
604/*ARGSUSED1*/
605int
606nvlist_dup(nvlist_t *nvl, nvlist_t **nvlp, int kmflag)
607{
608#if defined(_KERNEL) && !defined(_BOOT)
609	return (nvlist_xdup(nvl, nvlp,
610	    (kmflag == KM_SLEEP ? nv_alloc_sleep : nv_alloc_nosleep)));
611#else
612	return (nvlist_xdup(nvl, nvlp, nv_alloc_nosleep));
613#endif
614}
615
616int
617nvlist_xdup(nvlist_t *nvl, nvlist_t **nvlp, nv_alloc_t *nva)
618{
619	int err;
620	nvlist_t *ret;
621
622	if (nvl == NULL || nvlp == NULL)
623		return (EINVAL);
624
625	if ((err = nvlist_xalloc(&ret, nvl->nvl_nvflag, nva)) != 0)
626		return (err);
627
628	if ((err = nvlist_copy_pairs(nvl, ret)) != 0)
629		nvlist_free(ret);
630	else
631		*nvlp = ret;
632
633	return (err);
634}
635
636/*
637 * Remove all with matching name
638 */
639int
640nvlist_remove_all(nvlist_t *nvl, const char *name)
641{
642	nvpriv_t *priv;
643	i_nvp_t *curr;
644	int error = ENOENT;
645
646	if (nvl == NULL || name == NULL ||
647	    (priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL)
648		return (EINVAL);
649
650	curr = priv->nvp_list;
651	while (curr != NULL) {
652		nvpair_t *nvp = &curr->nvi_nvp;
653
654		curr = curr->nvi_next;
655		if (strcmp(name, NVP_NAME(nvp)) != 0)
656			continue;
657
658		nvp_buf_unlink(nvl, nvp);
659		nvpair_free(nvp);
660		nvp_buf_free(nvl, nvp);
661
662		error = 0;
663	}
664
665	return (error);
666}
667
668/*
669 * Remove first one with matching name and type
670 */
671int
672nvlist_remove(nvlist_t *nvl, const char *name, data_type_t type)
673{
674	nvpriv_t *priv;
675	i_nvp_t *curr;
676
677	if (nvl == NULL || name == NULL ||
678	    (priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL)
679		return (EINVAL);
680
681	curr = priv->nvp_list;
682	while (curr != NULL) {
683		nvpair_t *nvp = &curr->nvi_nvp;
684
685		if (strcmp(name, NVP_NAME(nvp)) == 0 && NVP_TYPE(nvp) == type) {
686			nvp_buf_unlink(nvl, nvp);
687			nvpair_free(nvp);
688			nvp_buf_free(nvl, nvp);
689
690			return (0);
691		}
692		curr = curr->nvi_next;
693	}
694
695	return (ENOENT);
696}
697
698int
699nvlist_remove_nvpair(nvlist_t *nvl, nvpair_t *nvp)
700{
701	if (nvl == NULL || nvp == NULL)
702		return (EINVAL);
703
704	nvp_buf_unlink(nvl, nvp);
705	nvpair_free(nvp);
706	nvp_buf_free(nvl, nvp);
707	return (0);
708}
709
710/*
711 * This function calculates the size of an nvpair value.
712 *
713 * The data argument controls the behavior in case of the data types
714 * 	DATA_TYPE_STRING    	and
715 *	DATA_TYPE_STRING_ARRAY
716 * Is data == NULL then the size of the string(s) is excluded.
717 */
718static int
719i_get_value_size(data_type_t type, const void *data, uint_t nelem)
720{
721	uint64_t value_sz;
722
723	if (i_validate_type_nelem(type, nelem) != 0)
724		return (-1);
725
726	/* Calculate required size for holding value */
727	switch (type) {
728	case DATA_TYPE_BOOLEAN:
729		value_sz = 0;
730		break;
731	case DATA_TYPE_BOOLEAN_VALUE:
732		value_sz = sizeof (boolean_t);
733		break;
734	case DATA_TYPE_BYTE:
735		value_sz = sizeof (uchar_t);
736		break;
737	case DATA_TYPE_INT8:
738		value_sz = sizeof (int8_t);
739		break;
740	case DATA_TYPE_UINT8:
741		value_sz = sizeof (uint8_t);
742		break;
743	case DATA_TYPE_INT16:
744		value_sz = sizeof (int16_t);
745		break;
746	case DATA_TYPE_UINT16:
747		value_sz = sizeof (uint16_t);
748		break;
749	case DATA_TYPE_INT32:
750		value_sz = sizeof (int32_t);
751		break;
752	case DATA_TYPE_UINT32:
753		value_sz = sizeof (uint32_t);
754		break;
755	case DATA_TYPE_INT64:
756		value_sz = sizeof (int64_t);
757		break;
758	case DATA_TYPE_UINT64:
759		value_sz = sizeof (uint64_t);
760		break;
761#if !defined(_KERNEL)
762	case DATA_TYPE_DOUBLE:
763		value_sz = sizeof (double);
764		break;
765#endif
766	case DATA_TYPE_STRING:
767		if (data == NULL)
768			value_sz = 0;
769		else
770			value_sz = strlen(data) + 1;
771		break;
772	case DATA_TYPE_BOOLEAN_ARRAY:
773		value_sz = (uint64_t)nelem * sizeof (boolean_t);
774		break;
775	case DATA_TYPE_BYTE_ARRAY:
776		value_sz = (uint64_t)nelem * sizeof (uchar_t);
777		break;
778	case DATA_TYPE_INT8_ARRAY:
779		value_sz = (uint64_t)nelem * sizeof (int8_t);
780		break;
781	case DATA_TYPE_UINT8_ARRAY:
782		value_sz = (uint64_t)nelem * sizeof (uint8_t);
783		break;
784	case DATA_TYPE_INT16_ARRAY:
785		value_sz = (uint64_t)nelem * sizeof (int16_t);
786		break;
787	case DATA_TYPE_UINT16_ARRAY:
788		value_sz = (uint64_t)nelem * sizeof (uint16_t);
789		break;
790	case DATA_TYPE_INT32_ARRAY:
791		value_sz = (uint64_t)nelem * sizeof (int32_t);
792		break;
793	case DATA_TYPE_UINT32_ARRAY:
794		value_sz = (uint64_t)nelem * sizeof (uint32_t);
795		break;
796	case DATA_TYPE_INT64_ARRAY:
797		value_sz = (uint64_t)nelem * sizeof (int64_t);
798		break;
799	case DATA_TYPE_UINT64_ARRAY:
800		value_sz = (uint64_t)nelem * sizeof (uint64_t);
801		break;
802	case DATA_TYPE_STRING_ARRAY:
803		value_sz = (uint64_t)nelem * sizeof (uint64_t);
804
805		if (data != NULL) {
806			char *const *strs = data;
807			uint_t i;
808
809			/* no alignment requirement for strings */
810			for (i = 0; i < nelem; i++) {
811				if (strs[i] == NULL)
812					return (-1);
813				value_sz += strlen(strs[i]) + 1;
814			}
815		}
816		break;
817	case DATA_TYPE_HRTIME:
818		value_sz = sizeof (hrtime_t);
819		break;
820	case DATA_TYPE_NVLIST:
821		value_sz = NV_ALIGN(sizeof (nvlist_t));
822		break;
823	case DATA_TYPE_NVLIST_ARRAY:
824		value_sz = (uint64_t)nelem * sizeof (uint64_t) +
825		    (uint64_t)nelem * NV_ALIGN(sizeof (nvlist_t));
826		break;
827	default:
828		return (-1);
829	}
830
831	return (value_sz > INT32_MAX ? -1 : (int)value_sz);
832}
833
834static int
835nvlist_copy_embedded(nvlist_t *nvl, nvlist_t *onvl, nvlist_t *emb_nvl)
836{
837	nvpriv_t *priv;
838	int err;
839
840	if ((priv = nv_priv_alloc_embedded((nvpriv_t *)(uintptr_t)
841	    nvl->nvl_priv)) == NULL)
842		return (ENOMEM);
843
844	nvlist_init(emb_nvl, onvl->nvl_nvflag, priv);
845
846	if ((err = nvlist_copy_pairs(onvl, emb_nvl)) != 0) {
847		nvlist_free(emb_nvl);
848		emb_nvl->nvl_priv = 0;
849	}
850
851	return (err);
852}
853
854/*
855 * nvlist_add_common - Add new <name,value> pair to nvlist
856 */
857static int
858nvlist_add_common(nvlist_t *nvl, const char *name,
859    data_type_t type, uint_t nelem, const void *data)
860{
861	nvpair_t *nvp;
862	uint_t i;
863
864	int nvp_sz, name_sz, value_sz;
865	int err = 0;
866
867	if (name == NULL || nvl == NULL || nvl->nvl_priv == 0)
868		return (EINVAL);
869
870	if (nelem != 0 && data == NULL)
871		return (EINVAL);
872
873	/*
874	 * Verify type and nelem and get the value size.
875	 * In case of data types DATA_TYPE_STRING and DATA_TYPE_STRING_ARRAY
876	 * is the size of the string(s) included.
877	 */
878	if ((value_sz = i_get_value_size(type, data, nelem)) < 0)
879		return (EINVAL);
880
881	if (i_validate_nvpair_value(type, nelem, data) != 0)
882		return (EINVAL);
883
884	/*
885	 * If we're adding an nvlist or nvlist array, ensure that we are not
886	 * adding the input nvlist to itself, which would cause recursion,
887	 * and ensure that no NULL nvlist pointers are present.
888	 */
889	switch (type) {
890	case DATA_TYPE_NVLIST:
891		if (data == nvl || data == NULL)
892			return (EINVAL);
893		break;
894	case DATA_TYPE_NVLIST_ARRAY: {
895		nvlist_t **onvlp = (nvlist_t **)data;
896		for (i = 0; i < nelem; i++) {
897			if (onvlp[i] == nvl || onvlp[i] == NULL)
898				return (EINVAL);
899		}
900		break;
901	}
902	default:
903		break;
904	}
905
906	/* calculate sizes of the nvpair elements and the nvpair itself */
907	name_sz = strlen(name) + 1;
908
909	nvp_sz = NVP_SIZE_CALC(name_sz, value_sz);
910
911	if ((nvp = nvp_buf_alloc(nvl, nvp_sz)) == NULL)
912		return (ENOMEM);
913
914	ASSERT(nvp->nvp_size == nvp_sz);
915	nvp->nvp_name_sz = name_sz;
916	nvp->nvp_value_elem = nelem;
917	nvp->nvp_type = type;
918	bcopy(name, NVP_NAME(nvp), name_sz);
919
920	switch (type) {
921	case DATA_TYPE_BOOLEAN:
922		break;
923	case DATA_TYPE_STRING_ARRAY: {
924		char *const *strs = data;
925		char *buf = NVP_VALUE(nvp);
926		char **cstrs = (void *)buf;
927
928		/* skip pre-allocated space for pointer array */
929		buf += nelem * sizeof (uint64_t);
930		for (i = 0; i < nelem; i++) {
931			int slen = strlen(strs[i]) + 1;
932			bcopy(strs[i], buf, slen);
933			cstrs[i] = buf;
934			buf += slen;
935		}
936		break;
937	}
938	case DATA_TYPE_NVLIST: {
939		nvlist_t *nnvl = EMBEDDED_NVL(nvp);
940		nvlist_t *onvl = (nvlist_t *)data;
941
942		if ((err = nvlist_copy_embedded(nvl, onvl, nnvl)) != 0) {
943			nvp_buf_free(nvl, nvp);
944			return (err);
945		}
946		break;
947	}
948	case DATA_TYPE_NVLIST_ARRAY: {
949		nvlist_t **onvlp = (nvlist_t **)data;
950		nvlist_t **nvlp = EMBEDDED_NVL_ARRAY(nvp);
951		nvlist_t *embedded = (nvlist_t *)
952		    ((uintptr_t)nvlp + nelem * sizeof (uint64_t));
953
954		for (i = 0; i < nelem; i++) {
955			if ((err = nvlist_copy_embedded(nvl,
956			    onvlp[i], embedded)) != 0) {
957				/*
958				 * Free any successfully created lists
959				 */
960				nvpair_free(nvp);
961				nvp_buf_free(nvl, nvp);
962				return (err);
963			}
964
965			nvlp[i] = embedded++;
966		}
967		break;
968	}
969	default:
970		bcopy(data, NVP_VALUE(nvp), value_sz);
971	}
972
973	/* if unique name, remove before add */
974	if (nvl->nvl_nvflag & NV_UNIQUE_NAME)
975		(void) nvlist_remove_all(nvl, name);
976	else if (nvl->nvl_nvflag & NV_UNIQUE_NAME_TYPE)
977		(void) nvlist_remove(nvl, name, type);
978
979	nvp_buf_link(nvl, nvp);
980
981	return (0);
982}
983
984int
985nvlist_add_boolean(nvlist_t *nvl, const char *name)
986{
987	return (nvlist_add_common(nvl, name, DATA_TYPE_BOOLEAN, 0, NULL));
988}
989
990int
991nvlist_add_boolean_value(nvlist_t *nvl, const char *name, boolean_t val)
992{
993	return (nvlist_add_common(nvl, name, DATA_TYPE_BOOLEAN_VALUE, 1, &val));
994}
995
996int
997nvlist_add_byte(nvlist_t *nvl, const char *name, uchar_t val)
998{
999	return (nvlist_add_common(nvl, name, DATA_TYPE_BYTE, 1, &val));
1000}
1001
1002int
1003nvlist_add_int8(nvlist_t *nvl, const char *name, int8_t val)
1004{
1005	return (nvlist_add_common(nvl, name, DATA_TYPE_INT8, 1, &val));
1006}
1007
1008int
1009nvlist_add_uint8(nvlist_t *nvl, const char *name, uint8_t val)
1010{
1011	return (nvlist_add_common(nvl, name, DATA_TYPE_UINT8, 1, &val));
1012}
1013
1014int
1015nvlist_add_int16(nvlist_t *nvl, const char *name, int16_t val)
1016{
1017	return (nvlist_add_common(nvl, name, DATA_TYPE_INT16, 1, &val));
1018}
1019
1020int
1021nvlist_add_uint16(nvlist_t *nvl, const char *name, uint16_t val)
1022{
1023	return (nvlist_add_common(nvl, name, DATA_TYPE_UINT16, 1, &val));
1024}
1025
1026int
1027nvlist_add_int32(nvlist_t *nvl, const char *name, int32_t val)
1028{
1029	return (nvlist_add_common(nvl, name, DATA_TYPE_INT32, 1, &val));
1030}
1031
1032int
1033nvlist_add_uint32(nvlist_t *nvl, const char *name, uint32_t val)
1034{
1035	return (nvlist_add_common(nvl, name, DATA_TYPE_UINT32, 1, &val));
1036}
1037
1038int
1039nvlist_add_int64(nvlist_t *nvl, const char *name, int64_t val)
1040{
1041	return (nvlist_add_common(nvl, name, DATA_TYPE_INT64, 1, &val));
1042}
1043
1044int
1045nvlist_add_uint64(nvlist_t *nvl, const char *name, uint64_t val)
1046{
1047	return (nvlist_add_common(nvl, name, DATA_TYPE_UINT64, 1, &val));
1048}
1049
1050#if !defined(_KERNEL)
1051int
1052nvlist_add_double(nvlist_t *nvl, const char *name, double val)
1053{
1054	return (nvlist_add_common(nvl, name, DATA_TYPE_DOUBLE, 1, &val));
1055}
1056#endif
1057
1058int
1059nvlist_add_string(nvlist_t *nvl, const char *name, const char *val)
1060{
1061	return (nvlist_add_common(nvl, name, DATA_TYPE_STRING, 1, (void *)val));
1062}
1063
1064int
1065nvlist_add_boolean_array(nvlist_t *nvl, const char *name,
1066    boolean_t *a, uint_t n)
1067{
1068	return (nvlist_add_common(nvl, name, DATA_TYPE_BOOLEAN_ARRAY, n, a));
1069}
1070
1071int
1072nvlist_add_byte_array(nvlist_t *nvl, const char *name, uchar_t *a, uint_t n)
1073{
1074	return (nvlist_add_common(nvl, name, DATA_TYPE_BYTE_ARRAY, n, a));
1075}
1076
1077int
1078nvlist_add_int8_array(nvlist_t *nvl, const char *name, int8_t *a, uint_t n)
1079{
1080	return (nvlist_add_common(nvl, name, DATA_TYPE_INT8_ARRAY, n, a));
1081}
1082
1083int
1084nvlist_add_uint8_array(nvlist_t *nvl, const char *name, uint8_t *a, uint_t n)
1085{
1086	return (nvlist_add_common(nvl, name, DATA_TYPE_UINT8_ARRAY, n, a));
1087}
1088
1089int
1090nvlist_add_int16_array(nvlist_t *nvl, const char *name, int16_t *a, uint_t n)
1091{
1092	return (nvlist_add_common(nvl, name, DATA_TYPE_INT16_ARRAY, n, a));
1093}
1094
1095int
1096nvlist_add_uint16_array(nvlist_t *nvl, const char *name, uint16_t *a, uint_t n)
1097{
1098	return (nvlist_add_common(nvl, name, DATA_TYPE_UINT16_ARRAY, n, a));
1099}
1100
1101int
1102nvlist_add_int32_array(nvlist_t *nvl, const char *name, int32_t *a, uint_t n)
1103{
1104	return (nvlist_add_common(nvl, name, DATA_TYPE_INT32_ARRAY, n, a));
1105}
1106
1107int
1108nvlist_add_uint32_array(nvlist_t *nvl, const char *name, uint32_t *a, uint_t n)
1109{
1110	return (nvlist_add_common(nvl, name, DATA_TYPE_UINT32_ARRAY, n, a));
1111}
1112
1113int
1114nvlist_add_int64_array(nvlist_t *nvl, const char *name, int64_t *a, uint_t n)
1115{
1116	return (nvlist_add_common(nvl, name, DATA_TYPE_INT64_ARRAY, n, a));
1117}
1118
1119int
1120nvlist_add_uint64_array(nvlist_t *nvl, const char *name, uint64_t *a, uint_t n)
1121{
1122	return (nvlist_add_common(nvl, name, DATA_TYPE_UINT64_ARRAY, n, a));
1123}
1124
1125int
1126nvlist_add_string_array(nvlist_t *nvl, const char *name,
1127    char *const *a, uint_t n)
1128{
1129	return (nvlist_add_common(nvl, name, DATA_TYPE_STRING_ARRAY, n, a));
1130}
1131
1132int
1133nvlist_add_hrtime(nvlist_t *nvl, const char *name, hrtime_t val)
1134{
1135	return (nvlist_add_common(nvl, name, DATA_TYPE_HRTIME, 1, &val));
1136}
1137
1138int
1139nvlist_add_nvlist(nvlist_t *nvl, const char *name, nvlist_t *val)
1140{
1141	return (nvlist_add_common(nvl, name, DATA_TYPE_NVLIST, 1, val));
1142}
1143
1144int
1145nvlist_add_nvlist_array(nvlist_t *nvl, const char *name, nvlist_t **a, uint_t n)
1146{
1147	return (nvlist_add_common(nvl, name, DATA_TYPE_NVLIST_ARRAY, n, a));
1148}
1149
1150/* reading name-value pairs */
1151nvpair_t *
1152nvlist_next_nvpair(nvlist_t *nvl, nvpair_t *nvp)
1153{
1154	nvpriv_t *priv;
1155	i_nvp_t *curr;
1156
1157	if (nvl == NULL ||
1158	    (priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL)
1159		return (NULL);
1160
1161	curr = NVPAIR2I_NVP(nvp);
1162
1163	/*
1164	 * Ensure that nvp is a valid nvpair on this nvlist.
1165	 * NB: nvp_curr is used only as a hint so that we don't always
1166	 * have to walk the list to determine if nvp is still on the list.
1167	 */
1168	if (nvp == NULL)
1169		curr = priv->nvp_list;
1170	else if (priv->nvp_curr == curr || nvlist_contains_nvp(nvl, nvp))
1171		curr = curr->nvi_next;
1172	else
1173		curr = NULL;
1174
1175	priv->nvp_curr = curr;
1176
1177	return (curr != NULL ? &curr->nvi_nvp : NULL);
1178}
1179
1180nvpair_t *
1181nvlist_prev_nvpair(nvlist_t *nvl, nvpair_t *nvp)
1182{
1183	nvpriv_t *priv;
1184	i_nvp_t *curr;
1185
1186	if (nvl == NULL ||
1187	    (priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL)
1188		return (NULL);
1189
1190	curr = NVPAIR2I_NVP(nvp);
1191
1192	if (nvp == NULL)
1193		curr = priv->nvp_last;
1194	else if (priv->nvp_curr == curr || nvlist_contains_nvp(nvl, nvp))
1195		curr = curr->nvi_prev;
1196	else
1197		curr = NULL;
1198
1199	priv->nvp_curr = curr;
1200
1201	return (curr != NULL ? &curr->nvi_nvp : NULL);
1202}
1203
1204boolean_t
1205nvlist_empty(nvlist_t *nvl)
1206{
1207	nvpriv_t *priv;
1208
1209	if (nvl == NULL ||
1210	    (priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL)
1211		return (B_TRUE);
1212
1213	return (priv->nvp_list == NULL);
1214}
1215
1216char *
1217nvpair_name(nvpair_t *nvp)
1218{
1219	return (NVP_NAME(nvp));
1220}
1221
1222data_type_t
1223nvpair_type(nvpair_t *nvp)
1224{
1225	return (NVP_TYPE(nvp));
1226}
1227
1228int
1229nvpair_type_is_array(nvpair_t *nvp)
1230{
1231	data_type_t type = NVP_TYPE(nvp);
1232
1233	if ((type == DATA_TYPE_BYTE_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	/* step through components of name */
1629	for (np = name; np && *np; np = sepp) {
1630		/* ensure unique names */
1631		if (!(nvl->nvl_nvflag & NV_UNIQUE_NAME))
1632			return (ENOTSUP);
1633
1634		/* skip white space */
1635		skip_whitespace(np);
1636		if (*np == 0)
1637			break;
1638
1639		/* set 'sepp' to end of current component 'np' */
1640		if (sep)
1641			sepp = strchr(np, sep);
1642		else
1643			sepp = NULL;
1644
1645		/* find start of next "[ index ]..." */
1646		idxp = strchr(np, '[');
1647
1648		/* if sepp comes first, set idxp to NULL */
1649		if (sepp && idxp && (sepp < idxp))
1650			idxp = NULL;
1651
1652		/*
1653		 * At this point 'idxp' is set if there is an index
1654		 * expected for the current component.
1655		 */
1656		if (idxp) {
1657			/* set 'n' to length of current 'np' name component */
1658			n = idxp++ - np;
1659
1660			/* keep sepp up to date for *ep use as we advance */
1661			skip_whitespace(idxp);
1662			sepp = idxp;
1663
1664			/* determine the index value */
1665#if defined(_KERNEL) && !defined(_BOOT)
1666			if (ddi_strtol(idxp, &idxep, 0, &idx))
1667				goto fail;
1668#else
1669			idx = strtol(idxp, &idxep, 0);
1670#endif
1671			if (idxep == idxp)
1672				goto fail;
1673
1674			/* keep sepp up to date for *ep use as we advance */
1675			sepp = idxep;
1676
1677			/* skip white space index value and check for ']' */
1678			skip_whitespace(sepp);
1679			if (*sepp++ != ']')
1680				goto fail;
1681
1682			/* for embedded arrays, support C syntax: "a[1].b" */
1683			skip_whitespace(sepp);
1684			if (sep && (*sepp == sep))
1685				sepp++;
1686		} else if (sepp) {
1687			n = sepp++ - np;
1688		} else {
1689			n = strlen(np);
1690		}
1691
1692		/* trim trailing whitespace by reducing length of 'np' */
1693		if (n == 0)
1694			goto fail;
1695		for (n--; (np[n] == ' ') || (np[n] == '\t'); n--)
1696			;
1697		n++;
1698
1699		/* skip whitespace, and set sepp to NULL if complete */
1700		if (sepp) {
1701			skip_whitespace(sepp);
1702			if (*sepp == 0)
1703				sepp = NULL;
1704		}
1705
1706		/*
1707		 * At this point:
1708		 * o  'n' is the length of current 'np' component.
1709		 * o  'idxp' is set if there was an index, and value 'idx'.
1710		 * o  'sepp' is set to the beginning of the next component,
1711		 *    and set to NULL if we have no more components.
1712		 *
1713		 * Search for nvpair with matching component name.
1714		 */
1715		for (nvp = nvlist_next_nvpair(nvl, NULL); nvp != NULL;
1716		    nvp = nvlist_next_nvpair(nvl, nvp)) {
1717
1718			/* continue if no match on name */
1719			if (strncmp(np, nvpair_name(nvp), n) ||
1720			    (strlen(nvpair_name(nvp)) != n))
1721				continue;
1722
1723			/* if indexed, verify type is array oriented */
1724			if (idxp && !nvpair_type_is_array(nvp))
1725				goto fail;
1726
1727			/*
1728			 * Full match found, return nvp and idx if this
1729			 * was the last component.
1730			 */
1731			if (sepp == NULL) {
1732				if (ret)
1733					*ret = nvp;
1734				if (ip && idxp)
1735					*ip = (int)idx;	/* return index */
1736				return (0);		/* found */
1737			}
1738
1739			/*
1740			 * More components: current match must be
1741			 * of DATA_TYPE_NVLIST or DATA_TYPE_NVLIST_ARRAY
1742			 * to support going deeper.
1743			 */
1744			if (nvpair_type(nvp) == DATA_TYPE_NVLIST) {
1745				nvl = EMBEDDED_NVL(nvp);
1746				break;
1747			} else if (nvpair_type(nvp) == DATA_TYPE_NVLIST_ARRAY) {
1748				(void) nvpair_value_nvlist_array(nvp,
1749				    &nva, (uint_t *)&n);
1750				if ((n < 0) || (idx >= n))
1751					goto fail;
1752				nvl = nva[idx];
1753				break;
1754			}
1755
1756			/* type does not support more levels */
1757			goto fail;
1758		}
1759		if (nvp == NULL)
1760			goto fail;		/* 'name' not found */
1761
1762		/* search for match of next component in embedded 'nvl' list */
1763	}
1764
1765fail:	if (ep && sepp)
1766		*ep = sepp;
1767	return (EINVAL);
1768}
1769
1770/*
1771 * Return pointer to nvpair with specified 'name'.
1772 */
1773int
1774nvlist_lookup_nvpair(nvlist_t *nvl, const char *name, nvpair_t **ret)
1775{
1776	return (nvlist_lookup_nvpair_ei_sep(nvl, name, 0, ret, NULL, NULL));
1777}
1778
1779/*
1780 * Determine if named nvpair exists in nvlist (use embedded separator of '.'
1781 * and return array index).  See nvlist_lookup_nvpair_ei_sep for more detailed
1782 * description.
1783 */
1784int nvlist_lookup_nvpair_embedded_index(nvlist_t *nvl,
1785    const char *name, nvpair_t **ret, int *ip, char **ep)
1786{
1787	return (nvlist_lookup_nvpair_ei_sep(nvl, name, '.', ret, ip, ep));
1788}
1789
1790boolean_t
1791nvlist_exists(nvlist_t *nvl, const char *name)
1792{
1793	nvpriv_t *priv;
1794	nvpair_t *nvp;
1795	i_nvp_t *curr;
1796
1797	if (name == NULL || nvl == NULL ||
1798	    (priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL)
1799		return (B_FALSE);
1800
1801	for (curr = priv->nvp_list; curr != NULL; curr = curr->nvi_next) {
1802		nvp = &curr->nvi_nvp;
1803
1804		if (strcmp(name, NVP_NAME(nvp)) == 0)
1805			return (B_TRUE);
1806	}
1807
1808	return (B_FALSE);
1809}
1810
1811int
1812nvpair_value_boolean_value(nvpair_t *nvp, boolean_t *val)
1813{
1814	return (nvpair_value_common(nvp, DATA_TYPE_BOOLEAN_VALUE, NULL, val));
1815}
1816
1817int
1818nvpair_value_byte(nvpair_t *nvp, uchar_t *val)
1819{
1820	return (nvpair_value_common(nvp, DATA_TYPE_BYTE, NULL, val));
1821}
1822
1823int
1824nvpair_value_int8(nvpair_t *nvp, int8_t *val)
1825{
1826	return (nvpair_value_common(nvp, DATA_TYPE_INT8, NULL, val));
1827}
1828
1829int
1830nvpair_value_uint8(nvpair_t *nvp, uint8_t *val)
1831{
1832	return (nvpair_value_common(nvp, DATA_TYPE_UINT8, NULL, val));
1833}
1834
1835int
1836nvpair_value_int16(nvpair_t *nvp, int16_t *val)
1837{
1838	return (nvpair_value_common(nvp, DATA_TYPE_INT16, NULL, val));
1839}
1840
1841int
1842nvpair_value_uint16(nvpair_t *nvp, uint16_t *val)
1843{
1844	return (nvpair_value_common(nvp, DATA_TYPE_UINT16, NULL, val));
1845}
1846
1847int
1848nvpair_value_int32(nvpair_t *nvp, int32_t *val)
1849{
1850	return (nvpair_value_common(nvp, DATA_TYPE_INT32, NULL, val));
1851}
1852
1853int
1854nvpair_value_uint32(nvpair_t *nvp, uint32_t *val)
1855{
1856	return (nvpair_value_common(nvp, DATA_TYPE_UINT32, NULL, val));
1857}
1858
1859int
1860nvpair_value_int64(nvpair_t *nvp, int64_t *val)
1861{
1862	return (nvpair_value_common(nvp, DATA_TYPE_INT64, NULL, val));
1863}
1864
1865int
1866nvpair_value_uint64(nvpair_t *nvp, uint64_t *val)
1867{
1868	return (nvpair_value_common(nvp, DATA_TYPE_UINT64, NULL, val));
1869}
1870
1871#if !defined(_KERNEL)
1872int
1873nvpair_value_double(nvpair_t *nvp, double *val)
1874{
1875	return (nvpair_value_common(nvp, DATA_TYPE_DOUBLE, NULL, val));
1876}
1877#endif
1878
1879int
1880nvpair_value_string(nvpair_t *nvp, char **val)
1881{
1882	return (nvpair_value_common(nvp, DATA_TYPE_STRING, NULL, val));
1883}
1884
1885int
1886nvpair_value_nvlist(nvpair_t *nvp, nvlist_t **val)
1887{
1888	return (nvpair_value_common(nvp, DATA_TYPE_NVLIST, NULL, val));
1889}
1890
1891int
1892nvpair_value_boolean_array(nvpair_t *nvp, boolean_t **val, uint_t *nelem)
1893{
1894	return (nvpair_value_common(nvp, DATA_TYPE_BOOLEAN_ARRAY, nelem, val));
1895}
1896
1897int
1898nvpair_value_byte_array(nvpair_t *nvp, uchar_t **val, uint_t *nelem)
1899{
1900	return (nvpair_value_common(nvp, DATA_TYPE_BYTE_ARRAY, nelem, val));
1901}
1902
1903int
1904nvpair_value_int8_array(nvpair_t *nvp, int8_t **val, uint_t *nelem)
1905{
1906	return (nvpair_value_common(nvp, DATA_TYPE_INT8_ARRAY, nelem, val));
1907}
1908
1909int
1910nvpair_value_uint8_array(nvpair_t *nvp, uint8_t **val, uint_t *nelem)
1911{
1912	return (nvpair_value_common(nvp, DATA_TYPE_UINT8_ARRAY, nelem, val));
1913}
1914
1915int
1916nvpair_value_int16_array(nvpair_t *nvp, int16_t **val, uint_t *nelem)
1917{
1918	return (nvpair_value_common(nvp, DATA_TYPE_INT16_ARRAY, nelem, val));
1919}
1920
1921int
1922nvpair_value_uint16_array(nvpair_t *nvp, uint16_t **val, uint_t *nelem)
1923{
1924	return (nvpair_value_common(nvp, DATA_TYPE_UINT16_ARRAY, nelem, val));
1925}
1926
1927int
1928nvpair_value_int32_array(nvpair_t *nvp, int32_t **val, uint_t *nelem)
1929{
1930	return (nvpair_value_common(nvp, DATA_TYPE_INT32_ARRAY, nelem, val));
1931}
1932
1933int
1934nvpair_value_uint32_array(nvpair_t *nvp, uint32_t **val, uint_t *nelem)
1935{
1936	return (nvpair_value_common(nvp, DATA_TYPE_UINT32_ARRAY, nelem, val));
1937}
1938
1939int
1940nvpair_value_int64_array(nvpair_t *nvp, int64_t **val, uint_t *nelem)
1941{
1942	return (nvpair_value_common(nvp, DATA_TYPE_INT64_ARRAY, nelem, val));
1943}
1944
1945int
1946nvpair_value_uint64_array(nvpair_t *nvp, uint64_t **val, uint_t *nelem)
1947{
1948	return (nvpair_value_common(nvp, DATA_TYPE_UINT64_ARRAY, nelem, val));
1949}
1950
1951int
1952nvpair_value_string_array(nvpair_t *nvp, char ***val, uint_t *nelem)
1953{
1954	return (nvpair_value_common(nvp, DATA_TYPE_STRING_ARRAY, nelem, val));
1955}
1956
1957int
1958nvpair_value_nvlist_array(nvpair_t *nvp, nvlist_t ***val, uint_t *nelem)
1959{
1960	return (nvpair_value_common(nvp, DATA_TYPE_NVLIST_ARRAY, nelem, val));
1961}
1962
1963int
1964nvpair_value_hrtime(nvpair_t *nvp, hrtime_t *val)
1965{
1966	return (nvpair_value_common(nvp, DATA_TYPE_HRTIME, NULL, val));
1967}
1968
1969/*
1970 * Add specified pair to the list.
1971 */
1972int
1973nvlist_add_nvpair(nvlist_t *nvl, nvpair_t *nvp)
1974{
1975	if (nvl == NULL || nvp == NULL)
1976		return (EINVAL);
1977
1978	return (nvlist_add_common(nvl, NVP_NAME(nvp), NVP_TYPE(nvp),
1979	    NVP_NELEM(nvp), NVP_VALUE(nvp)));
1980}
1981
1982/*
1983 * Merge the supplied nvlists and put the result in dst.
1984 * The merged list will contain all names specified in both lists,
1985 * the values are taken from nvl in the case of duplicates.
1986 * Return 0 on success.
1987 */
1988/*ARGSUSED*/
1989int
1990nvlist_merge(nvlist_t *dst, nvlist_t *nvl, int flag)
1991{
1992	if (nvl == NULL || dst == NULL)
1993		return (EINVAL);
1994
1995	if (dst != nvl)
1996		return (nvlist_copy_pairs(nvl, dst));
1997
1998	return (0);
1999}
2000
2001/*
2002 * Encoding related routines
2003 */
2004#define	NVS_OP_ENCODE	0
2005#define	NVS_OP_DECODE	1
2006#define	NVS_OP_GETSIZE	2
2007
2008typedef struct nvs_ops nvs_ops_t;
2009
2010typedef struct {
2011	int		nvs_op;
2012	const nvs_ops_t	*nvs_ops;
2013	void		*nvs_private;
2014	nvpriv_t	*nvs_priv;
2015} nvstream_t;
2016
2017/*
2018 * nvs operations are:
2019 *   - nvs_nvlist
2020 *     encoding / decoding of a nvlist header (nvlist_t)
2021 *     calculates the size used for header and end detection
2022 *
2023 *   - nvs_nvpair
2024 *     responsible for the first part of encoding / decoding of an nvpair
2025 *     calculates the decoded size of an nvpair
2026 *
2027 *   - nvs_nvp_op
2028 *     second part of encoding / decoding of an nvpair
2029 *
2030 *   - nvs_nvp_size
2031 *     calculates the encoding size of an nvpair
2032 *
2033 *   - nvs_nvl_fini
2034 *     encodes the end detection mark (zeros).
2035 */
2036struct nvs_ops {
2037	int (*nvs_nvlist)(nvstream_t *, nvlist_t *, size_t *);
2038	int (*nvs_nvpair)(nvstream_t *, nvpair_t *, size_t *);
2039	int (*nvs_nvp_op)(nvstream_t *, nvpair_t *);
2040	int (*nvs_nvp_size)(nvstream_t *, nvpair_t *, size_t *);
2041	int (*nvs_nvl_fini)(nvstream_t *);
2042};
2043
2044typedef struct {
2045	char	nvh_encoding;	/* nvs encoding method */
2046	char	nvh_endian;	/* nvs endian */
2047	char	nvh_reserved1;	/* reserved for future use */
2048	char	nvh_reserved2;	/* reserved for future use */
2049} nvs_header_t;
2050
2051static int
2052nvs_encode_pairs(nvstream_t *nvs, nvlist_t *nvl)
2053{
2054	nvpriv_t *priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv;
2055	i_nvp_t *curr;
2056
2057	/*
2058	 * Walk nvpair in list and encode each nvpair
2059	 */
2060	for (curr = priv->nvp_list; curr != NULL; curr = curr->nvi_next)
2061		if (nvs->nvs_ops->nvs_nvpair(nvs, &curr->nvi_nvp, NULL) != 0)
2062			return (EFAULT);
2063
2064	return (nvs->nvs_ops->nvs_nvl_fini(nvs));
2065}
2066
2067static int
2068nvs_decode_pairs(nvstream_t *nvs, nvlist_t *nvl)
2069{
2070	nvpair_t *nvp;
2071	size_t nvsize;
2072	int err;
2073
2074	/*
2075	 * Get decoded size of next pair in stream, alloc
2076	 * memory for nvpair_t, then decode the nvpair
2077	 */
2078	while ((err = nvs->nvs_ops->nvs_nvpair(nvs, NULL, &nvsize)) == 0) {
2079		if (nvsize == 0) /* end of list */
2080			break;
2081
2082		/* make sure len makes sense */
2083		if (nvsize < NVP_SIZE_CALC(1, 0))
2084			return (EFAULT);
2085
2086		if ((nvp = nvp_buf_alloc(nvl, nvsize)) == NULL)
2087			return (ENOMEM);
2088
2089		if ((err = nvs->nvs_ops->nvs_nvp_op(nvs, nvp)) != 0) {
2090			nvp_buf_free(nvl, nvp);
2091			return (err);
2092		}
2093
2094		if (i_validate_nvpair(nvp) != 0) {
2095			nvpair_free(nvp);
2096			nvp_buf_free(nvl, nvp);
2097			return (EFAULT);
2098		}
2099
2100		nvp_buf_link(nvl, nvp);
2101	}
2102	return (err);
2103}
2104
2105static int
2106nvs_getsize_pairs(nvstream_t *nvs, nvlist_t *nvl, size_t *buflen)
2107{
2108	nvpriv_t *priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv;
2109	i_nvp_t *curr;
2110	uint64_t nvsize = *buflen;
2111	size_t size;
2112
2113	/*
2114	 * Get encoded size of nvpairs in nvlist
2115	 */
2116	for (curr = priv->nvp_list; curr != NULL; curr = curr->nvi_next) {
2117		if (nvs->nvs_ops->nvs_nvp_size(nvs, &curr->nvi_nvp, &size) != 0)
2118			return (EINVAL);
2119
2120		if ((nvsize += size) > INT32_MAX)
2121			return (EINVAL);
2122	}
2123
2124	*buflen = nvsize;
2125	return (0);
2126}
2127
2128static int
2129nvs_operation(nvstream_t *nvs, nvlist_t *nvl, size_t *buflen)
2130{
2131	int err;
2132
2133	if (nvl->nvl_priv == 0)
2134		return (EFAULT);
2135
2136	/*
2137	 * Perform the operation, starting with header, then each nvpair
2138	 */
2139	if ((err = nvs->nvs_ops->nvs_nvlist(nvs, nvl, buflen)) != 0)
2140		return (err);
2141
2142	switch (nvs->nvs_op) {
2143	case NVS_OP_ENCODE:
2144		err = nvs_encode_pairs(nvs, nvl);
2145		break;
2146
2147	case NVS_OP_DECODE:
2148		err = nvs_decode_pairs(nvs, nvl);
2149		break;
2150
2151	case NVS_OP_GETSIZE:
2152		err = nvs_getsize_pairs(nvs, nvl, buflen);
2153		break;
2154
2155	default:
2156		err = EINVAL;
2157	}
2158
2159	return (err);
2160}
2161
2162static int
2163nvs_embedded(nvstream_t *nvs, nvlist_t *embedded)
2164{
2165	switch (nvs->nvs_op) {
2166	case NVS_OP_ENCODE:
2167		return (nvs_operation(nvs, embedded, NULL));
2168
2169	case NVS_OP_DECODE: {
2170		nvpriv_t *priv;
2171		int err;
2172
2173		if (embedded->nvl_version != NV_VERSION)
2174			return (ENOTSUP);
2175
2176		if ((priv = nv_priv_alloc_embedded(nvs->nvs_priv)) == NULL)
2177			return (ENOMEM);
2178
2179		nvlist_init(embedded, embedded->nvl_nvflag, priv);
2180
2181		if ((err = nvs_operation(nvs, embedded, NULL)) != 0)
2182			nvlist_free(embedded);
2183		return (err);
2184	}
2185	default:
2186		break;
2187	}
2188
2189	return (EINVAL);
2190}
2191
2192static int
2193nvs_embedded_nvl_array(nvstream_t *nvs, nvpair_t *nvp, size_t *size)
2194{
2195	size_t nelem = NVP_NELEM(nvp);
2196	nvlist_t **nvlp = EMBEDDED_NVL_ARRAY(nvp);
2197	int i;
2198
2199	switch (nvs->nvs_op) {
2200	case NVS_OP_ENCODE:
2201		for (i = 0; i < nelem; i++)
2202			if (nvs_embedded(nvs, nvlp[i]) != 0)
2203				return (EFAULT);
2204		break;
2205
2206	case NVS_OP_DECODE: {
2207		size_t len = nelem * sizeof (uint64_t);
2208		nvlist_t *embedded = (nvlist_t *)((uintptr_t)nvlp + len);
2209
2210		bzero(nvlp, len);	/* don't trust packed data */
2211		for (i = 0; i < nelem; i++) {
2212			if (nvs_embedded(nvs, embedded) != 0) {
2213				nvpair_free(nvp);
2214				return (EFAULT);
2215			}
2216
2217			nvlp[i] = embedded++;
2218		}
2219		break;
2220	}
2221	case NVS_OP_GETSIZE: {
2222		uint64_t nvsize = 0;
2223
2224		for (i = 0; i < nelem; i++) {
2225			size_t nvp_sz = 0;
2226
2227			if (nvs_operation(nvs, nvlp[i], &nvp_sz) != 0)
2228				return (EINVAL);
2229
2230			if ((nvsize += nvp_sz) > INT32_MAX)
2231				return (EINVAL);
2232		}
2233
2234		*size = nvsize;
2235		break;
2236	}
2237	default:
2238		return (EINVAL);
2239	}
2240
2241	return (0);
2242}
2243
2244static int nvs_native(nvstream_t *, nvlist_t *, char *, size_t *);
2245static int nvs_xdr(nvstream_t *, nvlist_t *, char *, size_t *);
2246
2247/*
2248 * Common routine for nvlist operations:
2249 * encode, decode, getsize (encoded size).
2250 */
2251static int
2252nvlist_common(nvlist_t *nvl, char *buf, size_t *buflen, int encoding,
2253    int nvs_op)
2254{
2255	int err = 0;
2256	nvstream_t nvs;
2257	int nvl_endian;
2258#ifdef	_LITTLE_ENDIAN
2259	int host_endian = 1;
2260#else
2261	int host_endian = 0;
2262#endif	/* _LITTLE_ENDIAN */
2263	nvs_header_t *nvh = (void *)buf;
2264
2265	if (buflen == NULL || nvl == NULL ||
2266	    (nvs.nvs_priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL)
2267		return (EINVAL);
2268
2269	nvs.nvs_op = nvs_op;
2270
2271	/*
2272	 * For NVS_OP_ENCODE and NVS_OP_DECODE make sure an nvlist and
2273	 * a buffer is allocated.  The first 4 bytes in the buffer are
2274	 * used for encoding method and host endian.
2275	 */
2276	switch (nvs_op) {
2277	case NVS_OP_ENCODE:
2278		if (buf == NULL || *buflen < sizeof (nvs_header_t))
2279			return (EINVAL);
2280
2281		nvh->nvh_encoding = encoding;
2282		nvh->nvh_endian = nvl_endian = host_endian;
2283		nvh->nvh_reserved1 = 0;
2284		nvh->nvh_reserved2 = 0;
2285		break;
2286
2287	case NVS_OP_DECODE:
2288		if (buf == NULL || *buflen < sizeof (nvs_header_t))
2289			return (EINVAL);
2290
2291		/* get method of encoding from first byte */
2292		encoding = nvh->nvh_encoding;
2293		nvl_endian = nvh->nvh_endian;
2294		break;
2295
2296	case NVS_OP_GETSIZE:
2297		nvl_endian = host_endian;
2298
2299		/*
2300		 * add the size for encoding
2301		 */
2302		*buflen = sizeof (nvs_header_t);
2303		break;
2304
2305	default:
2306		return (ENOTSUP);
2307	}
2308
2309	/*
2310	 * Create an nvstream with proper encoding method
2311	 */
2312	switch (encoding) {
2313	case NV_ENCODE_NATIVE:
2314		/*
2315		 * check endianness, in case we are unpacking
2316		 * from a file
2317		 */
2318		if (nvl_endian != host_endian)
2319			return (ENOTSUP);
2320		err = nvs_native(&nvs, nvl, buf, buflen);
2321		break;
2322	case NV_ENCODE_XDR:
2323		err = nvs_xdr(&nvs, nvl, buf, buflen);
2324		break;
2325	default:
2326		err = ENOTSUP;
2327		break;
2328	}
2329
2330	return (err);
2331}
2332
2333int
2334nvlist_size(nvlist_t *nvl, size_t *size, int encoding)
2335{
2336	return (nvlist_common(nvl, NULL, size, encoding, NVS_OP_GETSIZE));
2337}
2338
2339/*
2340 * Pack nvlist into contiguous memory
2341 */
2342/*ARGSUSED1*/
2343int
2344nvlist_pack(nvlist_t *nvl, char **bufp, size_t *buflen, int encoding,
2345    int kmflag)
2346{
2347#if defined(_KERNEL) && !defined(_BOOT)
2348	return (nvlist_xpack(nvl, bufp, buflen, encoding,
2349	    (kmflag == KM_SLEEP ? nv_alloc_sleep : nv_alloc_nosleep)));
2350#else
2351	return (nvlist_xpack(nvl, bufp, buflen, encoding, nv_alloc_nosleep));
2352#endif
2353}
2354
2355int
2356nvlist_xpack(nvlist_t *nvl, char **bufp, size_t *buflen, int encoding,
2357    nv_alloc_t *nva)
2358{
2359	nvpriv_t nvpriv;
2360	size_t alloc_size;
2361	char *buf;
2362	int err;
2363
2364	if (nva == NULL || nvl == NULL || bufp == NULL || buflen == NULL)
2365		return (EINVAL);
2366
2367	if (*bufp != NULL)
2368		return (nvlist_common(nvl, *bufp, buflen, encoding,
2369		    NVS_OP_ENCODE));
2370
2371	/*
2372	 * Here is a difficult situation:
2373	 * 1. The nvlist has fixed allocator properties.
2374	 *    All other nvlist routines (like nvlist_add_*, ...) use
2375	 *    these properties.
2376	 * 2. When using nvlist_pack() the user can specify his own
2377	 *    allocator properties (e.g. by using KM_NOSLEEP).
2378	 *
2379	 * We use the user specified properties (2). A clearer solution
2380	 * will be to remove the kmflag from nvlist_pack(), but we will
2381	 * not change the interface.
2382	 */
2383	nv_priv_init(&nvpriv, nva, 0);
2384
2385	if (err = nvlist_size(nvl, &alloc_size, encoding))
2386		return (err);
2387
2388	if ((buf = nv_mem_zalloc(&nvpriv, alloc_size)) == NULL)
2389		return (ENOMEM);
2390
2391	if ((err = nvlist_common(nvl, buf, &alloc_size, encoding,
2392	    NVS_OP_ENCODE)) != 0) {
2393		nv_mem_free(&nvpriv, buf, alloc_size);
2394	} else {
2395		*buflen = alloc_size;
2396		*bufp = buf;
2397	}
2398
2399	return (err);
2400}
2401
2402/*
2403 * Unpack buf into an nvlist_t
2404 */
2405/*ARGSUSED1*/
2406int
2407nvlist_unpack(char *buf, size_t buflen, nvlist_t **nvlp, int kmflag)
2408{
2409#if defined(_KERNEL) && !defined(_BOOT)
2410	return (nvlist_xunpack(buf, buflen, nvlp,
2411	    (kmflag == KM_SLEEP ? nv_alloc_sleep : nv_alloc_nosleep)));
2412#else
2413	return (nvlist_xunpack(buf, buflen, nvlp, nv_alloc_nosleep));
2414#endif
2415}
2416
2417int
2418nvlist_xunpack(char *buf, size_t buflen, nvlist_t **nvlp, nv_alloc_t *nva)
2419{
2420	nvlist_t *nvl;
2421	int err;
2422
2423	if (nvlp == NULL)
2424		return (EINVAL);
2425
2426	if ((err = nvlist_xalloc(&nvl, 0, nva)) != 0)
2427		return (err);
2428
2429	if ((err = nvlist_common(nvl, buf, &buflen, 0, NVS_OP_DECODE)) != 0)
2430		nvlist_free(nvl);
2431	else
2432		*nvlp = nvl;
2433
2434	return (err);
2435}
2436
2437/*
2438 * Native encoding functions
2439 */
2440typedef struct {
2441	/*
2442	 * This structure is used when decoding a packed nvpair in
2443	 * the native format.  n_base points to a buffer containing the
2444	 * packed nvpair.  n_end is a pointer to the end of the buffer.
2445	 * (n_end actually points to the first byte past the end of the
2446	 * buffer.)  n_curr is a pointer that lies between n_base and n_end.
2447	 * It points to the current data that we are decoding.
2448	 * The amount of data left in the buffer is equal to n_end - n_curr.
2449	 * n_flag is used to recognize a packed embedded list.
2450	 */
2451	caddr_t n_base;
2452	caddr_t n_end;
2453	caddr_t n_curr;
2454	uint_t  n_flag;
2455} nvs_native_t;
2456
2457static int
2458nvs_native_create(nvstream_t *nvs, nvs_native_t *native, char *buf,
2459    size_t buflen)
2460{
2461	switch (nvs->nvs_op) {
2462	case NVS_OP_ENCODE:
2463	case NVS_OP_DECODE:
2464		nvs->nvs_private = native;
2465		native->n_curr = native->n_base = buf;
2466		native->n_end = buf + buflen;
2467		native->n_flag = 0;
2468		return (0);
2469
2470	case NVS_OP_GETSIZE:
2471		nvs->nvs_private = native;
2472		native->n_curr = native->n_base = native->n_end = NULL;
2473		native->n_flag = 0;
2474		return (0);
2475	default:
2476		return (EINVAL);
2477	}
2478}
2479
2480/*ARGSUSED*/
2481static void
2482nvs_native_destroy(nvstream_t *nvs)
2483{
2484}
2485
2486static int
2487native_cp(nvstream_t *nvs, void *buf, size_t size)
2488{
2489	nvs_native_t *native = (nvs_native_t *)nvs->nvs_private;
2490
2491	if (native->n_curr + size > native->n_end)
2492		return (EFAULT);
2493
2494	/*
2495	 * The bcopy() below eliminates alignment requirement
2496	 * on the buffer (stream) and is preferred over direct access.
2497	 */
2498	switch (nvs->nvs_op) {
2499	case NVS_OP_ENCODE:
2500		bcopy(buf, native->n_curr, size);
2501		break;
2502	case NVS_OP_DECODE:
2503		bcopy(native->n_curr, buf, size);
2504		break;
2505	default:
2506		return (EINVAL);
2507	}
2508
2509	native->n_curr += size;
2510	return (0);
2511}
2512
2513/*
2514 * operate on nvlist_t header
2515 */
2516static int
2517nvs_native_nvlist(nvstream_t *nvs, nvlist_t *nvl, size_t *size)
2518{
2519	nvs_native_t *native = nvs->nvs_private;
2520
2521	switch (nvs->nvs_op) {
2522	case NVS_OP_ENCODE:
2523	case NVS_OP_DECODE:
2524		if (native->n_flag)
2525			return (0);	/* packed embedded list */
2526
2527		native->n_flag = 1;
2528
2529		/* copy version and nvflag of the nvlist_t */
2530		if (native_cp(nvs, &nvl->nvl_version, sizeof (int32_t)) != 0 ||
2531		    native_cp(nvs, &nvl->nvl_nvflag, sizeof (int32_t)) != 0)
2532			return (EFAULT);
2533
2534		return (0);
2535
2536	case NVS_OP_GETSIZE:
2537		/*
2538		 * if calculate for packed embedded list
2539		 * 	4 for end of the embedded list
2540		 * else
2541		 * 	2 * sizeof (int32_t) for nvl_version and nvl_nvflag
2542		 * 	and 4 for end of the entire list
2543		 */
2544		if (native->n_flag) {
2545			*size += 4;
2546		} else {
2547			native->n_flag = 1;
2548			*size += 2 * sizeof (int32_t) + 4;
2549		}
2550
2551		return (0);
2552
2553	default:
2554		return (EINVAL);
2555	}
2556}
2557
2558static int
2559nvs_native_nvl_fini(nvstream_t *nvs)
2560{
2561	if (nvs->nvs_op == NVS_OP_ENCODE) {
2562		nvs_native_t *native = (nvs_native_t *)nvs->nvs_private;
2563		/*
2564		 * Add 4 zero bytes at end of nvlist. They are used
2565		 * for end detection by the decode routine.
2566		 */
2567		if (native->n_curr + sizeof (int) > native->n_end)
2568			return (EFAULT);
2569
2570		bzero(native->n_curr, sizeof (int));
2571		native->n_curr += sizeof (int);
2572	}
2573
2574	return (0);
2575}
2576
2577static int
2578nvpair_native_embedded(nvstream_t *nvs, nvpair_t *nvp)
2579{
2580	if (nvs->nvs_op == NVS_OP_ENCODE) {
2581		nvs_native_t *native = (nvs_native_t *)nvs->nvs_private;
2582		nvlist_t *packed = (void *)
2583		    (native->n_curr - nvp->nvp_size + NVP_VALOFF(nvp));
2584		/*
2585		 * Null out the pointer that is meaningless in the packed
2586		 * structure. The address may not be aligned, so we have
2587		 * to use bzero.
2588		 */
2589		bzero(&packed->nvl_priv, sizeof (packed->nvl_priv));
2590	}
2591
2592	return (nvs_embedded(nvs, EMBEDDED_NVL(nvp)));
2593}
2594
2595static int
2596nvpair_native_embedded_array(nvstream_t *nvs, nvpair_t *nvp)
2597{
2598	if (nvs->nvs_op == NVS_OP_ENCODE) {
2599		nvs_native_t *native = (nvs_native_t *)nvs->nvs_private;
2600		char *value = native->n_curr - nvp->nvp_size + NVP_VALOFF(nvp);
2601		size_t len = NVP_NELEM(nvp) * sizeof (uint64_t);
2602		nvlist_t *packed = (nvlist_t *)((uintptr_t)value + len);
2603		int i;
2604		/*
2605		 * Null out pointers that are meaningless in the packed
2606		 * structure. The addresses may not be aligned, so we have
2607		 * to use bzero.
2608		 */
2609		bzero(value, len);
2610
2611		for (i = 0; i < NVP_NELEM(nvp); i++, packed++)
2612			/*
2613			 * Null out the pointer that is meaningless in the
2614			 * packed structure. The address may not be aligned,
2615			 * so we have to use bzero.
2616			 */
2617			bzero(&packed->nvl_priv, sizeof (packed->nvl_priv));
2618	}
2619
2620	return (nvs_embedded_nvl_array(nvs, nvp, NULL));
2621}
2622
2623static void
2624nvpair_native_string_array(nvstream_t *nvs, nvpair_t *nvp)
2625{
2626	switch (nvs->nvs_op) {
2627	case NVS_OP_ENCODE: {
2628		nvs_native_t *native = (nvs_native_t *)nvs->nvs_private;
2629		uint64_t *strp = (void *)
2630		    (native->n_curr - nvp->nvp_size + NVP_VALOFF(nvp));
2631		/*
2632		 * Null out pointers that are meaningless in the packed
2633		 * structure. The addresses may not be aligned, so we have
2634		 * to use bzero.
2635		 */
2636		bzero(strp, NVP_NELEM(nvp) * sizeof (uint64_t));
2637		break;
2638	}
2639	case NVS_OP_DECODE: {
2640		char **strp = (void *)NVP_VALUE(nvp);
2641		char *buf = ((char *)strp + NVP_NELEM(nvp) * sizeof (uint64_t));
2642		int i;
2643
2644		for (i = 0; i < NVP_NELEM(nvp); i++) {
2645			strp[i] = buf;
2646			buf += strlen(buf) + 1;
2647		}
2648		break;
2649	}
2650	}
2651}
2652
2653static int
2654nvs_native_nvp_op(nvstream_t *nvs, nvpair_t *nvp)
2655{
2656	data_type_t type;
2657	int value_sz;
2658	int ret = 0;
2659
2660	/*
2661	 * We do the initial bcopy of the data before we look at
2662	 * the nvpair type, because when we're decoding, we won't
2663	 * have the correct values for the pair until we do the bcopy.
2664	 */
2665	switch (nvs->nvs_op) {
2666	case NVS_OP_ENCODE:
2667	case NVS_OP_DECODE:
2668		if (native_cp(nvs, nvp, nvp->nvp_size) != 0)
2669			return (EFAULT);
2670		break;
2671	default:
2672		return (EINVAL);
2673	}
2674
2675	/* verify nvp_name_sz, check the name string length */
2676	if (i_validate_nvpair_name(nvp) != 0)
2677		return (EFAULT);
2678
2679	type = NVP_TYPE(nvp);
2680
2681	/*
2682	 * Verify type and nelem and get the value size.
2683	 * In case of data types DATA_TYPE_STRING and DATA_TYPE_STRING_ARRAY
2684	 * is the size of the string(s) excluded.
2685	 */
2686	if ((value_sz = i_get_value_size(type, NULL, NVP_NELEM(nvp))) < 0)
2687		return (EFAULT);
2688
2689	if (NVP_SIZE_CALC(nvp->nvp_name_sz, value_sz) > nvp->nvp_size)
2690		return (EFAULT);
2691
2692	switch (type) {
2693	case DATA_TYPE_NVLIST:
2694		ret = nvpair_native_embedded(nvs, nvp);
2695		break;
2696	case DATA_TYPE_NVLIST_ARRAY:
2697		ret = nvpair_native_embedded_array(nvs, nvp);
2698		break;
2699	case DATA_TYPE_STRING_ARRAY:
2700		nvpair_native_string_array(nvs, nvp);
2701		break;
2702	default:
2703		break;
2704	}
2705
2706	return (ret);
2707}
2708
2709static int
2710nvs_native_nvp_size(nvstream_t *nvs, nvpair_t *nvp, size_t *size)
2711{
2712	uint64_t nvp_sz = nvp->nvp_size;
2713
2714	switch (NVP_TYPE(nvp)) {
2715	case DATA_TYPE_NVLIST: {
2716		size_t nvsize = 0;
2717
2718		if (nvs_operation(nvs, EMBEDDED_NVL(nvp), &nvsize) != 0)
2719			return (EINVAL);
2720
2721		nvp_sz += nvsize;
2722		break;
2723	}
2724	case DATA_TYPE_NVLIST_ARRAY: {
2725		size_t nvsize;
2726
2727		if (nvs_embedded_nvl_array(nvs, nvp, &nvsize) != 0)
2728			return (EINVAL);
2729
2730		nvp_sz += nvsize;
2731		break;
2732	}
2733	default:
2734		break;
2735	}
2736
2737	if (nvp_sz > INT32_MAX)
2738		return (EINVAL);
2739
2740	*size = nvp_sz;
2741
2742	return (0);
2743}
2744
2745static int
2746nvs_native_nvpair(nvstream_t *nvs, nvpair_t *nvp, size_t *size)
2747{
2748	switch (nvs->nvs_op) {
2749	case NVS_OP_ENCODE:
2750		return (nvs_native_nvp_op(nvs, nvp));
2751
2752	case NVS_OP_DECODE: {
2753		nvs_native_t *native = (nvs_native_t *)nvs->nvs_private;
2754		int32_t decode_len;
2755
2756		/* try to read the size value from the stream */
2757		if (native->n_curr + sizeof (int32_t) > native->n_end)
2758			return (EFAULT);
2759		bcopy(native->n_curr, &decode_len, sizeof (int32_t));
2760
2761		/* sanity check the size value */
2762		if (decode_len < 0 ||
2763		    decode_len > native->n_end - native->n_curr)
2764			return (EFAULT);
2765
2766		*size = decode_len;
2767
2768		/*
2769		 * If at the end of the stream then move the cursor
2770		 * forward, otherwise nvpair_native_op() will read
2771		 * the entire nvpair at the same cursor position.
2772		 */
2773		if (*size == 0)
2774			native->n_curr += sizeof (int32_t);
2775		break;
2776	}
2777
2778	default:
2779		return (EINVAL);
2780	}
2781
2782	return (0);
2783}
2784
2785static const nvs_ops_t nvs_native_ops = {
2786	nvs_native_nvlist,
2787	nvs_native_nvpair,
2788	nvs_native_nvp_op,
2789	nvs_native_nvp_size,
2790	nvs_native_nvl_fini
2791};
2792
2793static int
2794nvs_native(nvstream_t *nvs, nvlist_t *nvl, char *buf, size_t *buflen)
2795{
2796	nvs_native_t native;
2797	int err;
2798
2799	nvs->nvs_ops = &nvs_native_ops;
2800
2801	if ((err = nvs_native_create(nvs, &native, buf + sizeof (nvs_header_t),
2802	    *buflen - sizeof (nvs_header_t))) != 0)
2803		return (err);
2804
2805	err = nvs_operation(nvs, nvl, buflen);
2806
2807	nvs_native_destroy(nvs);
2808
2809	return (err);
2810}
2811
2812/*
2813 * XDR encoding functions
2814 *
2815 * An xdr packed nvlist is encoded as:
2816 *
2817 *  - encoding methode and host endian (4 bytes)
2818 *  - nvl_version (4 bytes)
2819 *  - nvl_nvflag (4 bytes)
2820 *
2821 *  - encoded nvpairs, the format of one xdr encoded nvpair is:
2822 *	- encoded size of the nvpair (4 bytes)
2823 *	- decoded size of the nvpair (4 bytes)
2824 *	- name string, (4 + sizeof(NV_ALIGN4(string))
2825 *	  a string is coded as size (4 bytes) and data
2826 *	- data type (4 bytes)
2827 *	- number of elements in the nvpair (4 bytes)
2828 *	- data
2829 *
2830 *  - 2 zero's for end of the entire list (8 bytes)
2831 */
2832static int
2833nvs_xdr_create(nvstream_t *nvs, XDR *xdr, char *buf, size_t buflen)
2834{
2835	/* xdr data must be 4 byte aligned */
2836	if ((ulong_t)buf % 4 != 0)
2837		return (EFAULT);
2838
2839	switch (nvs->nvs_op) {
2840	case NVS_OP_ENCODE:
2841		xdrmem_create(xdr, buf, (uint_t)buflen, XDR_ENCODE);
2842		nvs->nvs_private = xdr;
2843		return (0);
2844	case NVS_OP_DECODE:
2845		xdrmem_create(xdr, buf, (uint_t)buflen, XDR_DECODE);
2846		nvs->nvs_private = xdr;
2847		return (0);
2848	case NVS_OP_GETSIZE:
2849		nvs->nvs_private = NULL;
2850		return (0);
2851	default:
2852		return (EINVAL);
2853	}
2854}
2855
2856static void
2857nvs_xdr_destroy(nvstream_t *nvs)
2858{
2859	switch (nvs->nvs_op) {
2860	case NVS_OP_ENCODE:
2861	case NVS_OP_DECODE:
2862		xdr_destroy((XDR *)nvs->nvs_private);
2863		break;
2864	default:
2865		break;
2866	}
2867}
2868
2869static int
2870nvs_xdr_nvlist(nvstream_t *nvs, nvlist_t *nvl, size_t *size)
2871{
2872	switch (nvs->nvs_op) {
2873	case NVS_OP_ENCODE:
2874	case NVS_OP_DECODE: {
2875		XDR 	*xdr = nvs->nvs_private;
2876
2877		if (!xdr_int(xdr, &nvl->nvl_version) ||
2878		    !xdr_u_int(xdr, &nvl->nvl_nvflag))
2879			return (EFAULT);
2880		break;
2881	}
2882	case NVS_OP_GETSIZE: {
2883		/*
2884		 * 2 * 4 for nvl_version + nvl_nvflag
2885		 * and 8 for end of the entire list
2886		 */
2887		*size += 2 * 4 + 8;
2888		break;
2889	}
2890	default:
2891		return (EINVAL);
2892	}
2893	return (0);
2894}
2895
2896static int
2897nvs_xdr_nvl_fini(nvstream_t *nvs)
2898{
2899	if (nvs->nvs_op == NVS_OP_ENCODE) {
2900		XDR *xdr = nvs->nvs_private;
2901		int zero = 0;
2902
2903		if (!xdr_int(xdr, &zero) || !xdr_int(xdr, &zero))
2904			return (EFAULT);
2905	}
2906
2907	return (0);
2908}
2909
2910/*
2911 * The format of xdr encoded nvpair is:
2912 * encode_size, decode_size, name string, data type, nelem, data
2913 */
2914static int
2915nvs_xdr_nvp_op(nvstream_t *nvs, nvpair_t *nvp)
2916{
2917	data_type_t type;
2918	char	*buf;
2919	char	*buf_end = (char *)nvp + nvp->nvp_size;
2920	int	value_sz;
2921	uint_t	nelem, buflen;
2922	bool_t	ret = FALSE;
2923	XDR	*xdr = nvs->nvs_private;
2924
2925	ASSERT(xdr != NULL && nvp != NULL);
2926
2927	/* name string */
2928	if ((buf = NVP_NAME(nvp)) >= buf_end)
2929		return (EFAULT);
2930	buflen = buf_end - buf;
2931
2932	if (!xdr_string(xdr, &buf, buflen - 1))
2933		return (EFAULT);
2934	nvp->nvp_name_sz = strlen(buf) + 1;
2935
2936	/* type and nelem */
2937	if (!xdr_int(xdr, (int *)&nvp->nvp_type) ||
2938	    !xdr_int(xdr, &nvp->nvp_value_elem))
2939		return (EFAULT);
2940
2941	type = NVP_TYPE(nvp);
2942	nelem = nvp->nvp_value_elem;
2943
2944	/*
2945	 * Verify type and nelem and get the value size.
2946	 * In case of data types DATA_TYPE_STRING and DATA_TYPE_STRING_ARRAY
2947	 * is the size of the string(s) excluded.
2948	 */
2949	if ((value_sz = i_get_value_size(type, NULL, nelem)) < 0)
2950		return (EFAULT);
2951
2952	/* if there is no data to extract then return */
2953	if (nelem == 0)
2954		return (0);
2955
2956	/* value */
2957	if ((buf = NVP_VALUE(nvp)) >= buf_end)
2958		return (EFAULT);
2959	buflen = buf_end - buf;
2960
2961	if (buflen < value_sz)
2962		return (EFAULT);
2963
2964	switch (type) {
2965	case DATA_TYPE_NVLIST:
2966		if (nvs_embedded(nvs, (void *)buf) == 0)
2967			return (0);
2968		break;
2969
2970	case DATA_TYPE_NVLIST_ARRAY:
2971		if (nvs_embedded_nvl_array(nvs, nvp, NULL) == 0)
2972			return (0);
2973		break;
2974
2975	case DATA_TYPE_BOOLEAN:
2976		ret = TRUE;
2977		break;
2978
2979	case DATA_TYPE_BYTE:
2980	case DATA_TYPE_INT8:
2981	case DATA_TYPE_UINT8:
2982		ret = xdr_char(xdr, buf);
2983		break;
2984
2985	case DATA_TYPE_INT16:
2986		ret = xdr_short(xdr, (void *)buf);
2987		break;
2988
2989	case DATA_TYPE_UINT16:
2990		ret = xdr_u_short(xdr, (void *)buf);
2991		break;
2992
2993	case DATA_TYPE_BOOLEAN_VALUE:
2994	case DATA_TYPE_INT32:
2995		ret = xdr_int(xdr, (void *)buf);
2996		break;
2997
2998	case DATA_TYPE_UINT32:
2999		ret = xdr_u_int(xdr, (void *)buf);
3000		break;
3001
3002	case DATA_TYPE_INT64:
3003		ret = xdr_longlong_t(xdr, (void *)buf);
3004		break;
3005
3006	case DATA_TYPE_UINT64:
3007		ret = xdr_u_longlong_t(xdr, (void *)buf);
3008		break;
3009
3010	case DATA_TYPE_HRTIME:
3011		/*
3012		 * NOTE: must expose the definition of hrtime_t here
3013		 */
3014		ret = xdr_longlong_t(xdr, (void *)buf);
3015		break;
3016#if !defined(_KERNEL)
3017	case DATA_TYPE_DOUBLE:
3018		ret = xdr_double(xdr, (void *)buf);
3019		break;
3020#endif
3021	case DATA_TYPE_STRING:
3022		ret = xdr_string(xdr, &buf, buflen - 1);
3023		break;
3024
3025	case DATA_TYPE_BYTE_ARRAY:
3026		ret = xdr_opaque(xdr, buf, nelem);
3027		break;
3028
3029	case DATA_TYPE_INT8_ARRAY:
3030	case DATA_TYPE_UINT8_ARRAY:
3031		ret = xdr_array(xdr, &buf, &nelem, buflen, sizeof (int8_t),
3032		    (xdrproc_t)xdr_char);
3033		break;
3034
3035	case DATA_TYPE_INT16_ARRAY:
3036		ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (int16_t),
3037		    sizeof (int16_t), (xdrproc_t)xdr_short);
3038		break;
3039
3040	case DATA_TYPE_UINT16_ARRAY:
3041		ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (uint16_t),
3042		    sizeof (uint16_t), (xdrproc_t)xdr_u_short);
3043		break;
3044
3045	case DATA_TYPE_BOOLEAN_ARRAY:
3046	case DATA_TYPE_INT32_ARRAY:
3047		ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (int32_t),
3048		    sizeof (int32_t), (xdrproc_t)xdr_int);
3049		break;
3050
3051	case DATA_TYPE_UINT32_ARRAY:
3052		ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (uint32_t),
3053		    sizeof (uint32_t), (xdrproc_t)xdr_u_int);
3054		break;
3055
3056	case DATA_TYPE_INT64_ARRAY:
3057		ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (int64_t),
3058		    sizeof (int64_t), (xdrproc_t)xdr_longlong_t);
3059		break;
3060
3061	case DATA_TYPE_UINT64_ARRAY:
3062		ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (uint64_t),
3063		    sizeof (uint64_t), (xdrproc_t)xdr_u_longlong_t);
3064		break;
3065
3066	case DATA_TYPE_STRING_ARRAY: {
3067		size_t len = nelem * sizeof (uint64_t);
3068		char **strp = (void *)buf;
3069		int i;
3070
3071		if (nvs->nvs_op == NVS_OP_DECODE)
3072			bzero(buf, len);	/* don't trust packed data */
3073
3074		for (i = 0; i < nelem; i++) {
3075			if (buflen <= len)
3076				return (EFAULT);
3077
3078			buf += len;
3079			buflen -= len;
3080
3081			if (xdr_string(xdr, &buf, buflen - 1) != TRUE)
3082				return (EFAULT);
3083
3084			if (nvs->nvs_op == NVS_OP_DECODE)
3085				strp[i] = buf;
3086			len = strlen(buf) + 1;
3087		}
3088		ret = TRUE;
3089		break;
3090	}
3091	default:
3092		break;
3093	}
3094
3095	return (ret == TRUE ? 0 : EFAULT);
3096}
3097
3098static int
3099nvs_xdr_nvp_size(nvstream_t *nvs, nvpair_t *nvp, size_t *size)
3100{
3101	data_type_t type = NVP_TYPE(nvp);
3102	/*
3103	 * encode_size + decode_size + name string size + data type + nelem
3104	 * where name string size = 4 + NV_ALIGN4(strlen(NVP_NAME(nvp)))
3105	 */
3106	uint64_t nvp_sz = 4 + 4 + 4 + NV_ALIGN4(strlen(NVP_NAME(nvp))) + 4 + 4;
3107
3108	switch (type) {
3109	case DATA_TYPE_BOOLEAN:
3110		break;
3111
3112	case DATA_TYPE_BOOLEAN_VALUE:
3113	case DATA_TYPE_BYTE:
3114	case DATA_TYPE_INT8:
3115	case DATA_TYPE_UINT8:
3116	case DATA_TYPE_INT16:
3117	case DATA_TYPE_UINT16:
3118	case DATA_TYPE_INT32:
3119	case DATA_TYPE_UINT32:
3120		nvp_sz += 4;	/* 4 is the minimum xdr unit */
3121		break;
3122
3123	case DATA_TYPE_INT64:
3124	case DATA_TYPE_UINT64:
3125	case DATA_TYPE_HRTIME:
3126#if !defined(_KERNEL)
3127	case DATA_TYPE_DOUBLE:
3128#endif
3129		nvp_sz += 8;
3130		break;
3131
3132	case DATA_TYPE_STRING:
3133		nvp_sz += 4 + NV_ALIGN4(strlen((char *)NVP_VALUE(nvp)));
3134		break;
3135
3136	case DATA_TYPE_BYTE_ARRAY:
3137		nvp_sz += NV_ALIGN4(NVP_NELEM(nvp));
3138		break;
3139
3140	case DATA_TYPE_BOOLEAN_ARRAY:
3141	case DATA_TYPE_INT8_ARRAY:
3142	case DATA_TYPE_UINT8_ARRAY:
3143	case DATA_TYPE_INT16_ARRAY:
3144	case DATA_TYPE_UINT16_ARRAY:
3145	case DATA_TYPE_INT32_ARRAY:
3146	case DATA_TYPE_UINT32_ARRAY:
3147		nvp_sz += 4 + 4 * (uint64_t)NVP_NELEM(nvp);
3148		break;
3149
3150	case DATA_TYPE_INT64_ARRAY:
3151	case DATA_TYPE_UINT64_ARRAY:
3152		nvp_sz += 4 + 8 * (uint64_t)NVP_NELEM(nvp);
3153		break;
3154
3155	case DATA_TYPE_STRING_ARRAY: {
3156		int i;
3157		char **strs = (void *)NVP_VALUE(nvp);
3158
3159		for (i = 0; i < NVP_NELEM(nvp); i++)
3160			nvp_sz += 4 + NV_ALIGN4(strlen(strs[i]));
3161
3162		break;
3163	}
3164
3165	case DATA_TYPE_NVLIST:
3166	case DATA_TYPE_NVLIST_ARRAY: {
3167		size_t nvsize = 0;
3168		int old_nvs_op = nvs->nvs_op;
3169		int err;
3170
3171		nvs->nvs_op = NVS_OP_GETSIZE;
3172		if (type == DATA_TYPE_NVLIST)
3173			err = nvs_operation(nvs, EMBEDDED_NVL(nvp), &nvsize);
3174		else
3175			err = nvs_embedded_nvl_array(nvs, nvp, &nvsize);
3176		nvs->nvs_op = old_nvs_op;
3177
3178		if (err != 0)
3179			return (EINVAL);
3180
3181		nvp_sz += nvsize;
3182		break;
3183	}
3184
3185	default:
3186		return (EINVAL);
3187	}
3188
3189	if (nvp_sz > INT32_MAX)
3190		return (EINVAL);
3191
3192	*size = nvp_sz;
3193
3194	return (0);
3195}
3196
3197
3198/*
3199 * The NVS_XDR_MAX_LEN macro takes a packed xdr buffer of size x and estimates
3200 * the largest nvpair that could be encoded in the buffer.
3201 *
3202 * See comments above nvpair_xdr_op() for the format of xdr encoding.
3203 * The size of a xdr packed nvpair without any data is 5 words.
3204 *
3205 * Using the size of the data directly as an estimate would be ok
3206 * in all cases except one.  If the data type is of DATA_TYPE_STRING_ARRAY
3207 * then the actual nvpair has space for an array of pointers to index
3208 * the strings.  These pointers are not encoded into the packed xdr buffer.
3209 *
3210 * If the data is of type DATA_TYPE_STRING_ARRAY and all the strings are
3211 * of length 0, then each string is endcoded in xdr format as a single word.
3212 * Therefore when expanded to an nvpair there will be 2.25 word used for
3213 * each string.  (a int64_t allocated for pointer usage, and a single char
3214 * for the null termination.)
3215 *
3216 * This is the calculation performed by the NVS_XDR_MAX_LEN macro.
3217 */
3218#define	NVS_XDR_HDR_LEN		((size_t)(5 * 4))
3219#define	NVS_XDR_DATA_LEN(y)	(((size_t)(y) <= NVS_XDR_HDR_LEN) ? \
3220					0 : ((size_t)(y) - NVS_XDR_HDR_LEN))
3221#define	NVS_XDR_MAX_LEN(x)	(NVP_SIZE_CALC(1, 0) + \
3222					(NVS_XDR_DATA_LEN(x) * 2) + \
3223					NV_ALIGN4((NVS_XDR_DATA_LEN(x) / 4)))
3224
3225static int
3226nvs_xdr_nvpair(nvstream_t *nvs, nvpair_t *nvp, size_t *size)
3227{
3228	XDR 	*xdr = nvs->nvs_private;
3229	int32_t	encode_len, decode_len;
3230
3231	switch (nvs->nvs_op) {
3232	case NVS_OP_ENCODE: {
3233		size_t nvsize;
3234
3235		if (nvs_xdr_nvp_size(nvs, nvp, &nvsize) != 0)
3236			return (EFAULT);
3237
3238		decode_len = nvp->nvp_size;
3239		encode_len = nvsize;
3240		if (!xdr_int(xdr, &encode_len) || !xdr_int(xdr, &decode_len))
3241			return (EFAULT);
3242
3243		return (nvs_xdr_nvp_op(nvs, nvp));
3244	}
3245	case NVS_OP_DECODE: {
3246		struct xdr_bytesrec bytesrec;
3247
3248		/* get the encode and decode size */
3249		if (!xdr_int(xdr, &encode_len) || !xdr_int(xdr, &decode_len))
3250			return (EFAULT);
3251		*size = decode_len;
3252
3253		/* are we at the end of the stream? */
3254		if (*size == 0)
3255			return (0);
3256
3257		/* sanity check the size parameter */
3258		if (!xdr_control(xdr, XDR_GET_BYTES_AVAIL, &bytesrec))
3259			return (EFAULT);
3260
3261		if (*size > NVS_XDR_MAX_LEN(bytesrec.xc_num_avail))
3262			return (EFAULT);
3263		break;
3264	}
3265
3266	default:
3267		return (EINVAL);
3268	}
3269	return (0);
3270}
3271
3272static const struct nvs_ops nvs_xdr_ops = {
3273	nvs_xdr_nvlist,
3274	nvs_xdr_nvpair,
3275	nvs_xdr_nvp_op,
3276	nvs_xdr_nvp_size,
3277	nvs_xdr_nvl_fini
3278};
3279
3280static int
3281nvs_xdr(nvstream_t *nvs, nvlist_t *nvl, char *buf, size_t *buflen)
3282{
3283	XDR xdr;
3284	int err;
3285
3286	nvs->nvs_ops = &nvs_xdr_ops;
3287
3288	if ((err = nvs_xdr_create(nvs, &xdr, buf + sizeof (nvs_header_t),
3289	    *buflen - sizeof (nvs_header_t))) != 0)
3290		return (err);
3291
3292	err = nvs_operation(nvs, nvl, buflen);
3293
3294	nvs_xdr_destroy(nvs);
3295
3296	return (err);
3297}
3298