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