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