]> git.proxmox.com Git - mirror_zfs-debian.git/blob - module/nvpair/nvpair.c
New upstream version 0.7.4
[mirror_zfs-debian.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 int value_sz;
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:
1289 #if !defined(_KERNEL)
1290 case DATA_TYPE_DOUBLE:
1291 #endif
1292 if (data == NULL)
1293 return (EINVAL);
1294 if ((value_sz = i_get_value_size(type, NULL, 1)) < 0)
1295 return (EINVAL);
1296 bcopy(NVP_VALUE(nvp), data, (size_t)value_sz);
1297 if (nelem != NULL)
1298 *nelem = 1;
1299 break;
1300
1301 case DATA_TYPE_NVLIST:
1302 case DATA_TYPE_STRING:
1303 if (data == NULL)
1304 return (EINVAL);
1305 *(void **)data = (void *)NVP_VALUE(nvp);
1306 if (nelem != NULL)
1307 *nelem = 1;
1308 break;
1309
1310 case DATA_TYPE_BOOLEAN_ARRAY:
1311 case DATA_TYPE_BYTE_ARRAY:
1312 case DATA_TYPE_INT8_ARRAY:
1313 case DATA_TYPE_UINT8_ARRAY:
1314 case DATA_TYPE_INT16_ARRAY:
1315 case DATA_TYPE_UINT16_ARRAY:
1316 case DATA_TYPE_INT32_ARRAY:
1317 case DATA_TYPE_UINT32_ARRAY:
1318 case DATA_TYPE_INT64_ARRAY:
1319 case DATA_TYPE_UINT64_ARRAY:
1320 case DATA_TYPE_STRING_ARRAY:
1321 case DATA_TYPE_NVLIST_ARRAY:
1322 if (nelem == NULL || data == NULL)
1323 return (EINVAL);
1324 if ((*nelem = NVP_NELEM(nvp)) != 0)
1325 *(void **)data = (void *)NVP_VALUE(nvp);
1326 else
1327 *(void **)data = NULL;
1328 break;
1329
1330 default:
1331 return (ENOTSUP);
1332 }
1333
1334 return (0);
1335 }
1336
1337 static int
1338 nvlist_lookup_common(nvlist_t *nvl, const char *name, data_type_t type,
1339 uint_t *nelem, void *data)
1340 {
1341 nvpriv_t *priv;
1342 nvpair_t *nvp;
1343 i_nvp_t *curr;
1344
1345 if (name == NULL || nvl == NULL ||
1346 (priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL)
1347 return (EINVAL);
1348
1349 if (!(nvl->nvl_nvflag & (NV_UNIQUE_NAME | NV_UNIQUE_NAME_TYPE)))
1350 return (ENOTSUP);
1351
1352 for (curr = priv->nvp_list; curr != NULL; curr = curr->nvi_next) {
1353 nvp = &curr->nvi_nvp;
1354
1355 if (strcmp(name, NVP_NAME(nvp)) == 0 && NVP_TYPE(nvp) == type)
1356 return (nvpair_value_common(nvp, type, nelem, data));
1357 }
1358
1359 return (ENOENT);
1360 }
1361
1362 int
1363 nvlist_lookup_boolean(nvlist_t *nvl, const char *name)
1364 {
1365 return (nvlist_lookup_common(nvl, name, DATA_TYPE_BOOLEAN, NULL, NULL));
1366 }
1367
1368 int
1369 nvlist_lookup_boolean_value(nvlist_t *nvl, const char *name, boolean_t *val)
1370 {
1371 return (nvlist_lookup_common(nvl, name,
1372 DATA_TYPE_BOOLEAN_VALUE, NULL, val));
1373 }
1374
1375 int
1376 nvlist_lookup_byte(nvlist_t *nvl, const char *name, uchar_t *val)
1377 {
1378 return (nvlist_lookup_common(nvl, name, DATA_TYPE_BYTE, NULL, val));
1379 }
1380
1381 int
1382 nvlist_lookup_int8(nvlist_t *nvl, const char *name, int8_t *val)
1383 {
1384 return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT8, NULL, val));
1385 }
1386
1387 int
1388 nvlist_lookup_uint8(nvlist_t *nvl, const char *name, uint8_t *val)
1389 {
1390 return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT8, NULL, val));
1391 }
1392
1393 int
1394 nvlist_lookup_int16(nvlist_t *nvl, const char *name, int16_t *val)
1395 {
1396 return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT16, NULL, val));
1397 }
1398
1399 int
1400 nvlist_lookup_uint16(nvlist_t *nvl, const char *name, uint16_t *val)
1401 {
1402 return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT16, NULL, val));
1403 }
1404
1405 int
1406 nvlist_lookup_int32(nvlist_t *nvl, const char *name, int32_t *val)
1407 {
1408 return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT32, NULL, val));
1409 }
1410
1411 int
1412 nvlist_lookup_uint32(nvlist_t *nvl, const char *name, uint32_t *val)
1413 {
1414 return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT32, NULL, val));
1415 }
1416
1417 int
1418 nvlist_lookup_int64(nvlist_t *nvl, const char *name, int64_t *val)
1419 {
1420 return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT64, NULL, val));
1421 }
1422
1423 int
1424 nvlist_lookup_uint64(nvlist_t *nvl, const char *name, uint64_t *val)
1425 {
1426 return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT64, NULL, val));
1427 }
1428
1429 #if !defined(_KERNEL)
1430 int
1431 nvlist_lookup_double(nvlist_t *nvl, const char *name, double *val)
1432 {
1433 return (nvlist_lookup_common(nvl, name, DATA_TYPE_DOUBLE, NULL, val));
1434 }
1435 #endif
1436
1437 int
1438 nvlist_lookup_string(nvlist_t *nvl, const char *name, char **val)
1439 {
1440 return (nvlist_lookup_common(nvl, name, DATA_TYPE_STRING, NULL, val));
1441 }
1442
1443 int
1444 nvlist_lookup_nvlist(nvlist_t *nvl, const char *name, nvlist_t **val)
1445 {
1446 return (nvlist_lookup_common(nvl, name, DATA_TYPE_NVLIST, NULL, val));
1447 }
1448
1449 int
1450 nvlist_lookup_boolean_array(nvlist_t *nvl, const char *name,
1451 boolean_t **a, uint_t *n)
1452 {
1453 return (nvlist_lookup_common(nvl, name,
1454 DATA_TYPE_BOOLEAN_ARRAY, n, a));
1455 }
1456
1457 int
1458 nvlist_lookup_byte_array(nvlist_t *nvl, const char *name,
1459 uchar_t **a, uint_t *n)
1460 {
1461 return (nvlist_lookup_common(nvl, name, DATA_TYPE_BYTE_ARRAY, n, a));
1462 }
1463
1464 int
1465 nvlist_lookup_int8_array(nvlist_t *nvl, const char *name, int8_t **a, uint_t *n)
1466 {
1467 return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT8_ARRAY, n, a));
1468 }
1469
1470 int
1471 nvlist_lookup_uint8_array(nvlist_t *nvl, const char *name,
1472 uint8_t **a, uint_t *n)
1473 {
1474 return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT8_ARRAY, n, a));
1475 }
1476
1477 int
1478 nvlist_lookup_int16_array(nvlist_t *nvl, const char *name,
1479 int16_t **a, uint_t *n)
1480 {
1481 return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT16_ARRAY, n, a));
1482 }
1483
1484 int
1485 nvlist_lookup_uint16_array(nvlist_t *nvl, const char *name,
1486 uint16_t **a, uint_t *n)
1487 {
1488 return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT16_ARRAY, n, a));
1489 }
1490
1491 int
1492 nvlist_lookup_int32_array(nvlist_t *nvl, const char *name,
1493 int32_t **a, uint_t *n)
1494 {
1495 return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT32_ARRAY, n, a));
1496 }
1497
1498 int
1499 nvlist_lookup_uint32_array(nvlist_t *nvl, const char *name,
1500 uint32_t **a, uint_t *n)
1501 {
1502 return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT32_ARRAY, n, a));
1503 }
1504
1505 int
1506 nvlist_lookup_int64_array(nvlist_t *nvl, const char *name,
1507 int64_t **a, uint_t *n)
1508 {
1509 return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT64_ARRAY, n, a));
1510 }
1511
1512 int
1513 nvlist_lookup_uint64_array(nvlist_t *nvl, const char *name,
1514 uint64_t **a, uint_t *n)
1515 {
1516 return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT64_ARRAY, n, a));
1517 }
1518
1519 int
1520 nvlist_lookup_string_array(nvlist_t *nvl, const char *name,
1521 char ***a, uint_t *n)
1522 {
1523 return (nvlist_lookup_common(nvl, name, DATA_TYPE_STRING_ARRAY, n, a));
1524 }
1525
1526 int
1527 nvlist_lookup_nvlist_array(nvlist_t *nvl, const char *name,
1528 nvlist_t ***a, uint_t *n)
1529 {
1530 return (nvlist_lookup_common(nvl, name, DATA_TYPE_NVLIST_ARRAY, n, a));
1531 }
1532
1533 int
1534 nvlist_lookup_hrtime(nvlist_t *nvl, const char *name, hrtime_t *val)
1535 {
1536 return (nvlist_lookup_common(nvl, name, DATA_TYPE_HRTIME, NULL, val));
1537 }
1538
1539 int
1540 nvlist_lookup_pairs(nvlist_t *nvl, int flag, ...)
1541 {
1542 va_list ap;
1543 char *name;
1544 int noentok = (flag & NV_FLAG_NOENTOK ? 1 : 0);
1545 int ret = 0;
1546
1547 va_start(ap, flag);
1548 while (ret == 0 && (name = va_arg(ap, char *)) != NULL) {
1549 data_type_t type;
1550 void *val;
1551 uint_t *nelem;
1552
1553 switch (type = va_arg(ap, data_type_t)) {
1554 case DATA_TYPE_BOOLEAN:
1555 ret = nvlist_lookup_common(nvl, name, type, NULL, NULL);
1556 break;
1557
1558 case DATA_TYPE_BOOLEAN_VALUE:
1559 case DATA_TYPE_BYTE:
1560 case DATA_TYPE_INT8:
1561 case DATA_TYPE_UINT8:
1562 case DATA_TYPE_INT16:
1563 case DATA_TYPE_UINT16:
1564 case DATA_TYPE_INT32:
1565 case DATA_TYPE_UINT32:
1566 case DATA_TYPE_INT64:
1567 case DATA_TYPE_UINT64:
1568 case DATA_TYPE_HRTIME:
1569 case DATA_TYPE_STRING:
1570 case DATA_TYPE_NVLIST:
1571 #if !defined(_KERNEL)
1572 case DATA_TYPE_DOUBLE:
1573 #endif
1574 val = va_arg(ap, void *);
1575 ret = nvlist_lookup_common(nvl, name, type, NULL, val);
1576 break;
1577
1578 case DATA_TYPE_BYTE_ARRAY:
1579 case DATA_TYPE_BOOLEAN_ARRAY:
1580 case DATA_TYPE_INT8_ARRAY:
1581 case DATA_TYPE_UINT8_ARRAY:
1582 case DATA_TYPE_INT16_ARRAY:
1583 case DATA_TYPE_UINT16_ARRAY:
1584 case DATA_TYPE_INT32_ARRAY:
1585 case DATA_TYPE_UINT32_ARRAY:
1586 case DATA_TYPE_INT64_ARRAY:
1587 case DATA_TYPE_UINT64_ARRAY:
1588 case DATA_TYPE_STRING_ARRAY:
1589 case DATA_TYPE_NVLIST_ARRAY:
1590 val = va_arg(ap, void *);
1591 nelem = va_arg(ap, uint_t *);
1592 ret = nvlist_lookup_common(nvl, name, type, nelem, val);
1593 break;
1594
1595 default:
1596 ret = EINVAL;
1597 }
1598
1599 if (ret == ENOENT && noentok)
1600 ret = 0;
1601 }
1602 va_end(ap);
1603
1604 return (ret);
1605 }
1606
1607 /*
1608 * Find the 'name'ed nvpair in the nvlist 'nvl'. If 'name' found, the function
1609 * returns zero and a pointer to the matching nvpair is returned in '*ret'
1610 * (given 'ret' is non-NULL). If 'sep' is specified then 'name' will penitrate
1611 * multiple levels of embedded nvlists, with 'sep' as the separator. As an
1612 * example, if sep is '.', name might look like: "a" or "a.b" or "a.c[3]" or
1613 * "a.d[3].e[1]". This matches the C syntax for array embed (for convience,
1614 * code also supports "a.d[3]e[1]" syntax).
1615 *
1616 * If 'ip' is non-NULL and the last name component is an array, return the
1617 * value of the "...[index]" array index in *ip. For an array reference that
1618 * is not indexed, *ip will be returned as -1. If there is a syntax error in
1619 * 'name', and 'ep' is non-NULL then *ep will be set to point to the location
1620 * inside the 'name' string where the syntax error was detected.
1621 */
1622 static int
1623 nvlist_lookup_nvpair_ei_sep(nvlist_t *nvl, const char *name, const char sep,
1624 nvpair_t **ret, int *ip, char **ep)
1625 {
1626 nvpair_t *nvp;
1627 const char *np;
1628 char *sepp = NULL;
1629 char *idxp, *idxep;
1630 nvlist_t **nva;
1631 long idx = 0;
1632 int n;
1633
1634 if (ip)
1635 *ip = -1; /* not indexed */
1636 if (ep)
1637 *ep = NULL;
1638
1639 if ((nvl == NULL) || (name == NULL))
1640 return (EINVAL);
1641
1642 /* step through components of name */
1643 for (np = name; np && *np; np = sepp) {
1644 /* ensure unique names */
1645 if (!(nvl->nvl_nvflag & NV_UNIQUE_NAME))
1646 return (ENOTSUP);
1647
1648 /* skip white space */
1649 skip_whitespace(np);
1650 if (*np == 0)
1651 break;
1652
1653 /* set 'sepp' to end of current component 'np' */
1654 if (sep)
1655 sepp = strchr(np, sep);
1656 else
1657 sepp = NULL;
1658
1659 /* find start of next "[ index ]..." */
1660 idxp = strchr(np, '[');
1661
1662 /* if sepp comes first, set idxp to NULL */
1663 if (sepp && idxp && (sepp < idxp))
1664 idxp = NULL;
1665
1666 /*
1667 * At this point 'idxp' is set if there is an index
1668 * expected for the current component.
1669 */
1670 if (idxp) {
1671 /* set 'n' to length of current 'np' name component */
1672 n = idxp++ - np;
1673
1674 /* keep sepp up to date for *ep use as we advance */
1675 skip_whitespace(idxp);
1676 sepp = idxp;
1677
1678 /* determine the index value */
1679 #if defined(_KERNEL) && !defined(_BOOT)
1680 if (ddi_strtol(idxp, &idxep, 0, &idx))
1681 goto fail;
1682 #else
1683 idx = strtol(idxp, &idxep, 0);
1684 #endif
1685 if (idxep == idxp)
1686 goto fail;
1687
1688 /* keep sepp up to date for *ep use as we advance */
1689 sepp = idxep;
1690
1691 /* skip white space index value and check for ']' */
1692 skip_whitespace(sepp);
1693 if (*sepp++ != ']')
1694 goto fail;
1695
1696 /* for embedded arrays, support C syntax: "a[1].b" */
1697 skip_whitespace(sepp);
1698 if (sep && (*sepp == sep))
1699 sepp++;
1700 } else if (sepp) {
1701 n = sepp++ - np;
1702 } else {
1703 n = strlen(np);
1704 }
1705
1706 /* trim trailing whitespace by reducing length of 'np' */
1707 if (n == 0)
1708 goto fail;
1709 for (n--; (np[n] == ' ') || (np[n] == '\t'); n--)
1710 ;
1711 n++;
1712
1713 /* skip whitespace, and set sepp to NULL if complete */
1714 if (sepp) {
1715 skip_whitespace(sepp);
1716 if (*sepp == 0)
1717 sepp = NULL;
1718 }
1719
1720 /*
1721 * At this point:
1722 * o 'n' is the length of current 'np' component.
1723 * o 'idxp' is set if there was an index, and value 'idx'.
1724 * o 'sepp' is set to the beginning of the next component,
1725 * and set to NULL if we have no more components.
1726 *
1727 * Search for nvpair with matching component name.
1728 */
1729 for (nvp = nvlist_next_nvpair(nvl, NULL); nvp != NULL;
1730 nvp = nvlist_next_nvpair(nvl, nvp)) {
1731
1732 /* continue if no match on name */
1733 if (strncmp(np, nvpair_name(nvp), n) ||
1734 (strlen(nvpair_name(nvp)) != n))
1735 continue;
1736
1737 /* if indexed, verify type is array oriented */
1738 if (idxp && !nvpair_type_is_array(nvp))
1739 goto fail;
1740
1741 /*
1742 * Full match found, return nvp and idx if this
1743 * was the last component.
1744 */
1745 if (sepp == NULL) {
1746 if (ret)
1747 *ret = nvp;
1748 if (ip && idxp)
1749 *ip = (int)idx; /* return index */
1750 return (0); /* found */
1751 }
1752
1753 /*
1754 * More components: current match must be
1755 * of DATA_TYPE_NVLIST or DATA_TYPE_NVLIST_ARRAY
1756 * to support going deeper.
1757 */
1758 if (nvpair_type(nvp) == DATA_TYPE_NVLIST) {
1759 nvl = EMBEDDED_NVL(nvp);
1760 break;
1761 } else if (nvpair_type(nvp) == DATA_TYPE_NVLIST_ARRAY) {
1762 (void) nvpair_value_nvlist_array(nvp,
1763 &nva, (uint_t *)&n);
1764 if ((n < 0) || (idx >= n))
1765 goto fail;
1766 nvl = nva[idx];
1767 break;
1768 }
1769
1770 /* type does not support more levels */
1771 goto fail;
1772 }
1773 if (nvp == NULL)
1774 goto fail; /* 'name' not found */
1775
1776 /* search for match of next component in embedded 'nvl' list */
1777 }
1778
1779 fail: if (ep && sepp)
1780 *ep = sepp;
1781 return (EINVAL);
1782 }
1783
1784 /*
1785 * Return pointer to nvpair with specified 'name'.
1786 */
1787 int
1788 nvlist_lookup_nvpair(nvlist_t *nvl, const char *name, nvpair_t **ret)
1789 {
1790 return (nvlist_lookup_nvpair_ei_sep(nvl, name, 0, ret, NULL, NULL));
1791 }
1792
1793 /*
1794 * Determine if named nvpair exists in nvlist (use embedded separator of '.'
1795 * and return array index). See nvlist_lookup_nvpair_ei_sep for more detailed
1796 * description.
1797 */
1798 int nvlist_lookup_nvpair_embedded_index(nvlist_t *nvl,
1799 const char *name, nvpair_t **ret, int *ip, char **ep)
1800 {
1801 return (nvlist_lookup_nvpair_ei_sep(nvl, name, '.', ret, ip, ep));
1802 }
1803
1804 boolean_t
1805 nvlist_exists(nvlist_t *nvl, const char *name)
1806 {
1807 nvpriv_t *priv;
1808 nvpair_t *nvp;
1809 i_nvp_t *curr;
1810
1811 if (name == NULL || nvl == NULL ||
1812 (priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL)
1813 return (B_FALSE);
1814
1815 for (curr = priv->nvp_list; curr != NULL; curr = curr->nvi_next) {
1816 nvp = &curr->nvi_nvp;
1817
1818 if (strcmp(name, NVP_NAME(nvp)) == 0)
1819 return (B_TRUE);
1820 }
1821
1822 return (B_FALSE);
1823 }
1824
1825 int
1826 nvpair_value_boolean_value(nvpair_t *nvp, boolean_t *val)
1827 {
1828 return (nvpair_value_common(nvp, DATA_TYPE_BOOLEAN_VALUE, NULL, val));
1829 }
1830
1831 int
1832 nvpair_value_byte(nvpair_t *nvp, uchar_t *val)
1833 {
1834 return (nvpair_value_common(nvp, DATA_TYPE_BYTE, NULL, val));
1835 }
1836
1837 int
1838 nvpair_value_int8(nvpair_t *nvp, int8_t *val)
1839 {
1840 return (nvpair_value_common(nvp, DATA_TYPE_INT8, NULL, val));
1841 }
1842
1843 int
1844 nvpair_value_uint8(nvpair_t *nvp, uint8_t *val)
1845 {
1846 return (nvpair_value_common(nvp, DATA_TYPE_UINT8, NULL, val));
1847 }
1848
1849 int
1850 nvpair_value_int16(nvpair_t *nvp, int16_t *val)
1851 {
1852 return (nvpair_value_common(nvp, DATA_TYPE_INT16, NULL, val));
1853 }
1854
1855 int
1856 nvpair_value_uint16(nvpair_t *nvp, uint16_t *val)
1857 {
1858 return (nvpair_value_common(nvp, DATA_TYPE_UINT16, NULL, val));
1859 }
1860
1861 int
1862 nvpair_value_int32(nvpair_t *nvp, int32_t *val)
1863 {
1864 return (nvpair_value_common(nvp, DATA_TYPE_INT32, NULL, val));
1865 }
1866
1867 int
1868 nvpair_value_uint32(nvpair_t *nvp, uint32_t *val)
1869 {
1870 return (nvpair_value_common(nvp, DATA_TYPE_UINT32, NULL, val));
1871 }
1872
1873 int
1874 nvpair_value_int64(nvpair_t *nvp, int64_t *val)
1875 {
1876 return (nvpair_value_common(nvp, DATA_TYPE_INT64, NULL, val));
1877 }
1878
1879 int
1880 nvpair_value_uint64(nvpair_t *nvp, uint64_t *val)
1881 {
1882 return (nvpair_value_common(nvp, DATA_TYPE_UINT64, NULL, val));
1883 }
1884
1885 #if !defined(_KERNEL)
1886 int
1887 nvpair_value_double(nvpair_t *nvp, double *val)
1888 {
1889 return (nvpair_value_common(nvp, DATA_TYPE_DOUBLE, NULL, val));
1890 }
1891 #endif
1892
1893 int
1894 nvpair_value_string(nvpair_t *nvp, char **val)
1895 {
1896 return (nvpair_value_common(nvp, DATA_TYPE_STRING, NULL, val));
1897 }
1898
1899 int
1900 nvpair_value_nvlist(nvpair_t *nvp, nvlist_t **val)
1901 {
1902 return (nvpair_value_common(nvp, DATA_TYPE_NVLIST, NULL, val));
1903 }
1904
1905 int
1906 nvpair_value_boolean_array(nvpair_t *nvp, boolean_t **val, uint_t *nelem)
1907 {
1908 return (nvpair_value_common(nvp, DATA_TYPE_BOOLEAN_ARRAY, nelem, val));
1909 }
1910
1911 int
1912 nvpair_value_byte_array(nvpair_t *nvp, uchar_t **val, uint_t *nelem)
1913 {
1914 return (nvpair_value_common(nvp, DATA_TYPE_BYTE_ARRAY, nelem, val));
1915 }
1916
1917 int
1918 nvpair_value_int8_array(nvpair_t *nvp, int8_t **val, uint_t *nelem)
1919 {
1920 return (nvpair_value_common(nvp, DATA_TYPE_INT8_ARRAY, nelem, val));
1921 }
1922
1923 int
1924 nvpair_value_uint8_array(nvpair_t *nvp, uint8_t **val, uint_t *nelem)
1925 {
1926 return (nvpair_value_common(nvp, DATA_TYPE_UINT8_ARRAY, nelem, val));
1927 }
1928
1929 int
1930 nvpair_value_int16_array(nvpair_t *nvp, int16_t **val, uint_t *nelem)
1931 {
1932 return (nvpair_value_common(nvp, DATA_TYPE_INT16_ARRAY, nelem, val));
1933 }
1934
1935 int
1936 nvpair_value_uint16_array(nvpair_t *nvp, uint16_t **val, uint_t *nelem)
1937 {
1938 return (nvpair_value_common(nvp, DATA_TYPE_UINT16_ARRAY, nelem, val));
1939 }
1940
1941 int
1942 nvpair_value_int32_array(nvpair_t *nvp, int32_t **val, uint_t *nelem)
1943 {
1944 return (nvpair_value_common(nvp, DATA_TYPE_INT32_ARRAY, nelem, val));
1945 }
1946
1947 int
1948 nvpair_value_uint32_array(nvpair_t *nvp, uint32_t **val, uint_t *nelem)
1949 {
1950 return (nvpair_value_common(nvp, DATA_TYPE_UINT32_ARRAY, nelem, val));
1951 }
1952
1953 int
1954 nvpair_value_int64_array(nvpair_t *nvp, int64_t **val, uint_t *nelem)
1955 {
1956 return (nvpair_value_common(nvp, DATA_TYPE_INT64_ARRAY, nelem, val));
1957 }
1958
1959 int
1960 nvpair_value_uint64_array(nvpair_t *nvp, uint64_t **val, uint_t *nelem)
1961 {
1962 return (nvpair_value_common(nvp, DATA_TYPE_UINT64_ARRAY, nelem, val));
1963 }
1964
1965 int
1966 nvpair_value_string_array(nvpair_t *nvp, char ***val, uint_t *nelem)
1967 {
1968 return (nvpair_value_common(nvp, DATA_TYPE_STRING_ARRAY, nelem, val));
1969 }
1970
1971 int
1972 nvpair_value_nvlist_array(nvpair_t *nvp, nvlist_t ***val, uint_t *nelem)
1973 {
1974 return (nvpair_value_common(nvp, DATA_TYPE_NVLIST_ARRAY, nelem, val));
1975 }
1976
1977 int
1978 nvpair_value_hrtime(nvpair_t *nvp, hrtime_t *val)
1979 {
1980 return (nvpair_value_common(nvp, DATA_TYPE_HRTIME, NULL, val));
1981 }
1982
1983 /*
1984 * Add specified pair to the list.
1985 */
1986 int
1987 nvlist_add_nvpair(nvlist_t *nvl, nvpair_t *nvp)
1988 {
1989 if (nvl == NULL || nvp == NULL)
1990 return (EINVAL);
1991
1992 return (nvlist_add_common(nvl, NVP_NAME(nvp), NVP_TYPE(nvp),
1993 NVP_NELEM(nvp), NVP_VALUE(nvp)));
1994 }
1995
1996 /*
1997 * Merge the supplied nvlists and put the result in dst.
1998 * The merged list will contain all names specified in both lists,
1999 * the values are taken from nvl in the case of duplicates.
2000 * Return 0 on success.
2001 */
2002 /*ARGSUSED*/
2003 int
2004 nvlist_merge(nvlist_t *dst, nvlist_t *nvl, int flag)
2005 {
2006 if (nvl == NULL || dst == NULL)
2007 return (EINVAL);
2008
2009 if (dst != nvl)
2010 return (nvlist_copy_pairs(nvl, dst));
2011
2012 return (0);
2013 }
2014
2015 /*
2016 * Encoding related routines
2017 */
2018 #define NVS_OP_ENCODE 0
2019 #define NVS_OP_DECODE 1
2020 #define NVS_OP_GETSIZE 2
2021
2022 typedef struct nvs_ops nvs_ops_t;
2023
2024 typedef struct {
2025 int nvs_op;
2026 const nvs_ops_t *nvs_ops;
2027 void *nvs_private;
2028 nvpriv_t *nvs_priv;
2029 int nvs_recursion;
2030 } nvstream_t;
2031
2032 /*
2033 * nvs operations are:
2034 * - nvs_nvlist
2035 * encoding / decoding of an nvlist header (nvlist_t)
2036 * calculates the size used for header and end detection
2037 *
2038 * - nvs_nvpair
2039 * responsible for the first part of encoding / decoding of an nvpair
2040 * calculates the decoded size of an nvpair
2041 *
2042 * - nvs_nvp_op
2043 * second part of encoding / decoding of an nvpair
2044 *
2045 * - nvs_nvp_size
2046 * calculates the encoding size of an nvpair
2047 *
2048 * - nvs_nvl_fini
2049 * encodes the end detection mark (zeros).
2050 */
2051 struct nvs_ops {
2052 int (*nvs_nvlist)(nvstream_t *, nvlist_t *, size_t *);
2053 int (*nvs_nvpair)(nvstream_t *, nvpair_t *, size_t *);
2054 int (*nvs_nvp_op)(nvstream_t *, nvpair_t *);
2055 int (*nvs_nvp_size)(nvstream_t *, nvpair_t *, size_t *);
2056 int (*nvs_nvl_fini)(nvstream_t *);
2057 };
2058
2059 typedef struct {
2060 char nvh_encoding; /* nvs encoding method */
2061 char nvh_endian; /* nvs endian */
2062 char nvh_reserved1; /* reserved for future use */
2063 char nvh_reserved2; /* reserved for future use */
2064 } nvs_header_t;
2065
2066 static int
2067 nvs_encode_pairs(nvstream_t *nvs, nvlist_t *nvl)
2068 {
2069 nvpriv_t *priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv;
2070 i_nvp_t *curr;
2071
2072 /*
2073 * Walk nvpair in list and encode each nvpair
2074 */
2075 for (curr = priv->nvp_list; curr != NULL; curr = curr->nvi_next)
2076 if (nvs->nvs_ops->nvs_nvpair(nvs, &curr->nvi_nvp, NULL) != 0)
2077 return (EFAULT);
2078
2079 return (nvs->nvs_ops->nvs_nvl_fini(nvs));
2080 }
2081
2082 static int
2083 nvs_decode_pairs(nvstream_t *nvs, nvlist_t *nvl)
2084 {
2085 nvpair_t *nvp;
2086 size_t nvsize;
2087 int err;
2088
2089 /*
2090 * Get decoded size of next pair in stream, alloc
2091 * memory for nvpair_t, then decode the nvpair
2092 */
2093 while ((err = nvs->nvs_ops->nvs_nvpair(nvs, NULL, &nvsize)) == 0) {
2094 if (nvsize == 0) /* end of list */
2095 break;
2096
2097 /* make sure len makes sense */
2098 if (nvsize < NVP_SIZE_CALC(1, 0))
2099 return (EFAULT);
2100
2101 if ((nvp = nvp_buf_alloc(nvl, nvsize)) == NULL)
2102 return (ENOMEM);
2103
2104 if ((err = nvs->nvs_ops->nvs_nvp_op(nvs, nvp)) != 0) {
2105 nvp_buf_free(nvl, nvp);
2106 return (err);
2107 }
2108
2109 if (i_validate_nvpair(nvp) != 0) {
2110 nvpair_free(nvp);
2111 nvp_buf_free(nvl, nvp);
2112 return (EFAULT);
2113 }
2114
2115 nvp_buf_link(nvl, nvp);
2116 }
2117 return (err);
2118 }
2119
2120 static int
2121 nvs_getsize_pairs(nvstream_t *nvs, nvlist_t *nvl, size_t *buflen)
2122 {
2123 nvpriv_t *priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv;
2124 i_nvp_t *curr;
2125 uint64_t nvsize = *buflen;
2126 size_t size;
2127
2128 /*
2129 * Get encoded size of nvpairs in nvlist
2130 */
2131 for (curr = priv->nvp_list; curr != NULL; curr = curr->nvi_next) {
2132 if (nvs->nvs_ops->nvs_nvp_size(nvs, &curr->nvi_nvp, &size) != 0)
2133 return (EINVAL);
2134
2135 if ((nvsize += size) > INT32_MAX)
2136 return (EINVAL);
2137 }
2138
2139 *buflen = nvsize;
2140 return (0);
2141 }
2142
2143 static int
2144 nvs_operation(nvstream_t *nvs, nvlist_t *nvl, size_t *buflen)
2145 {
2146 int err;
2147
2148 if (nvl->nvl_priv == 0)
2149 return (EFAULT);
2150
2151 /*
2152 * Perform the operation, starting with header, then each nvpair
2153 */
2154 if ((err = nvs->nvs_ops->nvs_nvlist(nvs, nvl, buflen)) != 0)
2155 return (err);
2156
2157 switch (nvs->nvs_op) {
2158 case NVS_OP_ENCODE:
2159 err = nvs_encode_pairs(nvs, nvl);
2160 break;
2161
2162 case NVS_OP_DECODE:
2163 err = nvs_decode_pairs(nvs, nvl);
2164 break;
2165
2166 case NVS_OP_GETSIZE:
2167 err = nvs_getsize_pairs(nvs, nvl, buflen);
2168 break;
2169
2170 default:
2171 err = EINVAL;
2172 }
2173
2174 return (err);
2175 }
2176
2177 static int
2178 nvs_embedded(nvstream_t *nvs, nvlist_t *embedded)
2179 {
2180 switch (nvs->nvs_op) {
2181 case NVS_OP_ENCODE: {
2182 int err;
2183
2184 if (nvs->nvs_recursion >= nvpair_max_recursion)
2185 return (EINVAL);
2186 nvs->nvs_recursion++;
2187 err = nvs_operation(nvs, embedded, NULL);
2188 nvs->nvs_recursion--;
2189 return (err);
2190 }
2191 case NVS_OP_DECODE: {
2192 nvpriv_t *priv;
2193 int err;
2194
2195 if (embedded->nvl_version != NV_VERSION)
2196 return (ENOTSUP);
2197
2198 if ((priv = nv_priv_alloc_embedded(nvs->nvs_priv)) == NULL)
2199 return (ENOMEM);
2200
2201 nvlist_init(embedded, embedded->nvl_nvflag, priv);
2202
2203 if (nvs->nvs_recursion >= nvpair_max_recursion)
2204 return (EINVAL);
2205 nvs->nvs_recursion++;
2206 if ((err = nvs_operation(nvs, embedded, NULL)) != 0)
2207 nvlist_free(embedded);
2208 nvs->nvs_recursion--;
2209 return (err);
2210 }
2211 default:
2212 break;
2213 }
2214
2215 return (EINVAL);
2216 }
2217
2218 static int
2219 nvs_embedded_nvl_array(nvstream_t *nvs, nvpair_t *nvp, size_t *size)
2220 {
2221 size_t nelem = NVP_NELEM(nvp);
2222 nvlist_t **nvlp = EMBEDDED_NVL_ARRAY(nvp);
2223 int i;
2224
2225 switch (nvs->nvs_op) {
2226 case NVS_OP_ENCODE:
2227 for (i = 0; i < nelem; i++)
2228 if (nvs_embedded(nvs, nvlp[i]) != 0)
2229 return (EFAULT);
2230 break;
2231
2232 case NVS_OP_DECODE: {
2233 size_t len = nelem * sizeof (uint64_t);
2234 nvlist_t *embedded = (nvlist_t *)((uintptr_t)nvlp + len);
2235
2236 bzero(nvlp, len); /* don't trust packed data */
2237 for (i = 0; i < nelem; i++) {
2238 if (nvs_embedded(nvs, embedded) != 0) {
2239 nvpair_free(nvp);
2240 return (EFAULT);
2241 }
2242
2243 nvlp[i] = embedded++;
2244 }
2245 break;
2246 }
2247 case NVS_OP_GETSIZE: {
2248 uint64_t nvsize = 0;
2249
2250 for (i = 0; i < nelem; i++) {
2251 size_t nvp_sz = 0;
2252
2253 if (nvs_operation(nvs, nvlp[i], &nvp_sz) != 0)
2254 return (EINVAL);
2255
2256 if ((nvsize += nvp_sz) > INT32_MAX)
2257 return (EINVAL);
2258 }
2259
2260 *size = nvsize;
2261 break;
2262 }
2263 default:
2264 return (EINVAL);
2265 }
2266
2267 return (0);
2268 }
2269
2270 static int nvs_native(nvstream_t *, nvlist_t *, char *, size_t *);
2271 static int nvs_xdr(nvstream_t *, nvlist_t *, char *, size_t *);
2272
2273 /*
2274 * Common routine for nvlist operations:
2275 * encode, decode, getsize (encoded size).
2276 */
2277 static int
2278 nvlist_common(nvlist_t *nvl, char *buf, size_t *buflen, int encoding,
2279 int nvs_op)
2280 {
2281 int err = 0;
2282 nvstream_t nvs;
2283 int nvl_endian;
2284 #ifdef _LITTLE_ENDIAN
2285 int host_endian = 1;
2286 #else
2287 int host_endian = 0;
2288 #endif /* _LITTLE_ENDIAN */
2289 nvs_header_t *nvh = (void *)buf;
2290
2291 if (buflen == NULL || nvl == NULL ||
2292 (nvs.nvs_priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL)
2293 return (EINVAL);
2294
2295 nvs.nvs_op = nvs_op;
2296 nvs.nvs_recursion = 0;
2297
2298 /*
2299 * For NVS_OP_ENCODE and NVS_OP_DECODE make sure an nvlist and
2300 * a buffer is allocated. The first 4 bytes in the buffer are
2301 * used for encoding method and host endian.
2302 */
2303 switch (nvs_op) {
2304 case NVS_OP_ENCODE:
2305 if (buf == NULL || *buflen < sizeof (nvs_header_t))
2306 return (EINVAL);
2307
2308 nvh->nvh_encoding = encoding;
2309 nvh->nvh_endian = nvl_endian = host_endian;
2310 nvh->nvh_reserved1 = 0;
2311 nvh->nvh_reserved2 = 0;
2312 break;
2313
2314 case NVS_OP_DECODE:
2315 if (buf == NULL || *buflen < sizeof (nvs_header_t))
2316 return (EINVAL);
2317
2318 /* get method of encoding from first byte */
2319 encoding = nvh->nvh_encoding;
2320 nvl_endian = nvh->nvh_endian;
2321 break;
2322
2323 case NVS_OP_GETSIZE:
2324 nvl_endian = host_endian;
2325
2326 /*
2327 * add the size for encoding
2328 */
2329 *buflen = sizeof (nvs_header_t);
2330 break;
2331
2332 default:
2333 return (ENOTSUP);
2334 }
2335
2336 /*
2337 * Create an nvstream with proper encoding method
2338 */
2339 switch (encoding) {
2340 case NV_ENCODE_NATIVE:
2341 /*
2342 * check endianness, in case we are unpacking
2343 * from a file
2344 */
2345 if (nvl_endian != host_endian)
2346 return (ENOTSUP);
2347 err = nvs_native(&nvs, nvl, buf, buflen);
2348 break;
2349 case NV_ENCODE_XDR:
2350 err = nvs_xdr(&nvs, nvl, buf, buflen);
2351 break;
2352 default:
2353 err = ENOTSUP;
2354 break;
2355 }
2356
2357 return (err);
2358 }
2359
2360 int
2361 nvlist_size(nvlist_t *nvl, size_t *size, int encoding)
2362 {
2363 return (nvlist_common(nvl, NULL, size, encoding, NVS_OP_GETSIZE));
2364 }
2365
2366 /*
2367 * Pack nvlist into contiguous memory
2368 */
2369 int
2370 nvlist_pack(nvlist_t *nvl, char **bufp, size_t *buflen, int encoding,
2371 int kmflag)
2372 {
2373 return (nvlist_xpack(nvl, bufp, buflen, encoding,
2374 nvlist_nv_alloc(kmflag)));
2375 }
2376
2377 int
2378 nvlist_xpack(nvlist_t *nvl, char **bufp, size_t *buflen, int encoding,
2379 nv_alloc_t *nva)
2380 {
2381 nvpriv_t nvpriv;
2382 size_t alloc_size;
2383 char *buf;
2384 int err;
2385
2386 if (nva == NULL || nvl == NULL || bufp == NULL || buflen == NULL)
2387 return (EINVAL);
2388
2389 if (*bufp != NULL)
2390 return (nvlist_common(nvl, *bufp, buflen, encoding,
2391 NVS_OP_ENCODE));
2392
2393 /*
2394 * Here is a difficult situation:
2395 * 1. The nvlist has fixed allocator properties.
2396 * All other nvlist routines (like nvlist_add_*, ...) use
2397 * these properties.
2398 * 2. When using nvlist_pack() the user can specify their own
2399 * allocator properties (e.g. by using KM_NOSLEEP).
2400 *
2401 * We use the user specified properties (2). A clearer solution
2402 * will be to remove the kmflag from nvlist_pack(), but we will
2403 * not change the interface.
2404 */
2405 nv_priv_init(&nvpriv, nva, 0);
2406
2407 if ((err = nvlist_size(nvl, &alloc_size, encoding)))
2408 return (err);
2409
2410 if ((buf = nv_mem_zalloc(&nvpriv, alloc_size)) == NULL)
2411 return (ENOMEM);
2412
2413 if ((err = nvlist_common(nvl, buf, &alloc_size, encoding,
2414 NVS_OP_ENCODE)) != 0) {
2415 nv_mem_free(&nvpriv, buf, alloc_size);
2416 } else {
2417 *buflen = alloc_size;
2418 *bufp = buf;
2419 }
2420
2421 return (err);
2422 }
2423
2424 /*
2425 * Unpack buf into an nvlist_t
2426 */
2427 int
2428 nvlist_unpack(char *buf, size_t buflen, nvlist_t **nvlp, int kmflag)
2429 {
2430 return (nvlist_xunpack(buf, buflen, nvlp, nvlist_nv_alloc(kmflag)));
2431 }
2432
2433 int
2434 nvlist_xunpack(char *buf, size_t buflen, nvlist_t **nvlp, nv_alloc_t *nva)
2435 {
2436 nvlist_t *nvl;
2437 int err;
2438
2439 if (nvlp == NULL)
2440 return (EINVAL);
2441
2442 if ((err = nvlist_xalloc(&nvl, 0, nva)) != 0)
2443 return (err);
2444
2445 if ((err = nvlist_common(nvl, buf, &buflen, 0, NVS_OP_DECODE)) != 0)
2446 nvlist_free(nvl);
2447 else
2448 *nvlp = nvl;
2449
2450 return (err);
2451 }
2452
2453 /*
2454 * Native encoding functions
2455 */
2456 typedef struct {
2457 /*
2458 * This structure is used when decoding a packed nvpair in
2459 * the native format. n_base points to a buffer containing the
2460 * packed nvpair. n_end is a pointer to the end of the buffer.
2461 * (n_end actually points to the first byte past the end of the
2462 * buffer.) n_curr is a pointer that lies between n_base and n_end.
2463 * It points to the current data that we are decoding.
2464 * The amount of data left in the buffer is equal to n_end - n_curr.
2465 * n_flag is used to recognize a packed embedded list.
2466 */
2467 caddr_t n_base;
2468 caddr_t n_end;
2469 caddr_t n_curr;
2470 uint_t n_flag;
2471 } nvs_native_t;
2472
2473 static int
2474 nvs_native_create(nvstream_t *nvs, nvs_native_t *native, char *buf,
2475 size_t buflen)
2476 {
2477 switch (nvs->nvs_op) {
2478 case NVS_OP_ENCODE:
2479 case NVS_OP_DECODE:
2480 nvs->nvs_private = native;
2481 native->n_curr = native->n_base = buf;
2482 native->n_end = buf + buflen;
2483 native->n_flag = 0;
2484 return (0);
2485
2486 case NVS_OP_GETSIZE:
2487 nvs->nvs_private = native;
2488 native->n_curr = native->n_base = native->n_end = NULL;
2489 native->n_flag = 0;
2490 return (0);
2491 default:
2492 return (EINVAL);
2493 }
2494 }
2495
2496 /*ARGSUSED*/
2497 static void
2498 nvs_native_destroy(nvstream_t *nvs)
2499 {
2500 }
2501
2502 static int
2503 native_cp(nvstream_t *nvs, void *buf, size_t size)
2504 {
2505 nvs_native_t *native = (nvs_native_t *)nvs->nvs_private;
2506
2507 if (native->n_curr + size > native->n_end)
2508 return (EFAULT);
2509
2510 /*
2511 * The bcopy() below eliminates alignment requirement
2512 * on the buffer (stream) and is preferred over direct access.
2513 */
2514 switch (nvs->nvs_op) {
2515 case NVS_OP_ENCODE:
2516 bcopy(buf, native->n_curr, size);
2517 break;
2518 case NVS_OP_DECODE:
2519 bcopy(native->n_curr, buf, size);
2520 break;
2521 default:
2522 return (EINVAL);
2523 }
2524
2525 native->n_curr += size;
2526 return (0);
2527 }
2528
2529 /*
2530 * operate on nvlist_t header
2531 */
2532 static int
2533 nvs_native_nvlist(nvstream_t *nvs, nvlist_t *nvl, size_t *size)
2534 {
2535 nvs_native_t *native = nvs->nvs_private;
2536
2537 switch (nvs->nvs_op) {
2538 case NVS_OP_ENCODE:
2539 case NVS_OP_DECODE:
2540 if (native->n_flag)
2541 return (0); /* packed embedded list */
2542
2543 native->n_flag = 1;
2544
2545 /* copy version and nvflag of the nvlist_t */
2546 if (native_cp(nvs, &nvl->nvl_version, sizeof (int32_t)) != 0 ||
2547 native_cp(nvs, &nvl->nvl_nvflag, sizeof (int32_t)) != 0)
2548 return (EFAULT);
2549
2550 return (0);
2551
2552 case NVS_OP_GETSIZE:
2553 /*
2554 * if calculate for packed embedded list
2555 * 4 for end of the embedded list
2556 * else
2557 * 2 * sizeof (int32_t) for nvl_version and nvl_nvflag
2558 * and 4 for end of the entire list
2559 */
2560 if (native->n_flag) {
2561 *size += 4;
2562 } else {
2563 native->n_flag = 1;
2564 *size += 2 * sizeof (int32_t) + 4;
2565 }
2566
2567 return (0);
2568
2569 default:
2570 return (EINVAL);
2571 }
2572 }
2573
2574 static int
2575 nvs_native_nvl_fini(nvstream_t *nvs)
2576 {
2577 if (nvs->nvs_op == NVS_OP_ENCODE) {
2578 nvs_native_t *native = (nvs_native_t *)nvs->nvs_private;
2579 /*
2580 * Add 4 zero bytes at end of nvlist. They are used
2581 * for end detection by the decode routine.
2582 */
2583 if (native->n_curr + sizeof (int) > native->n_end)
2584 return (EFAULT);
2585
2586 bzero(native->n_curr, sizeof (int));
2587 native->n_curr += sizeof (int);
2588 }
2589
2590 return (0);
2591 }
2592
2593 static int
2594 nvpair_native_embedded(nvstream_t *nvs, nvpair_t *nvp)
2595 {
2596 if (nvs->nvs_op == NVS_OP_ENCODE) {
2597 nvs_native_t *native = (nvs_native_t *)nvs->nvs_private;
2598 nvlist_t *packed = (void *)
2599 (native->n_curr - nvp->nvp_size + NVP_VALOFF(nvp));
2600 /*
2601 * Null out the pointer that is meaningless in the packed
2602 * structure. The address may not be aligned, so we have
2603 * to use bzero.
2604 */
2605 bzero((char *)packed + offsetof(nvlist_t, nvl_priv),
2606 sizeof (uint64_t));
2607 }
2608
2609 return (nvs_embedded(nvs, EMBEDDED_NVL(nvp)));
2610 }
2611
2612 static int
2613 nvpair_native_embedded_array(nvstream_t *nvs, nvpair_t *nvp)
2614 {
2615 if (nvs->nvs_op == NVS_OP_ENCODE) {
2616 nvs_native_t *native = (nvs_native_t *)nvs->nvs_private;
2617 char *value = native->n_curr - nvp->nvp_size + NVP_VALOFF(nvp);
2618 size_t len = NVP_NELEM(nvp) * sizeof (uint64_t);
2619 nvlist_t *packed = (nvlist_t *)((uintptr_t)value + len);
2620 int i;
2621 /*
2622 * Null out pointers that are meaningless in the packed
2623 * structure. The addresses may not be aligned, so we have
2624 * to use bzero.
2625 */
2626 bzero(value, len);
2627
2628 for (i = 0; i < NVP_NELEM(nvp); i++, packed++)
2629 /*
2630 * Null out the pointer that is meaningless in the
2631 * packed structure. The address may not be aligned,
2632 * so we have to use bzero.
2633 */
2634 bzero((char *)packed + offsetof(nvlist_t, nvl_priv),
2635 sizeof (uint64_t));
2636 }
2637
2638 return (nvs_embedded_nvl_array(nvs, nvp, NULL));
2639 }
2640
2641 static void
2642 nvpair_native_string_array(nvstream_t *nvs, nvpair_t *nvp)
2643 {
2644 switch (nvs->nvs_op) {
2645 case NVS_OP_ENCODE: {
2646 nvs_native_t *native = (nvs_native_t *)nvs->nvs_private;
2647 uint64_t *strp = (void *)
2648 (native->n_curr - nvp->nvp_size + NVP_VALOFF(nvp));
2649 /*
2650 * Null out pointers that are meaningless in the packed
2651 * structure. The addresses may not be aligned, so we have
2652 * to use bzero.
2653 */
2654 bzero(strp, NVP_NELEM(nvp) * sizeof (uint64_t));
2655 break;
2656 }
2657 case NVS_OP_DECODE: {
2658 char **strp = (void *)NVP_VALUE(nvp);
2659 char *buf = ((char *)strp + NVP_NELEM(nvp) * sizeof (uint64_t));
2660 int i;
2661
2662 for (i = 0; i < NVP_NELEM(nvp); i++) {
2663 strp[i] = buf;
2664 buf += strlen(buf) + 1;
2665 }
2666 break;
2667 }
2668 }
2669 }
2670
2671 static int
2672 nvs_native_nvp_op(nvstream_t *nvs, nvpair_t *nvp)
2673 {
2674 data_type_t type;
2675 int value_sz;
2676 int ret = 0;
2677
2678 /*
2679 * We do the initial bcopy of the data before we look at
2680 * the nvpair type, because when we're decoding, we won't
2681 * have the correct values for the pair until we do the bcopy.
2682 */
2683 switch (nvs->nvs_op) {
2684 case NVS_OP_ENCODE:
2685 case NVS_OP_DECODE:
2686 if (native_cp(nvs, nvp, nvp->nvp_size) != 0)
2687 return (EFAULT);
2688 break;
2689 default:
2690 return (EINVAL);
2691 }
2692
2693 /* verify nvp_name_sz, check the name string length */
2694 if (i_validate_nvpair_name(nvp) != 0)
2695 return (EFAULT);
2696
2697 type = NVP_TYPE(nvp);
2698
2699 /*
2700 * Verify type and nelem and get the value size.
2701 * In case of data types DATA_TYPE_STRING and DATA_TYPE_STRING_ARRAY
2702 * is the size of the string(s) excluded.
2703 */
2704 if ((value_sz = i_get_value_size(type, NULL, NVP_NELEM(nvp))) < 0)
2705 return (EFAULT);
2706
2707 if (NVP_SIZE_CALC(nvp->nvp_name_sz, value_sz) > nvp->nvp_size)
2708 return (EFAULT);
2709
2710 switch (type) {
2711 case DATA_TYPE_NVLIST:
2712 ret = nvpair_native_embedded(nvs, nvp);
2713 break;
2714 case DATA_TYPE_NVLIST_ARRAY:
2715 ret = nvpair_native_embedded_array(nvs, nvp);
2716 break;
2717 case DATA_TYPE_STRING_ARRAY:
2718 nvpair_native_string_array(nvs, nvp);
2719 break;
2720 default:
2721 break;
2722 }
2723
2724 return (ret);
2725 }
2726
2727 static int
2728 nvs_native_nvp_size(nvstream_t *nvs, nvpair_t *nvp, size_t *size)
2729 {
2730 uint64_t nvp_sz = nvp->nvp_size;
2731
2732 switch (NVP_TYPE(nvp)) {
2733 case DATA_TYPE_NVLIST: {
2734 size_t nvsize = 0;
2735
2736 if (nvs_operation(nvs, EMBEDDED_NVL(nvp), &nvsize) != 0)
2737 return (EINVAL);
2738
2739 nvp_sz += nvsize;
2740 break;
2741 }
2742 case DATA_TYPE_NVLIST_ARRAY: {
2743 size_t nvsize;
2744
2745 if (nvs_embedded_nvl_array(nvs, nvp, &nvsize) != 0)
2746 return (EINVAL);
2747
2748 nvp_sz += nvsize;
2749 break;
2750 }
2751 default:
2752 break;
2753 }
2754
2755 if (nvp_sz > INT32_MAX)
2756 return (EINVAL);
2757
2758 *size = nvp_sz;
2759
2760 return (0);
2761 }
2762
2763 static int
2764 nvs_native_nvpair(nvstream_t *nvs, nvpair_t *nvp, size_t *size)
2765 {
2766 switch (nvs->nvs_op) {
2767 case NVS_OP_ENCODE:
2768 return (nvs_native_nvp_op(nvs, nvp));
2769
2770 case NVS_OP_DECODE: {
2771 nvs_native_t *native = (nvs_native_t *)nvs->nvs_private;
2772 int32_t decode_len;
2773
2774 /* try to read the size value from the stream */
2775 if (native->n_curr + sizeof (int32_t) > native->n_end)
2776 return (EFAULT);
2777 bcopy(native->n_curr, &decode_len, sizeof (int32_t));
2778
2779 /* sanity check the size value */
2780 if (decode_len < 0 ||
2781 decode_len > native->n_end - native->n_curr)
2782 return (EFAULT);
2783
2784 *size = decode_len;
2785
2786 /*
2787 * If at the end of the stream then move the cursor
2788 * forward, otherwise nvpair_native_op() will read
2789 * the entire nvpair at the same cursor position.
2790 */
2791 if (*size == 0)
2792 native->n_curr += sizeof (int32_t);
2793 break;
2794 }
2795
2796 default:
2797 return (EINVAL);
2798 }
2799
2800 return (0);
2801 }
2802
2803 static const nvs_ops_t nvs_native_ops = {
2804 .nvs_nvlist = nvs_native_nvlist,
2805 .nvs_nvpair = nvs_native_nvpair,
2806 .nvs_nvp_op = nvs_native_nvp_op,
2807 .nvs_nvp_size = nvs_native_nvp_size,
2808 .nvs_nvl_fini = nvs_native_nvl_fini
2809 };
2810
2811 static int
2812 nvs_native(nvstream_t *nvs, nvlist_t *nvl, char *buf, size_t *buflen)
2813 {
2814 nvs_native_t native;
2815 int err;
2816
2817 nvs->nvs_ops = &nvs_native_ops;
2818
2819 if ((err = nvs_native_create(nvs, &native, buf + sizeof (nvs_header_t),
2820 *buflen - sizeof (nvs_header_t))) != 0)
2821 return (err);
2822
2823 err = nvs_operation(nvs, nvl, buflen);
2824
2825 nvs_native_destroy(nvs);
2826
2827 return (err);
2828 }
2829
2830 /*
2831 * XDR encoding functions
2832 *
2833 * An xdr packed nvlist is encoded as:
2834 *
2835 * - encoding methode and host endian (4 bytes)
2836 * - nvl_version (4 bytes)
2837 * - nvl_nvflag (4 bytes)
2838 *
2839 * - encoded nvpairs, the format of one xdr encoded nvpair is:
2840 * - encoded size of the nvpair (4 bytes)
2841 * - decoded size of the nvpair (4 bytes)
2842 * - name string, (4 + sizeof(NV_ALIGN4(string))
2843 * a string is coded as size (4 bytes) and data
2844 * - data type (4 bytes)
2845 * - number of elements in the nvpair (4 bytes)
2846 * - data
2847 *
2848 * - 2 zero's for end of the entire list (8 bytes)
2849 */
2850 static int
2851 nvs_xdr_create(nvstream_t *nvs, XDR *xdr, char *buf, size_t buflen)
2852 {
2853 /* xdr data must be 4 byte aligned */
2854 if ((ulong_t)buf % 4 != 0)
2855 return (EFAULT);
2856
2857 switch (nvs->nvs_op) {
2858 case NVS_OP_ENCODE:
2859 xdrmem_create(xdr, buf, (uint_t)buflen, XDR_ENCODE);
2860 nvs->nvs_private = xdr;
2861 return (0);
2862 case NVS_OP_DECODE:
2863 xdrmem_create(xdr, buf, (uint_t)buflen, XDR_DECODE);
2864 nvs->nvs_private = xdr;
2865 return (0);
2866 case NVS_OP_GETSIZE:
2867 nvs->nvs_private = NULL;
2868 return (0);
2869 default:
2870 return (EINVAL);
2871 }
2872 }
2873
2874 static void
2875 nvs_xdr_destroy(nvstream_t *nvs)
2876 {
2877 switch (nvs->nvs_op) {
2878 case NVS_OP_ENCODE:
2879 case NVS_OP_DECODE:
2880 xdr_destroy((XDR *)nvs->nvs_private);
2881 break;
2882 default:
2883 break;
2884 }
2885 }
2886
2887 static int
2888 nvs_xdr_nvlist(nvstream_t *nvs, nvlist_t *nvl, size_t *size)
2889 {
2890 switch (nvs->nvs_op) {
2891 case NVS_OP_ENCODE:
2892 case NVS_OP_DECODE: {
2893 XDR *xdr = nvs->nvs_private;
2894
2895 if (!xdr_int(xdr, &nvl->nvl_version) ||
2896 !xdr_u_int(xdr, &nvl->nvl_nvflag))
2897 return (EFAULT);
2898 break;
2899 }
2900 case NVS_OP_GETSIZE: {
2901 /*
2902 * 2 * 4 for nvl_version + nvl_nvflag
2903 * and 8 for end of the entire list
2904 */
2905 *size += 2 * 4 + 8;
2906 break;
2907 }
2908 default:
2909 return (EINVAL);
2910 }
2911 return (0);
2912 }
2913
2914 static int
2915 nvs_xdr_nvl_fini(nvstream_t *nvs)
2916 {
2917 if (nvs->nvs_op == NVS_OP_ENCODE) {
2918 XDR *xdr = nvs->nvs_private;
2919 int zero = 0;
2920
2921 if (!xdr_int(xdr, &zero) || !xdr_int(xdr, &zero))
2922 return (EFAULT);
2923 }
2924
2925 return (0);
2926 }
2927
2928 /*
2929 * The format of xdr encoded nvpair is:
2930 * encode_size, decode_size, name string, data type, nelem, data
2931 */
2932 static int
2933 nvs_xdr_nvp_op(nvstream_t *nvs, nvpair_t *nvp)
2934 {
2935 data_type_t type;
2936 char *buf;
2937 char *buf_end = (char *)nvp + nvp->nvp_size;
2938 int value_sz;
2939 uint_t nelem, buflen;
2940 bool_t ret = FALSE;
2941 XDR *xdr = nvs->nvs_private;
2942
2943 ASSERT(xdr != NULL && nvp != NULL);
2944
2945 /* name string */
2946 if ((buf = NVP_NAME(nvp)) >= buf_end)
2947 return (EFAULT);
2948 buflen = buf_end - buf;
2949
2950 if (!xdr_string(xdr, &buf, buflen - 1))
2951 return (EFAULT);
2952 nvp->nvp_name_sz = strlen(buf) + 1;
2953
2954 /* type and nelem */
2955 if (!xdr_int(xdr, (int *)&nvp->nvp_type) ||
2956 !xdr_int(xdr, &nvp->nvp_value_elem))
2957 return (EFAULT);
2958
2959 type = NVP_TYPE(nvp);
2960 nelem = nvp->nvp_value_elem;
2961
2962 /*
2963 * Verify type and nelem and get the value size.
2964 * In case of data types DATA_TYPE_STRING and DATA_TYPE_STRING_ARRAY
2965 * is the size of the string(s) excluded.
2966 */
2967 if ((value_sz = i_get_value_size(type, NULL, nelem)) < 0)
2968 return (EFAULT);
2969
2970 /* if there is no data to extract then return */
2971 if (nelem == 0)
2972 return (0);
2973
2974 /* value */
2975 if ((buf = NVP_VALUE(nvp)) >= buf_end)
2976 return (EFAULT);
2977 buflen = buf_end - buf;
2978
2979 if (buflen < value_sz)
2980 return (EFAULT);
2981
2982 switch (type) {
2983 case DATA_TYPE_NVLIST:
2984 if (nvs_embedded(nvs, (void *)buf) == 0)
2985 return (0);
2986 break;
2987
2988 case DATA_TYPE_NVLIST_ARRAY:
2989 if (nvs_embedded_nvl_array(nvs, nvp, NULL) == 0)
2990 return (0);
2991 break;
2992
2993 case DATA_TYPE_BOOLEAN:
2994 ret = TRUE;
2995 break;
2996
2997 case DATA_TYPE_BYTE:
2998 case DATA_TYPE_INT8:
2999 case DATA_TYPE_UINT8:
3000 ret = xdr_char(xdr, buf);
3001 break;
3002
3003 case DATA_TYPE_INT16:
3004 ret = xdr_short(xdr, (void *)buf);
3005 break;
3006
3007 case DATA_TYPE_UINT16:
3008 ret = xdr_u_short(xdr, (void *)buf);
3009 break;
3010
3011 case DATA_TYPE_BOOLEAN_VALUE:
3012 case DATA_TYPE_INT32:
3013 ret = xdr_int(xdr, (void *)buf);
3014 break;
3015
3016 case DATA_TYPE_UINT32:
3017 ret = xdr_u_int(xdr, (void *)buf);
3018 break;
3019
3020 case DATA_TYPE_INT64:
3021 ret = xdr_longlong_t(xdr, (void *)buf);
3022 break;
3023
3024 case DATA_TYPE_UINT64:
3025 ret = xdr_u_longlong_t(xdr, (void *)buf);
3026 break;
3027
3028 case DATA_TYPE_HRTIME:
3029 /*
3030 * NOTE: must expose the definition of hrtime_t here
3031 */
3032 ret = xdr_longlong_t(xdr, (void *)buf);
3033 break;
3034 #if !defined(_KERNEL)
3035 case DATA_TYPE_DOUBLE:
3036 ret = xdr_double(xdr, (void *)buf);
3037 break;
3038 #endif
3039 case DATA_TYPE_STRING:
3040 ret = xdr_string(xdr, &buf, buflen - 1);
3041 break;
3042
3043 case DATA_TYPE_BYTE_ARRAY:
3044 ret = xdr_opaque(xdr, buf, nelem);
3045 break;
3046
3047 case DATA_TYPE_INT8_ARRAY:
3048 case DATA_TYPE_UINT8_ARRAY:
3049 ret = xdr_array(xdr, &buf, &nelem, buflen, sizeof (int8_t),
3050 (xdrproc_t)xdr_char);
3051 break;
3052
3053 case DATA_TYPE_INT16_ARRAY:
3054 ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (int16_t),
3055 sizeof (int16_t), (xdrproc_t)xdr_short);
3056 break;
3057
3058 case DATA_TYPE_UINT16_ARRAY:
3059 ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (uint16_t),
3060 sizeof (uint16_t), (xdrproc_t)xdr_u_short);
3061 break;
3062
3063 case DATA_TYPE_BOOLEAN_ARRAY:
3064 case DATA_TYPE_INT32_ARRAY:
3065 ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (int32_t),
3066 sizeof (int32_t), (xdrproc_t)xdr_int);
3067 break;
3068
3069 case DATA_TYPE_UINT32_ARRAY:
3070 ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (uint32_t),
3071 sizeof (uint32_t), (xdrproc_t)xdr_u_int);
3072 break;
3073
3074 case DATA_TYPE_INT64_ARRAY:
3075 ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (int64_t),
3076 sizeof (int64_t), (xdrproc_t)xdr_longlong_t);
3077 break;
3078
3079 case DATA_TYPE_UINT64_ARRAY:
3080 ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (uint64_t),
3081 sizeof (uint64_t), (xdrproc_t)xdr_u_longlong_t);
3082 break;
3083
3084 case DATA_TYPE_STRING_ARRAY: {
3085 size_t len = nelem * sizeof (uint64_t);
3086 char **strp = (void *)buf;
3087 int i;
3088
3089 if (nvs->nvs_op == NVS_OP_DECODE)
3090 bzero(buf, len); /* don't trust packed data */
3091
3092 for (i = 0; i < nelem; i++) {
3093 if (buflen <= len)
3094 return (EFAULT);
3095
3096 buf += len;
3097 buflen -= len;
3098
3099 if (xdr_string(xdr, &buf, buflen - 1) != TRUE)
3100 return (EFAULT);
3101
3102 if (nvs->nvs_op == NVS_OP_DECODE)
3103 strp[i] = buf;
3104 len = strlen(buf) + 1;
3105 }
3106 ret = TRUE;
3107 break;
3108 }
3109 default:
3110 break;
3111 }
3112
3113 return (ret == TRUE ? 0 : EFAULT);
3114 }
3115
3116 static int
3117 nvs_xdr_nvp_size(nvstream_t *nvs, nvpair_t *nvp, size_t *size)
3118 {
3119 data_type_t type = NVP_TYPE(nvp);
3120 /*
3121 * encode_size + decode_size + name string size + data type + nelem
3122 * where name string size = 4 + NV_ALIGN4(strlen(NVP_NAME(nvp)))
3123 */
3124 uint64_t nvp_sz = 4 + 4 + 4 + NV_ALIGN4(strlen(NVP_NAME(nvp))) + 4 + 4;
3125
3126 switch (type) {
3127 case DATA_TYPE_BOOLEAN:
3128 break;
3129
3130 case DATA_TYPE_BOOLEAN_VALUE:
3131 case DATA_TYPE_BYTE:
3132 case DATA_TYPE_INT8:
3133 case DATA_TYPE_UINT8:
3134 case DATA_TYPE_INT16:
3135 case DATA_TYPE_UINT16:
3136 case DATA_TYPE_INT32:
3137 case DATA_TYPE_UINT32:
3138 nvp_sz += 4; /* 4 is the minimum xdr unit */
3139 break;
3140
3141 case DATA_TYPE_INT64:
3142 case DATA_TYPE_UINT64:
3143 case DATA_TYPE_HRTIME:
3144 #if !defined(_KERNEL)
3145 case DATA_TYPE_DOUBLE:
3146 #endif
3147 nvp_sz += 8;
3148 break;
3149
3150 case DATA_TYPE_STRING:
3151 nvp_sz += 4 + NV_ALIGN4(strlen((char *)NVP_VALUE(nvp)));
3152 break;
3153
3154 case DATA_TYPE_BYTE_ARRAY:
3155 nvp_sz += NV_ALIGN4(NVP_NELEM(nvp));
3156 break;
3157
3158 case DATA_TYPE_BOOLEAN_ARRAY:
3159 case DATA_TYPE_INT8_ARRAY:
3160 case DATA_TYPE_UINT8_ARRAY:
3161 case DATA_TYPE_INT16_ARRAY:
3162 case DATA_TYPE_UINT16_ARRAY:
3163 case DATA_TYPE_INT32_ARRAY:
3164 case DATA_TYPE_UINT32_ARRAY:
3165 nvp_sz += 4 + 4 * (uint64_t)NVP_NELEM(nvp);
3166 break;
3167
3168 case DATA_TYPE_INT64_ARRAY:
3169 case DATA_TYPE_UINT64_ARRAY:
3170 nvp_sz += 4 + 8 * (uint64_t)NVP_NELEM(nvp);
3171 break;
3172
3173 case DATA_TYPE_STRING_ARRAY: {
3174 int i;
3175 char **strs = (void *)NVP_VALUE(nvp);
3176
3177 for (i = 0; i < NVP_NELEM(nvp); i++)
3178 nvp_sz += 4 + NV_ALIGN4(strlen(strs[i]));
3179
3180 break;
3181 }
3182
3183 case DATA_TYPE_NVLIST:
3184 case DATA_TYPE_NVLIST_ARRAY: {
3185 size_t nvsize = 0;
3186 int old_nvs_op = nvs->nvs_op;
3187 int err;
3188
3189 nvs->nvs_op = NVS_OP_GETSIZE;
3190 if (type == DATA_TYPE_NVLIST)
3191 err = nvs_operation(nvs, EMBEDDED_NVL(nvp), &nvsize);
3192 else
3193 err = nvs_embedded_nvl_array(nvs, nvp, &nvsize);
3194 nvs->nvs_op = old_nvs_op;
3195
3196 if (err != 0)
3197 return (EINVAL);
3198
3199 nvp_sz += nvsize;
3200 break;
3201 }
3202
3203 default:
3204 return (EINVAL);
3205 }
3206
3207 if (nvp_sz > INT32_MAX)
3208 return (EINVAL);
3209
3210 *size = nvp_sz;
3211
3212 return (0);
3213 }
3214
3215
3216 /*
3217 * The NVS_XDR_MAX_LEN macro takes a packed xdr buffer of size x and estimates
3218 * the largest nvpair that could be encoded in the buffer.
3219 *
3220 * See comments above nvpair_xdr_op() for the format of xdr encoding.
3221 * The size of a xdr packed nvpair without any data is 5 words.
3222 *
3223 * Using the size of the data directly as an estimate would be ok
3224 * in all cases except one. If the data type is of DATA_TYPE_STRING_ARRAY
3225 * then the actual nvpair has space for an array of pointers to index
3226 * the strings. These pointers are not encoded into the packed xdr buffer.
3227 *
3228 * If the data is of type DATA_TYPE_STRING_ARRAY and all the strings are
3229 * of length 0, then each string is endcoded in xdr format as a single word.
3230 * Therefore when expanded to an nvpair there will be 2.25 word used for
3231 * each string. (a int64_t allocated for pointer usage, and a single char
3232 * for the null termination.)
3233 *
3234 * This is the calculation performed by the NVS_XDR_MAX_LEN macro.
3235 */
3236 #define NVS_XDR_HDR_LEN ((size_t)(5 * 4))
3237 #define NVS_XDR_DATA_LEN(y) (((size_t)(y) <= NVS_XDR_HDR_LEN) ? \
3238 0 : ((size_t)(y) - NVS_XDR_HDR_LEN))
3239 #define NVS_XDR_MAX_LEN(x) (NVP_SIZE_CALC(1, 0) + \
3240 (NVS_XDR_DATA_LEN(x) * 2) + \
3241 NV_ALIGN4((NVS_XDR_DATA_LEN(x) / 4)))
3242
3243 static int
3244 nvs_xdr_nvpair(nvstream_t *nvs, nvpair_t *nvp, size_t *size)
3245 {
3246 XDR *xdr = nvs->nvs_private;
3247 int32_t encode_len, decode_len;
3248
3249 switch (nvs->nvs_op) {
3250 case NVS_OP_ENCODE: {
3251 size_t nvsize;
3252
3253 if (nvs_xdr_nvp_size(nvs, nvp, &nvsize) != 0)
3254 return (EFAULT);
3255
3256 decode_len = nvp->nvp_size;
3257 encode_len = nvsize;
3258 if (!xdr_int(xdr, &encode_len) || !xdr_int(xdr, &decode_len))
3259 return (EFAULT);
3260
3261 return (nvs_xdr_nvp_op(nvs, nvp));
3262 }
3263 case NVS_OP_DECODE: {
3264 struct xdr_bytesrec bytesrec;
3265
3266 /* get the encode and decode size */
3267 if (!xdr_int(xdr, &encode_len) || !xdr_int(xdr, &decode_len))
3268 return (EFAULT);
3269 *size = decode_len;
3270
3271 /* are we at the end of the stream? */
3272 if (*size == 0)
3273 return (0);
3274
3275 /* sanity check the size parameter */
3276 if (!xdr_control(xdr, XDR_GET_BYTES_AVAIL, &bytesrec))
3277 return (EFAULT);
3278
3279 if (*size > NVS_XDR_MAX_LEN(bytesrec.xc_num_avail))
3280 return (EFAULT);
3281 break;
3282 }
3283
3284 default:
3285 return (EINVAL);
3286 }
3287 return (0);
3288 }
3289
3290 static const struct nvs_ops nvs_xdr_ops = {
3291 .nvs_nvlist = nvs_xdr_nvlist,
3292 .nvs_nvpair = nvs_xdr_nvpair,
3293 .nvs_nvp_op = nvs_xdr_nvp_op,
3294 .nvs_nvp_size = nvs_xdr_nvp_size,
3295 .nvs_nvl_fini = nvs_xdr_nvl_fini
3296 };
3297
3298 static int
3299 nvs_xdr(nvstream_t *nvs, nvlist_t *nvl, char *buf, size_t *buflen)
3300 {
3301 XDR xdr;
3302 int err;
3303
3304 nvs->nvs_ops = &nvs_xdr_ops;
3305
3306 if ((err = nvs_xdr_create(nvs, &xdr, buf + sizeof (nvs_header_t),
3307 *buflen - sizeof (nvs_header_t))) != 0)
3308 return (err);
3309
3310 err = nvs_operation(nvs, nvl, buflen);
3311
3312 nvs_xdr_destroy(nvs);
3313
3314 return (err);
3315 }
3316
3317 #if defined(_KERNEL) && defined(HAVE_SPL)
3318 static int __init
3319 nvpair_init(void)
3320 {
3321 return (0);
3322 }
3323
3324 static void __exit
3325 nvpair_fini(void)
3326 {
3327 }
3328
3329 module_init(nvpair_init);
3330 module_exit(nvpair_fini);
3331
3332 MODULE_DESCRIPTION("Generic name/value pair implementation");
3333 MODULE_AUTHOR(ZFS_META_AUTHOR);
3334 MODULE_LICENSE(ZFS_META_LICENSE);
3335 MODULE_VERSION(ZFS_META_VERSION "-" ZFS_META_RELEASE);
3336
3337 EXPORT_SYMBOL(nv_alloc_init);
3338 EXPORT_SYMBOL(nv_alloc_reset);
3339 EXPORT_SYMBOL(nv_alloc_fini);
3340
3341 /* list management */
3342 EXPORT_SYMBOL(nvlist_alloc);
3343 EXPORT_SYMBOL(nvlist_free);
3344 EXPORT_SYMBOL(nvlist_size);
3345 EXPORT_SYMBOL(nvlist_pack);
3346 EXPORT_SYMBOL(nvlist_unpack);
3347 EXPORT_SYMBOL(nvlist_dup);
3348 EXPORT_SYMBOL(nvlist_merge);
3349
3350 EXPORT_SYMBOL(nvlist_xalloc);
3351 EXPORT_SYMBOL(nvlist_xpack);
3352 EXPORT_SYMBOL(nvlist_xunpack);
3353 EXPORT_SYMBOL(nvlist_xdup);
3354 EXPORT_SYMBOL(nvlist_lookup_nv_alloc);
3355
3356 EXPORT_SYMBOL(nvlist_add_nvpair);
3357 EXPORT_SYMBOL(nvlist_add_boolean);
3358 EXPORT_SYMBOL(nvlist_add_boolean_value);
3359 EXPORT_SYMBOL(nvlist_add_byte);
3360 EXPORT_SYMBOL(nvlist_add_int8);
3361 EXPORT_SYMBOL(nvlist_add_uint8);
3362 EXPORT_SYMBOL(nvlist_add_int16);
3363 EXPORT_SYMBOL(nvlist_add_uint16);
3364 EXPORT_SYMBOL(nvlist_add_int32);
3365 EXPORT_SYMBOL(nvlist_add_uint32);
3366 EXPORT_SYMBOL(nvlist_add_int64);
3367 EXPORT_SYMBOL(nvlist_add_uint64);
3368 EXPORT_SYMBOL(nvlist_add_string);
3369 EXPORT_SYMBOL(nvlist_add_nvlist);
3370 EXPORT_SYMBOL(nvlist_add_boolean_array);
3371 EXPORT_SYMBOL(nvlist_add_byte_array);
3372 EXPORT_SYMBOL(nvlist_add_int8_array);
3373 EXPORT_SYMBOL(nvlist_add_uint8_array);
3374 EXPORT_SYMBOL(nvlist_add_int16_array);
3375 EXPORT_SYMBOL(nvlist_add_uint16_array);
3376 EXPORT_SYMBOL(nvlist_add_int32_array);
3377 EXPORT_SYMBOL(nvlist_add_uint32_array);
3378 EXPORT_SYMBOL(nvlist_add_int64_array);
3379 EXPORT_SYMBOL(nvlist_add_uint64_array);
3380 EXPORT_SYMBOL(nvlist_add_string_array);
3381 EXPORT_SYMBOL(nvlist_add_nvlist_array);
3382 EXPORT_SYMBOL(nvlist_next_nvpair);
3383 EXPORT_SYMBOL(nvlist_prev_nvpair);
3384 EXPORT_SYMBOL(nvlist_empty);
3385 EXPORT_SYMBOL(nvlist_add_hrtime);
3386
3387 EXPORT_SYMBOL(nvlist_remove);
3388 EXPORT_SYMBOL(nvlist_remove_nvpair);
3389 EXPORT_SYMBOL(nvlist_remove_all);
3390
3391 EXPORT_SYMBOL(nvlist_lookup_boolean);
3392 EXPORT_SYMBOL(nvlist_lookup_boolean_value);
3393 EXPORT_SYMBOL(nvlist_lookup_byte);
3394 EXPORT_SYMBOL(nvlist_lookup_int8);
3395 EXPORT_SYMBOL(nvlist_lookup_uint8);
3396 EXPORT_SYMBOL(nvlist_lookup_int16);
3397 EXPORT_SYMBOL(nvlist_lookup_uint16);
3398 EXPORT_SYMBOL(nvlist_lookup_int32);
3399 EXPORT_SYMBOL(nvlist_lookup_uint32);
3400 EXPORT_SYMBOL(nvlist_lookup_int64);
3401 EXPORT_SYMBOL(nvlist_lookup_uint64);
3402 EXPORT_SYMBOL(nvlist_lookup_string);
3403 EXPORT_SYMBOL(nvlist_lookup_nvlist);
3404 EXPORT_SYMBOL(nvlist_lookup_boolean_array);
3405 EXPORT_SYMBOL(nvlist_lookup_byte_array);
3406 EXPORT_SYMBOL(nvlist_lookup_int8_array);
3407 EXPORT_SYMBOL(nvlist_lookup_uint8_array);
3408 EXPORT_SYMBOL(nvlist_lookup_int16_array);
3409 EXPORT_SYMBOL(nvlist_lookup_uint16_array);
3410 EXPORT_SYMBOL(nvlist_lookup_int32_array);
3411 EXPORT_SYMBOL(nvlist_lookup_uint32_array);
3412 EXPORT_SYMBOL(nvlist_lookup_int64_array);
3413 EXPORT_SYMBOL(nvlist_lookup_uint64_array);
3414 EXPORT_SYMBOL(nvlist_lookup_string_array);
3415 EXPORT_SYMBOL(nvlist_lookup_nvlist_array);
3416 EXPORT_SYMBOL(nvlist_lookup_hrtime);
3417 EXPORT_SYMBOL(nvlist_lookup_pairs);
3418
3419 EXPORT_SYMBOL(nvlist_lookup_nvpair);
3420 EXPORT_SYMBOL(nvlist_exists);
3421
3422 /* processing nvpair */
3423 EXPORT_SYMBOL(nvpair_name);
3424 EXPORT_SYMBOL(nvpair_type);
3425 EXPORT_SYMBOL(nvpair_value_boolean_value);
3426 EXPORT_SYMBOL(nvpair_value_byte);
3427 EXPORT_SYMBOL(nvpair_value_int8);
3428 EXPORT_SYMBOL(nvpair_value_uint8);
3429 EXPORT_SYMBOL(nvpair_value_int16);
3430 EXPORT_SYMBOL(nvpair_value_uint16);
3431 EXPORT_SYMBOL(nvpair_value_int32);
3432 EXPORT_SYMBOL(nvpair_value_uint32);
3433 EXPORT_SYMBOL(nvpair_value_int64);
3434 EXPORT_SYMBOL(nvpair_value_uint64);
3435 EXPORT_SYMBOL(nvpair_value_string);
3436 EXPORT_SYMBOL(nvpair_value_nvlist);
3437 EXPORT_SYMBOL(nvpair_value_boolean_array);
3438 EXPORT_SYMBOL(nvpair_value_byte_array);
3439 EXPORT_SYMBOL(nvpair_value_int8_array);
3440 EXPORT_SYMBOL(nvpair_value_uint8_array);
3441 EXPORT_SYMBOL(nvpair_value_int16_array);
3442 EXPORT_SYMBOL(nvpair_value_uint16_array);
3443 EXPORT_SYMBOL(nvpair_value_int32_array);
3444 EXPORT_SYMBOL(nvpair_value_uint32_array);
3445 EXPORT_SYMBOL(nvpair_value_int64_array);
3446 EXPORT_SYMBOL(nvpair_value_uint64_array);
3447 EXPORT_SYMBOL(nvpair_value_string_array);
3448 EXPORT_SYMBOL(nvpair_value_nvlist_array);
3449 EXPORT_SYMBOL(nvpair_value_hrtime);
3450
3451 #endif