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