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