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