FreeBSD: Fix a pair of bugs in zfs_fhtovp()
[zfs.git] / module / nvpair / nvpair.c
blobc8161f116b60983e7105a6599ef40c0e1d0ab022
1 /*
2 * CDDL HEADER START
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.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or https://opensource.org/licenses/CDDL-1.0.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
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]
19 * CDDL HEADER END
23 * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright (c) 2015, 2017 by Delphix. All rights reserved.
25 * Copyright 2018 RackTop Systems.
29 * Links to Illumos.org for more information on Interface Libraries:
30 * [1] https://illumos.org/man/3lib/libnvpair
31 * [2] https://illumos.org/man/3nvpair/nvlist_alloc
32 * [3] https://illumos.org/man/9f/nvlist_alloc
33 * [4] https://illumos.org/man/9f/nvlist_next_nvpair
34 * [5] https://illumos.org/man/9f/nvpair_value_byte
37 #include <sys/debug.h>
38 #include <sys/isa_defs.h>
39 #include <sys/nvpair.h>
40 #include <sys/nvpair_impl.h>
41 #include <sys/types.h>
42 #include <sys/param.h>
43 #include <sys/string.h>
44 #include <rpc/xdr.h>
45 #include <sys/mod.h>
47 #if defined(_KERNEL)
48 #include <sys/sunddi.h>
49 #include <sys/sysmacros.h>
50 #else
51 #include <stdarg.h>
52 #include <stdlib.h>
53 #include <stddef.h>
54 #endif
56 #define skip_whitespace(p) while ((*(p) == ' ') || (*(p) == '\t')) (p)++
59 * nvpair.c - Provides kernel & userland interfaces for manipulating
60 * name-value pairs.
62 * Overview Diagram
64 * +--------------+
65 * | nvlist_t |
66 * |--------------|
67 * | nvl_version |
68 * | nvl_nvflag |
69 * | nvl_priv -+-+
70 * | nvl_flag | |
71 * | nvl_pad | |
72 * +--------------+ |
73 * V
74 * +--------------+ last i_nvp in list
75 * | nvpriv_t | +--------------------->
76 * |--------------| |
77 * +--+- nvp_list | | +------------+
78 * | | nvp_last -+--+ + nv_alloc_t |
79 * | | nvp_curr | |------------|
80 * | | nvp_nva -+----> | nva_ops |
81 * | | nvp_stat | | nva_arg |
82 * | +--------------+ +------------+
83 * |
84 * +-------+
85 * V
86 * +---------------------+ +-------------------+
87 * | i_nvp_t | +-->| i_nvp_t | +-->
88 * |---------------------| | |-------------------| |
89 * | nvi_next -+--+ | nvi_next -+--+
90 * | nvi_prev (NULL) | <----+ nvi_prev |
91 * | . . . . . . . . . . | | . . . . . . . . . |
92 * | nvp (nvpair_t) | | nvp (nvpair_t) |
93 * | - nvp_size | | - nvp_size |
94 * | - nvp_name_sz | | - nvp_name_sz |
95 * | - nvp_value_elem | | - nvp_value_elem |
96 * | - nvp_type | | - nvp_type |
97 * | - data ... | | - data ... |
98 * +---------------------+ +-------------------+
102 * +---------------------+ +---------------------+
103 * | i_nvp_t | +--> +-->| i_nvp_t (last) |
104 * |---------------------| | | |---------------------|
105 * | nvi_next -+--+ ... --+ | nvi_next (NULL) |
106 * <-+- nvi_prev |<-- ... <----+ nvi_prev |
107 * | . . . . . . . . . | | . . . . . . . . . |
108 * | nvp (nvpair_t) | | nvp (nvpair_t) |
109 * | - nvp_size | | - nvp_size |
110 * | - nvp_name_sz | | - nvp_name_sz |
111 * | - nvp_value_elem | | - nvp_value_elem |
112 * | - DATA_TYPE_NVLIST | | - nvp_type |
113 * | - data (embedded) | | - data ... |
114 * | nvlist name | +---------------------+
115 * | +--------------+ |
116 * | | nvlist_t | |
117 * | |--------------| |
118 * | | nvl_version | |
119 * | | nvl_nvflag | |
120 * | | nvl_priv --+---+---->
121 * | | nvl_flag | |
122 * | | nvl_pad | |
123 * | +--------------+ |
124 * +---------------------+
127 * N.B. nvpair_t may be aligned on 4 byte boundary, so +4 will
128 * allow value to be aligned on 8 byte boundary
130 * name_len is the length of the name string including the null terminator
131 * so it must be >= 1
133 #define NVP_SIZE_CALC(name_len, data_len) \
134 (NV_ALIGN((sizeof (nvpair_t)) + name_len) + NV_ALIGN(data_len))
136 static int i_get_value_size(data_type_t type, const void *data, uint_t nelem);
137 static int nvlist_add_common(nvlist_t *nvl, const char *name, data_type_t type,
138 uint_t nelem, const void *data);
140 #define NV_STAT_EMBEDDED 0x1
141 #define EMBEDDED_NVL(nvp) ((nvlist_t *)(void *)NVP_VALUE(nvp))
142 #define EMBEDDED_NVL_ARRAY(nvp) ((nvlist_t **)(void *)NVP_VALUE(nvp))
144 #define NVP_VALOFF(nvp) (NV_ALIGN(sizeof (nvpair_t) + (nvp)->nvp_name_sz))
145 #define NVPAIR2I_NVP(nvp) \
146 ((i_nvp_t *)((size_t)(nvp) - offsetof(i_nvp_t, nvi_nvp)))
148 #ifdef _KERNEL
149 static const int nvpair_max_recursion = 20;
150 #else
151 static const int nvpair_max_recursion = 100;
152 #endif
154 static const uint64_t nvlist_hashtable_init_size = (1 << 4);
157 nv_alloc_init(nv_alloc_t *nva, const nv_alloc_ops_t *nvo, /* args */ ...)
159 va_list valist;
160 int err = 0;
162 nva->nva_ops = nvo;
163 nva->nva_arg = NULL;
165 va_start(valist, nvo);
166 if (nva->nva_ops->nv_ao_init != NULL)
167 err = nva->nva_ops->nv_ao_init(nva, valist);
168 va_end(valist);
170 return (err);
173 void
174 nv_alloc_reset(nv_alloc_t *nva)
176 if (nva->nva_ops->nv_ao_reset != NULL)
177 nva->nva_ops->nv_ao_reset(nva);
180 void
181 nv_alloc_fini(nv_alloc_t *nva)
183 if (nva->nva_ops->nv_ao_fini != NULL)
184 nva->nva_ops->nv_ao_fini(nva);
187 nv_alloc_t *
188 nvlist_lookup_nv_alloc(nvlist_t *nvl)
190 nvpriv_t *priv;
192 if (nvl == NULL ||
193 (priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL)
194 return (NULL);
196 return (priv->nvp_nva);
199 static void *
200 nv_mem_zalloc(nvpriv_t *nvp, size_t size)
202 nv_alloc_t *nva = nvp->nvp_nva;
203 void *buf;
205 if ((buf = nva->nva_ops->nv_ao_alloc(nva, size)) != NULL)
206 memset(buf, 0, size);
208 return (buf);
211 static void
212 nv_mem_free(nvpriv_t *nvp, void *buf, size_t size)
214 nv_alloc_t *nva = nvp->nvp_nva;
216 nva->nva_ops->nv_ao_free(nva, buf, size);
219 static void
220 nv_priv_init(nvpriv_t *priv, nv_alloc_t *nva, uint32_t stat)
222 memset(priv, 0, sizeof (nvpriv_t));
224 priv->nvp_nva = nva;
225 priv->nvp_stat = stat;
228 static nvpriv_t *
229 nv_priv_alloc(nv_alloc_t *nva)
231 nvpriv_t *priv;
234 * nv_mem_alloc() cannot called here because it needs the priv
235 * argument.
237 if ((priv = nva->nva_ops->nv_ao_alloc(nva, sizeof (nvpriv_t))) == NULL)
238 return (NULL);
240 nv_priv_init(priv, nva, 0);
242 return (priv);
246 * Embedded lists need their own nvpriv_t's. We create a new
247 * nvpriv_t using the parameters and allocator from the parent
248 * list's nvpriv_t.
250 static nvpriv_t *
251 nv_priv_alloc_embedded(nvpriv_t *priv)
253 nvpriv_t *emb_priv;
255 if ((emb_priv = nv_mem_zalloc(priv, sizeof (nvpriv_t))) == NULL)
256 return (NULL);
258 nv_priv_init(emb_priv, priv->nvp_nva, NV_STAT_EMBEDDED);
260 return (emb_priv);
263 static int
264 nvt_tab_alloc(nvpriv_t *priv, uint64_t buckets)
266 ASSERT3P(priv->nvp_hashtable, ==, NULL);
267 ASSERT0(priv->nvp_nbuckets);
268 ASSERT0(priv->nvp_nentries);
270 i_nvp_t **tab = nv_mem_zalloc(priv, buckets * sizeof (i_nvp_t *));
271 if (tab == NULL)
272 return (ENOMEM);
274 priv->nvp_hashtable = tab;
275 priv->nvp_nbuckets = buckets;
276 return (0);
279 static void
280 nvt_tab_free(nvpriv_t *priv)
282 i_nvp_t **tab = priv->nvp_hashtable;
283 if (tab == NULL) {
284 ASSERT0(priv->nvp_nbuckets);
285 ASSERT0(priv->nvp_nentries);
286 return;
289 nv_mem_free(priv, tab, priv->nvp_nbuckets * sizeof (i_nvp_t *));
291 priv->nvp_hashtable = NULL;
292 priv->nvp_nbuckets = 0;
293 priv->nvp_nentries = 0;
296 static uint32_t
297 nvt_hash(const char *p)
299 uint32_t g, hval = 0;
301 while (*p) {
302 hval = (hval << 4) + *p++;
303 if ((g = (hval & 0xf0000000)) != 0)
304 hval ^= g >> 24;
305 hval &= ~g;
307 return (hval);
310 static boolean_t
311 nvt_nvpair_match(const nvpair_t *nvp1, const nvpair_t *nvp2, uint32_t nvflag)
313 boolean_t match = B_FALSE;
314 if (nvflag & NV_UNIQUE_NAME_TYPE) {
315 if (strcmp(NVP_NAME(nvp1), NVP_NAME(nvp2)) == 0 &&
316 NVP_TYPE(nvp1) == NVP_TYPE(nvp2))
317 match = B_TRUE;
318 } else {
319 ASSERT(nvflag == 0 || nvflag & NV_UNIQUE_NAME);
320 if (strcmp(NVP_NAME(nvp1), NVP_NAME(nvp2)) == 0)
321 match = B_TRUE;
323 return (match);
326 static nvpair_t *
327 nvt_lookup_name_type(const nvlist_t *nvl, const char *name, data_type_t type)
329 const nvpriv_t *priv = (const nvpriv_t *)(uintptr_t)nvl->nvl_priv;
330 ASSERT(priv != NULL);
332 i_nvp_t **tab = priv->nvp_hashtable;
334 if (tab == NULL) {
335 ASSERT3P(priv->nvp_list, ==, NULL);
336 ASSERT0(priv->nvp_nbuckets);
337 ASSERT0(priv->nvp_nentries);
338 return (NULL);
339 } else {
340 ASSERT(priv->nvp_nbuckets != 0);
343 uint64_t hash = nvt_hash(name);
344 uint64_t index = hash & (priv->nvp_nbuckets - 1);
346 ASSERT3U(index, <, priv->nvp_nbuckets);
347 i_nvp_t *entry = tab[index];
349 for (i_nvp_t *e = entry; e != NULL; e = e->nvi_hashtable_next) {
350 if (strcmp(NVP_NAME(&e->nvi_nvp), name) == 0 &&
351 (type == DATA_TYPE_DONTCARE ||
352 NVP_TYPE(&e->nvi_nvp) == type))
353 return (&e->nvi_nvp);
355 return (NULL);
358 static nvpair_t *
359 nvt_lookup_name(const nvlist_t *nvl, const char *name)
361 return (nvt_lookup_name_type(nvl, name, DATA_TYPE_DONTCARE));
364 static int
365 nvt_resize(nvpriv_t *priv, uint32_t new_size)
367 i_nvp_t **tab = priv->nvp_hashtable;
370 * Migrate all the entries from the current table
371 * to a newly-allocated table with the new size by
372 * re-adjusting the pointers of their entries.
374 uint32_t size = priv->nvp_nbuckets;
375 uint32_t new_mask = new_size - 1;
376 ASSERT(ISP2(new_size));
378 i_nvp_t **new_tab = nv_mem_zalloc(priv, new_size * sizeof (i_nvp_t *));
379 if (new_tab == NULL)
380 return (ENOMEM);
382 uint32_t nentries = 0;
383 for (uint32_t i = 0; i < size; i++) {
384 i_nvp_t *next, *e = tab[i];
386 while (e != NULL) {
387 next = e->nvi_hashtable_next;
389 uint32_t hash = nvt_hash(NVP_NAME(&e->nvi_nvp));
390 uint32_t index = hash & new_mask;
392 e->nvi_hashtable_next = new_tab[index];
393 new_tab[index] = e;
394 nentries++;
396 e = next;
398 tab[i] = NULL;
400 ASSERT3U(nentries, ==, priv->nvp_nentries);
402 nvt_tab_free(priv);
404 priv->nvp_hashtable = new_tab;
405 priv->nvp_nbuckets = new_size;
406 priv->nvp_nentries = nentries;
408 return (0);
411 static boolean_t
412 nvt_needs_togrow(nvpriv_t *priv)
415 * Grow only when we have more elements than buckets
416 * and the # of buckets doesn't overflow.
418 return (priv->nvp_nentries > priv->nvp_nbuckets &&
419 (UINT32_MAX >> 1) >= priv->nvp_nbuckets);
423 * Allocate a new table that's twice the size of the old one,
424 * and migrate all the entries from the old one to the new
425 * one by re-adjusting their pointers.
427 static int
428 nvt_grow(nvpriv_t *priv)
430 uint32_t current_size = priv->nvp_nbuckets;
431 /* ensure we won't overflow */
432 ASSERT3U(UINT32_MAX >> 1, >=, current_size);
433 return (nvt_resize(priv, current_size << 1));
436 static boolean_t
437 nvt_needs_toshrink(nvpriv_t *priv)
440 * Shrink only when the # of elements is less than or
441 * equal to 1/4 the # of buckets. Never shrink less than
442 * nvlist_hashtable_init_size.
444 ASSERT3U(priv->nvp_nbuckets, >=, nvlist_hashtable_init_size);
445 if (priv->nvp_nbuckets == nvlist_hashtable_init_size)
446 return (B_FALSE);
447 return (priv->nvp_nentries <= (priv->nvp_nbuckets >> 2));
451 * Allocate a new table that's half the size of the old one,
452 * and migrate all the entries from the old one to the new
453 * one by re-adjusting their pointers.
455 static int
456 nvt_shrink(nvpriv_t *priv)
458 uint32_t current_size = priv->nvp_nbuckets;
459 /* ensure we won't overflow */
460 ASSERT3U(current_size, >=, nvlist_hashtable_init_size);
461 return (nvt_resize(priv, current_size >> 1));
464 static int
465 nvt_remove_nvpair(nvlist_t *nvl, const nvpair_t *nvp)
467 nvpriv_t *priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv;
469 if (nvt_needs_toshrink(priv)) {
470 int err = nvt_shrink(priv);
471 if (err != 0)
472 return (err);
474 i_nvp_t **tab = priv->nvp_hashtable;
476 char *name = NVP_NAME(nvp);
477 uint64_t hash = nvt_hash(name);
478 uint64_t index = hash & (priv->nvp_nbuckets - 1);
480 ASSERT3U(index, <, priv->nvp_nbuckets);
481 i_nvp_t *bucket = tab[index];
483 for (i_nvp_t *prev = NULL, *e = bucket;
484 e != NULL; prev = e, e = e->nvi_hashtable_next) {
485 if (nvt_nvpair_match(&e->nvi_nvp, nvp, nvl->nvl_nvflag)) {
486 if (prev != NULL) {
487 prev->nvi_hashtable_next =
488 e->nvi_hashtable_next;
489 } else {
490 ASSERT3P(e, ==, bucket);
491 tab[index] = e->nvi_hashtable_next;
493 e->nvi_hashtable_next = NULL;
494 priv->nvp_nentries--;
495 break;
499 return (0);
502 static int
503 nvt_add_nvpair(nvlist_t *nvl, nvpair_t *nvp)
505 nvpriv_t *priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv;
507 /* initialize nvpair table now if it doesn't exist. */
508 if (priv->nvp_hashtable == NULL) {
509 int err = nvt_tab_alloc(priv, nvlist_hashtable_init_size);
510 if (err != 0)
511 return (err);
515 * if we don't allow duplicate entries, make sure to
516 * unlink any existing entries from the table.
518 if (nvl->nvl_nvflag != 0) {
519 int err = nvt_remove_nvpair(nvl, nvp);
520 if (err != 0)
521 return (err);
524 if (nvt_needs_togrow(priv)) {
525 int err = nvt_grow(priv);
526 if (err != 0)
527 return (err);
529 i_nvp_t **tab = priv->nvp_hashtable;
531 char *name = NVP_NAME(nvp);
532 uint64_t hash = nvt_hash(name);
533 uint64_t index = hash & (priv->nvp_nbuckets - 1);
535 ASSERT3U(index, <, priv->nvp_nbuckets);
536 // cppcheck-suppress nullPointerRedundantCheck
537 i_nvp_t *bucket = tab[index];
539 /* insert link at the beginning of the bucket */
540 i_nvp_t *new_entry = NVPAIR2I_NVP(nvp);
541 ASSERT3P(new_entry->nvi_hashtable_next, ==, NULL);
542 new_entry->nvi_hashtable_next = bucket;
543 // cppcheck-suppress nullPointerRedundantCheck
544 tab[index] = new_entry;
546 priv->nvp_nentries++;
547 return (0);
550 static void
551 nvlist_init(nvlist_t *nvl, uint32_t nvflag, nvpriv_t *priv)
553 nvl->nvl_version = NV_VERSION;
554 nvl->nvl_nvflag = nvflag & (NV_UNIQUE_NAME|NV_UNIQUE_NAME_TYPE);
555 nvl->nvl_priv = (uint64_t)(uintptr_t)priv;
556 nvl->nvl_flag = 0;
557 nvl->nvl_pad = 0;
560 uint_t
561 nvlist_nvflag(nvlist_t *nvl)
563 return (nvl->nvl_nvflag);
566 static nv_alloc_t *
567 nvlist_nv_alloc(int kmflag)
569 #if defined(_KERNEL)
570 switch (kmflag) {
571 case KM_SLEEP:
572 return (nv_alloc_sleep);
573 case KM_NOSLEEP:
574 return (nv_alloc_nosleep);
575 default:
576 return (nv_alloc_pushpage);
578 #else
579 (void) kmflag;
580 return (nv_alloc_nosleep);
581 #endif /* _KERNEL */
585 * nvlist_alloc - Allocate nvlist.
588 nvlist_alloc(nvlist_t **nvlp, uint_t nvflag, int kmflag)
590 return (nvlist_xalloc(nvlp, nvflag, nvlist_nv_alloc(kmflag)));
594 nvlist_xalloc(nvlist_t **nvlp, uint_t nvflag, nv_alloc_t *nva)
596 nvpriv_t *priv;
598 if (nvlp == NULL || nva == NULL)
599 return (EINVAL);
601 if ((priv = nv_priv_alloc(nva)) == NULL)
602 return (ENOMEM);
604 if ((*nvlp = nv_mem_zalloc(priv,
605 NV_ALIGN(sizeof (nvlist_t)))) == NULL) {
606 nv_mem_free(priv, priv, sizeof (nvpriv_t));
607 return (ENOMEM);
610 nvlist_init(*nvlp, nvflag, priv);
612 return (0);
616 * nvp_buf_alloc - Allocate i_nvp_t for storing a new nv pair.
618 static nvpair_t *
619 nvp_buf_alloc(nvlist_t *nvl, size_t len)
621 nvpriv_t *priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv;
622 i_nvp_t *buf;
623 nvpair_t *nvp;
624 size_t nvsize;
627 * Allocate the buffer
629 nvsize = len + offsetof(i_nvp_t, nvi_nvp);
631 if ((buf = nv_mem_zalloc(priv, nvsize)) == NULL)
632 return (NULL);
634 nvp = &buf->nvi_nvp;
635 nvp->nvp_size = len;
637 return (nvp);
641 * nvp_buf_free - de-Allocate an i_nvp_t.
643 static void
644 nvp_buf_free(nvlist_t *nvl, nvpair_t *nvp)
646 nvpriv_t *priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv;
647 size_t nvsize = nvp->nvp_size + offsetof(i_nvp_t, nvi_nvp);
649 nv_mem_free(priv, NVPAIR2I_NVP(nvp), nvsize);
653 * nvp_buf_link - link a new nv pair into the nvlist.
655 static void
656 nvp_buf_link(nvlist_t *nvl, nvpair_t *nvp)
658 nvpriv_t *priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv;
659 i_nvp_t *curr = NVPAIR2I_NVP(nvp);
661 /* Put element at end of nvlist */
662 if (priv->nvp_list == NULL) {
663 priv->nvp_list = priv->nvp_last = curr;
664 } else {
665 curr->nvi_prev = priv->nvp_last;
666 priv->nvp_last->nvi_next = curr;
667 priv->nvp_last = curr;
672 * nvp_buf_unlink - unlink an removed nvpair out of the nvlist.
674 static void
675 nvp_buf_unlink(nvlist_t *nvl, nvpair_t *nvp)
677 nvpriv_t *priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv;
678 i_nvp_t *curr = NVPAIR2I_NVP(nvp);
681 * protect nvlist_next_nvpair() against walking on freed memory.
683 if (priv->nvp_curr == curr)
684 priv->nvp_curr = curr->nvi_next;
686 if (curr == priv->nvp_list)
687 priv->nvp_list = curr->nvi_next;
688 else
689 curr->nvi_prev->nvi_next = curr->nvi_next;
691 if (curr == priv->nvp_last)
692 priv->nvp_last = curr->nvi_prev;
693 else
694 curr->nvi_next->nvi_prev = curr->nvi_prev;
698 * take a nvpair type and number of elements and make sure the are valid
700 static int
701 i_validate_type_nelem(data_type_t type, uint_t nelem)
703 switch (type) {
704 case DATA_TYPE_BOOLEAN:
705 if (nelem != 0)
706 return (EINVAL);
707 break;
708 case DATA_TYPE_BOOLEAN_VALUE:
709 case DATA_TYPE_BYTE:
710 case DATA_TYPE_INT8:
711 case DATA_TYPE_UINT8:
712 case DATA_TYPE_INT16:
713 case DATA_TYPE_UINT16:
714 case DATA_TYPE_INT32:
715 case DATA_TYPE_UINT32:
716 case DATA_TYPE_INT64:
717 case DATA_TYPE_UINT64:
718 case DATA_TYPE_STRING:
719 case DATA_TYPE_HRTIME:
720 case DATA_TYPE_NVLIST:
721 #if !defined(_KERNEL)
722 case DATA_TYPE_DOUBLE:
723 #endif
724 if (nelem != 1)
725 return (EINVAL);
726 break;
727 case DATA_TYPE_BOOLEAN_ARRAY:
728 case DATA_TYPE_BYTE_ARRAY:
729 case DATA_TYPE_INT8_ARRAY:
730 case DATA_TYPE_UINT8_ARRAY:
731 case DATA_TYPE_INT16_ARRAY:
732 case DATA_TYPE_UINT16_ARRAY:
733 case DATA_TYPE_INT32_ARRAY:
734 case DATA_TYPE_UINT32_ARRAY:
735 case DATA_TYPE_INT64_ARRAY:
736 case DATA_TYPE_UINT64_ARRAY:
737 case DATA_TYPE_STRING_ARRAY:
738 case DATA_TYPE_NVLIST_ARRAY:
739 /* we allow arrays with 0 elements */
740 break;
741 default:
742 return (EINVAL);
744 return (0);
748 * Verify nvp_name_sz and check the name string length.
750 static int
751 i_validate_nvpair_name(nvpair_t *nvp)
753 if ((nvp->nvp_name_sz <= 0) ||
754 (nvp->nvp_size < NVP_SIZE_CALC(nvp->nvp_name_sz, 0)))
755 return (EFAULT);
757 /* verify the name string, make sure its terminated */
758 if (NVP_NAME(nvp)[nvp->nvp_name_sz - 1] != '\0')
759 return (EFAULT);
761 return (strlen(NVP_NAME(nvp)) == nvp->nvp_name_sz - 1 ? 0 : EFAULT);
764 static int
765 i_validate_nvpair_value(data_type_t type, uint_t nelem, const void *data)
767 switch (type) {
768 case DATA_TYPE_BOOLEAN_VALUE:
769 if (*(boolean_t *)data != B_TRUE &&
770 *(boolean_t *)data != B_FALSE)
771 return (EINVAL);
772 break;
773 case DATA_TYPE_BOOLEAN_ARRAY: {
774 int i;
776 for (i = 0; i < nelem; i++)
777 if (((boolean_t *)data)[i] != B_TRUE &&
778 ((boolean_t *)data)[i] != B_FALSE)
779 return (EINVAL);
780 break;
782 default:
783 break;
786 return (0);
790 * This function takes a pointer to what should be a nvpair and it's size
791 * and then verifies that all the nvpair fields make sense and can be
792 * trusted. This function is used when decoding packed nvpairs.
794 static int
795 i_validate_nvpair(nvpair_t *nvp)
797 data_type_t type = NVP_TYPE(nvp);
798 int size1, size2;
800 /* verify nvp_name_sz, check the name string length */
801 if (i_validate_nvpair_name(nvp) != 0)
802 return (EFAULT);
804 if (i_validate_nvpair_value(type, NVP_NELEM(nvp), NVP_VALUE(nvp)) != 0)
805 return (EFAULT);
808 * verify nvp_type, nvp_value_elem, and also possibly
809 * verify string values and get the value size.
811 size2 = i_get_value_size(type, NVP_VALUE(nvp), NVP_NELEM(nvp));
812 size1 = nvp->nvp_size - NVP_VALOFF(nvp);
813 if (size2 < 0 || size1 != NV_ALIGN(size2))
814 return (EFAULT);
816 return (0);
819 static int
820 nvlist_copy_pairs(const nvlist_t *snvl, nvlist_t *dnvl)
822 const nvpriv_t *priv;
823 const i_nvp_t *curr;
825 if ((priv = (const nvpriv_t *)(uintptr_t)snvl->nvl_priv) == NULL)
826 return (EINVAL);
828 for (curr = priv->nvp_list; curr != NULL; curr = curr->nvi_next) {
829 const nvpair_t *nvp = &curr->nvi_nvp;
830 int err;
832 if ((err = nvlist_add_common(dnvl, NVP_NAME(nvp), NVP_TYPE(nvp),
833 NVP_NELEM(nvp), NVP_VALUE(nvp))) != 0)
834 return (err);
837 return (0);
841 * Frees all memory allocated for an nvpair (like embedded lists) with
842 * the exception of the nvpair buffer itself.
844 static void
845 nvpair_free(nvpair_t *nvp)
847 switch (NVP_TYPE(nvp)) {
848 case DATA_TYPE_NVLIST:
849 nvlist_free(EMBEDDED_NVL(nvp));
850 break;
851 case DATA_TYPE_NVLIST_ARRAY: {
852 nvlist_t **nvlp = EMBEDDED_NVL_ARRAY(nvp);
853 int i;
855 for (i = 0; i < NVP_NELEM(nvp); i++)
856 if (nvlp[i] != NULL)
857 nvlist_free(nvlp[i]);
858 break;
860 default:
861 break;
866 * nvlist_free - free an unpacked nvlist
868 void
869 nvlist_free(nvlist_t *nvl)
871 nvpriv_t *priv;
872 i_nvp_t *curr;
874 if (nvl == NULL ||
875 (priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL)
876 return;
879 * Unpacked nvlist are linked through i_nvp_t
881 curr = priv->nvp_list;
882 while (curr != NULL) {
883 nvpair_t *nvp = &curr->nvi_nvp;
884 curr = curr->nvi_next;
886 nvpair_free(nvp);
887 nvp_buf_free(nvl, nvp);
890 if (!(priv->nvp_stat & NV_STAT_EMBEDDED))
891 nv_mem_free(priv, nvl, NV_ALIGN(sizeof (nvlist_t)));
892 else
893 nvl->nvl_priv = 0;
895 nvt_tab_free(priv);
896 nv_mem_free(priv, priv, sizeof (nvpriv_t));
899 static int
900 nvlist_contains_nvp(const nvlist_t *nvl, const nvpair_t *nvp)
902 const nvpriv_t *priv = (const nvpriv_t *)(uintptr_t)nvl->nvl_priv;
903 const i_nvp_t *curr;
905 if (nvp == NULL)
906 return (0);
908 for (curr = priv->nvp_list; curr != NULL; curr = curr->nvi_next)
909 if (&curr->nvi_nvp == nvp)
910 return (1);
912 return (0);
916 * Make a copy of nvlist
919 nvlist_dup(const nvlist_t *nvl, nvlist_t **nvlp, int kmflag)
921 return (nvlist_xdup(nvl, nvlp, nvlist_nv_alloc(kmflag)));
925 nvlist_xdup(const nvlist_t *nvl, nvlist_t **nvlp, nv_alloc_t *nva)
927 int err;
928 nvlist_t *ret;
930 if (nvl == NULL || nvlp == NULL)
931 return (EINVAL);
933 if ((err = nvlist_xalloc(&ret, nvl->nvl_nvflag, nva)) != 0)
934 return (err);
936 if ((err = nvlist_copy_pairs(nvl, ret)) != 0)
937 nvlist_free(ret);
938 else
939 *nvlp = ret;
941 return (err);
945 * Remove all with matching name
948 nvlist_remove_all(nvlist_t *nvl, const char *name)
950 int error = ENOENT;
952 if (nvl == NULL || name == NULL || nvl->nvl_priv == 0)
953 return (EINVAL);
955 nvpair_t *nvp;
956 while ((nvp = nvt_lookup_name(nvl, name)) != NULL) {
957 VERIFY0(nvlist_remove_nvpair(nvl, nvp));
958 error = 0;
961 return (error);
965 * Remove first one with matching name and type
968 nvlist_remove(nvlist_t *nvl, const char *name, data_type_t type)
970 if (nvl == NULL || name == NULL || nvl->nvl_priv == 0)
971 return (EINVAL);
973 nvpair_t *nvp = nvt_lookup_name_type(nvl, name, type);
974 if (nvp == NULL)
975 return (ENOENT);
977 return (nvlist_remove_nvpair(nvl, nvp));
981 nvlist_remove_nvpair(nvlist_t *nvl, nvpair_t *nvp)
983 if (nvl == NULL || nvp == NULL)
984 return (EINVAL);
986 int err = nvt_remove_nvpair(nvl, nvp);
987 if (err != 0)
988 return (err);
990 nvp_buf_unlink(nvl, nvp);
991 nvpair_free(nvp);
992 nvp_buf_free(nvl, nvp);
993 return (0);
997 * This function calculates the size of an nvpair value.
999 * The data argument controls the behavior in case of the data types
1000 * DATA_TYPE_STRING and
1001 * DATA_TYPE_STRING_ARRAY
1002 * Is data == NULL then the size of the string(s) is excluded.
1004 static int
1005 i_get_value_size(data_type_t type, const void *data, uint_t nelem)
1007 uint64_t value_sz;
1009 if (i_validate_type_nelem(type, nelem) != 0)
1010 return (-1);
1012 /* Calculate required size for holding value */
1013 switch (type) {
1014 case DATA_TYPE_BOOLEAN:
1015 value_sz = 0;
1016 break;
1017 case DATA_TYPE_BOOLEAN_VALUE:
1018 value_sz = sizeof (boolean_t);
1019 break;
1020 case DATA_TYPE_BYTE:
1021 value_sz = sizeof (uchar_t);
1022 break;
1023 case DATA_TYPE_INT8:
1024 value_sz = sizeof (int8_t);
1025 break;
1026 case DATA_TYPE_UINT8:
1027 value_sz = sizeof (uint8_t);
1028 break;
1029 case DATA_TYPE_INT16:
1030 value_sz = sizeof (int16_t);
1031 break;
1032 case DATA_TYPE_UINT16:
1033 value_sz = sizeof (uint16_t);
1034 break;
1035 case DATA_TYPE_INT32:
1036 value_sz = sizeof (int32_t);
1037 break;
1038 case DATA_TYPE_UINT32:
1039 value_sz = sizeof (uint32_t);
1040 break;
1041 case DATA_TYPE_INT64:
1042 value_sz = sizeof (int64_t);
1043 break;
1044 case DATA_TYPE_UINT64:
1045 value_sz = sizeof (uint64_t);
1046 break;
1047 #if !defined(_KERNEL)
1048 case DATA_TYPE_DOUBLE:
1049 value_sz = sizeof (double);
1050 break;
1051 #endif
1052 case DATA_TYPE_STRING:
1053 if (data == NULL)
1054 value_sz = 0;
1055 else
1056 value_sz = strlen(data) + 1;
1057 break;
1058 case DATA_TYPE_BOOLEAN_ARRAY:
1059 value_sz = (uint64_t)nelem * sizeof (boolean_t);
1060 break;
1061 case DATA_TYPE_BYTE_ARRAY:
1062 value_sz = (uint64_t)nelem * sizeof (uchar_t);
1063 break;
1064 case DATA_TYPE_INT8_ARRAY:
1065 value_sz = (uint64_t)nelem * sizeof (int8_t);
1066 break;
1067 case DATA_TYPE_UINT8_ARRAY:
1068 value_sz = (uint64_t)nelem * sizeof (uint8_t);
1069 break;
1070 case DATA_TYPE_INT16_ARRAY:
1071 value_sz = (uint64_t)nelem * sizeof (int16_t);
1072 break;
1073 case DATA_TYPE_UINT16_ARRAY:
1074 value_sz = (uint64_t)nelem * sizeof (uint16_t);
1075 break;
1076 case DATA_TYPE_INT32_ARRAY:
1077 value_sz = (uint64_t)nelem * sizeof (int32_t);
1078 break;
1079 case DATA_TYPE_UINT32_ARRAY:
1080 value_sz = (uint64_t)nelem * sizeof (uint32_t);
1081 break;
1082 case DATA_TYPE_INT64_ARRAY:
1083 value_sz = (uint64_t)nelem * sizeof (int64_t);
1084 break;
1085 case DATA_TYPE_UINT64_ARRAY:
1086 value_sz = (uint64_t)nelem * sizeof (uint64_t);
1087 break;
1088 case DATA_TYPE_STRING_ARRAY:
1089 value_sz = (uint64_t)nelem * sizeof (uint64_t);
1091 if (data != NULL) {
1092 char *const *strs = data;
1093 uint_t i;
1095 /* no alignment requirement for strings */
1096 for (i = 0; i < nelem; i++) {
1097 if (strs[i] == NULL)
1098 return (-1);
1099 value_sz += strlen(strs[i]) + 1;
1102 break;
1103 case DATA_TYPE_HRTIME:
1104 value_sz = sizeof (hrtime_t);
1105 break;
1106 case DATA_TYPE_NVLIST:
1107 value_sz = NV_ALIGN(sizeof (nvlist_t));
1108 break;
1109 case DATA_TYPE_NVLIST_ARRAY:
1110 value_sz = (uint64_t)nelem * sizeof (uint64_t) +
1111 (uint64_t)nelem * NV_ALIGN(sizeof (nvlist_t));
1112 break;
1113 default:
1114 return (-1);
1117 return (value_sz > INT32_MAX ? -1 : (int)value_sz);
1120 static int
1121 nvlist_copy_embedded(nvlist_t *nvl, nvlist_t *onvl, nvlist_t *emb_nvl)
1123 nvpriv_t *priv;
1124 int err;
1126 if ((priv = nv_priv_alloc_embedded((nvpriv_t *)(uintptr_t)
1127 nvl->nvl_priv)) == NULL)
1128 return (ENOMEM);
1130 nvlist_init(emb_nvl, onvl->nvl_nvflag, priv);
1132 if ((err = nvlist_copy_pairs(onvl, emb_nvl)) != 0) {
1133 nvlist_free(emb_nvl);
1134 emb_nvl->nvl_priv = 0;
1137 return (err);
1141 * nvlist_add_common - Add new <name,value> pair to nvlist
1143 static int
1144 nvlist_add_common(nvlist_t *nvl, const char *name,
1145 data_type_t type, uint_t nelem, const void *data)
1147 nvpair_t *nvp;
1148 uint_t i;
1150 int nvp_sz, name_sz, value_sz;
1151 int err = 0;
1153 if (name == NULL || nvl == NULL || nvl->nvl_priv == 0)
1154 return (EINVAL);
1156 if (nelem != 0 && data == NULL)
1157 return (EINVAL);
1160 * Verify type and nelem and get the value size.
1161 * In case of data types DATA_TYPE_STRING and DATA_TYPE_STRING_ARRAY
1162 * is the size of the string(s) included.
1164 if ((value_sz = i_get_value_size(type, data, nelem)) < 0)
1165 return (EINVAL);
1167 if (i_validate_nvpair_value(type, nelem, data) != 0)
1168 return (EINVAL);
1171 * If we're adding an nvlist or nvlist array, ensure that we are not
1172 * adding the input nvlist to itself, which would cause recursion,
1173 * and ensure that no NULL nvlist pointers are present.
1175 switch (type) {
1176 case DATA_TYPE_NVLIST:
1177 if (data == nvl || data == NULL)
1178 return (EINVAL);
1179 break;
1180 case DATA_TYPE_NVLIST_ARRAY: {
1181 nvlist_t **onvlp = (nvlist_t **)data;
1182 for (i = 0; i < nelem; i++) {
1183 if (onvlp[i] == nvl || onvlp[i] == NULL)
1184 return (EINVAL);
1186 break;
1188 default:
1189 break;
1192 /* calculate sizes of the nvpair elements and the nvpair itself */
1193 name_sz = strlen(name) + 1;
1194 if (name_sz >= 1ULL << (sizeof (nvp->nvp_name_sz) * NBBY - 1))
1195 return (EINVAL);
1197 nvp_sz = NVP_SIZE_CALC(name_sz, value_sz);
1199 if ((nvp = nvp_buf_alloc(nvl, nvp_sz)) == NULL)
1200 return (ENOMEM);
1202 ASSERT(nvp->nvp_size == nvp_sz);
1203 nvp->nvp_name_sz = name_sz;
1204 nvp->nvp_value_elem = nelem;
1205 nvp->nvp_type = type;
1206 memcpy(NVP_NAME(nvp), name, name_sz);
1208 switch (type) {
1209 case DATA_TYPE_BOOLEAN:
1210 break;
1211 case DATA_TYPE_STRING_ARRAY: {
1212 char *const *strs = data;
1213 char *buf = NVP_VALUE(nvp);
1214 char **cstrs = (void *)buf;
1216 /* skip pre-allocated space for pointer array */
1217 buf += nelem * sizeof (uint64_t);
1218 for (i = 0; i < nelem; i++) {
1219 int slen = strlen(strs[i]) + 1;
1220 memcpy(buf, strs[i], slen);
1221 cstrs[i] = buf;
1222 buf += slen;
1224 break;
1226 case DATA_TYPE_NVLIST: {
1227 nvlist_t *nnvl = EMBEDDED_NVL(nvp);
1228 nvlist_t *onvl = (nvlist_t *)data;
1230 if ((err = nvlist_copy_embedded(nvl, onvl, nnvl)) != 0) {
1231 nvp_buf_free(nvl, nvp);
1232 return (err);
1234 break;
1236 case DATA_TYPE_NVLIST_ARRAY: {
1237 nvlist_t **onvlp = (nvlist_t **)data;
1238 nvlist_t **nvlp = EMBEDDED_NVL_ARRAY(nvp);
1239 nvlist_t *embedded = (nvlist_t *)
1240 ((uintptr_t)nvlp + nelem * sizeof (uint64_t));
1242 for (i = 0; i < nelem; i++) {
1243 if ((err = nvlist_copy_embedded(nvl,
1244 onvlp[i], embedded)) != 0) {
1246 * Free any successfully created lists
1248 nvpair_free(nvp);
1249 nvp_buf_free(nvl, nvp);
1250 return (err);
1253 nvlp[i] = embedded++;
1255 break;
1257 default:
1258 memcpy(NVP_VALUE(nvp), data, value_sz);
1261 /* if unique name, remove before add */
1262 if (nvl->nvl_nvflag & NV_UNIQUE_NAME)
1263 (void) nvlist_remove_all(nvl, name);
1264 else if (nvl->nvl_nvflag & NV_UNIQUE_NAME_TYPE)
1265 (void) nvlist_remove(nvl, name, type);
1267 err = nvt_add_nvpair(nvl, nvp);
1268 if (err != 0) {
1269 nvpair_free(nvp);
1270 nvp_buf_free(nvl, nvp);
1271 return (err);
1273 nvp_buf_link(nvl, nvp);
1275 return (0);
1279 nvlist_add_boolean(nvlist_t *nvl, const char *name)
1281 return (nvlist_add_common(nvl, name, DATA_TYPE_BOOLEAN, 0, NULL));
1285 nvlist_add_boolean_value(nvlist_t *nvl, const char *name, boolean_t val)
1287 return (nvlist_add_common(nvl, name, DATA_TYPE_BOOLEAN_VALUE, 1, &val));
1291 nvlist_add_byte(nvlist_t *nvl, const char *name, uchar_t val)
1293 return (nvlist_add_common(nvl, name, DATA_TYPE_BYTE, 1, &val));
1297 nvlist_add_int8(nvlist_t *nvl, const char *name, int8_t val)
1299 return (nvlist_add_common(nvl, name, DATA_TYPE_INT8, 1, &val));
1303 nvlist_add_uint8(nvlist_t *nvl, const char *name, uint8_t val)
1305 return (nvlist_add_common(nvl, name, DATA_TYPE_UINT8, 1, &val));
1309 nvlist_add_int16(nvlist_t *nvl, const char *name, int16_t val)
1311 return (nvlist_add_common(nvl, name, DATA_TYPE_INT16, 1, &val));
1315 nvlist_add_uint16(nvlist_t *nvl, const char *name, uint16_t val)
1317 return (nvlist_add_common(nvl, name, DATA_TYPE_UINT16, 1, &val));
1321 nvlist_add_int32(nvlist_t *nvl, const char *name, int32_t val)
1323 return (nvlist_add_common(nvl, name, DATA_TYPE_INT32, 1, &val));
1327 nvlist_add_uint32(nvlist_t *nvl, const char *name, uint32_t val)
1329 return (nvlist_add_common(nvl, name, DATA_TYPE_UINT32, 1, &val));
1333 nvlist_add_int64(nvlist_t *nvl, const char *name, int64_t val)
1335 return (nvlist_add_common(nvl, name, DATA_TYPE_INT64, 1, &val));
1339 nvlist_add_uint64(nvlist_t *nvl, const char *name, uint64_t val)
1341 return (nvlist_add_common(nvl, name, DATA_TYPE_UINT64, 1, &val));
1344 #if !defined(_KERNEL)
1346 nvlist_add_double(nvlist_t *nvl, const char *name, double val)
1348 return (nvlist_add_common(nvl, name, DATA_TYPE_DOUBLE, 1, &val));
1350 #endif
1353 nvlist_add_string(nvlist_t *nvl, const char *name, const char *val)
1355 return (nvlist_add_common(nvl, name, DATA_TYPE_STRING, 1, (void *)val));
1359 nvlist_add_boolean_array(nvlist_t *nvl, const char *name,
1360 const boolean_t *a, uint_t n)
1362 return (nvlist_add_common(nvl, name, DATA_TYPE_BOOLEAN_ARRAY, n, a));
1366 nvlist_add_byte_array(nvlist_t *nvl, const char *name, const uchar_t *a,
1367 uint_t n)
1369 return (nvlist_add_common(nvl, name, DATA_TYPE_BYTE_ARRAY, n, a));
1373 nvlist_add_int8_array(nvlist_t *nvl, const char *name, const int8_t *a,
1374 uint_t n)
1376 return (nvlist_add_common(nvl, name, DATA_TYPE_INT8_ARRAY, n, a));
1380 nvlist_add_uint8_array(nvlist_t *nvl, const char *name, const uint8_t *a,
1381 uint_t n)
1383 return (nvlist_add_common(nvl, name, DATA_TYPE_UINT8_ARRAY, n, a));
1387 nvlist_add_int16_array(nvlist_t *nvl, const char *name, const int16_t *a,
1388 uint_t n)
1390 return (nvlist_add_common(nvl, name, DATA_TYPE_INT16_ARRAY, n, a));
1394 nvlist_add_uint16_array(nvlist_t *nvl, const char *name, const uint16_t *a,
1395 uint_t n)
1397 return (nvlist_add_common(nvl, name, DATA_TYPE_UINT16_ARRAY, n, a));
1401 nvlist_add_int32_array(nvlist_t *nvl, const char *name, const int32_t *a,
1402 uint_t n)
1404 return (nvlist_add_common(nvl, name, DATA_TYPE_INT32_ARRAY, n, a));
1408 nvlist_add_uint32_array(nvlist_t *nvl, const char *name, const uint32_t *a,
1409 uint_t n)
1411 return (nvlist_add_common(nvl, name, DATA_TYPE_UINT32_ARRAY, n, a));
1415 nvlist_add_int64_array(nvlist_t *nvl, const char *name, const int64_t *a,
1416 uint_t n)
1418 return (nvlist_add_common(nvl, name, DATA_TYPE_INT64_ARRAY, n, a));
1422 nvlist_add_uint64_array(nvlist_t *nvl, const char *name, const uint64_t *a,
1423 uint_t n)
1425 return (nvlist_add_common(nvl, name, DATA_TYPE_UINT64_ARRAY, n, a));
1429 nvlist_add_string_array(nvlist_t *nvl, const char *name,
1430 const char *const *a, uint_t n)
1432 return (nvlist_add_common(nvl, name, DATA_TYPE_STRING_ARRAY, n, a));
1436 nvlist_add_hrtime(nvlist_t *nvl, const char *name, hrtime_t val)
1438 return (nvlist_add_common(nvl, name, DATA_TYPE_HRTIME, 1, &val));
1442 nvlist_add_nvlist(nvlist_t *nvl, const char *name, const nvlist_t *val)
1444 return (nvlist_add_common(nvl, name, DATA_TYPE_NVLIST, 1, val));
1448 nvlist_add_nvlist_array(nvlist_t *nvl, const char *name,
1449 const nvlist_t * const *a, uint_t n)
1451 return (nvlist_add_common(nvl, name, DATA_TYPE_NVLIST_ARRAY, n, a));
1454 /* reading name-value pairs */
1455 nvpair_t *
1456 nvlist_next_nvpair(nvlist_t *nvl, const nvpair_t *nvp)
1458 nvpriv_t *priv;
1459 i_nvp_t *curr;
1461 if (nvl == NULL ||
1462 (priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL)
1463 return (NULL);
1465 curr = NVPAIR2I_NVP(nvp);
1468 * Ensure that nvp is a valid nvpair on this nvlist.
1469 * NB: nvp_curr is used only as a hint so that we don't always
1470 * have to walk the list to determine if nvp is still on the list.
1472 if (nvp == NULL)
1473 curr = priv->nvp_list;
1474 else if (priv->nvp_curr == curr || nvlist_contains_nvp(nvl, nvp))
1475 curr = curr->nvi_next;
1476 else
1477 curr = NULL;
1479 priv->nvp_curr = curr;
1481 return (curr != NULL ? &curr->nvi_nvp : NULL);
1484 nvpair_t *
1485 nvlist_prev_nvpair(nvlist_t *nvl, const nvpair_t *nvp)
1487 nvpriv_t *priv;
1488 i_nvp_t *curr;
1490 if (nvl == NULL ||
1491 (priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL)
1492 return (NULL);
1494 curr = NVPAIR2I_NVP(nvp);
1496 if (nvp == NULL)
1497 curr = priv->nvp_last;
1498 else if (priv->nvp_curr == curr || nvlist_contains_nvp(nvl, nvp))
1499 curr = curr->nvi_prev;
1500 else
1501 curr = NULL;
1503 priv->nvp_curr = curr;
1505 return (curr != NULL ? &curr->nvi_nvp : NULL);
1508 boolean_t
1509 nvlist_empty(const nvlist_t *nvl)
1511 const nvpriv_t *priv;
1513 if (nvl == NULL ||
1514 (priv = (const nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL)
1515 return (B_TRUE);
1517 return (priv->nvp_list == NULL);
1520 char *
1521 nvpair_name(const nvpair_t *nvp)
1523 return (NVP_NAME(nvp));
1526 data_type_t
1527 nvpair_type(const nvpair_t *nvp)
1529 return (NVP_TYPE(nvp));
1533 nvpair_type_is_array(const nvpair_t *nvp)
1535 data_type_t type = NVP_TYPE(nvp);
1537 if ((type == DATA_TYPE_BYTE_ARRAY) ||
1538 (type == DATA_TYPE_INT8_ARRAY) ||
1539 (type == DATA_TYPE_UINT8_ARRAY) ||
1540 (type == DATA_TYPE_INT16_ARRAY) ||
1541 (type == DATA_TYPE_UINT16_ARRAY) ||
1542 (type == DATA_TYPE_INT32_ARRAY) ||
1543 (type == DATA_TYPE_UINT32_ARRAY) ||
1544 (type == DATA_TYPE_INT64_ARRAY) ||
1545 (type == DATA_TYPE_UINT64_ARRAY) ||
1546 (type == DATA_TYPE_BOOLEAN_ARRAY) ||
1547 (type == DATA_TYPE_STRING_ARRAY) ||
1548 (type == DATA_TYPE_NVLIST_ARRAY))
1549 return (1);
1550 return (0);
1554 static int
1555 nvpair_value_common(const nvpair_t *nvp, data_type_t type, uint_t *nelem,
1556 void *data)
1558 int value_sz;
1560 if (nvp == NULL || nvpair_type(nvp) != type)
1561 return (EINVAL);
1564 * For non-array types, we copy the data.
1565 * For array types (including string), we set a pointer.
1567 switch (type) {
1568 case DATA_TYPE_BOOLEAN:
1569 if (nelem != NULL)
1570 *nelem = 0;
1571 break;
1573 case DATA_TYPE_BOOLEAN_VALUE:
1574 case DATA_TYPE_BYTE:
1575 case DATA_TYPE_INT8:
1576 case DATA_TYPE_UINT8:
1577 case DATA_TYPE_INT16:
1578 case DATA_TYPE_UINT16:
1579 case DATA_TYPE_INT32:
1580 case DATA_TYPE_UINT32:
1581 case DATA_TYPE_INT64:
1582 case DATA_TYPE_UINT64:
1583 case DATA_TYPE_HRTIME:
1584 #if !defined(_KERNEL)
1585 case DATA_TYPE_DOUBLE:
1586 #endif
1587 if (data == NULL)
1588 return (EINVAL);
1589 if ((value_sz = i_get_value_size(type, NULL, 1)) < 0)
1590 return (EINVAL);
1591 memcpy(data, NVP_VALUE(nvp), (size_t)value_sz);
1592 if (nelem != NULL)
1593 *nelem = 1;
1594 break;
1596 case DATA_TYPE_NVLIST:
1597 case DATA_TYPE_STRING:
1598 if (data == NULL)
1599 return (EINVAL);
1601 * This discards the const from nvp, so all callers for these
1602 * types must not accept const nvpairs.
1604 *(void **)data = (void *)NVP_VALUE(nvp);
1605 if (nelem != NULL)
1606 *nelem = 1;
1607 break;
1609 case DATA_TYPE_BOOLEAN_ARRAY:
1610 case DATA_TYPE_BYTE_ARRAY:
1611 case DATA_TYPE_INT8_ARRAY:
1612 case DATA_TYPE_UINT8_ARRAY:
1613 case DATA_TYPE_INT16_ARRAY:
1614 case DATA_TYPE_UINT16_ARRAY:
1615 case DATA_TYPE_INT32_ARRAY:
1616 case DATA_TYPE_UINT32_ARRAY:
1617 case DATA_TYPE_INT64_ARRAY:
1618 case DATA_TYPE_UINT64_ARRAY:
1619 case DATA_TYPE_STRING_ARRAY:
1620 case DATA_TYPE_NVLIST_ARRAY:
1621 if (nelem == NULL || data == NULL)
1622 return (EINVAL);
1624 * This discards the const from nvp, so all callers for these
1625 * types must not accept const nvpairs.
1627 if ((*nelem = NVP_NELEM(nvp)) != 0)
1628 *(void **)data = (void *)NVP_VALUE(nvp);
1629 else
1630 *(void **)data = NULL;
1631 break;
1633 default:
1634 return (ENOTSUP);
1637 return (0);
1640 static int
1641 nvlist_lookup_common(const nvlist_t *nvl, const char *name, data_type_t type,
1642 uint_t *nelem, void *data)
1644 if (name == NULL || nvl == NULL || nvl->nvl_priv == 0)
1645 return (EINVAL);
1647 if (!(nvl->nvl_nvflag & (NV_UNIQUE_NAME | NV_UNIQUE_NAME_TYPE)))
1648 return (ENOTSUP);
1650 nvpair_t *nvp = nvt_lookup_name_type(nvl, name, type);
1651 if (nvp == NULL)
1652 return (ENOENT);
1654 return (nvpair_value_common(nvp, type, nelem, data));
1658 nvlist_lookup_boolean(const nvlist_t *nvl, const char *name)
1660 return (nvlist_lookup_common(nvl, name, DATA_TYPE_BOOLEAN, NULL, NULL));
1664 nvlist_lookup_boolean_value(const nvlist_t *nvl, const char *name,
1665 boolean_t *val)
1667 return (nvlist_lookup_common(nvl, name,
1668 DATA_TYPE_BOOLEAN_VALUE, NULL, val));
1672 nvlist_lookup_byte(const nvlist_t *nvl, const char *name, uchar_t *val)
1674 return (nvlist_lookup_common(nvl, name, DATA_TYPE_BYTE, NULL, val));
1678 nvlist_lookup_int8(const nvlist_t *nvl, const char *name, int8_t *val)
1680 return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT8, NULL, val));
1684 nvlist_lookup_uint8(const nvlist_t *nvl, const char *name, uint8_t *val)
1686 return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT8, NULL, val));
1690 nvlist_lookup_int16(const nvlist_t *nvl, const char *name, int16_t *val)
1692 return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT16, NULL, val));
1696 nvlist_lookup_uint16(const nvlist_t *nvl, const char *name, uint16_t *val)
1698 return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT16, NULL, val));
1702 nvlist_lookup_int32(const nvlist_t *nvl, const char *name, int32_t *val)
1704 return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT32, NULL, val));
1708 nvlist_lookup_uint32(const nvlist_t *nvl, const char *name, uint32_t *val)
1710 return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT32, NULL, val));
1714 nvlist_lookup_int64(const nvlist_t *nvl, const char *name, int64_t *val)
1716 return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT64, NULL, val));
1720 nvlist_lookup_uint64(const nvlist_t *nvl, const char *name, uint64_t *val)
1722 return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT64, NULL, val));
1725 #if !defined(_KERNEL)
1727 nvlist_lookup_double(const nvlist_t *nvl, const char *name, double *val)
1729 return (nvlist_lookup_common(nvl, name, DATA_TYPE_DOUBLE, NULL, val));
1731 #endif
1734 nvlist_lookup_string(nvlist_t *nvl, const char *name, char **val)
1736 return (nvlist_lookup_common(nvl, name, DATA_TYPE_STRING, NULL, val));
1740 nvlist_lookup_nvlist(nvlist_t *nvl, const char *name, nvlist_t **val)
1742 return (nvlist_lookup_common(nvl, name, DATA_TYPE_NVLIST, NULL, val));
1746 nvlist_lookup_boolean_array(nvlist_t *nvl, const char *name,
1747 boolean_t **a, uint_t *n)
1749 return (nvlist_lookup_common(nvl, name,
1750 DATA_TYPE_BOOLEAN_ARRAY, n, a));
1754 nvlist_lookup_byte_array(nvlist_t *nvl, const char *name,
1755 uchar_t **a, uint_t *n)
1757 return (nvlist_lookup_common(nvl, name, DATA_TYPE_BYTE_ARRAY, n, a));
1761 nvlist_lookup_int8_array(nvlist_t *nvl, const char *name, int8_t **a, uint_t *n)
1763 return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT8_ARRAY, n, a));
1767 nvlist_lookup_uint8_array(nvlist_t *nvl, const char *name,
1768 uint8_t **a, uint_t *n)
1770 return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT8_ARRAY, n, a));
1774 nvlist_lookup_int16_array(nvlist_t *nvl, const char *name,
1775 int16_t **a, uint_t *n)
1777 return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT16_ARRAY, n, a));
1781 nvlist_lookup_uint16_array(nvlist_t *nvl, const char *name,
1782 uint16_t **a, uint_t *n)
1784 return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT16_ARRAY, n, a));
1788 nvlist_lookup_int32_array(nvlist_t *nvl, const char *name,
1789 int32_t **a, uint_t *n)
1791 return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT32_ARRAY, n, a));
1795 nvlist_lookup_uint32_array(nvlist_t *nvl, const char *name,
1796 uint32_t **a, uint_t *n)
1798 return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT32_ARRAY, n, a));
1802 nvlist_lookup_int64_array(nvlist_t *nvl, const char *name,
1803 int64_t **a, uint_t *n)
1805 return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT64_ARRAY, n, a));
1809 nvlist_lookup_uint64_array(nvlist_t *nvl, const char *name,
1810 uint64_t **a, uint_t *n)
1812 return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT64_ARRAY, n, a));
1816 nvlist_lookup_string_array(nvlist_t *nvl, const char *name,
1817 char ***a, uint_t *n)
1819 return (nvlist_lookup_common(nvl, name, DATA_TYPE_STRING_ARRAY, n, a));
1823 nvlist_lookup_nvlist_array(nvlist_t *nvl, const char *name,
1824 nvlist_t ***a, uint_t *n)
1826 return (nvlist_lookup_common(nvl, name, DATA_TYPE_NVLIST_ARRAY, n, a));
1830 nvlist_lookup_hrtime(nvlist_t *nvl, const char *name, hrtime_t *val)
1832 return (nvlist_lookup_common(nvl, name, DATA_TYPE_HRTIME, NULL, val));
1836 nvlist_lookup_pairs(nvlist_t *nvl, int flag, ...)
1838 va_list ap;
1839 char *name;
1840 int noentok = (flag & NV_FLAG_NOENTOK ? 1 : 0);
1841 int ret = 0;
1843 va_start(ap, flag);
1844 while (ret == 0 && (name = va_arg(ap, char *)) != NULL) {
1845 data_type_t type;
1846 void *val;
1847 uint_t *nelem;
1849 switch (type = va_arg(ap, data_type_t)) {
1850 case DATA_TYPE_BOOLEAN:
1851 ret = nvlist_lookup_common(nvl, name, type, NULL, NULL);
1852 break;
1854 case DATA_TYPE_BOOLEAN_VALUE:
1855 case DATA_TYPE_BYTE:
1856 case DATA_TYPE_INT8:
1857 case DATA_TYPE_UINT8:
1858 case DATA_TYPE_INT16:
1859 case DATA_TYPE_UINT16:
1860 case DATA_TYPE_INT32:
1861 case DATA_TYPE_UINT32:
1862 case DATA_TYPE_INT64:
1863 case DATA_TYPE_UINT64:
1864 case DATA_TYPE_HRTIME:
1865 case DATA_TYPE_STRING:
1866 case DATA_TYPE_NVLIST:
1867 #if !defined(_KERNEL)
1868 case DATA_TYPE_DOUBLE:
1869 #endif
1870 val = va_arg(ap, void *);
1871 ret = nvlist_lookup_common(nvl, name, type, NULL, val);
1872 break;
1874 case DATA_TYPE_BYTE_ARRAY:
1875 case DATA_TYPE_BOOLEAN_ARRAY:
1876 case DATA_TYPE_INT8_ARRAY:
1877 case DATA_TYPE_UINT8_ARRAY:
1878 case DATA_TYPE_INT16_ARRAY:
1879 case DATA_TYPE_UINT16_ARRAY:
1880 case DATA_TYPE_INT32_ARRAY:
1881 case DATA_TYPE_UINT32_ARRAY:
1882 case DATA_TYPE_INT64_ARRAY:
1883 case DATA_TYPE_UINT64_ARRAY:
1884 case DATA_TYPE_STRING_ARRAY:
1885 case DATA_TYPE_NVLIST_ARRAY:
1886 val = va_arg(ap, void *);
1887 nelem = va_arg(ap, uint_t *);
1888 ret = nvlist_lookup_common(nvl, name, type, nelem, val);
1889 break;
1891 default:
1892 ret = EINVAL;
1895 if (ret == ENOENT && noentok)
1896 ret = 0;
1898 va_end(ap);
1900 return (ret);
1904 * Find the 'name'ed nvpair in the nvlist 'nvl'. If 'name' found, the function
1905 * returns zero and a pointer to the matching nvpair is returned in '*ret'
1906 * (given 'ret' is non-NULL). If 'sep' is specified then 'name' will penitrate
1907 * multiple levels of embedded nvlists, with 'sep' as the separator. As an
1908 * example, if sep is '.', name might look like: "a" or "a.b" or "a.c[3]" or
1909 * "a.d[3].e[1]". This matches the C syntax for array embed (for convenience,
1910 * code also supports "a.d[3]e[1]" syntax).
1912 * If 'ip' is non-NULL and the last name component is an array, return the
1913 * value of the "...[index]" array index in *ip. For an array reference that
1914 * is not indexed, *ip will be returned as -1. If there is a syntax error in
1915 * 'name', and 'ep' is non-NULL then *ep will be set to point to the location
1916 * inside the 'name' string where the syntax error was detected.
1918 static int
1919 nvlist_lookup_nvpair_ei_sep(nvlist_t *nvl, const char *name, const char sep,
1920 nvpair_t **ret, int *ip, char **ep)
1922 nvpair_t *nvp;
1923 const char *np;
1924 char *sepp = NULL;
1925 char *idxp, *idxep;
1926 nvlist_t **nva;
1927 long idx = 0;
1928 int n;
1930 if (ip)
1931 *ip = -1; /* not indexed */
1932 if (ep)
1933 *ep = NULL;
1935 if ((nvl == NULL) || (name == NULL))
1936 return (EINVAL);
1938 sepp = NULL;
1939 idx = 0;
1940 /* step through components of name */
1941 for (np = name; np && *np; np = sepp) {
1942 /* ensure unique names */
1943 if (!(nvl->nvl_nvflag & NV_UNIQUE_NAME))
1944 return (ENOTSUP);
1946 /* skip white space */
1947 skip_whitespace(np);
1948 if (*np == 0)
1949 break;
1951 /* set 'sepp' to end of current component 'np' */
1952 if (sep)
1953 sepp = strchr(np, sep);
1954 else
1955 sepp = NULL;
1957 /* find start of next "[ index ]..." */
1958 idxp = strchr(np, '[');
1960 /* if sepp comes first, set idxp to NULL */
1961 if (sepp && idxp && (sepp < idxp))
1962 idxp = NULL;
1965 * At this point 'idxp' is set if there is an index
1966 * expected for the current component.
1968 if (idxp) {
1969 /* set 'n' to length of current 'np' name component */
1970 n = idxp++ - np;
1972 /* keep sepp up to date for *ep use as we advance */
1973 skip_whitespace(idxp);
1974 sepp = idxp;
1976 /* determine the index value */
1977 #if defined(_KERNEL)
1978 if (ddi_strtol(idxp, &idxep, 0, &idx))
1979 goto fail;
1980 #else
1981 idx = strtol(idxp, &idxep, 0);
1982 #endif
1983 if (idxep == idxp)
1984 goto fail;
1986 /* keep sepp up to date for *ep use as we advance */
1987 sepp = idxep;
1989 /* skip white space index value and check for ']' */
1990 skip_whitespace(sepp);
1991 if (*sepp++ != ']')
1992 goto fail;
1994 /* for embedded arrays, support C syntax: "a[1].b" */
1995 skip_whitespace(sepp);
1996 if (sep && (*sepp == sep))
1997 sepp++;
1998 } else if (sepp) {
1999 n = sepp++ - np;
2000 } else {
2001 n = strlen(np);
2004 /* trim trailing whitespace by reducing length of 'np' */
2005 if (n == 0)
2006 goto fail;
2007 for (n--; (np[n] == ' ') || (np[n] == '\t'); n--)
2009 n++;
2011 /* skip whitespace, and set sepp to NULL if complete */
2012 if (sepp) {
2013 skip_whitespace(sepp);
2014 if (*sepp == 0)
2015 sepp = NULL;
2019 * At this point:
2020 * o 'n' is the length of current 'np' component.
2021 * o 'idxp' is set if there was an index, and value 'idx'.
2022 * o 'sepp' is set to the beginning of the next component,
2023 * and set to NULL if we have no more components.
2025 * Search for nvpair with matching component name.
2027 for (nvp = nvlist_next_nvpair(nvl, NULL); nvp != NULL;
2028 nvp = nvlist_next_nvpair(nvl, nvp)) {
2030 /* continue if no match on name */
2031 if (strncmp(np, nvpair_name(nvp), n) ||
2032 (strlen(nvpair_name(nvp)) != n))
2033 continue;
2035 /* if indexed, verify type is array oriented */
2036 if (idxp && !nvpair_type_is_array(nvp))
2037 goto fail;
2040 * Full match found, return nvp and idx if this
2041 * was the last component.
2043 if (sepp == NULL) {
2044 if (ret)
2045 *ret = nvp;
2046 if (ip && idxp)
2047 *ip = (int)idx; /* return index */
2048 return (0); /* found */
2052 * More components: current match must be
2053 * of DATA_TYPE_NVLIST or DATA_TYPE_NVLIST_ARRAY
2054 * to support going deeper.
2056 if (nvpair_type(nvp) == DATA_TYPE_NVLIST) {
2057 nvl = EMBEDDED_NVL(nvp);
2058 break;
2059 } else if (nvpair_type(nvp) == DATA_TYPE_NVLIST_ARRAY) {
2060 (void) nvpair_value_nvlist_array(nvp,
2061 &nva, (uint_t *)&n);
2062 if ((n < 0) || (idx >= n))
2063 goto fail;
2064 nvl = nva[idx];
2065 break;
2068 /* type does not support more levels */
2069 goto fail;
2071 if (nvp == NULL)
2072 goto fail; /* 'name' not found */
2074 /* search for match of next component in embedded 'nvl' list */
2077 fail: if (ep && sepp)
2078 *ep = sepp;
2079 return (EINVAL);
2083 * Return pointer to nvpair with specified 'name'.
2086 nvlist_lookup_nvpair(nvlist_t *nvl, const char *name, nvpair_t **ret)
2088 return (nvlist_lookup_nvpair_ei_sep(nvl, name, 0, ret, NULL, NULL));
2092 * Determine if named nvpair exists in nvlist (use embedded separator of '.'
2093 * and return array index). See nvlist_lookup_nvpair_ei_sep for more detailed
2094 * description.
2096 int nvlist_lookup_nvpair_embedded_index(nvlist_t *nvl,
2097 const char *name, nvpair_t **ret, int *ip, char **ep)
2099 return (nvlist_lookup_nvpair_ei_sep(nvl, name, '.', ret, ip, ep));
2102 boolean_t
2103 nvlist_exists(const nvlist_t *nvl, const char *name)
2105 nvpriv_t *priv;
2106 nvpair_t *nvp;
2107 i_nvp_t *curr;
2109 if (name == NULL || nvl == NULL ||
2110 (priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL)
2111 return (B_FALSE);
2113 for (curr = priv->nvp_list; curr != NULL; curr = curr->nvi_next) {
2114 nvp = &curr->nvi_nvp;
2116 if (strcmp(name, NVP_NAME(nvp)) == 0)
2117 return (B_TRUE);
2120 return (B_FALSE);
2124 nvpair_value_boolean_value(const nvpair_t *nvp, boolean_t *val)
2126 return (nvpair_value_common(nvp, DATA_TYPE_BOOLEAN_VALUE, NULL, val));
2130 nvpair_value_byte(const nvpair_t *nvp, uchar_t *val)
2132 return (nvpair_value_common(nvp, DATA_TYPE_BYTE, NULL, val));
2136 nvpair_value_int8(const nvpair_t *nvp, int8_t *val)
2138 return (nvpair_value_common(nvp, DATA_TYPE_INT8, NULL, val));
2142 nvpair_value_uint8(const nvpair_t *nvp, uint8_t *val)
2144 return (nvpair_value_common(nvp, DATA_TYPE_UINT8, NULL, val));
2148 nvpair_value_int16(const nvpair_t *nvp, int16_t *val)
2150 return (nvpair_value_common(nvp, DATA_TYPE_INT16, NULL, val));
2154 nvpair_value_uint16(const nvpair_t *nvp, uint16_t *val)
2156 return (nvpair_value_common(nvp, DATA_TYPE_UINT16, NULL, val));
2160 nvpair_value_int32(const nvpair_t *nvp, int32_t *val)
2162 return (nvpair_value_common(nvp, DATA_TYPE_INT32, NULL, val));
2166 nvpair_value_uint32(const nvpair_t *nvp, uint32_t *val)
2168 return (nvpair_value_common(nvp, DATA_TYPE_UINT32, NULL, val));
2172 nvpair_value_int64(const nvpair_t *nvp, int64_t *val)
2174 return (nvpair_value_common(nvp, DATA_TYPE_INT64, NULL, val));
2178 nvpair_value_uint64(const nvpair_t *nvp, uint64_t *val)
2180 return (nvpair_value_common(nvp, DATA_TYPE_UINT64, NULL, val));
2183 #if !defined(_KERNEL)
2185 nvpair_value_double(const nvpair_t *nvp, double *val)
2187 return (nvpair_value_common(nvp, DATA_TYPE_DOUBLE, NULL, val));
2189 #endif
2192 nvpair_value_string(nvpair_t *nvp, char **val)
2194 return (nvpair_value_common(nvp, DATA_TYPE_STRING, NULL, val));
2198 nvpair_value_nvlist(nvpair_t *nvp, nvlist_t **val)
2200 return (nvpair_value_common(nvp, DATA_TYPE_NVLIST, NULL, val));
2204 nvpair_value_boolean_array(nvpair_t *nvp, boolean_t **val, uint_t *nelem)
2206 return (nvpair_value_common(nvp, DATA_TYPE_BOOLEAN_ARRAY, nelem, val));
2210 nvpair_value_byte_array(nvpair_t *nvp, uchar_t **val, uint_t *nelem)
2212 return (nvpair_value_common(nvp, DATA_TYPE_BYTE_ARRAY, nelem, val));
2216 nvpair_value_int8_array(nvpair_t *nvp, int8_t **val, uint_t *nelem)
2218 return (nvpair_value_common(nvp, DATA_TYPE_INT8_ARRAY, nelem, val));
2222 nvpair_value_uint8_array(nvpair_t *nvp, uint8_t **val, uint_t *nelem)
2224 return (nvpair_value_common(nvp, DATA_TYPE_UINT8_ARRAY, nelem, val));
2228 nvpair_value_int16_array(nvpair_t *nvp, int16_t **val, uint_t *nelem)
2230 return (nvpair_value_common(nvp, DATA_TYPE_INT16_ARRAY, nelem, val));
2234 nvpair_value_uint16_array(nvpair_t *nvp, uint16_t **val, uint_t *nelem)
2236 return (nvpair_value_common(nvp, DATA_TYPE_UINT16_ARRAY, nelem, val));
2240 nvpair_value_int32_array(nvpair_t *nvp, int32_t **val, uint_t *nelem)
2242 return (nvpair_value_common(nvp, DATA_TYPE_INT32_ARRAY, nelem, val));
2246 nvpair_value_uint32_array(nvpair_t *nvp, uint32_t **val, uint_t *nelem)
2248 return (nvpair_value_common(nvp, DATA_TYPE_UINT32_ARRAY, nelem, val));
2252 nvpair_value_int64_array(nvpair_t *nvp, int64_t **val, uint_t *nelem)
2254 return (nvpair_value_common(nvp, DATA_TYPE_INT64_ARRAY, nelem, val));
2258 nvpair_value_uint64_array(nvpair_t *nvp, uint64_t **val, uint_t *nelem)
2260 return (nvpair_value_common(nvp, DATA_TYPE_UINT64_ARRAY, nelem, val));
2264 nvpair_value_string_array(nvpair_t *nvp, char ***val, uint_t *nelem)
2266 return (nvpair_value_common(nvp, DATA_TYPE_STRING_ARRAY, nelem, val));
2270 nvpair_value_nvlist_array(nvpair_t *nvp, nvlist_t ***val, uint_t *nelem)
2272 return (nvpair_value_common(nvp, DATA_TYPE_NVLIST_ARRAY, nelem, val));
2276 nvpair_value_hrtime(nvpair_t *nvp, hrtime_t *val)
2278 return (nvpair_value_common(nvp, DATA_TYPE_HRTIME, NULL, val));
2282 * Add specified pair to the list.
2285 nvlist_add_nvpair(nvlist_t *nvl, nvpair_t *nvp)
2287 if (nvl == NULL || nvp == NULL)
2288 return (EINVAL);
2290 return (nvlist_add_common(nvl, NVP_NAME(nvp), NVP_TYPE(nvp),
2291 NVP_NELEM(nvp), NVP_VALUE(nvp)));
2295 * Merge the supplied nvlists and put the result in dst.
2296 * The merged list will contain all names specified in both lists,
2297 * the values are taken from nvl in the case of duplicates.
2298 * Return 0 on success.
2301 nvlist_merge(nvlist_t *dst, nvlist_t *nvl, int flag)
2303 (void) flag;
2305 if (nvl == NULL || dst == NULL)
2306 return (EINVAL);
2308 if (dst != nvl)
2309 return (nvlist_copy_pairs(nvl, dst));
2311 return (0);
2315 * Encoding related routines
2317 #define NVS_OP_ENCODE 0
2318 #define NVS_OP_DECODE 1
2319 #define NVS_OP_GETSIZE 2
2321 typedef struct nvs_ops nvs_ops_t;
2323 typedef struct {
2324 int nvs_op;
2325 const nvs_ops_t *nvs_ops;
2326 void *nvs_private;
2327 nvpriv_t *nvs_priv;
2328 int nvs_recursion;
2329 } nvstream_t;
2332 * nvs operations are:
2333 * - nvs_nvlist
2334 * encoding / decoding of an nvlist header (nvlist_t)
2335 * calculates the size used for header and end detection
2337 * - nvs_nvpair
2338 * responsible for the first part of encoding / decoding of an nvpair
2339 * calculates the decoded size of an nvpair
2341 * - nvs_nvp_op
2342 * second part of encoding / decoding of an nvpair
2344 * - nvs_nvp_size
2345 * calculates the encoding size of an nvpair
2347 * - nvs_nvl_fini
2348 * encodes the end detection mark (zeros).
2350 struct nvs_ops {
2351 int (*nvs_nvlist)(nvstream_t *, nvlist_t *, size_t *);
2352 int (*nvs_nvpair)(nvstream_t *, nvpair_t *, size_t *);
2353 int (*nvs_nvp_op)(nvstream_t *, nvpair_t *);
2354 int (*nvs_nvp_size)(nvstream_t *, nvpair_t *, size_t *);
2355 int (*nvs_nvl_fini)(nvstream_t *);
2358 typedef struct {
2359 char nvh_encoding; /* nvs encoding method */
2360 char nvh_endian; /* nvs endian */
2361 char nvh_reserved1; /* reserved for future use */
2362 char nvh_reserved2; /* reserved for future use */
2363 } nvs_header_t;
2365 static int
2366 nvs_encode_pairs(nvstream_t *nvs, nvlist_t *nvl)
2368 nvpriv_t *priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv;
2369 i_nvp_t *curr;
2372 * Walk nvpair in list and encode each nvpair
2374 for (curr = priv->nvp_list; curr != NULL; curr = curr->nvi_next)
2375 if (nvs->nvs_ops->nvs_nvpair(nvs, &curr->nvi_nvp, NULL) != 0)
2376 return (EFAULT);
2378 return (nvs->nvs_ops->nvs_nvl_fini(nvs));
2381 static int
2382 nvs_decode_pairs(nvstream_t *nvs, nvlist_t *nvl)
2384 nvpair_t *nvp;
2385 size_t nvsize;
2386 int err;
2389 * Get decoded size of next pair in stream, alloc
2390 * memory for nvpair_t, then decode the nvpair
2392 while ((err = nvs->nvs_ops->nvs_nvpair(nvs, NULL, &nvsize)) == 0) {
2393 if (nvsize == 0) /* end of list */
2394 break;
2396 /* make sure len makes sense */
2397 if (nvsize < NVP_SIZE_CALC(1, 0))
2398 return (EFAULT);
2400 if ((nvp = nvp_buf_alloc(nvl, nvsize)) == NULL)
2401 return (ENOMEM);
2403 if ((err = nvs->nvs_ops->nvs_nvp_op(nvs, nvp)) != 0) {
2404 nvp_buf_free(nvl, nvp);
2405 return (err);
2408 if (i_validate_nvpair(nvp) != 0) {
2409 nvpair_free(nvp);
2410 nvp_buf_free(nvl, nvp);
2411 return (EFAULT);
2414 err = nvt_add_nvpair(nvl, nvp);
2415 if (err != 0) {
2416 nvpair_free(nvp);
2417 nvp_buf_free(nvl, nvp);
2418 return (err);
2420 nvp_buf_link(nvl, nvp);
2422 return (err);
2425 static int
2426 nvs_getsize_pairs(nvstream_t *nvs, nvlist_t *nvl, size_t *buflen)
2428 nvpriv_t *priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv;
2429 i_nvp_t *curr;
2430 uint64_t nvsize = *buflen;
2431 size_t size;
2434 * Get encoded size of nvpairs in nvlist
2436 for (curr = priv->nvp_list; curr != NULL; curr = curr->nvi_next) {
2437 if (nvs->nvs_ops->nvs_nvp_size(nvs, &curr->nvi_nvp, &size) != 0)
2438 return (EINVAL);
2440 if ((nvsize += size) > INT32_MAX)
2441 return (EINVAL);
2444 *buflen = nvsize;
2445 return (0);
2448 static int
2449 nvs_operation(nvstream_t *nvs, nvlist_t *nvl, size_t *buflen)
2451 int err;
2453 if (nvl->nvl_priv == 0)
2454 return (EFAULT);
2457 * Perform the operation, starting with header, then each nvpair
2459 if ((err = nvs->nvs_ops->nvs_nvlist(nvs, nvl, buflen)) != 0)
2460 return (err);
2462 switch (nvs->nvs_op) {
2463 case NVS_OP_ENCODE:
2464 err = nvs_encode_pairs(nvs, nvl);
2465 break;
2467 case NVS_OP_DECODE:
2468 err = nvs_decode_pairs(nvs, nvl);
2469 break;
2471 case NVS_OP_GETSIZE:
2472 err = nvs_getsize_pairs(nvs, nvl, buflen);
2473 break;
2475 default:
2476 err = EINVAL;
2479 return (err);
2482 static int
2483 nvs_embedded(nvstream_t *nvs, nvlist_t *embedded)
2485 switch (nvs->nvs_op) {
2486 case NVS_OP_ENCODE: {
2487 int err;
2489 if (nvs->nvs_recursion >= nvpair_max_recursion)
2490 return (EINVAL);
2491 nvs->nvs_recursion++;
2492 err = nvs_operation(nvs, embedded, NULL);
2493 nvs->nvs_recursion--;
2494 return (err);
2496 case NVS_OP_DECODE: {
2497 nvpriv_t *priv;
2498 int err;
2500 if (embedded->nvl_version != NV_VERSION)
2501 return (ENOTSUP);
2503 if ((priv = nv_priv_alloc_embedded(nvs->nvs_priv)) == NULL)
2504 return (ENOMEM);
2506 nvlist_init(embedded, embedded->nvl_nvflag, priv);
2508 if (nvs->nvs_recursion >= nvpair_max_recursion) {
2509 nvlist_free(embedded);
2510 return (EINVAL);
2512 nvs->nvs_recursion++;
2513 if ((err = nvs_operation(nvs, embedded, NULL)) != 0)
2514 nvlist_free(embedded);
2515 nvs->nvs_recursion--;
2516 return (err);
2518 default:
2519 break;
2522 return (EINVAL);
2525 static int
2526 nvs_embedded_nvl_array(nvstream_t *nvs, nvpair_t *nvp, size_t *size)
2528 size_t nelem = NVP_NELEM(nvp);
2529 nvlist_t **nvlp = EMBEDDED_NVL_ARRAY(nvp);
2530 int i;
2532 switch (nvs->nvs_op) {
2533 case NVS_OP_ENCODE:
2534 for (i = 0; i < nelem; i++)
2535 if (nvs_embedded(nvs, nvlp[i]) != 0)
2536 return (EFAULT);
2537 break;
2539 case NVS_OP_DECODE: {
2540 size_t len = nelem * sizeof (uint64_t);
2541 nvlist_t *embedded = (nvlist_t *)((uintptr_t)nvlp + len);
2543 memset(nvlp, 0, len); /* don't trust packed data */
2544 for (i = 0; i < nelem; i++) {
2545 if (nvs_embedded(nvs, embedded) != 0) {
2546 nvpair_free(nvp);
2547 return (EFAULT);
2550 nvlp[i] = embedded++;
2552 break;
2554 case NVS_OP_GETSIZE: {
2555 uint64_t nvsize = 0;
2557 for (i = 0; i < nelem; i++) {
2558 size_t nvp_sz = 0;
2560 if (nvs_operation(nvs, nvlp[i], &nvp_sz) != 0)
2561 return (EINVAL);
2563 if ((nvsize += nvp_sz) > INT32_MAX)
2564 return (EINVAL);
2567 *size = nvsize;
2568 break;
2570 default:
2571 return (EINVAL);
2574 return (0);
2577 static int nvs_native(nvstream_t *, nvlist_t *, char *, size_t *);
2578 static int nvs_xdr(nvstream_t *, nvlist_t *, char *, size_t *);
2581 * Common routine for nvlist operations:
2582 * encode, decode, getsize (encoded size).
2584 static int
2585 nvlist_common(nvlist_t *nvl, char *buf, size_t *buflen, int encoding,
2586 int nvs_op)
2588 int err = 0;
2589 nvstream_t nvs;
2590 int nvl_endian;
2591 #if defined(_ZFS_LITTLE_ENDIAN)
2592 int host_endian = 1;
2593 #elif defined(_ZFS_BIG_ENDIAN)
2594 int host_endian = 0;
2595 #else
2596 #error "No endian defined!"
2597 #endif /* _ZFS_LITTLE_ENDIAN */
2598 nvs_header_t *nvh;
2600 if (buflen == NULL || nvl == NULL ||
2601 (nvs.nvs_priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL)
2602 return (EINVAL);
2604 nvs.nvs_op = nvs_op;
2605 nvs.nvs_recursion = 0;
2608 * For NVS_OP_ENCODE and NVS_OP_DECODE make sure an nvlist and
2609 * a buffer is allocated. The first 4 bytes in the buffer are
2610 * used for encoding method and host endian.
2612 switch (nvs_op) {
2613 case NVS_OP_ENCODE:
2614 if (buf == NULL || *buflen < sizeof (nvs_header_t))
2615 return (EINVAL);
2617 nvh = (void *)buf;
2618 nvh->nvh_encoding = encoding;
2619 nvh->nvh_endian = nvl_endian = host_endian;
2620 nvh->nvh_reserved1 = 0;
2621 nvh->nvh_reserved2 = 0;
2622 break;
2624 case NVS_OP_DECODE:
2625 if (buf == NULL || *buflen < sizeof (nvs_header_t))
2626 return (EINVAL);
2628 /* get method of encoding from first byte */
2629 nvh = (void *)buf;
2630 encoding = nvh->nvh_encoding;
2631 nvl_endian = nvh->nvh_endian;
2632 break;
2634 case NVS_OP_GETSIZE:
2635 nvl_endian = host_endian;
2638 * add the size for encoding
2640 *buflen = sizeof (nvs_header_t);
2641 break;
2643 default:
2644 return (ENOTSUP);
2648 * Create an nvstream with proper encoding method
2650 switch (encoding) {
2651 case NV_ENCODE_NATIVE:
2653 * check endianness, in case we are unpacking
2654 * from a file
2656 if (nvl_endian != host_endian)
2657 return (ENOTSUP);
2658 err = nvs_native(&nvs, nvl, buf, buflen);
2659 break;
2660 case NV_ENCODE_XDR:
2661 err = nvs_xdr(&nvs, nvl, buf, buflen);
2662 break;
2663 default:
2664 err = ENOTSUP;
2665 break;
2668 return (err);
2672 nvlist_size(nvlist_t *nvl, size_t *size, int encoding)
2674 return (nvlist_common(nvl, NULL, size, encoding, NVS_OP_GETSIZE));
2678 * Pack nvlist into contiguous memory
2681 nvlist_pack(nvlist_t *nvl, char **bufp, size_t *buflen, int encoding,
2682 int kmflag)
2684 return (nvlist_xpack(nvl, bufp, buflen, encoding,
2685 nvlist_nv_alloc(kmflag)));
2689 nvlist_xpack(nvlist_t *nvl, char **bufp, size_t *buflen, int encoding,
2690 nv_alloc_t *nva)
2692 nvpriv_t nvpriv;
2693 size_t alloc_size;
2694 char *buf;
2695 int err;
2697 if (nva == NULL || nvl == NULL || bufp == NULL || buflen == NULL)
2698 return (EINVAL);
2700 if (*bufp != NULL)
2701 return (nvlist_common(nvl, *bufp, buflen, encoding,
2702 NVS_OP_ENCODE));
2705 * Here is a difficult situation:
2706 * 1. The nvlist has fixed allocator properties.
2707 * All other nvlist routines (like nvlist_add_*, ...) use
2708 * these properties.
2709 * 2. When using nvlist_pack() the user can specify their own
2710 * allocator properties (e.g. by using KM_NOSLEEP).
2712 * We use the user specified properties (2). A clearer solution
2713 * will be to remove the kmflag from nvlist_pack(), but we will
2714 * not change the interface.
2716 nv_priv_init(&nvpriv, nva, 0);
2718 if ((err = nvlist_size(nvl, &alloc_size, encoding)))
2719 return (err);
2721 if ((buf = nv_mem_zalloc(&nvpriv, alloc_size)) == NULL)
2722 return (ENOMEM);
2724 if ((err = nvlist_common(nvl, buf, &alloc_size, encoding,
2725 NVS_OP_ENCODE)) != 0) {
2726 nv_mem_free(&nvpriv, buf, alloc_size);
2727 } else {
2728 *buflen = alloc_size;
2729 *bufp = buf;
2732 return (err);
2736 * Unpack buf into an nvlist_t
2739 nvlist_unpack(char *buf, size_t buflen, nvlist_t **nvlp, int kmflag)
2741 return (nvlist_xunpack(buf, buflen, nvlp, nvlist_nv_alloc(kmflag)));
2745 nvlist_xunpack(char *buf, size_t buflen, nvlist_t **nvlp, nv_alloc_t *nva)
2747 nvlist_t *nvl;
2748 int err;
2750 if (nvlp == NULL)
2751 return (EINVAL);
2753 if ((err = nvlist_xalloc(&nvl, 0, nva)) != 0)
2754 return (err);
2756 if ((err = nvlist_common(nvl, buf, &buflen, NV_ENCODE_NATIVE,
2757 NVS_OP_DECODE)) != 0)
2758 nvlist_free(nvl);
2759 else
2760 *nvlp = nvl;
2762 return (err);
2766 * Native encoding functions
2768 typedef struct {
2770 * This structure is used when decoding a packed nvpair in
2771 * the native format. n_base points to a buffer containing the
2772 * packed nvpair. n_end is a pointer to the end of the buffer.
2773 * (n_end actually points to the first byte past the end of the
2774 * buffer.) n_curr is a pointer that lies between n_base and n_end.
2775 * It points to the current data that we are decoding.
2776 * The amount of data left in the buffer is equal to n_end - n_curr.
2777 * n_flag is used to recognize a packed embedded list.
2779 caddr_t n_base;
2780 caddr_t n_end;
2781 caddr_t n_curr;
2782 uint_t n_flag;
2783 } nvs_native_t;
2785 static int
2786 nvs_native_create(nvstream_t *nvs, nvs_native_t *native, char *buf,
2787 size_t buflen)
2789 switch (nvs->nvs_op) {
2790 case NVS_OP_ENCODE:
2791 case NVS_OP_DECODE:
2792 nvs->nvs_private = native;
2793 native->n_curr = native->n_base = buf;
2794 native->n_end = buf + buflen;
2795 native->n_flag = 0;
2796 return (0);
2798 case NVS_OP_GETSIZE:
2799 nvs->nvs_private = native;
2800 native->n_curr = native->n_base = native->n_end = NULL;
2801 native->n_flag = 0;
2802 return (0);
2803 default:
2804 return (EINVAL);
2808 static void
2809 nvs_native_destroy(nvstream_t *nvs)
2811 (void) nvs;
2814 static int
2815 native_cp(nvstream_t *nvs, void *buf, size_t size)
2817 nvs_native_t *native = (nvs_native_t *)nvs->nvs_private;
2819 if (native->n_curr + size > native->n_end)
2820 return (EFAULT);
2823 * The memcpy() below eliminates alignment requirement
2824 * on the buffer (stream) and is preferred over direct access.
2826 switch (nvs->nvs_op) {
2827 case NVS_OP_ENCODE:
2828 memcpy(native->n_curr, buf, size);
2829 break;
2830 case NVS_OP_DECODE:
2831 memcpy(buf, native->n_curr, size);
2832 break;
2833 default:
2834 return (EINVAL);
2837 native->n_curr += size;
2838 return (0);
2842 * operate on nvlist_t header
2844 static int
2845 nvs_native_nvlist(nvstream_t *nvs, nvlist_t *nvl, size_t *size)
2847 nvs_native_t *native = nvs->nvs_private;
2849 switch (nvs->nvs_op) {
2850 case NVS_OP_ENCODE:
2851 case NVS_OP_DECODE:
2852 if (native->n_flag)
2853 return (0); /* packed embedded list */
2855 native->n_flag = 1;
2857 /* copy version and nvflag of the nvlist_t */
2858 if (native_cp(nvs, &nvl->nvl_version, sizeof (int32_t)) != 0 ||
2859 native_cp(nvs, &nvl->nvl_nvflag, sizeof (int32_t)) != 0)
2860 return (EFAULT);
2862 return (0);
2864 case NVS_OP_GETSIZE:
2866 * if calculate for packed embedded list
2867 * 4 for end of the embedded list
2868 * else
2869 * 2 * sizeof (int32_t) for nvl_version and nvl_nvflag
2870 * and 4 for end of the entire list
2872 if (native->n_flag) {
2873 *size += 4;
2874 } else {
2875 native->n_flag = 1;
2876 *size += 2 * sizeof (int32_t) + 4;
2879 return (0);
2881 default:
2882 return (EINVAL);
2886 static int
2887 nvs_native_nvl_fini(nvstream_t *nvs)
2889 if (nvs->nvs_op == NVS_OP_ENCODE) {
2890 nvs_native_t *native = (nvs_native_t *)nvs->nvs_private;
2892 * Add 4 zero bytes at end of nvlist. They are used
2893 * for end detection by the decode routine.
2895 if (native->n_curr + sizeof (int) > native->n_end)
2896 return (EFAULT);
2898 memset(native->n_curr, 0, sizeof (int));
2899 native->n_curr += sizeof (int);
2902 return (0);
2905 static int
2906 nvpair_native_embedded(nvstream_t *nvs, nvpair_t *nvp)
2908 if (nvs->nvs_op == NVS_OP_ENCODE) {
2909 nvs_native_t *native = (nvs_native_t *)nvs->nvs_private;
2910 nvlist_t *packed = (void *)
2911 (native->n_curr - nvp->nvp_size + NVP_VALOFF(nvp));
2913 * Null out the pointer that is meaningless in the packed
2914 * structure. The address may not be aligned, so we have
2915 * to use memset.
2917 memset((char *)packed + offsetof(nvlist_t, nvl_priv),
2918 0, sizeof (uint64_t));
2921 return (nvs_embedded(nvs, EMBEDDED_NVL(nvp)));
2924 static int
2925 nvpair_native_embedded_array(nvstream_t *nvs, nvpair_t *nvp)
2927 if (nvs->nvs_op == NVS_OP_ENCODE) {
2928 nvs_native_t *native = (nvs_native_t *)nvs->nvs_private;
2929 char *value = native->n_curr - nvp->nvp_size + NVP_VALOFF(nvp);
2930 size_t len = NVP_NELEM(nvp) * sizeof (uint64_t);
2931 nvlist_t *packed = (nvlist_t *)((uintptr_t)value + len);
2932 int i;
2934 * Null out pointers that are meaningless in the packed
2935 * structure. The addresses may not be aligned, so we have
2936 * to use memset.
2938 memset(value, 0, len);
2940 for (i = 0; i < NVP_NELEM(nvp); i++, packed++)
2942 * Null out the pointer that is meaningless in the
2943 * packed structure. The address may not be aligned,
2944 * so we have to use memset.
2946 memset((char *)packed + offsetof(nvlist_t, nvl_priv),
2947 0, sizeof (uint64_t));
2950 return (nvs_embedded_nvl_array(nvs, nvp, NULL));
2953 static void
2954 nvpair_native_string_array(nvstream_t *nvs, nvpair_t *nvp)
2956 switch (nvs->nvs_op) {
2957 case NVS_OP_ENCODE: {
2958 nvs_native_t *native = (nvs_native_t *)nvs->nvs_private;
2959 uint64_t *strp = (void *)
2960 (native->n_curr - nvp->nvp_size + NVP_VALOFF(nvp));
2962 * Null out pointers that are meaningless in the packed
2963 * structure. The addresses may not be aligned, so we have
2964 * to use memset.
2966 memset(strp, 0, NVP_NELEM(nvp) * sizeof (uint64_t));
2967 break;
2969 case NVS_OP_DECODE: {
2970 char **strp = (void *)NVP_VALUE(nvp);
2971 char *buf = ((char *)strp + NVP_NELEM(nvp) * sizeof (uint64_t));
2972 int i;
2974 for (i = 0; i < NVP_NELEM(nvp); i++) {
2975 strp[i] = buf;
2976 buf += strlen(buf) + 1;
2978 break;
2983 static int
2984 nvs_native_nvp_op(nvstream_t *nvs, nvpair_t *nvp)
2986 data_type_t type;
2987 int value_sz;
2988 int ret = 0;
2991 * We do the initial memcpy of the data before we look at
2992 * the nvpair type, because when we're decoding, we won't
2993 * have the correct values for the pair until we do the memcpy.
2995 switch (nvs->nvs_op) {
2996 case NVS_OP_ENCODE:
2997 case NVS_OP_DECODE:
2998 if (native_cp(nvs, nvp, nvp->nvp_size) != 0)
2999 return (EFAULT);
3000 break;
3001 default:
3002 return (EINVAL);
3005 /* verify nvp_name_sz, check the name string length */
3006 if (i_validate_nvpair_name(nvp) != 0)
3007 return (EFAULT);
3009 type = NVP_TYPE(nvp);
3012 * Verify type and nelem and get the value size.
3013 * In case of data types DATA_TYPE_STRING and DATA_TYPE_STRING_ARRAY
3014 * is the size of the string(s) excluded.
3016 if ((value_sz = i_get_value_size(type, NULL, NVP_NELEM(nvp))) < 0)
3017 return (EFAULT);
3019 if (NVP_SIZE_CALC(nvp->nvp_name_sz, value_sz) > nvp->nvp_size)
3020 return (EFAULT);
3022 switch (type) {
3023 case DATA_TYPE_NVLIST:
3024 ret = nvpair_native_embedded(nvs, nvp);
3025 break;
3026 case DATA_TYPE_NVLIST_ARRAY:
3027 ret = nvpair_native_embedded_array(nvs, nvp);
3028 break;
3029 case DATA_TYPE_STRING_ARRAY:
3030 nvpair_native_string_array(nvs, nvp);
3031 break;
3032 default:
3033 break;
3036 return (ret);
3039 static int
3040 nvs_native_nvp_size(nvstream_t *nvs, nvpair_t *nvp, size_t *size)
3042 uint64_t nvp_sz = nvp->nvp_size;
3044 switch (NVP_TYPE(nvp)) {
3045 case DATA_TYPE_NVLIST: {
3046 size_t nvsize = 0;
3048 if (nvs_operation(nvs, EMBEDDED_NVL(nvp), &nvsize) != 0)
3049 return (EINVAL);
3051 nvp_sz += nvsize;
3052 break;
3054 case DATA_TYPE_NVLIST_ARRAY: {
3055 size_t nvsize;
3057 if (nvs_embedded_nvl_array(nvs, nvp, &nvsize) != 0)
3058 return (EINVAL);
3060 nvp_sz += nvsize;
3061 break;
3063 default:
3064 break;
3067 if (nvp_sz > INT32_MAX)
3068 return (EINVAL);
3070 *size = nvp_sz;
3072 return (0);
3075 static int
3076 nvs_native_nvpair(nvstream_t *nvs, nvpair_t *nvp, size_t *size)
3078 switch (nvs->nvs_op) {
3079 case NVS_OP_ENCODE:
3080 return (nvs_native_nvp_op(nvs, nvp));
3082 case NVS_OP_DECODE: {
3083 nvs_native_t *native = (nvs_native_t *)nvs->nvs_private;
3084 int32_t decode_len;
3086 /* try to read the size value from the stream */
3087 if (native->n_curr + sizeof (int32_t) > native->n_end)
3088 return (EFAULT);
3089 memcpy(&decode_len, native->n_curr, sizeof (int32_t));
3091 /* sanity check the size value */
3092 if (decode_len < 0 ||
3093 decode_len > native->n_end - native->n_curr)
3094 return (EFAULT);
3096 *size = decode_len;
3099 * If at the end of the stream then move the cursor
3100 * forward, otherwise nvpair_native_op() will read
3101 * the entire nvpair at the same cursor position.
3103 if (*size == 0)
3104 native->n_curr += sizeof (int32_t);
3105 break;
3108 default:
3109 return (EINVAL);
3112 return (0);
3115 static const nvs_ops_t nvs_native_ops = {
3116 .nvs_nvlist = nvs_native_nvlist,
3117 .nvs_nvpair = nvs_native_nvpair,
3118 .nvs_nvp_op = nvs_native_nvp_op,
3119 .nvs_nvp_size = nvs_native_nvp_size,
3120 .nvs_nvl_fini = nvs_native_nvl_fini
3123 static int
3124 nvs_native(nvstream_t *nvs, nvlist_t *nvl, char *buf, size_t *buflen)
3126 nvs_native_t native;
3127 int err;
3129 nvs->nvs_ops = &nvs_native_ops;
3131 if ((err = nvs_native_create(nvs, &native, buf + sizeof (nvs_header_t),
3132 *buflen - sizeof (nvs_header_t))) != 0)
3133 return (err);
3135 err = nvs_operation(nvs, nvl, buflen);
3137 nvs_native_destroy(nvs);
3139 return (err);
3143 * XDR encoding functions
3145 * An xdr packed nvlist is encoded as:
3147 * - encoding method and host endian (4 bytes)
3148 * - nvl_version (4 bytes)
3149 * - nvl_nvflag (4 bytes)
3151 * - encoded nvpairs, the format of one xdr encoded nvpair is:
3152 * - encoded size of the nvpair (4 bytes)
3153 * - decoded size of the nvpair (4 bytes)
3154 * - name string, (4 + sizeof(NV_ALIGN4(string))
3155 * a string is coded as size (4 bytes) and data
3156 * - data type (4 bytes)
3157 * - number of elements in the nvpair (4 bytes)
3158 * - data
3160 * - 2 zero's for end of the entire list (8 bytes)
3162 static int
3163 nvs_xdr_create(nvstream_t *nvs, XDR *xdr, char *buf, size_t buflen)
3165 /* xdr data must be 4 byte aligned */
3166 if ((ulong_t)buf % 4 != 0)
3167 return (EFAULT);
3169 switch (nvs->nvs_op) {
3170 case NVS_OP_ENCODE:
3171 xdrmem_create(xdr, buf, (uint_t)buflen, XDR_ENCODE);
3172 nvs->nvs_private = xdr;
3173 return (0);
3174 case NVS_OP_DECODE:
3175 xdrmem_create(xdr, buf, (uint_t)buflen, XDR_DECODE);
3176 nvs->nvs_private = xdr;
3177 return (0);
3178 case NVS_OP_GETSIZE:
3179 nvs->nvs_private = NULL;
3180 return (0);
3181 default:
3182 return (EINVAL);
3186 static void
3187 nvs_xdr_destroy(nvstream_t *nvs)
3189 switch (nvs->nvs_op) {
3190 case NVS_OP_ENCODE:
3191 case NVS_OP_DECODE:
3192 xdr_destroy((XDR *)nvs->nvs_private);
3193 break;
3194 default:
3195 break;
3199 static int
3200 nvs_xdr_nvlist(nvstream_t *nvs, nvlist_t *nvl, size_t *size)
3202 switch (nvs->nvs_op) {
3203 case NVS_OP_ENCODE:
3204 case NVS_OP_DECODE: {
3205 XDR *xdr = nvs->nvs_private;
3207 if (!xdr_int(xdr, &nvl->nvl_version) ||
3208 !xdr_u_int(xdr, &nvl->nvl_nvflag))
3209 return (EFAULT);
3210 break;
3212 case NVS_OP_GETSIZE: {
3214 * 2 * 4 for nvl_version + nvl_nvflag
3215 * and 8 for end of the entire list
3217 *size += 2 * 4 + 8;
3218 break;
3220 default:
3221 return (EINVAL);
3223 return (0);
3226 static int
3227 nvs_xdr_nvl_fini(nvstream_t *nvs)
3229 if (nvs->nvs_op == NVS_OP_ENCODE) {
3230 XDR *xdr = nvs->nvs_private;
3231 int zero = 0;
3233 if (!xdr_int(xdr, &zero) || !xdr_int(xdr, &zero))
3234 return (EFAULT);
3237 return (0);
3241 * xdrproc_t-compatible callbacks for xdr_array()
3244 #if defined(_KERNEL) && defined(__linux__) /* Linux kernel */
3246 #define NVS_BUILD_XDRPROC_T(type) \
3247 static bool_t \
3248 nvs_xdr_nvp_##type(XDR *xdrs, void *ptr) \
3250 return (xdr_##type(xdrs, ptr)); \
3253 #elif !defined(_KERNEL) && defined(XDR_CONTROL) /* tirpc */
3255 #define NVS_BUILD_XDRPROC_T(type) \
3256 static bool_t \
3257 nvs_xdr_nvp_##type(XDR *xdrs, ...) \
3259 va_list args; \
3260 void *ptr; \
3262 va_start(args, xdrs); \
3263 ptr = va_arg(args, void *); \
3264 va_end(args); \
3266 return (xdr_##type(xdrs, ptr)); \
3269 #else /* FreeBSD, sunrpc */
3271 #define NVS_BUILD_XDRPROC_T(type) \
3272 static bool_t \
3273 nvs_xdr_nvp_##type(XDR *xdrs, void *ptr, ...) \
3275 return (xdr_##type(xdrs, ptr)); \
3278 #endif
3280 /* BEGIN CSTYLED */
3281 NVS_BUILD_XDRPROC_T(char);
3282 NVS_BUILD_XDRPROC_T(short);
3283 NVS_BUILD_XDRPROC_T(u_short);
3284 NVS_BUILD_XDRPROC_T(int);
3285 NVS_BUILD_XDRPROC_T(u_int);
3286 NVS_BUILD_XDRPROC_T(longlong_t);
3287 NVS_BUILD_XDRPROC_T(u_longlong_t);
3288 /* END CSTYLED */
3291 * The format of xdr encoded nvpair is:
3292 * encode_size, decode_size, name string, data type, nelem, data
3294 static int
3295 nvs_xdr_nvp_op(nvstream_t *nvs, nvpair_t *nvp)
3297 ASSERT(nvs != NULL && nvp != NULL);
3299 data_type_t type;
3300 char *buf;
3301 char *buf_end = (char *)nvp + nvp->nvp_size;
3302 int value_sz;
3303 uint_t nelem, buflen;
3304 bool_t ret = FALSE;
3305 XDR *xdr = nvs->nvs_private;
3307 ASSERT(xdr != NULL);
3309 /* name string */
3310 if ((buf = NVP_NAME(nvp)) >= buf_end)
3311 return (EFAULT);
3312 buflen = buf_end - buf;
3314 if (!xdr_string(xdr, &buf, buflen - 1))
3315 return (EFAULT);
3316 nvp->nvp_name_sz = strlen(buf) + 1;
3318 /* type and nelem */
3319 if (!xdr_int(xdr, (int *)&nvp->nvp_type) ||
3320 !xdr_int(xdr, &nvp->nvp_value_elem))
3321 return (EFAULT);
3323 type = NVP_TYPE(nvp);
3324 nelem = nvp->nvp_value_elem;
3327 * Verify type and nelem and get the value size.
3328 * In case of data types DATA_TYPE_STRING and DATA_TYPE_STRING_ARRAY
3329 * is the size of the string(s) excluded.
3331 if ((value_sz = i_get_value_size(type, NULL, nelem)) < 0)
3332 return (EFAULT);
3334 /* if there is no data to extract then return */
3335 if (nelem == 0)
3336 return (0);
3338 /* value */
3339 if ((buf = NVP_VALUE(nvp)) >= buf_end)
3340 return (EFAULT);
3341 buflen = buf_end - buf;
3343 if (buflen < value_sz)
3344 return (EFAULT);
3346 switch (type) {
3347 case DATA_TYPE_NVLIST:
3348 if (nvs_embedded(nvs, (void *)buf) == 0)
3349 return (0);
3350 break;
3352 case DATA_TYPE_NVLIST_ARRAY:
3353 if (nvs_embedded_nvl_array(nvs, nvp, NULL) == 0)
3354 return (0);
3355 break;
3357 case DATA_TYPE_BOOLEAN:
3358 ret = TRUE;
3359 break;
3361 case DATA_TYPE_BYTE:
3362 case DATA_TYPE_INT8:
3363 case DATA_TYPE_UINT8:
3364 ret = xdr_char(xdr, buf);
3365 break;
3367 case DATA_TYPE_INT16:
3368 ret = xdr_short(xdr, (void *)buf);
3369 break;
3371 case DATA_TYPE_UINT16:
3372 ret = xdr_u_short(xdr, (void *)buf);
3373 break;
3375 case DATA_TYPE_BOOLEAN_VALUE:
3376 case DATA_TYPE_INT32:
3377 ret = xdr_int(xdr, (void *)buf);
3378 break;
3380 case DATA_TYPE_UINT32:
3381 ret = xdr_u_int(xdr, (void *)buf);
3382 break;
3384 case DATA_TYPE_INT64:
3385 ret = xdr_longlong_t(xdr, (void *)buf);
3386 break;
3388 case DATA_TYPE_UINT64:
3389 ret = xdr_u_longlong_t(xdr, (void *)buf);
3390 break;
3392 case DATA_TYPE_HRTIME:
3394 * NOTE: must expose the definition of hrtime_t here
3396 ret = xdr_longlong_t(xdr, (void *)buf);
3397 break;
3398 #if !defined(_KERNEL)
3399 case DATA_TYPE_DOUBLE:
3400 ret = xdr_double(xdr, (void *)buf);
3401 break;
3402 #endif
3403 case DATA_TYPE_STRING:
3404 ret = xdr_string(xdr, &buf, buflen - 1);
3405 break;
3407 case DATA_TYPE_BYTE_ARRAY:
3408 ret = xdr_opaque(xdr, buf, nelem);
3409 break;
3411 case DATA_TYPE_INT8_ARRAY:
3412 case DATA_TYPE_UINT8_ARRAY:
3413 ret = xdr_array(xdr, &buf, &nelem, buflen, sizeof (int8_t),
3414 nvs_xdr_nvp_char);
3415 break;
3417 case DATA_TYPE_INT16_ARRAY:
3418 ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (int16_t),
3419 sizeof (int16_t), nvs_xdr_nvp_short);
3420 break;
3422 case DATA_TYPE_UINT16_ARRAY:
3423 ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (uint16_t),
3424 sizeof (uint16_t), nvs_xdr_nvp_u_short);
3425 break;
3427 case DATA_TYPE_BOOLEAN_ARRAY:
3428 case DATA_TYPE_INT32_ARRAY:
3429 ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (int32_t),
3430 sizeof (int32_t), nvs_xdr_nvp_int);
3431 break;
3433 case DATA_TYPE_UINT32_ARRAY:
3434 ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (uint32_t),
3435 sizeof (uint32_t), nvs_xdr_nvp_u_int);
3436 break;
3438 case DATA_TYPE_INT64_ARRAY:
3439 ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (int64_t),
3440 sizeof (int64_t), nvs_xdr_nvp_longlong_t);
3441 break;
3443 case DATA_TYPE_UINT64_ARRAY:
3444 ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (uint64_t),
3445 sizeof (uint64_t), nvs_xdr_nvp_u_longlong_t);
3446 break;
3448 case DATA_TYPE_STRING_ARRAY: {
3449 size_t len = nelem * sizeof (uint64_t);
3450 char **strp = (void *)buf;
3451 int i;
3453 if (nvs->nvs_op == NVS_OP_DECODE)
3454 memset(buf, 0, len); /* don't trust packed data */
3456 for (i = 0; i < nelem; i++) {
3457 if (buflen <= len)
3458 return (EFAULT);
3460 buf += len;
3461 buflen -= len;
3463 if (xdr_string(xdr, &buf, buflen - 1) != TRUE)
3464 return (EFAULT);
3466 if (nvs->nvs_op == NVS_OP_DECODE)
3467 strp[i] = buf;
3468 len = strlen(buf) + 1;
3470 ret = TRUE;
3471 break;
3473 default:
3474 break;
3477 return (ret == TRUE ? 0 : EFAULT);
3480 static int
3481 nvs_xdr_nvp_size(nvstream_t *nvs, nvpair_t *nvp, size_t *size)
3483 data_type_t type = NVP_TYPE(nvp);
3485 * encode_size + decode_size + name string size + data type + nelem
3486 * where name string size = 4 + NV_ALIGN4(strlen(NVP_NAME(nvp)))
3488 uint64_t nvp_sz = 4 + 4 + 4 + NV_ALIGN4(strlen(NVP_NAME(nvp))) + 4 + 4;
3490 switch (type) {
3491 case DATA_TYPE_BOOLEAN:
3492 break;
3494 case DATA_TYPE_BOOLEAN_VALUE:
3495 case DATA_TYPE_BYTE:
3496 case DATA_TYPE_INT8:
3497 case DATA_TYPE_UINT8:
3498 case DATA_TYPE_INT16:
3499 case DATA_TYPE_UINT16:
3500 case DATA_TYPE_INT32:
3501 case DATA_TYPE_UINT32:
3502 nvp_sz += 4; /* 4 is the minimum xdr unit */
3503 break;
3505 case DATA_TYPE_INT64:
3506 case DATA_TYPE_UINT64:
3507 case DATA_TYPE_HRTIME:
3508 #if !defined(_KERNEL)
3509 case DATA_TYPE_DOUBLE:
3510 #endif
3511 nvp_sz += 8;
3512 break;
3514 case DATA_TYPE_STRING:
3515 nvp_sz += 4 + NV_ALIGN4(strlen((char *)NVP_VALUE(nvp)));
3516 break;
3518 case DATA_TYPE_BYTE_ARRAY:
3519 nvp_sz += NV_ALIGN4(NVP_NELEM(nvp));
3520 break;
3522 case DATA_TYPE_BOOLEAN_ARRAY:
3523 case DATA_TYPE_INT8_ARRAY:
3524 case DATA_TYPE_UINT8_ARRAY:
3525 case DATA_TYPE_INT16_ARRAY:
3526 case DATA_TYPE_UINT16_ARRAY:
3527 case DATA_TYPE_INT32_ARRAY:
3528 case DATA_TYPE_UINT32_ARRAY:
3529 nvp_sz += 4 + 4 * (uint64_t)NVP_NELEM(nvp);
3530 break;
3532 case DATA_TYPE_INT64_ARRAY:
3533 case DATA_TYPE_UINT64_ARRAY:
3534 nvp_sz += 4 + 8 * (uint64_t)NVP_NELEM(nvp);
3535 break;
3537 case DATA_TYPE_STRING_ARRAY: {
3538 int i;
3539 char **strs = (void *)NVP_VALUE(nvp);
3541 for (i = 0; i < NVP_NELEM(nvp); i++)
3542 nvp_sz += 4 + NV_ALIGN4(strlen(strs[i]));
3544 break;
3547 case DATA_TYPE_NVLIST:
3548 case DATA_TYPE_NVLIST_ARRAY: {
3549 size_t nvsize = 0;
3550 int old_nvs_op = nvs->nvs_op;
3551 int err;
3553 nvs->nvs_op = NVS_OP_GETSIZE;
3554 if (type == DATA_TYPE_NVLIST)
3555 err = nvs_operation(nvs, EMBEDDED_NVL(nvp), &nvsize);
3556 else
3557 err = nvs_embedded_nvl_array(nvs, nvp, &nvsize);
3558 nvs->nvs_op = old_nvs_op;
3560 if (err != 0)
3561 return (EINVAL);
3563 nvp_sz += nvsize;
3564 break;
3567 default:
3568 return (EINVAL);
3571 if (nvp_sz > INT32_MAX)
3572 return (EINVAL);
3574 *size = nvp_sz;
3576 return (0);
3581 * The NVS_XDR_MAX_LEN macro takes a packed xdr buffer of size x and estimates
3582 * the largest nvpair that could be encoded in the buffer.
3584 * See comments above nvpair_xdr_op() for the format of xdr encoding.
3585 * The size of a xdr packed nvpair without any data is 5 words.
3587 * Using the size of the data directly as an estimate would be ok
3588 * in all cases except one. If the data type is of DATA_TYPE_STRING_ARRAY
3589 * then the actual nvpair has space for an array of pointers to index
3590 * the strings. These pointers are not encoded into the packed xdr buffer.
3592 * If the data is of type DATA_TYPE_STRING_ARRAY and all the strings are
3593 * of length 0, then each string is encoded in xdr format as a single word.
3594 * Therefore when expanded to an nvpair there will be 2.25 word used for
3595 * each string. (a int64_t allocated for pointer usage, and a single char
3596 * for the null termination.)
3598 * This is the calculation performed by the NVS_XDR_MAX_LEN macro.
3600 #define NVS_XDR_HDR_LEN ((size_t)(5 * 4))
3601 #define NVS_XDR_DATA_LEN(y) (((size_t)(y) <= NVS_XDR_HDR_LEN) ? \
3602 0 : ((size_t)(y) - NVS_XDR_HDR_LEN))
3603 #define NVS_XDR_MAX_LEN(x) (NVP_SIZE_CALC(1, 0) + \
3604 (NVS_XDR_DATA_LEN(x) * 2) + \
3605 NV_ALIGN4((NVS_XDR_DATA_LEN(x) / 4)))
3607 static int
3608 nvs_xdr_nvpair(nvstream_t *nvs, nvpair_t *nvp, size_t *size)
3610 XDR *xdr = nvs->nvs_private;
3611 int32_t encode_len, decode_len;
3613 switch (nvs->nvs_op) {
3614 case NVS_OP_ENCODE: {
3615 size_t nvsize;
3617 if (nvs_xdr_nvp_size(nvs, nvp, &nvsize) != 0)
3618 return (EFAULT);
3620 decode_len = nvp->nvp_size;
3621 encode_len = nvsize;
3622 if (!xdr_int(xdr, &encode_len) || !xdr_int(xdr, &decode_len))
3623 return (EFAULT);
3625 return (nvs_xdr_nvp_op(nvs, nvp));
3627 case NVS_OP_DECODE: {
3628 struct xdr_bytesrec bytesrec;
3630 /* get the encode and decode size */
3631 if (!xdr_int(xdr, &encode_len) || !xdr_int(xdr, &decode_len))
3632 return (EFAULT);
3633 *size = decode_len;
3635 /* are we at the end of the stream? */
3636 if (*size == 0)
3637 return (0);
3639 /* sanity check the size parameter */
3640 if (!xdr_control(xdr, XDR_GET_BYTES_AVAIL, &bytesrec))
3641 return (EFAULT);
3643 if (*size > NVS_XDR_MAX_LEN(bytesrec.xc_num_avail))
3644 return (EFAULT);
3645 break;
3648 default:
3649 return (EINVAL);
3651 return (0);
3654 static const struct nvs_ops nvs_xdr_ops = {
3655 .nvs_nvlist = nvs_xdr_nvlist,
3656 .nvs_nvpair = nvs_xdr_nvpair,
3657 .nvs_nvp_op = nvs_xdr_nvp_op,
3658 .nvs_nvp_size = nvs_xdr_nvp_size,
3659 .nvs_nvl_fini = nvs_xdr_nvl_fini
3662 static int
3663 nvs_xdr(nvstream_t *nvs, nvlist_t *nvl, char *buf, size_t *buflen)
3665 XDR xdr;
3666 int err;
3668 nvs->nvs_ops = &nvs_xdr_ops;
3670 if ((err = nvs_xdr_create(nvs, &xdr, buf + sizeof (nvs_header_t),
3671 *buflen - sizeof (nvs_header_t))) != 0)
3672 return (err);
3674 err = nvs_operation(nvs, nvl, buflen);
3676 nvs_xdr_destroy(nvs);
3678 return (err);
3681 EXPORT_SYMBOL(nv_alloc_init);
3682 EXPORT_SYMBOL(nv_alloc_reset);
3683 EXPORT_SYMBOL(nv_alloc_fini);
3685 /* list management */
3686 EXPORT_SYMBOL(nvlist_alloc);
3687 EXPORT_SYMBOL(nvlist_free);
3688 EXPORT_SYMBOL(nvlist_size);
3689 EXPORT_SYMBOL(nvlist_pack);
3690 EXPORT_SYMBOL(nvlist_unpack);
3691 EXPORT_SYMBOL(nvlist_dup);
3692 EXPORT_SYMBOL(nvlist_merge);
3694 EXPORT_SYMBOL(nvlist_xalloc);
3695 EXPORT_SYMBOL(nvlist_xpack);
3696 EXPORT_SYMBOL(nvlist_xunpack);
3697 EXPORT_SYMBOL(nvlist_xdup);
3698 EXPORT_SYMBOL(nvlist_lookup_nv_alloc);
3700 EXPORT_SYMBOL(nvlist_add_nvpair);
3701 EXPORT_SYMBOL(nvlist_add_boolean);
3702 EXPORT_SYMBOL(nvlist_add_boolean_value);
3703 EXPORT_SYMBOL(nvlist_add_byte);
3704 EXPORT_SYMBOL(nvlist_add_int8);
3705 EXPORT_SYMBOL(nvlist_add_uint8);
3706 EXPORT_SYMBOL(nvlist_add_int16);
3707 EXPORT_SYMBOL(nvlist_add_uint16);
3708 EXPORT_SYMBOL(nvlist_add_int32);
3709 EXPORT_SYMBOL(nvlist_add_uint32);
3710 EXPORT_SYMBOL(nvlist_add_int64);
3711 EXPORT_SYMBOL(nvlist_add_uint64);
3712 EXPORT_SYMBOL(nvlist_add_string);
3713 EXPORT_SYMBOL(nvlist_add_nvlist);
3714 EXPORT_SYMBOL(nvlist_add_boolean_array);
3715 EXPORT_SYMBOL(nvlist_add_byte_array);
3716 EXPORT_SYMBOL(nvlist_add_int8_array);
3717 EXPORT_SYMBOL(nvlist_add_uint8_array);
3718 EXPORT_SYMBOL(nvlist_add_int16_array);
3719 EXPORT_SYMBOL(nvlist_add_uint16_array);
3720 EXPORT_SYMBOL(nvlist_add_int32_array);
3721 EXPORT_SYMBOL(nvlist_add_uint32_array);
3722 EXPORT_SYMBOL(nvlist_add_int64_array);
3723 EXPORT_SYMBOL(nvlist_add_uint64_array);
3724 EXPORT_SYMBOL(nvlist_add_string_array);
3725 EXPORT_SYMBOL(nvlist_add_nvlist_array);
3726 EXPORT_SYMBOL(nvlist_next_nvpair);
3727 EXPORT_SYMBOL(nvlist_prev_nvpair);
3728 EXPORT_SYMBOL(nvlist_empty);
3729 EXPORT_SYMBOL(nvlist_add_hrtime);
3731 EXPORT_SYMBOL(nvlist_remove);
3732 EXPORT_SYMBOL(nvlist_remove_nvpair);
3733 EXPORT_SYMBOL(nvlist_remove_all);
3735 EXPORT_SYMBOL(nvlist_lookup_boolean);
3736 EXPORT_SYMBOL(nvlist_lookup_boolean_value);
3737 EXPORT_SYMBOL(nvlist_lookup_byte);
3738 EXPORT_SYMBOL(nvlist_lookup_int8);
3739 EXPORT_SYMBOL(nvlist_lookup_uint8);
3740 EXPORT_SYMBOL(nvlist_lookup_int16);
3741 EXPORT_SYMBOL(nvlist_lookup_uint16);
3742 EXPORT_SYMBOL(nvlist_lookup_int32);
3743 EXPORT_SYMBOL(nvlist_lookup_uint32);
3744 EXPORT_SYMBOL(nvlist_lookup_int64);
3745 EXPORT_SYMBOL(nvlist_lookup_uint64);
3746 EXPORT_SYMBOL(nvlist_lookup_string);
3747 EXPORT_SYMBOL(nvlist_lookup_nvlist);
3748 EXPORT_SYMBOL(nvlist_lookup_boolean_array);
3749 EXPORT_SYMBOL(nvlist_lookup_byte_array);
3750 EXPORT_SYMBOL(nvlist_lookup_int8_array);
3751 EXPORT_SYMBOL(nvlist_lookup_uint8_array);
3752 EXPORT_SYMBOL(nvlist_lookup_int16_array);
3753 EXPORT_SYMBOL(nvlist_lookup_uint16_array);
3754 EXPORT_SYMBOL(nvlist_lookup_int32_array);
3755 EXPORT_SYMBOL(nvlist_lookup_uint32_array);
3756 EXPORT_SYMBOL(nvlist_lookup_int64_array);
3757 EXPORT_SYMBOL(nvlist_lookup_uint64_array);
3758 EXPORT_SYMBOL(nvlist_lookup_string_array);
3759 EXPORT_SYMBOL(nvlist_lookup_nvlist_array);
3760 EXPORT_SYMBOL(nvlist_lookup_hrtime);
3761 EXPORT_SYMBOL(nvlist_lookup_pairs);
3763 EXPORT_SYMBOL(nvlist_lookup_nvpair);
3764 EXPORT_SYMBOL(nvlist_exists);
3766 /* processing nvpair */
3767 EXPORT_SYMBOL(nvpair_name);
3768 EXPORT_SYMBOL(nvpair_type);
3769 EXPORT_SYMBOL(nvpair_value_boolean_value);
3770 EXPORT_SYMBOL(nvpair_value_byte);
3771 EXPORT_SYMBOL(nvpair_value_int8);
3772 EXPORT_SYMBOL(nvpair_value_uint8);
3773 EXPORT_SYMBOL(nvpair_value_int16);
3774 EXPORT_SYMBOL(nvpair_value_uint16);
3775 EXPORT_SYMBOL(nvpair_value_int32);
3776 EXPORT_SYMBOL(nvpair_value_uint32);
3777 EXPORT_SYMBOL(nvpair_value_int64);
3778 EXPORT_SYMBOL(nvpair_value_uint64);
3779 EXPORT_SYMBOL(nvpair_value_string);
3780 EXPORT_SYMBOL(nvpair_value_nvlist);
3781 EXPORT_SYMBOL(nvpair_value_boolean_array);
3782 EXPORT_SYMBOL(nvpair_value_byte_array);
3783 EXPORT_SYMBOL(nvpair_value_int8_array);
3784 EXPORT_SYMBOL(nvpair_value_uint8_array);
3785 EXPORT_SYMBOL(nvpair_value_int16_array);
3786 EXPORT_SYMBOL(nvpair_value_uint16_array);
3787 EXPORT_SYMBOL(nvpair_value_int32_array);
3788 EXPORT_SYMBOL(nvpair_value_uint32_array);
3789 EXPORT_SYMBOL(nvpair_value_int64_array);
3790 EXPORT_SYMBOL(nvpair_value_uint64_array);
3791 EXPORT_SYMBOL(nvpair_value_string_array);
3792 EXPORT_SYMBOL(nvpair_value_nvlist_array);
3793 EXPORT_SYMBOL(nvpair_value_hrtime);