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