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