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