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