]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/cddl/contrib/opensolaris/common/nvpair/opensolaris_nvpair.c
MFV r337220: 8375 Kernel memory leak in nvpair code
[FreeBSD/FreeBSD.git] / sys / cddl / contrib / opensolaris / common / nvpair / opensolaris_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, 2017 by Delphix. All rights reserved.
25  */
26
27 #include <sys/debug.h>
28 #include <sys/nvpair.h>
29 #include <sys/nvpair_impl.h>
30 #include <rpc/types.h>
31 #include <rpc/xdr.h>
32
33 #if defined(_KERNEL) && !defined(_BOOT)
34 #include <sys/varargs.h>
35 #include <sys/sunddi.h>
36 #else
37 #include <stdarg.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <strings.h>
41 #endif
42
43 #ifndef offsetof
44 #define offsetof(s, m)          ((size_t)(&(((s *)0)->m)))
45 #endif
46 #define skip_whitespace(p)      while ((*(p) == ' ') || (*(p) == '\t')) p++
47
48 #if defined(__FreeBSD__) && !defined(_KERNEL)
49 /*
50  * libnvpair is the lowest commen denominator for ZFS related libraries,
51  * defining aok here makes it usable by all ZFS related libraries
52  */
53 int aok;
54 #endif
55
56 /*
57  * nvpair.c - Provides kernel & userland interfaces for manipulating
58  *      name-value pairs.
59  *
60  * Overview Diagram
61  *
62  *  +--------------+
63  *  |  nvlist_t    |
64  *  |--------------|
65  *  | nvl_version  |
66  *  | nvl_nvflag   |
67  *  | nvl_priv    -+-+
68  *  | nvl_flag     | |
69  *  | nvl_pad      | |
70  *  +--------------+ |
71  *                   V
72  *      +--------------+      last i_nvp in list
73  *      | nvpriv_t     |  +--------------------->
74  *      |--------------|  |
75  *   +--+- nvp_list    |  |   +------------+
76  *   |  |  nvp_last   -+--+   + nv_alloc_t |
77  *   |  |  nvp_curr    |      |------------|
78  *   |  |  nvp_nva    -+----> | nva_ops    |
79  *   |  |  nvp_stat    |      | nva_arg    |
80  *   |  +--------------+      +------------+
81  *   |
82  *   +-------+
83  *           V
84  *   +---------------------+      +-------------------+
85  *   |  i_nvp_t            |  +-->|  i_nvp_t          |  +-->
86  *   |---------------------|  |   |-------------------|  |
87  *   | nvi_next           -+--+   | nvi_next         -+--+
88  *   | nvi_prev (NULL)     | <----+ nvi_prev          |
89  *   | . . . . . . . . . . |      | . . . . . . . . . |
90  *   | nvp (nvpair_t)      |      | nvp (nvpair_t)    |
91  *   |  - nvp_size         |      |  - nvp_size       |
92  *   |  - nvp_name_sz      |      |  - nvp_name_sz    |
93  *   |  - nvp_value_elem   |      |  - nvp_value_elem |
94  *   |  - nvp_type         |      |  - nvp_type       |
95  *   |  - data ...         |      |  - data ...       |
96  *   +---------------------+      +-------------------+
97  *
98  *
99  *
100  *   +---------------------+              +---------------------+
101  *   |  i_nvp_t            |  +-->    +-->|  i_nvp_t (last)     |
102  *   |---------------------|  |       |   |---------------------|
103  *   |  nvi_next          -+--+ ... --+   | nvi_next (NULL)     |
104  * <-+- nvi_prev           |<-- ...  <----+ nvi_prev            |
105  *   | . . . . . . . . .   |              | . . . . . . . . .   |
106  *   | nvp (nvpair_t)      |              | nvp (nvpair_t)      |
107  *   |  - nvp_size         |              |  - nvp_size         |
108  *   |  - nvp_name_sz      |              |  - nvp_name_sz      |
109  *   |  - nvp_value_elem   |              |  - nvp_value_elem   |
110  *   |  - DATA_TYPE_NVLIST |              |  - nvp_type         |
111  *   |  - data (embedded)  |              |  - data ...         |
112  *   |    nvlist name      |              +---------------------+
113  *   |  +--------------+   |
114  *   |  |  nvlist_t    |   |
115  *   |  |--------------|   |
116  *   |  | nvl_version  |   |
117  *   |  | nvl_nvflag   |   |
118  *   |  | nvl_priv   --+---+---->
119  *   |  | nvl_flag     |   |
120  *   |  | nvl_pad      |   |
121  *   |  +--------------+   |
122  *   +---------------------+
123  *
124  *
125  * N.B. nvpair_t may be aligned on 4 byte boundary, so +4 will
126  * allow value to be aligned on 8 byte boundary
127  *
128  * name_len is the length of the name string including the null terminator
129  * so it must be >= 1
130  */
131 #define NVP_SIZE_CALC(name_len, data_len) \
132         (NV_ALIGN((sizeof (nvpair_t)) + name_len) + NV_ALIGN(data_len))
133
134 static int i_get_value_size(data_type_t type, const void *data, uint_t nelem);
135 static int nvlist_add_common(nvlist_t *nvl, const char *name, data_type_t type,
136     uint_t nelem, const void *data);
137
138 #define NV_STAT_EMBEDDED        0x1
139 #define EMBEDDED_NVL(nvp)       ((nvlist_t *)(void *)NVP_VALUE(nvp))
140 #define EMBEDDED_NVL_ARRAY(nvp) ((nvlist_t **)(void *)NVP_VALUE(nvp))
141
142 #define NVP_VALOFF(nvp) (NV_ALIGN(sizeof (nvpair_t) + (nvp)->nvp_name_sz))
143 #define NVPAIR2I_NVP(nvp) \
144         ((i_nvp_t *)((size_t)(nvp) - offsetof(i_nvp_t, nvi_nvp)))
145
146 #ifdef _KERNEL
147 int nvpair_max_recursion = 20;
148 #else
149 int nvpair_max_recursion = 100;
150 #endif
151
152 int
153 nv_alloc_init(nv_alloc_t *nva, const nv_alloc_ops_t *nvo, /* args */ ...)
154 {
155         va_list valist;
156         int err = 0;
157
158         nva->nva_ops = nvo;
159         nva->nva_arg = NULL;
160
161         va_start(valist, nvo);
162         if (nva->nva_ops->nv_ao_init != NULL)
163                 err = nva->nva_ops->nv_ao_init(nva, valist);
164         va_end(valist);
165
166         return (err);
167 }
168
169 void
170 nv_alloc_reset(nv_alloc_t *nva)
171 {
172         if (nva->nva_ops->nv_ao_reset != NULL)
173                 nva->nva_ops->nv_ao_reset(nva);
174 }
175
176 void
177 nv_alloc_fini(nv_alloc_t *nva)
178 {
179         if (nva->nva_ops->nv_ao_fini != NULL)
180                 nva->nva_ops->nv_ao_fini(nva);
181 }
182
183 nv_alloc_t *
184 nvlist_lookup_nv_alloc(nvlist_t *nvl)
185 {
186         nvpriv_t *priv;
187
188         if (nvl == NULL ||
189             (priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL)
190                 return (NULL);
191
192         return (priv->nvp_nva);
193 }
194
195 static void *
196 nv_mem_zalloc(nvpriv_t *nvp, size_t size)
197 {
198         nv_alloc_t *nva = nvp->nvp_nva;
199         void *buf;
200
201         if ((buf = nva->nva_ops->nv_ao_alloc(nva, size)) != NULL)
202                 bzero(buf, size);
203
204         return (buf);
205 }
206
207 static void
208 nv_mem_free(nvpriv_t *nvp, void *buf, size_t size)
209 {
210         nv_alloc_t *nva = nvp->nvp_nva;
211
212         nva->nva_ops->nv_ao_free(nva, buf, size);
213 }
214
215 static void
216 nv_priv_init(nvpriv_t *priv, nv_alloc_t *nva, uint32_t stat)
217 {
218         bzero(priv, sizeof (nvpriv_t));
219
220         priv->nvp_nva = nva;
221         priv->nvp_stat = stat;
222 }
223
224 static nvpriv_t *
225 nv_priv_alloc(nv_alloc_t *nva)
226 {
227         nvpriv_t *priv;
228
229         /*
230          * nv_mem_alloc() cannot called here because it needs the priv
231          * argument.
232          */
233         if ((priv = nva->nva_ops->nv_ao_alloc(nva, sizeof (nvpriv_t))) == NULL)
234                 return (NULL);
235
236         nv_priv_init(priv, nva, 0);
237
238         return (priv);
239 }
240
241 /*
242  * Embedded lists need their own nvpriv_t's.  We create a new
243  * nvpriv_t using the parameters and allocator from the parent
244  * list's nvpriv_t.
245  */
246 static nvpriv_t *
247 nv_priv_alloc_embedded(nvpriv_t *priv)
248 {
249         nvpriv_t *emb_priv;
250
251         if ((emb_priv = nv_mem_zalloc(priv, sizeof (nvpriv_t))) == NULL)
252                 return (NULL);
253
254         nv_priv_init(emb_priv, priv->nvp_nva, NV_STAT_EMBEDDED);
255
256         return (emb_priv);
257 }
258
259 static void
260 nvlist_init(nvlist_t *nvl, uint32_t nvflag, nvpriv_t *priv)
261 {
262         nvl->nvl_version = NV_VERSION;
263         nvl->nvl_nvflag = nvflag & (NV_UNIQUE_NAME|NV_UNIQUE_NAME_TYPE);
264         nvl->nvl_priv = (uint64_t)(uintptr_t)priv;
265         nvl->nvl_flag = 0;
266         nvl->nvl_pad = 0;
267 }
268
269 uint_t
270 nvlist_nvflag(nvlist_t *nvl)
271 {
272         return (nvl->nvl_nvflag);
273 }
274
275 /*
276  * nvlist_alloc - Allocate nvlist.
277  */
278 /*ARGSUSED1*/
279 int
280 nvlist_alloc(nvlist_t **nvlp, uint_t nvflag, int kmflag)
281 {
282 #if defined(_KERNEL) && !defined(_BOOT)
283         return (nvlist_xalloc(nvlp, nvflag,
284             (kmflag == KM_SLEEP ? nv_alloc_sleep : nv_alloc_nosleep)));
285 #else
286         return (nvlist_xalloc(nvlp, nvflag, nv_alloc_nosleep));
287 #endif
288 }
289
290 int
291 nvlist_xalloc(nvlist_t **nvlp, uint_t nvflag, nv_alloc_t *nva)
292 {
293         nvpriv_t *priv;
294
295         if (nvlp == NULL || nva == NULL)
296                 return (EINVAL);
297
298         if ((priv = nv_priv_alloc(nva)) == NULL)
299                 return (ENOMEM);
300
301         if ((*nvlp = nv_mem_zalloc(priv,
302             NV_ALIGN(sizeof (nvlist_t)))) == NULL) {
303                 nv_mem_free(priv, priv, sizeof (nvpriv_t));
304                 return (ENOMEM);
305         }
306
307         nvlist_init(*nvlp, nvflag, priv);
308
309         return (0);
310 }
311
312 /*
313  * nvp_buf_alloc - Allocate i_nvp_t for storing a new nv pair.
314  */
315 static nvpair_t *
316 nvp_buf_alloc(nvlist_t *nvl, size_t len)
317 {
318         nvpriv_t *priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv;
319         i_nvp_t *buf;
320         nvpair_t *nvp;
321         size_t nvsize;
322
323         /*
324          * Allocate the buffer
325          */
326         nvsize = len + offsetof(i_nvp_t, nvi_nvp);
327
328         if ((buf = nv_mem_zalloc(priv, nvsize)) == NULL)
329                 return (NULL);
330
331         nvp = &buf->nvi_nvp;
332         nvp->nvp_size = len;
333
334         return (nvp);
335 }
336
337 /*
338  * nvp_buf_free - de-Allocate an i_nvp_t.
339  */
340 static void
341 nvp_buf_free(nvlist_t *nvl, nvpair_t *nvp)
342 {
343         nvpriv_t *priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv;
344         size_t nvsize = nvp->nvp_size + offsetof(i_nvp_t, nvi_nvp);
345
346         nv_mem_free(priv, NVPAIR2I_NVP(nvp), nvsize);
347 }
348
349 /*
350  * nvp_buf_link - link a new nv pair into the nvlist.
351  */
352 static void
353 nvp_buf_link(nvlist_t *nvl, nvpair_t *nvp)
354 {
355         nvpriv_t *priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv;
356         i_nvp_t *curr = NVPAIR2I_NVP(nvp);
357
358         /* Put element at end of nvlist */
359         if (priv->nvp_list == NULL) {
360                 priv->nvp_list = priv->nvp_last = curr;
361         } else {
362                 curr->nvi_prev = priv->nvp_last;
363                 priv->nvp_last->nvi_next = curr;
364                 priv->nvp_last = curr;
365         }
366 }
367
368 /*
369  * nvp_buf_unlink - unlink an removed nvpair out of the nvlist.
370  */
371 static void
372 nvp_buf_unlink(nvlist_t *nvl, nvpair_t *nvp)
373 {
374         nvpriv_t *priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv;
375         i_nvp_t *curr = NVPAIR2I_NVP(nvp);
376
377         /*
378          * protect nvlist_next_nvpair() against walking on freed memory.
379          */
380         if (priv->nvp_curr == curr)
381                 priv->nvp_curr = curr->nvi_next;
382
383         if (curr == priv->nvp_list)
384                 priv->nvp_list = curr->nvi_next;
385         else
386                 curr->nvi_prev->nvi_next = curr->nvi_next;
387
388         if (curr == priv->nvp_last)
389                 priv->nvp_last = curr->nvi_prev;
390         else
391                 curr->nvi_next->nvi_prev = curr->nvi_prev;
392 }
393
394 /*
395  * take a nvpair type and number of elements and make sure the are valid
396  */
397 static int
398 i_validate_type_nelem(data_type_t type, uint_t nelem)
399 {
400         switch (type) {
401         case DATA_TYPE_BOOLEAN:
402                 if (nelem != 0)
403                         return (EINVAL);
404                 break;
405         case DATA_TYPE_BOOLEAN_VALUE:
406         case DATA_TYPE_BYTE:
407         case DATA_TYPE_INT8:
408         case DATA_TYPE_UINT8:
409         case DATA_TYPE_INT16:
410         case DATA_TYPE_UINT16:
411         case DATA_TYPE_INT32:
412         case DATA_TYPE_UINT32:
413         case DATA_TYPE_INT64:
414         case DATA_TYPE_UINT64:
415         case DATA_TYPE_STRING:
416         case DATA_TYPE_HRTIME:
417         case DATA_TYPE_NVLIST:
418 #if !defined(_KERNEL)
419         case DATA_TYPE_DOUBLE:
420 #endif
421                 if (nelem != 1)
422                         return (EINVAL);
423                 break;
424         case DATA_TYPE_BOOLEAN_ARRAY:
425         case DATA_TYPE_BYTE_ARRAY:
426         case DATA_TYPE_INT8_ARRAY:
427         case DATA_TYPE_UINT8_ARRAY:
428         case DATA_TYPE_INT16_ARRAY:
429         case DATA_TYPE_UINT16_ARRAY:
430         case DATA_TYPE_INT32_ARRAY:
431         case DATA_TYPE_UINT32_ARRAY:
432         case DATA_TYPE_INT64_ARRAY:
433         case DATA_TYPE_UINT64_ARRAY:
434         case DATA_TYPE_STRING_ARRAY:
435         case DATA_TYPE_NVLIST_ARRAY:
436                 /* we allow arrays with 0 elements */
437                 break;
438         default:
439                 return (EINVAL);
440         }
441         return (0);
442 }
443
444 /*
445  * Verify nvp_name_sz and check the name string length.
446  */
447 static int
448 i_validate_nvpair_name(nvpair_t *nvp)
449 {
450         if ((nvp->nvp_name_sz <= 0) ||
451             (nvp->nvp_size < NVP_SIZE_CALC(nvp->nvp_name_sz, 0)))
452                 return (EFAULT);
453
454         /* verify the name string, make sure its terminated */
455         if (NVP_NAME(nvp)[nvp->nvp_name_sz - 1] != '\0')
456                 return (EFAULT);
457
458         return (strlen(NVP_NAME(nvp)) == nvp->nvp_name_sz - 1 ? 0 : EFAULT);
459 }
460
461 static int
462 i_validate_nvpair_value(data_type_t type, uint_t nelem, const void *data)
463 {
464         switch (type) {
465         case DATA_TYPE_BOOLEAN_VALUE:
466                 if (*(boolean_t *)data != B_TRUE &&
467                     *(boolean_t *)data != B_FALSE)
468                         return (EINVAL);
469                 break;
470         case DATA_TYPE_BOOLEAN_ARRAY: {
471                 int i;
472
473                 for (i = 0; i < nelem; i++)
474                         if (((boolean_t *)data)[i] != B_TRUE &&
475                             ((boolean_t *)data)[i] != B_FALSE)
476                                 return (EINVAL);
477                 break;
478         }
479         default:
480                 break;
481         }
482
483         return (0);
484 }
485
486 /*
487  * This function takes a pointer to what should be a nvpair and it's size
488  * and then verifies that all the nvpair fields make sense and can be
489  * trusted.  This function is used when decoding packed nvpairs.
490  */
491 static int
492 i_validate_nvpair(nvpair_t *nvp)
493 {
494         data_type_t type = NVP_TYPE(nvp);
495         int size1, size2;
496
497         /* verify nvp_name_sz, check the name string length */
498         if (i_validate_nvpair_name(nvp) != 0)
499                 return (EFAULT);
500
501         if (i_validate_nvpair_value(type, NVP_NELEM(nvp), NVP_VALUE(nvp)) != 0)
502                 return (EFAULT);
503
504         /*
505          * verify nvp_type, nvp_value_elem, and also possibly
506          * verify string values and get the value size.
507          */
508         size2 = i_get_value_size(type, NVP_VALUE(nvp), NVP_NELEM(nvp));
509         size1 = nvp->nvp_size - NVP_VALOFF(nvp);
510         if (size2 < 0 || size1 != NV_ALIGN(size2))
511                 return (EFAULT);
512
513         return (0);
514 }
515
516 static int
517 nvlist_copy_pairs(nvlist_t *snvl, nvlist_t *dnvl)
518 {
519         nvpriv_t *priv;
520         i_nvp_t *curr;
521
522         if ((priv = (nvpriv_t *)(uintptr_t)snvl->nvl_priv) == NULL)
523                 return (EINVAL);
524
525         for (curr = priv->nvp_list; curr != NULL; curr = curr->nvi_next) {
526                 nvpair_t *nvp = &curr->nvi_nvp;
527                 int err;
528
529                 if ((err = nvlist_add_common(dnvl, NVP_NAME(nvp), NVP_TYPE(nvp),
530                     NVP_NELEM(nvp), NVP_VALUE(nvp))) != 0)
531                         return (err);
532         }
533
534         return (0);
535 }
536
537 /*
538  * Frees all memory allocated for an nvpair (like embedded lists) with
539  * the exception of the nvpair buffer itself.
540  */
541 static void
542 nvpair_free(nvpair_t *nvp)
543 {
544         switch (NVP_TYPE(nvp)) {
545         case DATA_TYPE_NVLIST:
546                 nvlist_free(EMBEDDED_NVL(nvp));
547                 break;
548         case DATA_TYPE_NVLIST_ARRAY: {
549                 nvlist_t **nvlp = EMBEDDED_NVL_ARRAY(nvp);
550                 int i;
551
552                 for (i = 0; i < NVP_NELEM(nvp); i++)
553                         nvlist_free(nvlp[i]);
554                 break;
555         }
556         default:
557                 break;
558         }
559 }
560
561 /*
562  * nvlist_free - free an unpacked nvlist
563  */
564 void
565 nvlist_free(nvlist_t *nvl)
566 {
567         nvpriv_t *priv;
568         i_nvp_t *curr;
569
570         if (nvl == NULL ||
571             (priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL)
572                 return;
573
574         /*
575          * Unpacked nvlist are linked through i_nvp_t
576          */
577         curr = priv->nvp_list;
578         while (curr != NULL) {
579                 nvpair_t *nvp = &curr->nvi_nvp;
580                 curr = curr->nvi_next;
581
582                 nvpair_free(nvp);
583                 nvp_buf_free(nvl, nvp);
584         }
585
586         if (!(priv->nvp_stat & NV_STAT_EMBEDDED))
587                 nv_mem_free(priv, nvl, NV_ALIGN(sizeof (nvlist_t)));
588         else
589                 nvl->nvl_priv = 0;
590
591         nv_mem_free(priv, priv, sizeof (nvpriv_t));
592 }
593
594 static int
595 nvlist_contains_nvp(nvlist_t *nvl, nvpair_t *nvp)
596 {
597         nvpriv_t *priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv;
598         i_nvp_t *curr;
599
600         if (nvp == NULL)
601                 return (0);
602
603         for (curr = priv->nvp_list; curr != NULL; curr = curr->nvi_next)
604                 if (&curr->nvi_nvp == nvp)
605                         return (1);
606
607         return (0);
608 }
609
610 /*
611  * Make a copy of nvlist
612  */
613 /*ARGSUSED1*/
614 int
615 nvlist_dup(nvlist_t *nvl, nvlist_t **nvlp, int kmflag)
616 {
617 #if defined(_KERNEL) && !defined(_BOOT)
618         return (nvlist_xdup(nvl, nvlp,
619             (kmflag == KM_SLEEP ? nv_alloc_sleep : nv_alloc_nosleep)));
620 #else
621         return (nvlist_xdup(nvl, nvlp, nv_alloc_nosleep));
622 #endif
623 }
624
625 int
626 nvlist_xdup(nvlist_t *nvl, nvlist_t **nvlp, nv_alloc_t *nva)
627 {
628         int err;
629         nvlist_t *ret;
630
631         if (nvl == NULL || nvlp == NULL)
632                 return (EINVAL);
633
634         if ((err = nvlist_xalloc(&ret, nvl->nvl_nvflag, nva)) != 0)
635                 return (err);
636
637         if ((err = nvlist_copy_pairs(nvl, ret)) != 0)
638                 nvlist_free(ret);
639         else
640                 *nvlp = ret;
641
642         return (err);
643 }
644
645 /*
646  * Remove all with matching name
647  */
648 int
649 nvlist_remove_all(nvlist_t *nvl, const char *name)
650 {
651         nvpriv_t *priv;
652         i_nvp_t *curr;
653         int error = ENOENT;
654
655         if (nvl == NULL || name == NULL ||
656             (priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL)
657                 return (EINVAL);
658
659         curr = priv->nvp_list;
660         while (curr != NULL) {
661                 nvpair_t *nvp = &curr->nvi_nvp;
662
663                 curr = curr->nvi_next;
664                 if (strcmp(name, NVP_NAME(nvp)) != 0)
665                         continue;
666
667                 nvp_buf_unlink(nvl, nvp);
668                 nvpair_free(nvp);
669                 nvp_buf_free(nvl, nvp);
670
671                 error = 0;
672         }
673
674         return (error);
675 }
676
677 /*
678  * Remove first one with matching name and type
679  */
680 int
681 nvlist_remove(nvlist_t *nvl, const char *name, data_type_t type)
682 {
683         nvpriv_t *priv;
684         i_nvp_t *curr;
685
686         if (nvl == NULL || name == NULL ||
687             (priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL)
688                 return (EINVAL);
689
690         curr = priv->nvp_list;
691         while (curr != NULL) {
692                 nvpair_t *nvp = &curr->nvi_nvp;
693
694                 if (strcmp(name, NVP_NAME(nvp)) == 0 && NVP_TYPE(nvp) == type) {
695                         nvp_buf_unlink(nvl, nvp);
696                         nvpair_free(nvp);
697                         nvp_buf_free(nvl, nvp);
698
699                         return (0);
700                 }
701                 curr = curr->nvi_next;
702         }
703
704         return (ENOENT);
705 }
706
707 int
708 nvlist_remove_nvpair(nvlist_t *nvl, nvpair_t *nvp)
709 {
710         if (nvl == NULL || nvp == NULL)
711                 return (EINVAL);
712
713         nvp_buf_unlink(nvl, nvp);
714         nvpair_free(nvp);
715         nvp_buf_free(nvl, nvp);
716         return (0);
717 }
718
719 /*
720  * This function calculates the size of an nvpair value.
721  *
722  * The data argument controls the behavior in case of the data types
723  *      DATA_TYPE_STRING        and
724  *      DATA_TYPE_STRING_ARRAY
725  * Is data == NULL then the size of the string(s) is excluded.
726  */
727 static int
728 i_get_value_size(data_type_t type, const void *data, uint_t nelem)
729 {
730         uint64_t value_sz;
731
732         if (i_validate_type_nelem(type, nelem) != 0)
733                 return (-1);
734
735         /* Calculate required size for holding value */
736         switch (type) {
737         case DATA_TYPE_BOOLEAN:
738                 value_sz = 0;
739                 break;
740         case DATA_TYPE_BOOLEAN_VALUE:
741                 value_sz = sizeof (boolean_t);
742                 break;
743         case DATA_TYPE_BYTE:
744                 value_sz = sizeof (uchar_t);
745                 break;
746         case DATA_TYPE_INT8:
747                 value_sz = sizeof (int8_t);
748                 break;
749         case DATA_TYPE_UINT8:
750                 value_sz = sizeof (uint8_t);
751                 break;
752         case DATA_TYPE_INT16:
753                 value_sz = sizeof (int16_t);
754                 break;
755         case DATA_TYPE_UINT16:
756                 value_sz = sizeof (uint16_t);
757                 break;
758         case DATA_TYPE_INT32:
759                 value_sz = sizeof (int32_t);
760                 break;
761         case DATA_TYPE_UINT32:
762                 value_sz = sizeof (uint32_t);
763                 break;
764         case DATA_TYPE_INT64:
765                 value_sz = sizeof (int64_t);
766                 break;
767         case DATA_TYPE_UINT64:
768                 value_sz = sizeof (uint64_t);
769                 break;
770 #if !defined(_KERNEL)
771         case DATA_TYPE_DOUBLE:
772                 value_sz = sizeof (double);
773                 break;
774 #endif
775         case DATA_TYPE_STRING:
776                 if (data == NULL)
777                         value_sz = 0;
778                 else
779                         value_sz = strlen(data) + 1;
780                 break;
781         case DATA_TYPE_BOOLEAN_ARRAY:
782                 value_sz = (uint64_t)nelem * sizeof (boolean_t);
783                 break;
784         case DATA_TYPE_BYTE_ARRAY:
785                 value_sz = (uint64_t)nelem * sizeof (uchar_t);
786                 break;
787         case DATA_TYPE_INT8_ARRAY:
788                 value_sz = (uint64_t)nelem * sizeof (int8_t);
789                 break;
790         case DATA_TYPE_UINT8_ARRAY:
791                 value_sz = (uint64_t)nelem * sizeof (uint8_t);
792                 break;
793         case DATA_TYPE_INT16_ARRAY:
794                 value_sz = (uint64_t)nelem * sizeof (int16_t);
795                 break;
796         case DATA_TYPE_UINT16_ARRAY:
797                 value_sz = (uint64_t)nelem * sizeof (uint16_t);
798                 break;
799         case DATA_TYPE_INT32_ARRAY:
800                 value_sz = (uint64_t)nelem * sizeof (int32_t);
801                 break;
802         case DATA_TYPE_UINT32_ARRAY:
803                 value_sz = (uint64_t)nelem * sizeof (uint32_t);
804                 break;
805         case DATA_TYPE_INT64_ARRAY:
806                 value_sz = (uint64_t)nelem * sizeof (int64_t);
807                 break;
808         case DATA_TYPE_UINT64_ARRAY:
809                 value_sz = (uint64_t)nelem * sizeof (uint64_t);
810                 break;
811         case DATA_TYPE_STRING_ARRAY:
812                 value_sz = (uint64_t)nelem * sizeof (uint64_t);
813
814                 if (data != NULL) {
815                         char *const *strs = data;
816                         uint_t i;
817
818                         /* no alignment requirement for strings */
819                         for (i = 0; i < nelem; i++) {
820                                 if (strs[i] == NULL)
821                                         return (-1);
822                                 value_sz += strlen(strs[i]) + 1;
823                         }
824                 }
825                 break;
826         case DATA_TYPE_HRTIME:
827                 value_sz = sizeof (hrtime_t);
828                 break;
829         case DATA_TYPE_NVLIST:
830                 value_sz = NV_ALIGN(sizeof (nvlist_t));
831                 break;
832         case DATA_TYPE_NVLIST_ARRAY:
833                 value_sz = (uint64_t)nelem * sizeof (uint64_t) +
834                     (uint64_t)nelem * NV_ALIGN(sizeof (nvlist_t));
835                 break;
836         default:
837                 return (-1);
838         }
839
840         return (value_sz > INT32_MAX ? -1 : (int)value_sz);
841 }
842
843 static int
844 nvlist_copy_embedded(nvlist_t *nvl, nvlist_t *onvl, nvlist_t *emb_nvl)
845 {
846         nvpriv_t *priv;
847         int err;
848
849         if ((priv = nv_priv_alloc_embedded((nvpriv_t *)(uintptr_t)
850             nvl->nvl_priv)) == NULL)
851                 return (ENOMEM);
852
853         nvlist_init(emb_nvl, onvl->nvl_nvflag, priv);
854
855         if ((err = nvlist_copy_pairs(onvl, emb_nvl)) != 0) {
856                 nvlist_free(emb_nvl);
857                 emb_nvl->nvl_priv = 0;
858         }
859
860         return (err);
861 }
862
863 /*
864  * nvlist_add_common - Add new <name,value> pair to nvlist
865  */
866 static int
867 nvlist_add_common(nvlist_t *nvl, const char *name,
868     data_type_t type, uint_t nelem, const void *data)
869 {
870         nvpair_t *nvp;
871         uint_t i;
872
873         int nvp_sz, name_sz, value_sz;
874         int err = 0;
875
876         if (name == NULL || nvl == NULL || nvl->nvl_priv == 0)
877                 return (EINVAL);
878
879         if (nelem != 0 && data == NULL)
880                 return (EINVAL);
881
882         /*
883          * Verify type and nelem and get the value size.
884          * In case of data types DATA_TYPE_STRING and DATA_TYPE_STRING_ARRAY
885          * is the size of the string(s) included.
886          */
887         if ((value_sz = i_get_value_size(type, data, nelem)) < 0)
888                 return (EINVAL);
889
890         if (i_validate_nvpair_value(type, nelem, data) != 0)
891                 return (EINVAL);
892
893         /*
894          * If we're adding an nvlist or nvlist array, ensure that we are not
895          * adding the input nvlist to itself, which would cause recursion,
896          * and ensure that no NULL nvlist pointers are present.
897          */
898         switch (type) {
899         case DATA_TYPE_NVLIST:
900                 if (data == nvl || data == NULL)
901                         return (EINVAL);
902                 break;
903         case DATA_TYPE_NVLIST_ARRAY: {
904                 nvlist_t **onvlp = (nvlist_t **)data;
905                 for (i = 0; i < nelem; i++) {
906                         if (onvlp[i] == nvl || onvlp[i] == NULL)
907                                 return (EINVAL);
908                 }
909                 break;
910         }
911         default:
912                 break;
913         }
914
915         /* calculate sizes of the nvpair elements and the nvpair itself */
916         name_sz = strlen(name) + 1;
917         if (name_sz >= 1ULL << (sizeof (nvp->nvp_name_sz) * 8 - 1))
918                 return (EINVAL);
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_INT8_ARRAY) ||
1246             (type == DATA_TYPE_UINT8_ARRAY) ||
1247             (type == DATA_TYPE_INT16_ARRAY) ||
1248             (type == DATA_TYPE_UINT16_ARRAY) ||
1249             (type == DATA_TYPE_INT32_ARRAY) ||
1250             (type == DATA_TYPE_UINT32_ARRAY) ||
1251             (type == DATA_TYPE_INT64_ARRAY) ||
1252             (type == DATA_TYPE_UINT64_ARRAY) ||
1253             (type == DATA_TYPE_BOOLEAN_ARRAY) ||
1254             (type == DATA_TYPE_STRING_ARRAY) ||
1255             (type == DATA_TYPE_NVLIST_ARRAY))
1256                 return (1);
1257         return (0);
1258
1259 }
1260
1261 static int
1262 nvpair_value_common(nvpair_t *nvp, data_type_t type, uint_t *nelem, void *data)
1263 {
1264         if (nvp == NULL || nvpair_type(nvp) != type)
1265                 return (EINVAL);
1266
1267         /*
1268          * For non-array types, we copy the data.
1269          * For array types (including string), we set a pointer.
1270          */
1271         switch (type) {
1272         case DATA_TYPE_BOOLEAN:
1273                 if (nelem != NULL)
1274                         *nelem = 0;
1275                 break;
1276
1277         case DATA_TYPE_BOOLEAN_VALUE:
1278         case DATA_TYPE_BYTE:
1279         case DATA_TYPE_INT8:
1280         case DATA_TYPE_UINT8:
1281         case DATA_TYPE_INT16:
1282         case DATA_TYPE_UINT16:
1283         case DATA_TYPE_INT32:
1284         case DATA_TYPE_UINT32:
1285         case DATA_TYPE_INT64:
1286         case DATA_TYPE_UINT64:
1287         case DATA_TYPE_HRTIME:
1288 #if !defined(_KERNEL)
1289         case DATA_TYPE_DOUBLE:
1290 #endif
1291                 if (data == NULL)
1292                         return (EINVAL);
1293                 bcopy(NVP_VALUE(nvp), data,
1294                     (size_t)i_get_value_size(type, NULL, 1));
1295                 if (nelem != NULL)
1296                         *nelem = 1;
1297                 break;
1298
1299         case DATA_TYPE_NVLIST:
1300         case DATA_TYPE_STRING:
1301                 if (data == NULL)
1302                         return (EINVAL);
1303                 *(void **)data = (void *)NVP_VALUE(nvp);
1304                 if (nelem != NULL)
1305                         *nelem = 1;
1306                 break;
1307
1308         case DATA_TYPE_BOOLEAN_ARRAY:
1309         case DATA_TYPE_BYTE_ARRAY:
1310         case DATA_TYPE_INT8_ARRAY:
1311         case DATA_TYPE_UINT8_ARRAY:
1312         case DATA_TYPE_INT16_ARRAY:
1313         case DATA_TYPE_UINT16_ARRAY:
1314         case DATA_TYPE_INT32_ARRAY:
1315         case DATA_TYPE_UINT32_ARRAY:
1316         case DATA_TYPE_INT64_ARRAY:
1317         case DATA_TYPE_UINT64_ARRAY:
1318         case DATA_TYPE_STRING_ARRAY:
1319         case DATA_TYPE_NVLIST_ARRAY:
1320                 if (nelem == NULL || data == NULL)
1321                         return (EINVAL);
1322                 if ((*nelem = NVP_NELEM(nvp)) != 0)
1323                         *(void **)data = (void *)NVP_VALUE(nvp);
1324                 else
1325                         *(void **)data = NULL;
1326                 break;
1327
1328         default:
1329                 return (ENOTSUP);
1330         }
1331
1332         return (0);
1333 }
1334
1335 static int
1336 nvlist_lookup_common(nvlist_t *nvl, const char *name, data_type_t type,
1337     uint_t *nelem, void *data)
1338 {
1339         nvpriv_t *priv;
1340         nvpair_t *nvp;
1341         i_nvp_t *curr;
1342
1343         if (name == NULL || nvl == NULL ||
1344             (priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL)
1345                 return (EINVAL);
1346
1347         if (!(nvl->nvl_nvflag & (NV_UNIQUE_NAME | NV_UNIQUE_NAME_TYPE)))
1348                 return (ENOTSUP);
1349
1350         for (curr = priv->nvp_list; curr != NULL; curr = curr->nvi_next) {
1351                 nvp = &curr->nvi_nvp;
1352
1353                 if (strcmp(name, NVP_NAME(nvp)) == 0 && NVP_TYPE(nvp) == type)
1354                         return (nvpair_value_common(nvp, type, nelem, data));
1355         }
1356
1357         return (ENOENT);
1358 }
1359
1360 int
1361 nvlist_lookup_boolean(nvlist_t *nvl, const char *name)
1362 {
1363         return (nvlist_lookup_common(nvl, name, DATA_TYPE_BOOLEAN, NULL, NULL));
1364 }
1365
1366 int
1367 nvlist_lookup_boolean_value(nvlist_t *nvl, const char *name, boolean_t *val)
1368 {
1369         return (nvlist_lookup_common(nvl, name,
1370             DATA_TYPE_BOOLEAN_VALUE, NULL, val));
1371 }
1372
1373 int
1374 nvlist_lookup_byte(nvlist_t *nvl, const char *name, uchar_t *val)
1375 {
1376         return (nvlist_lookup_common(nvl, name, DATA_TYPE_BYTE, NULL, val));
1377 }
1378
1379 int
1380 nvlist_lookup_int8(nvlist_t *nvl, const char *name, int8_t *val)
1381 {
1382         return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT8, NULL, val));
1383 }
1384
1385 int
1386 nvlist_lookup_uint8(nvlist_t *nvl, const char *name, uint8_t *val)
1387 {
1388         return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT8, NULL, val));
1389 }
1390
1391 int
1392 nvlist_lookup_int16(nvlist_t *nvl, const char *name, int16_t *val)
1393 {
1394         return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT16, NULL, val));
1395 }
1396
1397 int
1398 nvlist_lookup_uint16(nvlist_t *nvl, const char *name, uint16_t *val)
1399 {
1400         return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT16, NULL, val));
1401 }
1402
1403 int
1404 nvlist_lookup_int32(nvlist_t *nvl, const char *name, int32_t *val)
1405 {
1406         return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT32, NULL, val));
1407 }
1408
1409 int
1410 nvlist_lookup_uint32(nvlist_t *nvl, const char *name, uint32_t *val)
1411 {
1412         return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT32, NULL, val));
1413 }
1414
1415 int
1416 nvlist_lookup_int64(nvlist_t *nvl, const char *name, int64_t *val)
1417 {
1418         return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT64, NULL, val));
1419 }
1420
1421 int
1422 nvlist_lookup_uint64(nvlist_t *nvl, const char *name, uint64_t *val)
1423 {
1424         return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT64, NULL, val));
1425 }
1426
1427 #if !defined(_KERNEL)
1428 int
1429 nvlist_lookup_double(nvlist_t *nvl, const char *name, double *val)
1430 {
1431         return (nvlist_lookup_common(nvl, name, DATA_TYPE_DOUBLE, NULL, val));
1432 }
1433 #endif
1434
1435 int
1436 nvlist_lookup_string(nvlist_t *nvl, const char *name, char **val)
1437 {
1438         return (nvlist_lookup_common(nvl, name, DATA_TYPE_STRING, NULL, val));
1439 }
1440
1441 int
1442 nvlist_lookup_nvlist(nvlist_t *nvl, const char *name, nvlist_t **val)
1443 {
1444         return (nvlist_lookup_common(nvl, name, DATA_TYPE_NVLIST, NULL, val));
1445 }
1446
1447 int
1448 nvlist_lookup_boolean_array(nvlist_t *nvl, const char *name,
1449     boolean_t **a, uint_t *n)
1450 {
1451         return (nvlist_lookup_common(nvl, name,
1452             DATA_TYPE_BOOLEAN_ARRAY, n, a));
1453 }
1454
1455 int
1456 nvlist_lookup_byte_array(nvlist_t *nvl, const char *name,
1457     uchar_t **a, uint_t *n)
1458 {
1459         return (nvlist_lookup_common(nvl, name, DATA_TYPE_BYTE_ARRAY, n, a));
1460 }
1461
1462 int
1463 nvlist_lookup_int8_array(nvlist_t *nvl, const char *name, int8_t **a, uint_t *n)
1464 {
1465         return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT8_ARRAY, n, a));
1466 }
1467
1468 int
1469 nvlist_lookup_uint8_array(nvlist_t *nvl, const char *name,
1470     uint8_t **a, uint_t *n)
1471 {
1472         return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT8_ARRAY, n, a));
1473 }
1474
1475 int
1476 nvlist_lookup_int16_array(nvlist_t *nvl, const char *name,
1477     int16_t **a, uint_t *n)
1478 {
1479         return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT16_ARRAY, n, a));
1480 }
1481
1482 int
1483 nvlist_lookup_uint16_array(nvlist_t *nvl, const char *name,
1484     uint16_t **a, uint_t *n)
1485 {
1486         return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT16_ARRAY, n, a));
1487 }
1488
1489 int
1490 nvlist_lookup_int32_array(nvlist_t *nvl, const char *name,
1491     int32_t **a, uint_t *n)
1492 {
1493         return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT32_ARRAY, n, a));
1494 }
1495
1496 int
1497 nvlist_lookup_uint32_array(nvlist_t *nvl, const char *name,
1498     uint32_t **a, uint_t *n)
1499 {
1500         return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT32_ARRAY, n, a));
1501 }
1502
1503 int
1504 nvlist_lookup_int64_array(nvlist_t *nvl, const char *name,
1505     int64_t **a, uint_t *n)
1506 {
1507         return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT64_ARRAY, n, a));
1508 }
1509
1510 int
1511 nvlist_lookup_uint64_array(nvlist_t *nvl, const char *name,
1512     uint64_t **a, uint_t *n)
1513 {
1514         return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT64_ARRAY, n, a));
1515 }
1516
1517 int
1518 nvlist_lookup_string_array(nvlist_t *nvl, const char *name,
1519     char ***a, uint_t *n)
1520 {
1521         return (nvlist_lookup_common(nvl, name, DATA_TYPE_STRING_ARRAY, n, a));
1522 }
1523
1524 int
1525 nvlist_lookup_nvlist_array(nvlist_t *nvl, const char *name,
1526     nvlist_t ***a, uint_t *n)
1527 {
1528         return (nvlist_lookup_common(nvl, name, DATA_TYPE_NVLIST_ARRAY, n, a));
1529 }
1530
1531 int
1532 nvlist_lookup_hrtime(nvlist_t *nvl, const char *name, hrtime_t *val)
1533 {
1534         return (nvlist_lookup_common(nvl, name, DATA_TYPE_HRTIME, NULL, val));
1535 }
1536
1537 int
1538 nvlist_lookup_pairs(nvlist_t *nvl, int flag, ...)
1539 {
1540         va_list ap;
1541         char *name;
1542         int noentok = (flag & NV_FLAG_NOENTOK ? 1 : 0);
1543         int ret = 0;
1544
1545         va_start(ap, flag);
1546         while (ret == 0 && (name = va_arg(ap, char *)) != NULL) {
1547                 data_type_t type;
1548                 void *val;
1549                 uint_t *nelem;
1550
1551                 switch (type = va_arg(ap, data_type_t)) {
1552                 case DATA_TYPE_BOOLEAN:
1553                         ret = nvlist_lookup_common(nvl, name, type, NULL, NULL);
1554                         break;
1555
1556                 case DATA_TYPE_BOOLEAN_VALUE:
1557                 case DATA_TYPE_BYTE:
1558                 case DATA_TYPE_INT8:
1559                 case DATA_TYPE_UINT8:
1560                 case DATA_TYPE_INT16:
1561                 case DATA_TYPE_UINT16:
1562                 case DATA_TYPE_INT32:
1563                 case DATA_TYPE_UINT32:
1564                 case DATA_TYPE_INT64:
1565                 case DATA_TYPE_UINT64:
1566                 case DATA_TYPE_HRTIME:
1567                 case DATA_TYPE_STRING:
1568                 case DATA_TYPE_NVLIST:
1569 #if !defined(_KERNEL)
1570                 case DATA_TYPE_DOUBLE:
1571 #endif
1572                         val = va_arg(ap, void *);
1573                         ret = nvlist_lookup_common(nvl, name, type, NULL, val);
1574                         break;
1575
1576                 case DATA_TYPE_BYTE_ARRAY:
1577                 case DATA_TYPE_BOOLEAN_ARRAY:
1578                 case DATA_TYPE_INT8_ARRAY:
1579                 case DATA_TYPE_UINT8_ARRAY:
1580                 case DATA_TYPE_INT16_ARRAY:
1581                 case DATA_TYPE_UINT16_ARRAY:
1582                 case DATA_TYPE_INT32_ARRAY:
1583                 case DATA_TYPE_UINT32_ARRAY:
1584                 case DATA_TYPE_INT64_ARRAY:
1585                 case DATA_TYPE_UINT64_ARRAY:
1586                 case DATA_TYPE_STRING_ARRAY:
1587                 case DATA_TYPE_NVLIST_ARRAY:
1588                         val = va_arg(ap, void *);
1589                         nelem = va_arg(ap, uint_t *);
1590                         ret = nvlist_lookup_common(nvl, name, type, nelem, val);
1591                         break;
1592
1593                 default:
1594                         ret = EINVAL;
1595                 }
1596
1597                 if (ret == ENOENT && noentok)
1598                         ret = 0;
1599         }
1600         va_end(ap);
1601
1602         return (ret);
1603 }
1604
1605 /*
1606  * Find the 'name'ed nvpair in the nvlist 'nvl'. If 'name' found, the function
1607  * returns zero and a pointer to the matching nvpair is returned in '*ret'
1608  * (given 'ret' is non-NULL). If 'sep' is specified then 'name' will penitrate
1609  * multiple levels of embedded nvlists, with 'sep' as the separator. As an
1610  * example, if sep is '.', name might look like: "a" or "a.b" or "a.c[3]" or
1611  * "a.d[3].e[1]".  This matches the C syntax for array embed (for convience,
1612  * code also supports "a.d[3]e[1]" syntax).
1613  *
1614  * If 'ip' is non-NULL and the last name component is an array, return the
1615  * value of the "...[index]" array index in *ip. For an array reference that
1616  * is not indexed, *ip will be returned as -1. If there is a syntax error in
1617  * 'name', and 'ep' is non-NULL then *ep will be set to point to the location
1618  * inside the 'name' string where the syntax error was detected.
1619  */
1620 static int
1621 nvlist_lookup_nvpair_ei_sep(nvlist_t *nvl, const char *name, const char sep,
1622     nvpair_t **ret, int *ip, char **ep)
1623 {
1624         nvpair_t        *nvp;
1625         const char      *np;
1626         char            *sepp;
1627         char            *idxp, *idxep;
1628         nvlist_t        **nva;
1629         long            idx;
1630         int             n;
1631
1632         if (ip)
1633                 *ip = -1;                       /* not indexed */
1634         if (ep)
1635                 *ep = NULL;
1636
1637         if ((nvl == NULL) || (name == NULL))
1638                 return (EINVAL);
1639
1640         sepp = NULL;
1641         idx = 0;
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 a 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                         nvlist_free(embedded);
2205                         return (EINVAL);
2206                 }
2207                 nvs->nvs_recursion++;
2208                 if ((err = nvs_operation(nvs, embedded, NULL)) != 0)
2209                         nvlist_free(embedded);
2210                 nvs->nvs_recursion--;
2211                 return (err);
2212         }
2213         default:
2214                 break;
2215         }
2216
2217         return (EINVAL);
2218 }
2219
2220 static int
2221 nvs_embedded_nvl_array(nvstream_t *nvs, nvpair_t *nvp, size_t *size)
2222 {
2223         size_t nelem = NVP_NELEM(nvp);
2224         nvlist_t **nvlp = EMBEDDED_NVL_ARRAY(nvp);
2225         int i;
2226
2227         switch (nvs->nvs_op) {
2228         case NVS_OP_ENCODE:
2229                 for (i = 0; i < nelem; i++)
2230                         if (nvs_embedded(nvs, nvlp[i]) != 0)
2231                                 return (EFAULT);
2232                 break;
2233
2234         case NVS_OP_DECODE: {
2235                 size_t len = nelem * sizeof (uint64_t);
2236                 nvlist_t *embedded = (nvlist_t *)((uintptr_t)nvlp + len);
2237
2238                 bzero(nvlp, len);       /* don't trust packed data */
2239                 for (i = 0; i < nelem; i++) {
2240                         if (nvs_embedded(nvs, embedded) != 0) {
2241                                 nvpair_free(nvp);
2242                                 return (EFAULT);
2243                         }
2244
2245                         nvlp[i] = embedded++;
2246                 }
2247                 break;
2248         }
2249         case NVS_OP_GETSIZE: {
2250                 uint64_t nvsize = 0;
2251
2252                 for (i = 0; i < nelem; i++) {
2253                         size_t nvp_sz = 0;
2254
2255                         if (nvs_operation(nvs, nvlp[i], &nvp_sz) != 0)
2256                                 return (EINVAL);
2257
2258                         if ((nvsize += nvp_sz) > INT32_MAX)
2259                                 return (EINVAL);
2260                 }
2261
2262                 *size = nvsize;
2263                 break;
2264         }
2265         default:
2266                 return (EINVAL);
2267         }
2268
2269         return (0);
2270 }
2271
2272 static int nvs_native(nvstream_t *, nvlist_t *, char *, size_t *);
2273 static int nvs_xdr(nvstream_t *, nvlist_t *, char *, size_t *);
2274
2275 /*
2276  * Common routine for nvlist operations:
2277  * encode, decode, getsize (encoded size).
2278  */
2279 static int
2280 nvlist_common(nvlist_t *nvl, char *buf, size_t *buflen, int encoding,
2281     int nvs_op)
2282 {
2283         int err = 0;
2284         nvstream_t nvs;
2285         int nvl_endian;
2286 #if BYTE_ORDER == _LITTLE_ENDIAN
2287         int host_endian = 1;
2288 #else
2289         int host_endian = 0;
2290 #endif  /* _LITTLE_ENDIAN */
2291         nvs_header_t *nvh = (void *)buf;
2292
2293         if (buflen == NULL || nvl == NULL ||
2294             (nvs.nvs_priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL)
2295                 return (EINVAL);
2296
2297         nvs.nvs_op = nvs_op;
2298         nvs.nvs_recursion = 0;
2299
2300         /*
2301          * For NVS_OP_ENCODE and NVS_OP_DECODE make sure an nvlist and
2302          * a buffer is allocated.  The first 4 bytes in the buffer are
2303          * used for encoding method and host endian.
2304          */
2305         switch (nvs_op) {
2306         case NVS_OP_ENCODE:
2307                 if (buf == NULL || *buflen < sizeof (nvs_header_t))
2308                         return (EINVAL);
2309
2310                 nvh->nvh_encoding = encoding;
2311                 nvh->nvh_endian = nvl_endian = host_endian;
2312                 nvh->nvh_reserved1 = 0;
2313                 nvh->nvh_reserved2 = 0;
2314                 break;
2315
2316         case NVS_OP_DECODE:
2317                 if (buf == NULL || *buflen < sizeof (nvs_header_t))
2318                         return (EINVAL);
2319
2320                 /* get method of encoding from first byte */
2321                 encoding = nvh->nvh_encoding;
2322                 nvl_endian = nvh->nvh_endian;
2323                 break;
2324
2325         case NVS_OP_GETSIZE:
2326                 nvl_endian = host_endian;
2327
2328                 /*
2329                  * add the size for encoding
2330                  */
2331                 *buflen = sizeof (nvs_header_t);
2332                 break;
2333
2334         default:
2335                 return (ENOTSUP);
2336         }
2337
2338         /*
2339          * Create an nvstream with proper encoding method
2340          */
2341         switch (encoding) {
2342         case NV_ENCODE_NATIVE:
2343                 /*
2344                  * check endianness, in case we are unpacking
2345                  * from a file
2346                  */
2347                 if (nvl_endian != host_endian)
2348                         return (ENOTSUP);
2349                 err = nvs_native(&nvs, nvl, buf, buflen);
2350                 break;
2351         case NV_ENCODE_XDR:
2352                 err = nvs_xdr(&nvs, nvl, buf, buflen);
2353                 break;
2354         default:
2355                 err = ENOTSUP;
2356                 break;
2357         }
2358
2359         return (err);
2360 }
2361
2362 int
2363 nvlist_size(nvlist_t *nvl, size_t *size, int encoding)
2364 {
2365         return (nvlist_common(nvl, NULL, size, encoding, NVS_OP_GETSIZE));
2366 }
2367
2368 /*
2369  * Pack nvlist into contiguous memory
2370  */
2371 /*ARGSUSED1*/
2372 int
2373 nvlist_pack(nvlist_t *nvl, char **bufp, size_t *buflen, int encoding,
2374     int kmflag)
2375 {
2376 #if defined(_KERNEL) && !defined(_BOOT)
2377         return (nvlist_xpack(nvl, bufp, buflen, encoding,
2378             (kmflag == KM_SLEEP ? nv_alloc_sleep : nv_alloc_nosleep)));
2379 #else
2380         return (nvlist_xpack(nvl, bufp, buflen, encoding, nv_alloc_nosleep));
2381 #endif
2382 }
2383
2384 int
2385 nvlist_xpack(nvlist_t *nvl, char **bufp, size_t *buflen, int encoding,
2386     nv_alloc_t *nva)
2387 {
2388         nvpriv_t nvpriv;
2389         size_t alloc_size;
2390         char *buf;
2391         int err;
2392
2393         if (nva == NULL || nvl == NULL || bufp == NULL || buflen == NULL)
2394                 return (EINVAL);
2395
2396         if (*bufp != NULL)
2397                 return (nvlist_common(nvl, *bufp, buflen, encoding,
2398                     NVS_OP_ENCODE));
2399
2400         /*
2401          * Here is a difficult situation:
2402          * 1. The nvlist has fixed allocator properties.
2403          *    All other nvlist routines (like nvlist_add_*, ...) use
2404          *    these properties.
2405          * 2. When using nvlist_pack() the user can specify their own
2406          *    allocator properties (e.g. by using KM_NOSLEEP).
2407          *
2408          * We use the user specified properties (2). A clearer solution
2409          * will be to remove the kmflag from nvlist_pack(), but we will
2410          * not change the interface.
2411          */
2412         nv_priv_init(&nvpriv, nva, 0);
2413
2414         if ((err = nvlist_size(nvl, &alloc_size, encoding)))
2415                 return (err);
2416
2417         if ((buf = nv_mem_zalloc(&nvpriv, alloc_size)) == NULL)
2418                 return (ENOMEM);
2419
2420         if ((err = nvlist_common(nvl, buf, &alloc_size, encoding,
2421             NVS_OP_ENCODE)) != 0) {
2422                 nv_mem_free(&nvpriv, buf, alloc_size);
2423         } else {
2424                 *buflen = alloc_size;
2425                 *bufp = buf;
2426         }
2427
2428         return (err);
2429 }
2430
2431 /*
2432  * Unpack buf into an nvlist_t
2433  */
2434 /*ARGSUSED1*/
2435 int
2436 nvlist_unpack(char *buf, size_t buflen, nvlist_t **nvlp, int kmflag)
2437 {
2438 #if defined(_KERNEL) && !defined(_BOOT)
2439         return (nvlist_xunpack(buf, buflen, nvlp,
2440             (kmflag == KM_SLEEP ? nv_alloc_sleep : nv_alloc_nosleep)));
2441 #else
2442         return (nvlist_xunpack(buf, buflen, nvlp, nv_alloc_nosleep));
2443 #endif
2444 }
2445
2446 int
2447 nvlist_xunpack(char *buf, size_t buflen, nvlist_t **nvlp, nv_alloc_t *nva)
2448 {
2449         nvlist_t *nvl;
2450         int err;
2451
2452         if (nvlp == NULL)
2453                 return (EINVAL);
2454
2455         if ((err = nvlist_xalloc(&nvl, 0, nva)) != 0)
2456                 return (err);
2457
2458         if ((err = nvlist_common(nvl, buf, &buflen, 0, NVS_OP_DECODE)) != 0)
2459                 nvlist_free(nvl);
2460         else
2461                 *nvlp = nvl;
2462
2463         return (err);
2464 }
2465
2466 /*
2467  * Native encoding functions
2468  */
2469 typedef struct {
2470         /*
2471          * This structure is used when decoding a packed nvpair in
2472          * the native format.  n_base points to a buffer containing the
2473          * packed nvpair.  n_end is a pointer to the end of the buffer.
2474          * (n_end actually points to the first byte past the end of the
2475          * buffer.)  n_curr is a pointer that lies between n_base and n_end.
2476          * It points to the current data that we are decoding.
2477          * The amount of data left in the buffer is equal to n_end - n_curr.
2478          * n_flag is used to recognize a packed embedded list.
2479          */
2480         caddr_t n_base;
2481         caddr_t n_end;
2482         caddr_t n_curr;
2483         uint_t  n_flag;
2484 } nvs_native_t;
2485
2486 static int
2487 nvs_native_create(nvstream_t *nvs, nvs_native_t *native, char *buf,
2488     size_t buflen)
2489 {
2490         switch (nvs->nvs_op) {
2491         case NVS_OP_ENCODE:
2492         case NVS_OP_DECODE:
2493                 nvs->nvs_private = native;
2494                 native->n_curr = native->n_base = buf;
2495                 native->n_end = buf + buflen;
2496                 native->n_flag = 0;
2497                 return (0);
2498
2499         case NVS_OP_GETSIZE:
2500                 nvs->nvs_private = native;
2501                 native->n_curr = native->n_base = native->n_end = NULL;
2502                 native->n_flag = 0;
2503                 return (0);
2504         default:
2505                 return (EINVAL);
2506         }
2507 }
2508
2509 /*ARGSUSED*/
2510 static void
2511 nvs_native_destroy(nvstream_t *nvs)
2512 {
2513 }
2514
2515 static int
2516 native_cp(nvstream_t *nvs, void *buf, size_t size)
2517 {
2518         nvs_native_t *native = (nvs_native_t *)nvs->nvs_private;
2519
2520         if (native->n_curr + size > native->n_end)
2521                 return (EFAULT);
2522
2523         /*
2524          * The bcopy() below eliminates alignment requirement
2525          * on the buffer (stream) and is preferred over direct access.
2526          */
2527         switch (nvs->nvs_op) {
2528         case NVS_OP_ENCODE:
2529                 bcopy(buf, native->n_curr, size);
2530                 break;
2531         case NVS_OP_DECODE:
2532                 bcopy(native->n_curr, buf, size);
2533                 break;
2534         default:
2535                 return (EINVAL);
2536         }
2537
2538         native->n_curr += size;
2539         return (0);
2540 }
2541
2542 /*
2543  * operate on nvlist_t header
2544  */
2545 static int
2546 nvs_native_nvlist(nvstream_t *nvs, nvlist_t *nvl, size_t *size)
2547 {
2548         nvs_native_t *native = nvs->nvs_private;
2549
2550         switch (nvs->nvs_op) {
2551         case NVS_OP_ENCODE:
2552         case NVS_OP_DECODE:
2553                 if (native->n_flag)
2554                         return (0);     /* packed embedded list */
2555
2556                 native->n_flag = 1;
2557
2558                 /* copy version and nvflag of the nvlist_t */
2559                 if (native_cp(nvs, &nvl->nvl_version, sizeof (int32_t)) != 0 ||
2560                     native_cp(nvs, &nvl->nvl_nvflag, sizeof (int32_t)) != 0)
2561                         return (EFAULT);
2562
2563                 return (0);
2564
2565         case NVS_OP_GETSIZE:
2566                 /*
2567                  * if calculate for packed embedded list
2568                  *      4 for end of the embedded list
2569                  * else
2570                  *      2 * sizeof (int32_t) for nvl_version and nvl_nvflag
2571                  *      and 4 for end of the entire list
2572                  */
2573                 if (native->n_flag) {
2574                         *size += 4;
2575                 } else {
2576                         native->n_flag = 1;
2577                         *size += 2 * sizeof (int32_t) + 4;
2578                 }
2579
2580                 return (0);
2581
2582         default:
2583                 return (EINVAL);
2584         }
2585 }
2586
2587 static int
2588 nvs_native_nvl_fini(nvstream_t *nvs)
2589 {
2590         if (nvs->nvs_op == NVS_OP_ENCODE) {
2591                 nvs_native_t *native = (nvs_native_t *)nvs->nvs_private;
2592                 /*
2593                  * Add 4 zero bytes at end of nvlist. They are used
2594                  * for end detection by the decode routine.
2595                  */
2596                 if (native->n_curr + sizeof (int) > native->n_end)
2597                         return (EFAULT);
2598
2599                 bzero(native->n_curr, sizeof (int));
2600                 native->n_curr += sizeof (int);
2601         }
2602
2603         return (0);
2604 }
2605
2606 static int
2607 nvpair_native_embedded(nvstream_t *nvs, nvpair_t *nvp)
2608 {
2609         if (nvs->nvs_op == NVS_OP_ENCODE) {
2610                 nvs_native_t *native = (nvs_native_t *)nvs->nvs_private;
2611                 char *packed = (void *)
2612                     (native->n_curr - nvp->nvp_size + NVP_VALOFF(nvp));
2613                 /*
2614                  * Null out the pointer that is meaningless in the packed
2615                  * structure. The address may not be aligned, so we have
2616                  * to use bzero.
2617                  */
2618                 bzero(packed + offsetof(nvlist_t, nvl_priv),
2619                     sizeof(((nvlist_t *)NULL)->nvl_priv));
2620         }
2621
2622         return (nvs_embedded(nvs, EMBEDDED_NVL(nvp)));
2623 }
2624
2625 static int
2626 nvpair_native_embedded_array(nvstream_t *nvs, nvpair_t *nvp)
2627 {
2628         if (nvs->nvs_op == NVS_OP_ENCODE) {
2629                 nvs_native_t *native = (nvs_native_t *)nvs->nvs_private;
2630                 char *value = native->n_curr - nvp->nvp_size + NVP_VALOFF(nvp);
2631                 size_t len = NVP_NELEM(nvp) * sizeof (uint64_t);
2632                 int i;
2633                 /*
2634                  * Null out pointers that are meaningless in the packed
2635                  * structure. The addresses may not be aligned, so we have
2636                  * to use bzero.
2637                  */
2638                 bzero(value, len);
2639
2640                 value += len;
2641                 for (i = 0; i < NVP_NELEM(nvp); i++) {
2642                         /*
2643                          * Null out the pointer that is meaningless in the
2644                          * packed structure. The address may not be aligned,
2645                          * so we have to use bzero.
2646                          */
2647                         bzero(value + offsetof(nvlist_t, nvl_priv),
2648                             sizeof(((nvlist_t *)NULL)->nvl_priv));
2649                         value += sizeof(nvlist_t);
2650                 }
2651         }
2652
2653         return (nvs_embedded_nvl_array(nvs, nvp, NULL));
2654 }
2655
2656 static void
2657 nvpair_native_string_array(nvstream_t *nvs, nvpair_t *nvp)
2658 {
2659         switch (nvs->nvs_op) {
2660         case NVS_OP_ENCODE: {
2661                 nvs_native_t *native = (nvs_native_t *)nvs->nvs_private;
2662                 uint64_t *strp = (void *)
2663                     (native->n_curr - nvp->nvp_size + NVP_VALOFF(nvp));
2664                 /*
2665                  * Null out pointers that are meaningless in the packed
2666                  * structure. The addresses may not be aligned, so we have
2667                  * to use bzero.
2668                  */
2669                 bzero(strp, NVP_NELEM(nvp) * sizeof (uint64_t));
2670                 break;
2671         }
2672         case NVS_OP_DECODE: {
2673                 char **strp = (void *)NVP_VALUE(nvp);
2674                 char *buf = ((char *)strp + NVP_NELEM(nvp) * sizeof (uint64_t));
2675                 int i;
2676
2677                 for (i = 0; i < NVP_NELEM(nvp); i++) {
2678                         strp[i] = buf;
2679                         buf += strlen(buf) + 1;
2680                 }
2681                 break;
2682         }
2683         }
2684 }
2685
2686 static int
2687 nvs_native_nvp_op(nvstream_t *nvs, nvpair_t *nvp)
2688 {
2689         data_type_t type;
2690         int value_sz;
2691         int ret = 0;
2692
2693         /*
2694          * We do the initial bcopy of the data before we look at
2695          * the nvpair type, because when we're decoding, we won't
2696          * have the correct values for the pair until we do the bcopy.
2697          */
2698         switch (nvs->nvs_op) {
2699         case NVS_OP_ENCODE:
2700         case NVS_OP_DECODE:
2701                 if (native_cp(nvs, nvp, nvp->nvp_size) != 0)
2702                         return (EFAULT);
2703                 break;
2704         default:
2705                 return (EINVAL);
2706         }
2707
2708         /* verify nvp_name_sz, check the name string length */
2709         if (i_validate_nvpair_name(nvp) != 0)
2710                 return (EFAULT);
2711
2712         type = NVP_TYPE(nvp);
2713
2714         /*
2715          * Verify type and nelem and get the value size.
2716          * In case of data types DATA_TYPE_STRING and DATA_TYPE_STRING_ARRAY
2717          * is the size of the string(s) excluded.
2718          */
2719         if ((value_sz = i_get_value_size(type, NULL, NVP_NELEM(nvp))) < 0)
2720                 return (EFAULT);
2721
2722         if (NVP_SIZE_CALC(nvp->nvp_name_sz, value_sz) > nvp->nvp_size)
2723                 return (EFAULT);
2724
2725         switch (type) {
2726         case DATA_TYPE_NVLIST:
2727                 ret = nvpair_native_embedded(nvs, nvp);
2728                 break;
2729         case DATA_TYPE_NVLIST_ARRAY:
2730                 ret = nvpair_native_embedded_array(nvs, nvp);
2731                 break;
2732         case DATA_TYPE_STRING_ARRAY:
2733                 nvpair_native_string_array(nvs, nvp);
2734                 break;
2735         default:
2736                 break;
2737         }
2738
2739         return (ret);
2740 }
2741
2742 static int
2743 nvs_native_nvp_size(nvstream_t *nvs, nvpair_t *nvp, size_t *size)
2744 {
2745         uint64_t nvp_sz = nvp->nvp_size;
2746
2747         switch (NVP_TYPE(nvp)) {
2748         case DATA_TYPE_NVLIST: {
2749                 size_t nvsize = 0;
2750
2751                 if (nvs_operation(nvs, EMBEDDED_NVL(nvp), &nvsize) != 0)
2752                         return (EINVAL);
2753
2754                 nvp_sz += nvsize;
2755                 break;
2756         }
2757         case DATA_TYPE_NVLIST_ARRAY: {
2758                 size_t nvsize;
2759
2760                 if (nvs_embedded_nvl_array(nvs, nvp, &nvsize) != 0)
2761                         return (EINVAL);
2762
2763                 nvp_sz += nvsize;
2764                 break;
2765         }
2766         default:
2767                 break;
2768         }
2769
2770         if (nvp_sz > INT32_MAX)
2771                 return (EINVAL);
2772
2773         *size = nvp_sz;
2774
2775         return (0);
2776 }
2777
2778 static int
2779 nvs_native_nvpair(nvstream_t *nvs, nvpair_t *nvp, size_t *size)
2780 {
2781         switch (nvs->nvs_op) {
2782         case NVS_OP_ENCODE:
2783                 return (nvs_native_nvp_op(nvs, nvp));
2784
2785         case NVS_OP_DECODE: {
2786                 nvs_native_t *native = (nvs_native_t *)nvs->nvs_private;
2787                 int32_t decode_len;
2788
2789                 /* try to read the size value from the stream */
2790                 if (native->n_curr + sizeof (int32_t) > native->n_end)
2791                         return (EFAULT);
2792                 bcopy(native->n_curr, &decode_len, sizeof (int32_t));
2793
2794                 /* sanity check the size value */
2795                 if (decode_len < 0 ||
2796                     decode_len > native->n_end - native->n_curr)
2797                         return (EFAULT);
2798
2799                 *size = decode_len;
2800
2801                 /*
2802                  * If at the end of the stream then move the cursor
2803                  * forward, otherwise nvpair_native_op() will read
2804                  * the entire nvpair at the same cursor position.
2805                  */
2806                 if (*size == 0)
2807                         native->n_curr += sizeof (int32_t);
2808                 break;
2809         }
2810
2811         default:
2812                 return (EINVAL);
2813         }
2814
2815         return (0);
2816 }
2817
2818 static const nvs_ops_t nvs_native_ops = {
2819         nvs_native_nvlist,
2820         nvs_native_nvpair,
2821         nvs_native_nvp_op,
2822         nvs_native_nvp_size,
2823         nvs_native_nvl_fini
2824 };
2825
2826 static int
2827 nvs_native(nvstream_t *nvs, nvlist_t *nvl, char *buf, size_t *buflen)
2828 {
2829         nvs_native_t native;
2830         int err;
2831
2832         nvs->nvs_ops = &nvs_native_ops;
2833
2834         if ((err = nvs_native_create(nvs, &native, buf + sizeof (nvs_header_t),
2835             *buflen - sizeof (nvs_header_t))) != 0)
2836                 return (err);
2837
2838         err = nvs_operation(nvs, nvl, buflen);
2839
2840         nvs_native_destroy(nvs);
2841
2842         return (err);
2843 }
2844
2845 /*
2846  * XDR encoding functions
2847  *
2848  * An xdr packed nvlist is encoded as:
2849  *
2850  *  - encoding methode and host endian (4 bytes)
2851  *  - nvl_version (4 bytes)
2852  *  - nvl_nvflag (4 bytes)
2853  *
2854  *  - encoded nvpairs, the format of one xdr encoded nvpair is:
2855  *      - encoded size of the nvpair (4 bytes)
2856  *      - decoded size of the nvpair (4 bytes)
2857  *      - name string, (4 + sizeof(NV_ALIGN4(string))
2858  *        a string is coded as size (4 bytes) and data
2859  *      - data type (4 bytes)
2860  *      - number of elements in the nvpair (4 bytes)
2861  *      - data
2862  *
2863  *  - 2 zero's for end of the entire list (8 bytes)
2864  */
2865 static int
2866 nvs_xdr_create(nvstream_t *nvs, XDR *xdr, char *buf, size_t buflen)
2867 {
2868         /* xdr data must be 4 byte aligned */
2869         if ((ulong_t)buf % 4 != 0)
2870                 return (EFAULT);
2871
2872         switch (nvs->nvs_op) {
2873         case NVS_OP_ENCODE:
2874                 xdrmem_create(xdr, buf, (uint_t)buflen, XDR_ENCODE);
2875                 nvs->nvs_private = xdr;
2876                 return (0);
2877         case NVS_OP_DECODE:
2878                 xdrmem_create(xdr, buf, (uint_t)buflen, XDR_DECODE);
2879                 nvs->nvs_private = xdr;
2880                 return (0);
2881         case NVS_OP_GETSIZE:
2882                 nvs->nvs_private = NULL;
2883                 return (0);
2884         default:
2885                 return (EINVAL);
2886         }
2887 }
2888
2889 static void
2890 nvs_xdr_destroy(nvstream_t *nvs)
2891 {
2892         switch (nvs->nvs_op) {
2893         case NVS_OP_ENCODE:
2894         case NVS_OP_DECODE:
2895                 xdr_destroy((XDR *)nvs->nvs_private);
2896                 break;
2897         default:
2898                 break;
2899         }
2900 }
2901
2902 static int
2903 nvs_xdr_nvlist(nvstream_t *nvs, nvlist_t *nvl, size_t *size)
2904 {
2905         switch (nvs->nvs_op) {
2906         case NVS_OP_ENCODE:
2907         case NVS_OP_DECODE: {
2908                 XDR     *xdr = nvs->nvs_private;
2909
2910                 if (!xdr_int(xdr, &nvl->nvl_version) ||
2911                     !xdr_u_int(xdr, &nvl->nvl_nvflag))
2912                         return (EFAULT);
2913                 break;
2914         }
2915         case NVS_OP_GETSIZE: {
2916                 /*
2917                  * 2 * 4 for nvl_version + nvl_nvflag
2918                  * and 8 for end of the entire list
2919                  */
2920                 *size += 2 * 4 + 8;
2921                 break;
2922         }
2923         default:
2924                 return (EINVAL);
2925         }
2926         return (0);
2927 }
2928
2929 static int
2930 nvs_xdr_nvl_fini(nvstream_t *nvs)
2931 {
2932         if (nvs->nvs_op == NVS_OP_ENCODE) {
2933                 XDR *xdr = nvs->nvs_private;
2934                 int zero = 0;
2935
2936                 if (!xdr_int(xdr, &zero) || !xdr_int(xdr, &zero))
2937                         return (EFAULT);
2938         }
2939
2940         return (0);
2941 }
2942
2943 /*
2944  * The format of xdr encoded nvpair is:
2945  * encode_size, decode_size, name string, data type, nelem, data
2946  */
2947 static int
2948 nvs_xdr_nvp_op(nvstream_t *nvs, nvpair_t *nvp)
2949 {
2950         data_type_t type;
2951         char    *buf;
2952         char    *buf_end = (char *)nvp + nvp->nvp_size;
2953         int     value_sz;
2954         uint_t  nelem, buflen;
2955         bool_t  ret = FALSE;
2956         XDR     *xdr = nvs->nvs_private;
2957
2958         ASSERT(xdr != NULL && nvp != NULL);
2959
2960         /* name string */
2961         if ((buf = NVP_NAME(nvp)) >= buf_end)
2962                 return (EFAULT);
2963         buflen = buf_end - buf;
2964
2965         if (!xdr_string(xdr, &buf, buflen - 1))
2966                 return (EFAULT);
2967         nvp->nvp_name_sz = strlen(buf) + 1;
2968
2969         /* type and nelem */
2970         if (!xdr_int(xdr, (int *)&nvp->nvp_type) ||
2971             !xdr_int(xdr, &nvp->nvp_value_elem))
2972                 return (EFAULT);
2973
2974         type = NVP_TYPE(nvp);
2975         nelem = nvp->nvp_value_elem;
2976
2977         /*
2978          * Verify type and nelem and get the value size.
2979          * In case of data types DATA_TYPE_STRING and DATA_TYPE_STRING_ARRAY
2980          * is the size of the string(s) excluded.
2981          */
2982         if ((value_sz = i_get_value_size(type, NULL, nelem)) < 0)
2983                 return (EFAULT);
2984
2985         /* if there is no data to extract then return */
2986         if (nelem == 0)
2987                 return (0);
2988
2989         /* value */
2990         if ((buf = NVP_VALUE(nvp)) >= buf_end)
2991                 return (EFAULT);
2992         buflen = buf_end - buf;
2993
2994         if (buflen < value_sz)
2995                 return (EFAULT);
2996
2997         switch (type) {
2998         case DATA_TYPE_NVLIST:
2999                 if (nvs_embedded(nvs, (void *)buf) == 0)
3000                         return (0);
3001                 break;
3002
3003         case DATA_TYPE_NVLIST_ARRAY:
3004                 if (nvs_embedded_nvl_array(nvs, nvp, NULL) == 0)
3005                         return (0);
3006                 break;
3007
3008         case DATA_TYPE_BOOLEAN:
3009                 ret = TRUE;
3010                 break;
3011
3012         case DATA_TYPE_BYTE:
3013         case DATA_TYPE_INT8:
3014         case DATA_TYPE_UINT8:
3015                 ret = xdr_char(xdr, buf);
3016                 break;
3017
3018         case DATA_TYPE_INT16:
3019                 ret = xdr_short(xdr, (void *)buf);
3020                 break;
3021
3022         case DATA_TYPE_UINT16:
3023                 ret = xdr_u_short(xdr, (void *)buf);
3024                 break;
3025
3026         case DATA_TYPE_BOOLEAN_VALUE:
3027         case DATA_TYPE_INT32:
3028                 ret = xdr_int(xdr, (void *)buf);
3029                 break;
3030
3031         case DATA_TYPE_UINT32:
3032                 ret = xdr_u_int(xdr, (void *)buf);
3033                 break;
3034
3035         case DATA_TYPE_INT64:
3036                 ret = xdr_longlong_t(xdr, (void *)buf);
3037                 break;
3038
3039         case DATA_TYPE_UINT64:
3040                 ret = xdr_u_longlong_t(xdr, (void *)buf);
3041                 break;
3042
3043         case DATA_TYPE_HRTIME:
3044                 /*
3045                  * NOTE: must expose the definition of hrtime_t here
3046                  */
3047                 ret = xdr_longlong_t(xdr, (void *)buf);
3048                 break;
3049 #if !defined(_KERNEL)
3050         case DATA_TYPE_DOUBLE:
3051                 ret = xdr_double(xdr, (void *)buf);
3052                 break;
3053 #endif
3054         case DATA_TYPE_STRING:
3055                 ret = xdr_string(xdr, &buf, buflen - 1);
3056                 break;
3057
3058         case DATA_TYPE_BYTE_ARRAY:
3059                 ret = xdr_opaque(xdr, buf, nelem);
3060                 break;
3061
3062         case DATA_TYPE_INT8_ARRAY:
3063         case DATA_TYPE_UINT8_ARRAY:
3064                 ret = xdr_array(xdr, &buf, &nelem, buflen, sizeof (int8_t),
3065                     (xdrproc_t)xdr_char);
3066                 break;
3067
3068         case DATA_TYPE_INT16_ARRAY:
3069                 ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (int16_t),
3070                     sizeof (int16_t), (xdrproc_t)xdr_short);
3071                 break;
3072
3073         case DATA_TYPE_UINT16_ARRAY:
3074                 ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (uint16_t),
3075                     sizeof (uint16_t), (xdrproc_t)xdr_u_short);
3076                 break;
3077
3078         case DATA_TYPE_BOOLEAN_ARRAY:
3079         case DATA_TYPE_INT32_ARRAY:
3080                 ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (int32_t),
3081                     sizeof (int32_t), (xdrproc_t)xdr_int);
3082                 break;
3083
3084         case DATA_TYPE_UINT32_ARRAY:
3085                 ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (uint32_t),
3086                     sizeof (uint32_t), (xdrproc_t)xdr_u_int);
3087                 break;
3088
3089         case DATA_TYPE_INT64_ARRAY:
3090                 ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (int64_t),
3091                     sizeof (int64_t), (xdrproc_t)xdr_longlong_t);
3092                 break;
3093
3094         case DATA_TYPE_UINT64_ARRAY:
3095                 ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (uint64_t),
3096                     sizeof (uint64_t), (xdrproc_t)xdr_u_longlong_t);
3097                 break;
3098
3099         case DATA_TYPE_STRING_ARRAY: {
3100                 size_t len = nelem * sizeof (uint64_t);
3101                 char **strp = (void *)buf;
3102                 int i;
3103
3104                 if (nvs->nvs_op == NVS_OP_DECODE)
3105                         bzero(buf, len);        /* don't trust packed data */
3106
3107                 for (i = 0; i < nelem; i++) {
3108                         if (buflen <= len)
3109                                 return (EFAULT);
3110
3111                         buf += len;
3112                         buflen -= len;
3113
3114                         if (xdr_string(xdr, &buf, buflen - 1) != TRUE)
3115                                 return (EFAULT);
3116
3117                         if (nvs->nvs_op == NVS_OP_DECODE)
3118                                 strp[i] = buf;
3119                         len = strlen(buf) + 1;
3120                 }
3121                 ret = TRUE;
3122                 break;
3123         }
3124         default:
3125                 break;
3126         }
3127
3128         return (ret == TRUE ? 0 : EFAULT);
3129 }
3130
3131 static int
3132 nvs_xdr_nvp_size(nvstream_t *nvs, nvpair_t *nvp, size_t *size)
3133 {
3134         data_type_t type = NVP_TYPE(nvp);
3135         /*
3136          * encode_size + decode_size + name string size + data type + nelem
3137          * where name string size = 4 + NV_ALIGN4(strlen(NVP_NAME(nvp)))
3138          */
3139         uint64_t nvp_sz = 4 + 4 + 4 + NV_ALIGN4(strlen(NVP_NAME(nvp))) + 4 + 4;
3140
3141         switch (type) {
3142         case DATA_TYPE_BOOLEAN:
3143                 break;
3144
3145         case DATA_TYPE_BOOLEAN_VALUE:
3146         case DATA_TYPE_BYTE:
3147         case DATA_TYPE_INT8:
3148         case DATA_TYPE_UINT8:
3149         case DATA_TYPE_INT16:
3150         case DATA_TYPE_UINT16:
3151         case DATA_TYPE_INT32:
3152         case DATA_TYPE_UINT32:
3153                 nvp_sz += 4;    /* 4 is the minimum xdr unit */
3154                 break;
3155
3156         case DATA_TYPE_INT64:
3157         case DATA_TYPE_UINT64:
3158         case DATA_TYPE_HRTIME:
3159 #if !defined(_KERNEL)
3160         case DATA_TYPE_DOUBLE:
3161 #endif
3162                 nvp_sz += 8;
3163                 break;
3164
3165         case DATA_TYPE_STRING:
3166                 nvp_sz += 4 + NV_ALIGN4(strlen((char *)NVP_VALUE(nvp)));
3167                 break;
3168
3169         case DATA_TYPE_BYTE_ARRAY:
3170                 nvp_sz += NV_ALIGN4(NVP_NELEM(nvp));
3171                 break;
3172
3173         case DATA_TYPE_BOOLEAN_ARRAY:
3174         case DATA_TYPE_INT8_ARRAY:
3175         case DATA_TYPE_UINT8_ARRAY:
3176         case DATA_TYPE_INT16_ARRAY:
3177         case DATA_TYPE_UINT16_ARRAY:
3178         case DATA_TYPE_INT32_ARRAY:
3179         case DATA_TYPE_UINT32_ARRAY:
3180                 nvp_sz += 4 + 4 * (uint64_t)NVP_NELEM(nvp);
3181                 break;
3182
3183         case DATA_TYPE_INT64_ARRAY:
3184         case DATA_TYPE_UINT64_ARRAY:
3185                 nvp_sz += 4 + 8 * (uint64_t)NVP_NELEM(nvp);
3186                 break;
3187
3188         case DATA_TYPE_STRING_ARRAY: {
3189                 int i;
3190                 char **strs = (void *)NVP_VALUE(nvp);
3191
3192                 for (i = 0; i < NVP_NELEM(nvp); i++)
3193                         nvp_sz += 4 + NV_ALIGN4(strlen(strs[i]));
3194
3195                 break;
3196         }
3197
3198         case DATA_TYPE_NVLIST:
3199         case DATA_TYPE_NVLIST_ARRAY: {
3200                 size_t nvsize = 0;
3201                 int old_nvs_op = nvs->nvs_op;
3202                 int err;
3203
3204                 nvs->nvs_op = NVS_OP_GETSIZE;
3205                 if (type == DATA_TYPE_NVLIST)
3206                         err = nvs_operation(nvs, EMBEDDED_NVL(nvp), &nvsize);
3207                 else
3208                         err = nvs_embedded_nvl_array(nvs, nvp, &nvsize);
3209                 nvs->nvs_op = old_nvs_op;
3210
3211                 if (err != 0)
3212                         return (EINVAL);
3213
3214                 nvp_sz += nvsize;
3215                 break;
3216         }
3217
3218         default:
3219                 return (EINVAL);
3220         }
3221
3222         if (nvp_sz > INT32_MAX)
3223                 return (EINVAL);
3224
3225         *size = nvp_sz;
3226
3227         return (0);
3228 }
3229
3230
3231 /*
3232  * The NVS_XDR_MAX_LEN macro takes a packed xdr buffer of size x and estimates
3233  * the largest nvpair that could be encoded in the buffer.
3234  *
3235  * See comments above nvpair_xdr_op() for the format of xdr encoding.
3236  * The size of a xdr packed nvpair without any data is 5 words.
3237  *
3238  * Using the size of the data directly as an estimate would be ok
3239  * in all cases except one.  If the data type is of DATA_TYPE_STRING_ARRAY
3240  * then the actual nvpair has space for an array of pointers to index
3241  * the strings.  These pointers are not encoded into the packed xdr buffer.
3242  *
3243  * If the data is of type DATA_TYPE_STRING_ARRAY and all the strings are
3244  * of length 0, then each string is endcoded in xdr format as a single word.
3245  * Therefore when expanded to an nvpair there will be 2.25 word used for
3246  * each string.  (a int64_t allocated for pointer usage, and a single char
3247  * for the null termination.)
3248  *
3249  * This is the calculation performed by the NVS_XDR_MAX_LEN macro.
3250  */
3251 #define NVS_XDR_HDR_LEN         ((size_t)(5 * 4))
3252 #define NVS_XDR_DATA_LEN(y)     (((size_t)(y) <= NVS_XDR_HDR_LEN) ? \
3253                                         0 : ((size_t)(y) - NVS_XDR_HDR_LEN))
3254 #define NVS_XDR_MAX_LEN(x)      (NVP_SIZE_CALC(1, 0) + \
3255                                         (NVS_XDR_DATA_LEN(x) * 2) + \
3256                                         NV_ALIGN4((NVS_XDR_DATA_LEN(x) / 4)))
3257
3258 static int
3259 nvs_xdr_nvpair(nvstream_t *nvs, nvpair_t *nvp, size_t *size)
3260 {
3261         XDR     *xdr = nvs->nvs_private;
3262         int32_t encode_len, decode_len;
3263
3264         switch (nvs->nvs_op) {
3265         case NVS_OP_ENCODE: {
3266                 size_t nvsize;
3267
3268                 if (nvs_xdr_nvp_size(nvs, nvp, &nvsize) != 0)
3269                         return (EFAULT);
3270
3271                 decode_len = nvp->nvp_size;
3272                 encode_len = nvsize;
3273                 if (!xdr_int(xdr, &encode_len) || !xdr_int(xdr, &decode_len))
3274                         return (EFAULT);
3275
3276                 return (nvs_xdr_nvp_op(nvs, nvp));
3277         }
3278         case NVS_OP_DECODE: {
3279                 struct xdr_bytesrec bytesrec;
3280
3281                 /* get the encode and decode size */
3282                 if (!xdr_int(xdr, &encode_len) || !xdr_int(xdr, &decode_len))
3283                         return (EFAULT);
3284                 *size = decode_len;
3285
3286                 /* are we at the end of the stream? */
3287                 if (*size == 0)
3288                         return (0);
3289
3290                 /* sanity check the size parameter */
3291                 if (!xdr_control(xdr, XDR_GET_BYTES_AVAIL, &bytesrec))
3292                         return (EFAULT);
3293
3294                 if (*size > NVS_XDR_MAX_LEN(bytesrec.xc_num_avail))
3295                         return (EFAULT);
3296                 break;
3297         }
3298
3299         default:
3300                 return (EINVAL);
3301         }
3302         return (0);
3303 }
3304
3305 static const struct nvs_ops nvs_xdr_ops = {
3306         nvs_xdr_nvlist,
3307         nvs_xdr_nvpair,
3308         nvs_xdr_nvp_op,
3309         nvs_xdr_nvp_size,
3310         nvs_xdr_nvl_fini
3311 };
3312
3313 static int
3314 nvs_xdr(nvstream_t *nvs, nvlist_t *nvl, char *buf, size_t *buflen)
3315 {
3316         XDR xdr;
3317         int err;
3318
3319         nvs->nvs_ops = &nvs_xdr_ops;
3320
3321         if ((err = nvs_xdr_create(nvs, &xdr, buf + sizeof (nvs_header_t),
3322             *buflen - sizeof (nvs_header_t))) != 0)
3323                 return (err);
3324
3325         err = nvs_operation(nvs, nvl, buflen);
3326
3327         nvs_xdr_destroy(nvs);
3328
3329         return (err);
3330 }