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