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