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