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