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