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