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