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