Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/contrib/openzfs/module/nvpair/nvpair.c
48383 views
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
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
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
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 *
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 *
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
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
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 *
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 *
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
266
nvt_tab_alloc(nvpriv_t *priv, uint64_t buckets)
267
{
268
ASSERT0P(priv->nvp_hashtable);
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
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
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
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 *
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
ASSERT0P(priv->nvp_list);
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 *
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
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
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
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
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
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
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
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
ASSERT0P(new_entry->nvi_hashtable_next);
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
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
563
nvlist_nvflag(nvlist_t *nvl)
564
{
565
return (nvl->nvl_nvflag);
566
}
567
568
static nv_alloc_t *
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
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
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 *
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 *
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 *
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
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 *
1523
nvpair_name(const nvpair_t *nvp)
1524
{
1525
return (NVP_NAME(nvp));
1526
}
1527
1528
data_type_t
1529
nvpair_type(const nvpair_t *nvp)
1530
{
1531
return (NVP_TYPE(nvp));
1532
}
1533
1534
int
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
*/
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
2814
nvs_native_destroy(nvstream_t *nvs)
2815
{
2816
nvs->nvs_private = NULL;
2817
}
2818
2819
static int
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
#define NVP(buf, size, len, buf_end, elem, type, vtype, ptype, format) { \
3685
vtype value; \
3686
int rc; \
3687
\
3688
(void) nvpair_value_##type(elem, &value); \
3689
rc = snprintf(buf, size, "%*s%s: " format "\n", indent, "", \
3690
nvpair_name(elem), (ptype)value); \
3691
if (rc < 0) \
3692
return (rc); \
3693
size = MAX((int)size - rc, 0); \
3694
buf = size == 0 ? NULL : buf_end - size; \
3695
len += rc; \
3696
}
3697
3698
#define NVPA(buf, size, len, buf_end, elem, type, vtype, ptype, format) \
3699
{ \
3700
uint_t i, count; \
3701
vtype *value; \
3702
int rc; \
3703
\
3704
(void) nvpair_value_##type(elem, &value, &count); \
3705
for (i = 0; i < count; i++) { \
3706
rc = snprintf(buf, size, "%*s%s[%d]: " format "\n", indent, \
3707
"", nvpair_name(elem), i, (ptype)value[i]); \
3708
if (rc < 0) \
3709
return (rc); \
3710
size = MAX((int)size - rc, 0); \
3711
buf = size == 0 ? NULL : buf_end - size; \
3712
len += rc; \
3713
} \
3714
}
3715
3716
/*
3717
* snprintf() version of dump_nvlist()
3718
*
3719
* Works just like snprintf(), but with an nvlist and indent count as args.
3720
*
3721
* Output is similar to nvlist_print() but handles arrays slightly differently.
3722
*
3723
* Return value matches C99 snprintf() return value conventions.
3724
*/
3725
int
3726
nvlist_snprintf(char *buf, size_t size, nvlist_t *list, int indent)
3727
{
3728
nvpair_t *elem = NULL;
3729
boolean_t bool_value;
3730
nvlist_t *nvlist_value;
3731
nvlist_t **nvlist_array_value;
3732
uint_t i, count;
3733
int len = 0;
3734
int rc;
3735
char *buf_end = &buf[size];
3736
3737
if (list == NULL)
3738
return (0);
3739
3740
while ((elem = nvlist_next_nvpair(list, elem)) != NULL) {
3741
switch (nvpair_type(elem)) {
3742
case DATA_TYPE_BOOLEAN:
3743
rc = snprintf(buf, size, "%*s%s\n", indent, "",
3744
nvpair_name(elem));
3745
if (rc < 0)
3746
return (rc);
3747
size = MAX((int)size - rc, 0);
3748
buf = size == 0 ? NULL : buf_end - size;
3749
len += rc;
3750
break;
3751
3752
case DATA_TYPE_BOOLEAN_VALUE:
3753
(void) nvpair_value_boolean_value(elem, &bool_value);
3754
rc = snprintf(buf, size, "%*s%s: %s\n", indent, "",
3755
nvpair_name(elem), bool_value ? "true" : "false");
3756
if (rc < 0)
3757
return (rc);
3758
size = MAX((int)size - rc, 0);
3759
buf = size == 0 ? NULL : buf_end - size;
3760
len += rc;
3761
break;
3762
3763
case DATA_TYPE_BYTE:
3764
NVP(buf, size, len, buf_end, elem, byte, uchar_t, int,
3765
"%u");
3766
break;
3767
3768
case DATA_TYPE_INT8:
3769
NVP(buf, size, len, buf_end, elem, int8, int8_t, int,
3770
"%d");
3771
break;
3772
3773
case DATA_TYPE_UINT8:
3774
NVP(buf, size, len, buf_end, elem, uint8, uint8_t, int,
3775
"%u");
3776
break;
3777
3778
case DATA_TYPE_INT16:
3779
NVP(buf, size, len, buf_end, elem, int16, int16_t, int,
3780
"%d");
3781
break;
3782
3783
case DATA_TYPE_UINT16:
3784
NVP(buf, size, len, buf_end, elem, uint16, uint16_t,
3785
int, "%u");
3786
break;
3787
3788
case DATA_TYPE_INT32:
3789
NVP(buf, size, len, buf_end, elem, int32, int32_t,
3790
long, "%ld");
3791
break;
3792
3793
case DATA_TYPE_UINT32:
3794
NVP(buf, size, len, buf_end, elem, uint32, uint32_t,
3795
ulong_t, "%lu");
3796
break;
3797
3798
case DATA_TYPE_INT64:
3799
NVP(buf, size, len, buf_end, elem, int64, int64_t,
3800
longlong_t, "%lld");
3801
break;
3802
3803
case DATA_TYPE_UINT64:
3804
NVP(buf, size, len, buf_end, elem, uint64, uint64_t,
3805
u_longlong_t, "%llu");
3806
break;
3807
3808
case DATA_TYPE_STRING:
3809
NVP(buf, size, len, buf_end, elem, string, const char *,
3810
const char *, "'%s'");
3811
break;
3812
3813
case DATA_TYPE_BYTE_ARRAY:
3814
NVPA(buf, size, len, buf_end, elem, byte_array, uchar_t,
3815
int, "%u");
3816
break;
3817
3818
case DATA_TYPE_INT8_ARRAY:
3819
NVPA(buf, size, len, buf_end, elem, int8_array, int8_t,
3820
int, "%d");
3821
break;
3822
3823
case DATA_TYPE_UINT8_ARRAY:
3824
NVPA(buf, size, len, buf_end, elem, uint8_array,
3825
uint8_t, int, "%u");
3826
break;
3827
3828
case DATA_TYPE_INT16_ARRAY:
3829
NVPA(buf, size, len, buf_end, elem, int16_array,
3830
int16_t, int, "%d");
3831
break;
3832
3833
case DATA_TYPE_UINT16_ARRAY:
3834
NVPA(buf, size, len, buf_end, elem, uint16_array,
3835
uint16_t, int, "%u");
3836
break;
3837
3838
case DATA_TYPE_INT32_ARRAY:
3839
NVPA(buf, size, len, buf_end, elem, int32_array,
3840
int32_t, long, "%ld");
3841
break;
3842
3843
case DATA_TYPE_UINT32_ARRAY:
3844
NVPA(buf, size, len, buf_end, elem, uint32_array,
3845
uint32_t, ulong_t, "%lu");
3846
break;
3847
3848
case DATA_TYPE_INT64_ARRAY:
3849
NVPA(buf, size, len, buf_end, elem, int64_array,
3850
int64_t, longlong_t, "%lld");
3851
break;
3852
3853
case DATA_TYPE_UINT64_ARRAY:
3854
NVPA(buf, size, len, buf_end, elem, uint64_array,
3855
uint64_t, u_longlong_t, "%llu");
3856
break;
3857
3858
case DATA_TYPE_STRING_ARRAY:
3859
NVPA(buf, size, len, buf_end, elem, string_array,
3860
const char *, const char *, "'%s'");
3861
break;
3862
3863
case DATA_TYPE_NVLIST:
3864
(void) nvpair_value_nvlist(elem, &nvlist_value);
3865
3866
rc = snprintf(buf, size, "%*s%s:\n", indent, "",
3867
nvpair_name(elem));
3868
if (rc < 0)
3869
return (rc);
3870
size = MAX((int)size - rc, 0);
3871
buf = size == 0 ? NULL : buf_end - size;
3872
len += rc;
3873
3874
rc = nvlist_snprintf(buf, size, nvlist_value,
3875
indent + 4);
3876
if (rc < 0)
3877
return (rc);
3878
size = MAX((int)size - rc, 0);
3879
buf = size == 0 ? NULL : buf_end - size;
3880
len += rc;
3881
break;
3882
3883
case DATA_TYPE_NVLIST_ARRAY:
3884
(void) nvpair_value_nvlist_array(elem,
3885
&nvlist_array_value, &count);
3886
for (i = 0; i < count; i++) {
3887
rc = snprintf(buf, size, "%*s%s[%u]:\n",
3888
indent, "", nvpair_name(elem), i);
3889
if (rc < 0)
3890
return (rc);
3891
size = MAX((int)size - rc, 0);
3892
buf = size == 0 ? NULL : buf_end - size;
3893
len += rc;
3894
3895
rc = nvlist_snprintf(buf, size,
3896
nvlist_array_value[i], indent + 4);
3897
if (rc < 0)
3898
return (rc);
3899
size = MAX((int)size - rc, 0);
3900
buf = size == 0 ? NULL : buf_end - size;
3901
len += rc;
3902
}
3903
break;
3904
3905
default:
3906
rc = snprintf(buf, size, "bad config type %d for %s\n",
3907
nvpair_type(elem), nvpair_name(elem));
3908
if (rc < 0)
3909
return (rc);
3910
size = MAX((int)size - rc, 0);
3911
buf = size == 0 ? NULL : buf_end - size;
3912
len += rc;
3913
}
3914
}
3915
return (len);
3916
}
3917
3918
EXPORT_SYMBOL(nv_alloc_init);
3919
EXPORT_SYMBOL(nv_alloc_reset);
3920
EXPORT_SYMBOL(nv_alloc_fini);
3921
3922
/* list management */
3923
EXPORT_SYMBOL(nvlist_alloc);
3924
EXPORT_SYMBOL(nvlist_free);
3925
EXPORT_SYMBOL(nvlist_size);
3926
EXPORT_SYMBOL(nvlist_pack);
3927
EXPORT_SYMBOL(nvlist_unpack);
3928
EXPORT_SYMBOL(nvlist_dup);
3929
EXPORT_SYMBOL(nvlist_merge);
3930
3931
EXPORT_SYMBOL(nvlist_xalloc);
3932
EXPORT_SYMBOL(nvlist_xpack);
3933
EXPORT_SYMBOL(nvlist_xunpack);
3934
EXPORT_SYMBOL(nvlist_xdup);
3935
EXPORT_SYMBOL(nvlist_lookup_nv_alloc);
3936
3937
EXPORT_SYMBOL(nvlist_add_nvpair);
3938
EXPORT_SYMBOL(nvlist_add_boolean);
3939
EXPORT_SYMBOL(nvlist_add_boolean_value);
3940
EXPORT_SYMBOL(nvlist_add_byte);
3941
EXPORT_SYMBOL(nvlist_add_int8);
3942
EXPORT_SYMBOL(nvlist_add_uint8);
3943
EXPORT_SYMBOL(nvlist_add_int16);
3944
EXPORT_SYMBOL(nvlist_add_uint16);
3945
EXPORT_SYMBOL(nvlist_add_int32);
3946
EXPORT_SYMBOL(nvlist_add_uint32);
3947
EXPORT_SYMBOL(nvlist_add_int64);
3948
EXPORT_SYMBOL(nvlist_add_uint64);
3949
EXPORT_SYMBOL(nvlist_add_string);
3950
EXPORT_SYMBOL(nvlist_add_nvlist);
3951
EXPORT_SYMBOL(nvlist_add_boolean_array);
3952
EXPORT_SYMBOL(nvlist_add_byte_array);
3953
EXPORT_SYMBOL(nvlist_add_int8_array);
3954
EXPORT_SYMBOL(nvlist_add_uint8_array);
3955
EXPORT_SYMBOL(nvlist_add_int16_array);
3956
EXPORT_SYMBOL(nvlist_add_uint16_array);
3957
EXPORT_SYMBOL(nvlist_add_int32_array);
3958
EXPORT_SYMBOL(nvlist_add_uint32_array);
3959
EXPORT_SYMBOL(nvlist_add_int64_array);
3960
EXPORT_SYMBOL(nvlist_add_uint64_array);
3961
EXPORT_SYMBOL(nvlist_add_string_array);
3962
EXPORT_SYMBOL(nvlist_add_nvlist_array);
3963
EXPORT_SYMBOL(nvlist_next_nvpair);
3964
EXPORT_SYMBOL(nvlist_prev_nvpair);
3965
EXPORT_SYMBOL(nvlist_empty);
3966
EXPORT_SYMBOL(nvlist_add_hrtime);
3967
3968
EXPORT_SYMBOL(nvlist_remove);
3969
EXPORT_SYMBOL(nvlist_remove_nvpair);
3970
EXPORT_SYMBOL(nvlist_remove_all);
3971
3972
EXPORT_SYMBOL(nvlist_lookup_boolean);
3973
EXPORT_SYMBOL(nvlist_lookup_boolean_value);
3974
EXPORT_SYMBOL(nvlist_lookup_byte);
3975
EXPORT_SYMBOL(nvlist_lookup_int8);
3976
EXPORT_SYMBOL(nvlist_lookup_uint8);
3977
EXPORT_SYMBOL(nvlist_lookup_int16);
3978
EXPORT_SYMBOL(nvlist_lookup_uint16);
3979
EXPORT_SYMBOL(nvlist_lookup_int32);
3980
EXPORT_SYMBOL(nvlist_lookup_uint32);
3981
EXPORT_SYMBOL(nvlist_lookup_int64);
3982
EXPORT_SYMBOL(nvlist_lookup_uint64);
3983
EXPORT_SYMBOL(nvlist_lookup_string);
3984
EXPORT_SYMBOL(nvlist_lookup_nvlist);
3985
EXPORT_SYMBOL(nvlist_lookup_boolean_array);
3986
EXPORT_SYMBOL(nvlist_lookup_byte_array);
3987
EXPORT_SYMBOL(nvlist_lookup_int8_array);
3988
EXPORT_SYMBOL(nvlist_lookup_uint8_array);
3989
EXPORT_SYMBOL(nvlist_lookup_int16_array);
3990
EXPORT_SYMBOL(nvlist_lookup_uint16_array);
3991
EXPORT_SYMBOL(nvlist_lookup_int32_array);
3992
EXPORT_SYMBOL(nvlist_lookup_uint32_array);
3993
EXPORT_SYMBOL(nvlist_lookup_int64_array);
3994
EXPORT_SYMBOL(nvlist_lookup_uint64_array);
3995
EXPORT_SYMBOL(nvlist_lookup_string_array);
3996
EXPORT_SYMBOL(nvlist_lookup_nvlist_array);
3997
EXPORT_SYMBOL(nvlist_lookup_hrtime);
3998
EXPORT_SYMBOL(nvlist_lookup_pairs);
3999
4000
EXPORT_SYMBOL(nvlist_lookup_nvpair);
4001
EXPORT_SYMBOL(nvlist_exists);
4002
4003
EXPORT_SYMBOL(nvlist_snprintf);
4004
4005
/* processing nvpair */
4006
EXPORT_SYMBOL(nvpair_name);
4007
EXPORT_SYMBOL(nvpair_type);
4008
EXPORT_SYMBOL(nvpair_value_boolean_value);
4009
EXPORT_SYMBOL(nvpair_value_byte);
4010
EXPORT_SYMBOL(nvpair_value_int8);
4011
EXPORT_SYMBOL(nvpair_value_uint8);
4012
EXPORT_SYMBOL(nvpair_value_int16);
4013
EXPORT_SYMBOL(nvpair_value_uint16);
4014
EXPORT_SYMBOL(nvpair_value_int32);
4015
EXPORT_SYMBOL(nvpair_value_uint32);
4016
EXPORT_SYMBOL(nvpair_value_int64);
4017
EXPORT_SYMBOL(nvpair_value_uint64);
4018
EXPORT_SYMBOL(nvpair_value_string);
4019
EXPORT_SYMBOL(nvpair_value_nvlist);
4020
EXPORT_SYMBOL(nvpair_value_boolean_array);
4021
EXPORT_SYMBOL(nvpair_value_byte_array);
4022
EXPORT_SYMBOL(nvpair_value_int8_array);
4023
EXPORT_SYMBOL(nvpair_value_uint8_array);
4024
EXPORT_SYMBOL(nvpair_value_int16_array);
4025
EXPORT_SYMBOL(nvpair_value_uint16_array);
4026
EXPORT_SYMBOL(nvpair_value_int32_array);
4027
EXPORT_SYMBOL(nvpair_value_uint32_array);
4028
EXPORT_SYMBOL(nvpair_value_int64_array);
4029
EXPORT_SYMBOL(nvpair_value_uint64_array);
4030
EXPORT_SYMBOL(nvpair_value_string_array);
4031
EXPORT_SYMBOL(nvpair_value_nvlist_array);
4032
EXPORT_SYMBOL(nvpair_value_hrtime);
4033
4034