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