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