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