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