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