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