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_INT8_ARRAY) ||
1233 (type == DATA_TYPE_UINT8_ARRAY) ||
1234 (type == DATA_TYPE_INT16_ARRAY) ||
1235 (type == DATA_TYPE_UINT16_ARRAY) ||
1236 (type == DATA_TYPE_INT32_ARRAY) ||
1237 (type == DATA_TYPE_UINT32_ARRAY) ||
1238 (type == DATA_TYPE_INT64_ARRAY) ||
1239 (type == DATA_TYPE_UINT64_ARRAY) ||
1240 (type == DATA_TYPE_BOOLEAN_ARRAY) ||
1241 (type == DATA_TYPE_STRING_ARRAY) ||
1242 (type == DATA_TYPE_NVLIST_ARRAY))
1243 return (1);
1244 return (0);
1245
1246 }
1247
1248 static int
nvpair_value_common(nvpair_t * nvp,data_type_t type,uint_t * nelem,void * data)1249 nvpair_value_common(nvpair_t *nvp, data_type_t type, uint_t *nelem, void *data)
1250 {
1251 if (nvp == NULL || nvpair_type(nvp) != type)
1252 return (EINVAL);
1253
1254 /*
1255 * For non-array types, we copy the data.
1256 * For array types (including string), we set a pointer.
1257 */
1258 switch (type) {
1259 case DATA_TYPE_BOOLEAN:
1260 if (nelem != NULL)
1261 *nelem = 0;
1262 break;
1263
1264 case DATA_TYPE_BOOLEAN_VALUE:
1265 case DATA_TYPE_BYTE:
1266 case DATA_TYPE_INT8:
1267 case DATA_TYPE_UINT8:
1268 case DATA_TYPE_INT16:
1269 case DATA_TYPE_UINT16:
1270 case DATA_TYPE_INT32:
1271 case DATA_TYPE_UINT32:
1272 case DATA_TYPE_INT64:
1273 case DATA_TYPE_UINT64:
1274 case DATA_TYPE_HRTIME:
1275 #if !defined(_KERNEL)
1276 case DATA_TYPE_DOUBLE:
1277 #endif
1278 if (data == NULL)
1279 return (EINVAL);
1280 bcopy(NVP_VALUE(nvp), data,
1281 (size_t)i_get_value_size(type, NULL, 1));
1282 if (nelem != NULL)
1283 *nelem = 1;
1284 break;
1285
1286 case DATA_TYPE_NVLIST:
1287 case DATA_TYPE_STRING:
1288 if (data == NULL)
1289 return (EINVAL);
1290 *(void **)data = (void *)NVP_VALUE(nvp);
1291 if (nelem != NULL)
1292 *nelem = 1;
1293 break;
1294
1295 case DATA_TYPE_BOOLEAN_ARRAY:
1296 case DATA_TYPE_BYTE_ARRAY:
1297 case DATA_TYPE_INT8_ARRAY:
1298 case DATA_TYPE_UINT8_ARRAY:
1299 case DATA_TYPE_INT16_ARRAY:
1300 case DATA_TYPE_UINT16_ARRAY:
1301 case DATA_TYPE_INT32_ARRAY:
1302 case DATA_TYPE_UINT32_ARRAY:
1303 case DATA_TYPE_INT64_ARRAY:
1304 case DATA_TYPE_UINT64_ARRAY:
1305 case DATA_TYPE_STRING_ARRAY:
1306 case DATA_TYPE_NVLIST_ARRAY:
1307 if (nelem == NULL || data == NULL)
1308 return (EINVAL);
1309 if ((*nelem = NVP_NELEM(nvp)) != 0)
1310 *(void **)data = (void *)NVP_VALUE(nvp);
1311 else
1312 *(void **)data = NULL;
1313 break;
1314
1315 default:
1316 return (ENOTSUP);
1317 }
1318
1319 return (0);
1320 }
1321
1322 static int
nvlist_lookup_common(nvlist_t * nvl,const char * name,data_type_t type,uint_t * nelem,void * data)1323 nvlist_lookup_common(nvlist_t *nvl, const char *name, data_type_t type,
1324 uint_t *nelem, void *data)
1325 {
1326 nvpriv_t *priv;
1327 nvpair_t *nvp;
1328 i_nvp_t *curr;
1329
1330 if (name == NULL || nvl == NULL ||
1331 (priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL)
1332 return (EINVAL);
1333
1334 if (!(nvl->nvl_nvflag & (NV_UNIQUE_NAME | NV_UNIQUE_NAME_TYPE)))
1335 return (ENOTSUP);
1336
1337 for (curr = priv->nvp_list; curr != NULL; curr = curr->nvi_next) {
1338 nvp = &curr->nvi_nvp;
1339
1340 if (strcmp(name, NVP_NAME(nvp)) == 0 && NVP_TYPE(nvp) == type)
1341 return (nvpair_value_common(nvp, type, nelem, data));
1342 }
1343
1344 return (ENOENT);
1345 }
1346
1347 int
nvlist_lookup_boolean(nvlist_t * nvl,const char * name)1348 nvlist_lookup_boolean(nvlist_t *nvl, const char *name)
1349 {
1350 return (nvlist_lookup_common(nvl, name, DATA_TYPE_BOOLEAN, NULL, NULL));
1351 }
1352
1353 int
nvlist_lookup_boolean_value(nvlist_t * nvl,const char * name,boolean_t * val)1354 nvlist_lookup_boolean_value(nvlist_t *nvl, const char *name, boolean_t *val)
1355 {
1356 return (nvlist_lookup_common(nvl, name,
1357 DATA_TYPE_BOOLEAN_VALUE, NULL, val));
1358 }
1359
1360 int
nvlist_lookup_byte(nvlist_t * nvl,const char * name,uchar_t * val)1361 nvlist_lookup_byte(nvlist_t *nvl, const char *name, uchar_t *val)
1362 {
1363 return (nvlist_lookup_common(nvl, name, DATA_TYPE_BYTE, NULL, val));
1364 }
1365
1366 int
nvlist_lookup_int8(nvlist_t * nvl,const char * name,int8_t * val)1367 nvlist_lookup_int8(nvlist_t *nvl, const char *name, int8_t *val)
1368 {
1369 return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT8, NULL, val));
1370 }
1371
1372 int
nvlist_lookup_uint8(nvlist_t * nvl,const char * name,uint8_t * val)1373 nvlist_lookup_uint8(nvlist_t *nvl, const char *name, uint8_t *val)
1374 {
1375 return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT8, NULL, val));
1376 }
1377
1378 int
nvlist_lookup_int16(nvlist_t * nvl,const char * name,int16_t * val)1379 nvlist_lookup_int16(nvlist_t *nvl, const char *name, int16_t *val)
1380 {
1381 return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT16, NULL, val));
1382 }
1383
1384 int
nvlist_lookup_uint16(nvlist_t * nvl,const char * name,uint16_t * val)1385 nvlist_lookup_uint16(nvlist_t *nvl, const char *name, uint16_t *val)
1386 {
1387 return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT16, NULL, val));
1388 }
1389
1390 int
nvlist_lookup_int32(nvlist_t * nvl,const char * name,int32_t * val)1391 nvlist_lookup_int32(nvlist_t *nvl, const char *name, int32_t *val)
1392 {
1393 return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT32, NULL, val));
1394 }
1395
1396 int
nvlist_lookup_uint32(nvlist_t * nvl,const char * name,uint32_t * val)1397 nvlist_lookup_uint32(nvlist_t *nvl, const char *name, uint32_t *val)
1398 {
1399 return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT32, NULL, val));
1400 }
1401
1402 int
nvlist_lookup_int64(nvlist_t * nvl,const char * name,int64_t * val)1403 nvlist_lookup_int64(nvlist_t *nvl, const char *name, int64_t *val)
1404 {
1405 return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT64, NULL, val));
1406 }
1407
1408 int
nvlist_lookup_uint64(nvlist_t * nvl,const char * name,uint64_t * val)1409 nvlist_lookup_uint64(nvlist_t *nvl, const char *name, uint64_t *val)
1410 {
1411 return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT64, NULL, val));
1412 }
1413
1414 #if !defined(_KERNEL)
1415 int
nvlist_lookup_double(nvlist_t * nvl,const char * name,double * val)1416 nvlist_lookup_double(nvlist_t *nvl, const char *name, double *val)
1417 {
1418 return (nvlist_lookup_common(nvl, name, DATA_TYPE_DOUBLE, NULL, val));
1419 }
1420 #endif
1421
1422 int
nvlist_lookup_string(nvlist_t * nvl,const char * name,char ** val)1423 nvlist_lookup_string(nvlist_t *nvl, const char *name, char **val)
1424 {
1425 return (nvlist_lookup_common(nvl, name, DATA_TYPE_STRING, NULL, val));
1426 }
1427
1428 int
nvlist_lookup_nvlist(nvlist_t * nvl,const char * name,nvlist_t ** val)1429 nvlist_lookup_nvlist(nvlist_t *nvl, const char *name, nvlist_t **val)
1430 {
1431 return (nvlist_lookup_common(nvl, name, DATA_TYPE_NVLIST, NULL, val));
1432 }
1433
1434 int
nvlist_lookup_boolean_array(nvlist_t * nvl,const char * name,boolean_t ** a,uint_t * n)1435 nvlist_lookup_boolean_array(nvlist_t *nvl, const char *name,
1436 boolean_t **a, uint_t *n)
1437 {
1438 return (nvlist_lookup_common(nvl, name,
1439 DATA_TYPE_BOOLEAN_ARRAY, n, a));
1440 }
1441
1442 int
nvlist_lookup_byte_array(nvlist_t * nvl,const char * name,uchar_t ** a,uint_t * n)1443 nvlist_lookup_byte_array(nvlist_t *nvl, const char *name,
1444 uchar_t **a, uint_t *n)
1445 {
1446 return (nvlist_lookup_common(nvl, name, DATA_TYPE_BYTE_ARRAY, n, a));
1447 }
1448
1449 int
nvlist_lookup_int8_array(nvlist_t * nvl,const char * name,int8_t ** a,uint_t * n)1450 nvlist_lookup_int8_array(nvlist_t *nvl, const char *name, int8_t **a, uint_t *n)
1451 {
1452 return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT8_ARRAY, n, a));
1453 }
1454
1455 int
nvlist_lookup_uint8_array(nvlist_t * nvl,const char * name,uint8_t ** a,uint_t * n)1456 nvlist_lookup_uint8_array(nvlist_t *nvl, const char *name,
1457 uint8_t **a, uint_t *n)
1458 {
1459 return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT8_ARRAY, n, a));
1460 }
1461
1462 int
nvlist_lookup_int16_array(nvlist_t * nvl,const char * name,int16_t ** a,uint_t * n)1463 nvlist_lookup_int16_array(nvlist_t *nvl, const char *name,
1464 int16_t **a, uint_t *n)
1465 {
1466 return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT16_ARRAY, n, a));
1467 }
1468
1469 int
nvlist_lookup_uint16_array(nvlist_t * nvl,const char * name,uint16_t ** a,uint_t * n)1470 nvlist_lookup_uint16_array(nvlist_t *nvl, const char *name,
1471 uint16_t **a, uint_t *n)
1472 {
1473 return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT16_ARRAY, n, a));
1474 }
1475
1476 int
nvlist_lookup_int32_array(nvlist_t * nvl,const char * name,int32_t ** a,uint_t * n)1477 nvlist_lookup_int32_array(nvlist_t *nvl, const char *name,
1478 int32_t **a, uint_t *n)
1479 {
1480 return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT32_ARRAY, n, a));
1481 }
1482
1483 int
nvlist_lookup_uint32_array(nvlist_t * nvl,const char * name,uint32_t ** a,uint_t * n)1484 nvlist_lookup_uint32_array(nvlist_t *nvl, const char *name,
1485 uint32_t **a, uint_t *n)
1486 {
1487 return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT32_ARRAY, n, a));
1488 }
1489
1490 int
nvlist_lookup_int64_array(nvlist_t * nvl,const char * name,int64_t ** a,uint_t * n)1491 nvlist_lookup_int64_array(nvlist_t *nvl, const char *name,
1492 int64_t **a, uint_t *n)
1493 {
1494 return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT64_ARRAY, n, a));
1495 }
1496
1497 int
nvlist_lookup_uint64_array(nvlist_t * nvl,const char * name,uint64_t ** a,uint_t * n)1498 nvlist_lookup_uint64_array(nvlist_t *nvl, const char *name,
1499 uint64_t **a, uint_t *n)
1500 {
1501 return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT64_ARRAY, n, a));
1502 }
1503
1504 int
nvlist_lookup_string_array(nvlist_t * nvl,const char * name,char *** a,uint_t * n)1505 nvlist_lookup_string_array(nvlist_t *nvl, const char *name,
1506 char ***a, uint_t *n)
1507 {
1508 return (nvlist_lookup_common(nvl, name, DATA_TYPE_STRING_ARRAY, n, a));
1509 }
1510
1511 int
nvlist_lookup_nvlist_array(nvlist_t * nvl,const char * name,nvlist_t *** a,uint_t * n)1512 nvlist_lookup_nvlist_array(nvlist_t *nvl, const char *name,
1513 nvlist_t ***a, uint_t *n)
1514 {
1515 return (nvlist_lookup_common(nvl, name, DATA_TYPE_NVLIST_ARRAY, n, a));
1516 }
1517
1518 int
nvlist_lookup_hrtime(nvlist_t * nvl,const char * name,hrtime_t * val)1519 nvlist_lookup_hrtime(nvlist_t *nvl, const char *name, hrtime_t *val)
1520 {
1521 return (nvlist_lookup_common(nvl, name, DATA_TYPE_HRTIME, NULL, val));
1522 }
1523
1524 int
nvlist_lookup_pairs(nvlist_t * nvl,int flag,...)1525 nvlist_lookup_pairs(nvlist_t *nvl, int flag, ...)
1526 {
1527 va_list ap;
1528 char *name;
1529 int noentok = (flag & NV_FLAG_NOENTOK ? 1 : 0);
1530 int ret = 0;
1531
1532 va_start(ap, flag);
1533 while (ret == 0 && (name = va_arg(ap, char *)) != NULL) {
1534 data_type_t type;
1535 void *val;
1536 uint_t *nelem;
1537
1538 switch (type = va_arg(ap, data_type_t)) {
1539 case DATA_TYPE_BOOLEAN:
1540 ret = nvlist_lookup_common(nvl, name, type, NULL, NULL);
1541 break;
1542
1543 case DATA_TYPE_BOOLEAN_VALUE:
1544 case DATA_TYPE_BYTE:
1545 case DATA_TYPE_INT8:
1546 case DATA_TYPE_UINT8:
1547 case DATA_TYPE_INT16:
1548 case DATA_TYPE_UINT16:
1549 case DATA_TYPE_INT32:
1550 case DATA_TYPE_UINT32:
1551 case DATA_TYPE_INT64:
1552 case DATA_TYPE_UINT64:
1553 case DATA_TYPE_HRTIME:
1554 case DATA_TYPE_STRING:
1555 case DATA_TYPE_NVLIST:
1556 #if !defined(_KERNEL)
1557 case DATA_TYPE_DOUBLE:
1558 #endif
1559 val = va_arg(ap, void *);
1560 ret = nvlist_lookup_common(nvl, name, type, NULL, val);
1561 break;
1562
1563 case DATA_TYPE_BYTE_ARRAY:
1564 case DATA_TYPE_BOOLEAN_ARRAY:
1565 case DATA_TYPE_INT8_ARRAY:
1566 case DATA_TYPE_UINT8_ARRAY:
1567 case DATA_TYPE_INT16_ARRAY:
1568 case DATA_TYPE_UINT16_ARRAY:
1569 case DATA_TYPE_INT32_ARRAY:
1570 case DATA_TYPE_UINT32_ARRAY:
1571 case DATA_TYPE_INT64_ARRAY:
1572 case DATA_TYPE_UINT64_ARRAY:
1573 case DATA_TYPE_STRING_ARRAY:
1574 case DATA_TYPE_NVLIST_ARRAY:
1575 val = va_arg(ap, void *);
1576 nelem = va_arg(ap, uint_t *);
1577 ret = nvlist_lookup_common(nvl, name, type, nelem, val);
1578 break;
1579
1580 default:
1581 ret = EINVAL;
1582 }
1583
1584 if (ret == ENOENT && noentok)
1585 ret = 0;
1586 }
1587 va_end(ap);
1588
1589 return (ret);
1590 }
1591
1592 /*
1593 * Find the 'name'ed nvpair in the nvlist 'nvl'. If 'name' found, the function
1594 * returns zero and a pointer to the matching nvpair is returned in '*ret'
1595 * (given 'ret' is non-NULL). If 'sep' is specified then 'name' will penitrate
1596 * multiple levels of embedded nvlists, with 'sep' as the separator. As an
1597 * example, if sep is '.', name might look like: "a" or "a.b" or "a.c[3]" or
1598 * "a.d[3].e[1]". This matches the C syntax for array embed (for convience,
1599 * code also supports "a.d[3]e[1]" syntax).
1600 *
1601 * If 'ip' is non-NULL and the last name component is an array, return the
1602 * value of the "...[index]" array index in *ip. For an array reference that
1603 * is not indexed, *ip will be returned as -1. If there is a syntax error in
1604 * 'name', and 'ep' is non-NULL then *ep will be set to point to the location
1605 * inside the 'name' string where the syntax error was detected.
1606 */
1607 static int
nvlist_lookup_nvpair_ei_sep(nvlist_t * nvl,const char * name,const char sep,nvpair_t ** ret,int * ip,char ** ep)1608 nvlist_lookup_nvpair_ei_sep(nvlist_t *nvl, const char *name, const char sep,
1609 nvpair_t **ret, int *ip, char **ep)
1610 {
1611 nvpair_t *nvp;
1612 const char *np;
1613 char *sepp;
1614 char *idxp, *idxep;
1615 nvlist_t **nva;
1616 long idx;
1617 int n;
1618
1619 if (ip)
1620 *ip = -1; /* not indexed */
1621 if (ep)
1622 *ep = NULL;
1623
1624 if ((nvl == NULL) || (name == NULL))
1625 return (EINVAL);
1626
1627 sepp = NULL;
1628 idx = 0;
1629 /* step through components of name */
1630 for (np = name; np && *np; np = sepp) {
1631 /* ensure unique names */
1632 if (!(nvl->nvl_nvflag & NV_UNIQUE_NAME))
1633 return (ENOTSUP);
1634
1635 /* skip white space */
1636 skip_whitespace(np);
1637 if (*np == 0)
1638 break;
1639
1640 /* set 'sepp' to end of current component 'np' */
1641 if (sep)
1642 sepp = strchr(np, sep);
1643 else
1644 sepp = NULL;
1645
1646 /* find start of next "[ index ]..." */
1647 idxp = strchr(np, '[');
1648
1649 /* if sepp comes first, set idxp to NULL */
1650 if (sepp && idxp && (sepp < idxp))
1651 idxp = NULL;
1652
1653 /*
1654 * At this point 'idxp' is set if there is an index
1655 * expected for the current component.
1656 */
1657 if (idxp) {
1658 /* set 'n' to length of current 'np' name component */
1659 n = idxp++ - np;
1660
1661 /* keep sepp up to date for *ep use as we advance */
1662 skip_whitespace(idxp);
1663 sepp = idxp;
1664
1665 /* determine the index value */
1666 #if defined(_KERNEL) && !defined(_BOOT)
1667 if (ddi_strtol(idxp, &idxep, 0, &idx))
1668 goto fail;
1669 #else
1670 idx = strtol(idxp, &idxep, 0);
1671 #endif
1672 if (idxep == idxp)
1673 goto fail;
1674
1675 /* keep sepp up to date for *ep use as we advance */
1676 sepp = idxep;
1677
1678 /* skip white space index value and check for ']' */
1679 skip_whitespace(sepp);
1680 if (*sepp++ != ']')
1681 goto fail;
1682
1683 /* for embedded arrays, support C syntax: "a[1].b" */
1684 skip_whitespace(sepp);
1685 if (sep && (*sepp == sep))
1686 sepp++;
1687 } else if (sepp) {
1688 n = sepp++ - np;
1689 } else {
1690 n = strlen(np);
1691 }
1692
1693 /* trim trailing whitespace by reducing length of 'np' */
1694 if (n == 0)
1695 goto fail;
1696 for (n--; (np[n] == ' ') || (np[n] == '\t'); n--)
1697 ;
1698 n++;
1699
1700 /* skip whitespace, and set sepp to NULL if complete */
1701 if (sepp) {
1702 skip_whitespace(sepp);
1703 if (*sepp == 0)
1704 sepp = NULL;
1705 }
1706
1707 /*
1708 * At this point:
1709 * o 'n' is the length of current 'np' component.
1710 * o 'idxp' is set if there was an index, and value 'idx'.
1711 * o 'sepp' is set to the beginning of the next component,
1712 * and set to NULL if we have no more components.
1713 *
1714 * Search for nvpair with matching component name.
1715 */
1716 for (nvp = nvlist_next_nvpair(nvl, NULL); nvp != NULL;
1717 nvp = nvlist_next_nvpair(nvl, nvp)) {
1718
1719 /* continue if no match on name */
1720 if (strncmp(np, nvpair_name(nvp), n) ||
1721 (strlen(nvpair_name(nvp)) != n))
1722 continue;
1723
1724 /* if indexed, verify type is array oriented */
1725 if (idxp && !nvpair_type_is_array(nvp))
1726 goto fail;
1727
1728 /*
1729 * Full match found, return nvp and idx if this
1730 * was the last component.
1731 */
1732 if (sepp == NULL) {
1733 if (ret)
1734 *ret = nvp;
1735 if (ip && idxp)
1736 *ip = (int)idx; /* return index */
1737 return (0); /* found */
1738 }
1739
1740 /*
1741 * More components: current match must be
1742 * of DATA_TYPE_NVLIST or DATA_TYPE_NVLIST_ARRAY
1743 * to support going deeper.
1744 */
1745 if (nvpair_type(nvp) == DATA_TYPE_NVLIST) {
1746 nvl = EMBEDDED_NVL(nvp);
1747 break;
1748 } else if (nvpair_type(nvp) == DATA_TYPE_NVLIST_ARRAY) {
1749 (void) nvpair_value_nvlist_array(nvp,
1750 &nva, (uint_t *)&n);
1751 if ((n < 0) || (idx >= n))
1752 goto fail;
1753 nvl = nva[idx];
1754 break;
1755 }
1756
1757 /* type does not support more levels */
1758 goto fail;
1759 }
1760 if (nvp == NULL)
1761 goto fail; /* 'name' not found */
1762
1763 /* search for match of next component in embedded 'nvl' list */
1764 }
1765
1766 fail: if (ep && sepp)
1767 *ep = sepp;
1768 return (EINVAL);
1769 }
1770
1771 /*
1772 * Return pointer to nvpair with specified 'name'.
1773 */
1774 int
nvlist_lookup_nvpair(nvlist_t * nvl,const char * name,nvpair_t ** ret)1775 nvlist_lookup_nvpair(nvlist_t *nvl, const char *name, nvpair_t **ret)
1776 {
1777 return (nvlist_lookup_nvpair_ei_sep(nvl, name, 0, ret, NULL, NULL));
1778 }
1779
1780 /*
1781 * Determine if named nvpair exists in nvlist (use embedded separator of '.'
1782 * and return array index). See nvlist_lookup_nvpair_ei_sep for more detailed
1783 * description.
1784 */
nvlist_lookup_nvpair_embedded_index(nvlist_t * nvl,const char * name,nvpair_t ** ret,int * ip,char ** ep)1785 int nvlist_lookup_nvpair_embedded_index(nvlist_t *nvl,
1786 const char *name, nvpair_t **ret, int *ip, char **ep)
1787 {
1788 return (nvlist_lookup_nvpair_ei_sep(nvl, name, '.', ret, ip, ep));
1789 }
1790
1791 boolean_t
nvlist_exists(nvlist_t * nvl,const char * name)1792 nvlist_exists(nvlist_t *nvl, const char *name)
1793 {
1794 nvpriv_t *priv;
1795 nvpair_t *nvp;
1796 i_nvp_t *curr;
1797
1798 if (name == NULL || nvl == NULL ||
1799 (priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL)
1800 return (B_FALSE);
1801
1802 for (curr = priv->nvp_list; curr != NULL; curr = curr->nvi_next) {
1803 nvp = &curr->nvi_nvp;
1804
1805 if (strcmp(name, NVP_NAME(nvp)) == 0)
1806 return (B_TRUE);
1807 }
1808
1809 return (B_FALSE);
1810 }
1811
1812 int
nvpair_value_boolean_value(nvpair_t * nvp,boolean_t * val)1813 nvpair_value_boolean_value(nvpair_t *nvp, boolean_t *val)
1814 {
1815 return (nvpair_value_common(nvp, DATA_TYPE_BOOLEAN_VALUE, NULL, val));
1816 }
1817
1818 int
nvpair_value_byte(nvpair_t * nvp,uchar_t * val)1819 nvpair_value_byte(nvpair_t *nvp, uchar_t *val)
1820 {
1821 return (nvpair_value_common(nvp, DATA_TYPE_BYTE, NULL, val));
1822 }
1823
1824 int
nvpair_value_int8(nvpair_t * nvp,int8_t * val)1825 nvpair_value_int8(nvpair_t *nvp, int8_t *val)
1826 {
1827 return (nvpair_value_common(nvp, DATA_TYPE_INT8, NULL, val));
1828 }
1829
1830 int
nvpair_value_uint8(nvpair_t * nvp,uint8_t * val)1831 nvpair_value_uint8(nvpair_t *nvp, uint8_t *val)
1832 {
1833 return (nvpair_value_common(nvp, DATA_TYPE_UINT8, NULL, val));
1834 }
1835
1836 int
nvpair_value_int16(nvpair_t * nvp,int16_t * val)1837 nvpair_value_int16(nvpair_t *nvp, int16_t *val)
1838 {
1839 return (nvpair_value_common(nvp, DATA_TYPE_INT16, NULL, val));
1840 }
1841
1842 int
nvpair_value_uint16(nvpair_t * nvp,uint16_t * val)1843 nvpair_value_uint16(nvpair_t *nvp, uint16_t *val)
1844 {
1845 return (nvpair_value_common(nvp, DATA_TYPE_UINT16, NULL, val));
1846 }
1847
1848 int
nvpair_value_int32(nvpair_t * nvp,int32_t * val)1849 nvpair_value_int32(nvpair_t *nvp, int32_t *val)
1850 {
1851 return (nvpair_value_common(nvp, DATA_TYPE_INT32, NULL, val));
1852 }
1853
1854 int
nvpair_value_uint32(nvpair_t * nvp,uint32_t * val)1855 nvpair_value_uint32(nvpair_t *nvp, uint32_t *val)
1856 {
1857 return (nvpair_value_common(nvp, DATA_TYPE_UINT32, NULL, val));
1858 }
1859
1860 int
nvpair_value_int64(nvpair_t * nvp,int64_t * val)1861 nvpair_value_int64(nvpair_t *nvp, int64_t *val)
1862 {
1863 return (nvpair_value_common(nvp, DATA_TYPE_INT64, NULL, val));
1864 }
1865
1866 int
nvpair_value_uint64(nvpair_t * nvp,uint64_t * val)1867 nvpair_value_uint64(nvpair_t *nvp, uint64_t *val)
1868 {
1869 return (nvpair_value_common(nvp, DATA_TYPE_UINT64, NULL, val));
1870 }
1871
1872 #if !defined(_KERNEL)
1873 int
nvpair_value_double(nvpair_t * nvp,double * val)1874 nvpair_value_double(nvpair_t *nvp, double *val)
1875 {
1876 return (nvpair_value_common(nvp, DATA_TYPE_DOUBLE, NULL, val));
1877 }
1878 #endif
1879
1880 int
nvpair_value_string(nvpair_t * nvp,char ** val)1881 nvpair_value_string(nvpair_t *nvp, char **val)
1882 {
1883 return (nvpair_value_common(nvp, DATA_TYPE_STRING, NULL, val));
1884 }
1885
1886 int
nvpair_value_nvlist(nvpair_t * nvp,nvlist_t ** val)1887 nvpair_value_nvlist(nvpair_t *nvp, nvlist_t **val)
1888 {
1889 return (nvpair_value_common(nvp, DATA_TYPE_NVLIST, NULL, val));
1890 }
1891
1892 int
nvpair_value_boolean_array(nvpair_t * nvp,boolean_t ** val,uint_t * nelem)1893 nvpair_value_boolean_array(nvpair_t *nvp, boolean_t **val, uint_t *nelem)
1894 {
1895 return (nvpair_value_common(nvp, DATA_TYPE_BOOLEAN_ARRAY, nelem, val));
1896 }
1897
1898 int
nvpair_value_byte_array(nvpair_t * nvp,uchar_t ** val,uint_t * nelem)1899 nvpair_value_byte_array(nvpair_t *nvp, uchar_t **val, uint_t *nelem)
1900 {
1901 return (nvpair_value_common(nvp, DATA_TYPE_BYTE_ARRAY, nelem, val));
1902 }
1903
1904 int
nvpair_value_int8_array(nvpair_t * nvp,int8_t ** val,uint_t * nelem)1905 nvpair_value_int8_array(nvpair_t *nvp, int8_t **val, uint_t *nelem)
1906 {
1907 return (nvpair_value_common(nvp, DATA_TYPE_INT8_ARRAY, nelem, val));
1908 }
1909
1910 int
nvpair_value_uint8_array(nvpair_t * nvp,uint8_t ** val,uint_t * nelem)1911 nvpair_value_uint8_array(nvpair_t *nvp, uint8_t **val, uint_t *nelem)
1912 {
1913 return (nvpair_value_common(nvp, DATA_TYPE_UINT8_ARRAY, nelem, val));
1914 }
1915
1916 int
nvpair_value_int16_array(nvpair_t * nvp,int16_t ** val,uint_t * nelem)1917 nvpair_value_int16_array(nvpair_t *nvp, int16_t **val, uint_t *nelem)
1918 {
1919 return (nvpair_value_common(nvp, DATA_TYPE_INT16_ARRAY, nelem, val));
1920 }
1921
1922 int
nvpair_value_uint16_array(nvpair_t * nvp,uint16_t ** val,uint_t * nelem)1923 nvpair_value_uint16_array(nvpair_t *nvp, uint16_t **val, uint_t *nelem)
1924 {
1925 return (nvpair_value_common(nvp, DATA_TYPE_UINT16_ARRAY, nelem, val));
1926 }
1927
1928 int
nvpair_value_int32_array(nvpair_t * nvp,int32_t ** val,uint_t * nelem)1929 nvpair_value_int32_array(nvpair_t *nvp, int32_t **val, uint_t *nelem)
1930 {
1931 return (nvpair_value_common(nvp, DATA_TYPE_INT32_ARRAY, nelem, val));
1932 }
1933
1934 int
nvpair_value_uint32_array(nvpair_t * nvp,uint32_t ** val,uint_t * nelem)1935 nvpair_value_uint32_array(nvpair_t *nvp, uint32_t **val, uint_t *nelem)
1936 {
1937 return (nvpair_value_common(nvp, DATA_TYPE_UINT32_ARRAY, nelem, val));
1938 }
1939
1940 int
nvpair_value_int64_array(nvpair_t * nvp,int64_t ** val,uint_t * nelem)1941 nvpair_value_int64_array(nvpair_t *nvp, int64_t **val, uint_t *nelem)
1942 {
1943 return (nvpair_value_common(nvp, DATA_TYPE_INT64_ARRAY, nelem, val));
1944 }
1945
1946 int
nvpair_value_uint64_array(nvpair_t * nvp,uint64_t ** val,uint_t * nelem)1947 nvpair_value_uint64_array(nvpair_t *nvp, uint64_t **val, uint_t *nelem)
1948 {
1949 return (nvpair_value_common(nvp, DATA_TYPE_UINT64_ARRAY, nelem, val));
1950 }
1951
1952 int
nvpair_value_string_array(nvpair_t * nvp,char *** val,uint_t * nelem)1953 nvpair_value_string_array(nvpair_t *nvp, char ***val, uint_t *nelem)
1954 {
1955 return (nvpair_value_common(nvp, DATA_TYPE_STRING_ARRAY, nelem, val));
1956 }
1957
1958 int
nvpair_value_nvlist_array(nvpair_t * nvp,nvlist_t *** val,uint_t * nelem)1959 nvpair_value_nvlist_array(nvpair_t *nvp, nvlist_t ***val, uint_t *nelem)
1960 {
1961 return (nvpair_value_common(nvp, DATA_TYPE_NVLIST_ARRAY, nelem, val));
1962 }
1963
1964 int
nvpair_value_hrtime(nvpair_t * nvp,hrtime_t * val)1965 nvpair_value_hrtime(nvpair_t *nvp, hrtime_t *val)
1966 {
1967 return (nvpair_value_common(nvp, DATA_TYPE_HRTIME, NULL, val));
1968 }
1969
1970 /*
1971 * Add specified pair to the list.
1972 */
1973 int
nvlist_add_nvpair(nvlist_t * nvl,nvpair_t * nvp)1974 nvlist_add_nvpair(nvlist_t *nvl, nvpair_t *nvp)
1975 {
1976 if (nvl == NULL || nvp == NULL)
1977 return (EINVAL);
1978
1979 return (nvlist_add_common(nvl, NVP_NAME(nvp), NVP_TYPE(nvp),
1980 NVP_NELEM(nvp), NVP_VALUE(nvp)));
1981 }
1982
1983 /*
1984 * Merge the supplied nvlists and put the result in dst.
1985 * The merged list will contain all names specified in both lists,
1986 * the values are taken from nvl in the case of duplicates.
1987 * Return 0 on success.
1988 */
1989 /*ARGSUSED*/
1990 int
nvlist_merge(nvlist_t * dst,nvlist_t * nvl,int flag)1991 nvlist_merge(nvlist_t *dst, nvlist_t *nvl, int flag)
1992 {
1993 if (nvl == NULL || dst == NULL)
1994 return (EINVAL);
1995
1996 if (dst != nvl)
1997 return (nvlist_copy_pairs(nvl, dst));
1998
1999 return (0);
2000 }
2001
2002 /*
2003 * Encoding related routines
2004 */
2005 #define NVS_OP_ENCODE 0
2006 #define NVS_OP_DECODE 1
2007 #define NVS_OP_GETSIZE 2
2008
2009 typedef struct nvs_ops nvs_ops_t;
2010
2011 typedef struct {
2012 int nvs_op;
2013 const nvs_ops_t *nvs_ops;
2014 void *nvs_private;
2015 nvpriv_t *nvs_priv;
2016 } nvstream_t;
2017
2018 /*
2019 * nvs operations are:
2020 * - nvs_nvlist
2021 * encoding / decoding of a nvlist header (nvlist_t)
2022 * calculates the size used for header and end detection
2023 *
2024 * - nvs_nvpair
2025 * responsible for the first part of encoding / decoding of an nvpair
2026 * calculates the decoded size of an nvpair
2027 *
2028 * - nvs_nvp_op
2029 * second part of encoding / decoding of an nvpair
2030 *
2031 * - nvs_nvp_size
2032 * calculates the encoding size of an nvpair
2033 *
2034 * - nvs_nvl_fini
2035 * encodes the end detection mark (zeros).
2036 */
2037 struct nvs_ops {
2038 int (*nvs_nvlist)(nvstream_t *, nvlist_t *, size_t *);
2039 int (*nvs_nvpair)(nvstream_t *, nvpair_t *, size_t *);
2040 int (*nvs_nvp_op)(nvstream_t *, nvpair_t *);
2041 int (*nvs_nvp_size)(nvstream_t *, nvpair_t *, size_t *);
2042 int (*nvs_nvl_fini)(nvstream_t *);
2043 };
2044
2045 typedef struct {
2046 char nvh_encoding; /* nvs encoding method */
2047 char nvh_endian; /* nvs endian */
2048 char nvh_reserved1; /* reserved for future use */
2049 char nvh_reserved2; /* reserved for future use */
2050 } nvs_header_t;
2051
2052 static int
nvs_encode_pairs(nvstream_t * nvs,nvlist_t * nvl)2053 nvs_encode_pairs(nvstream_t *nvs, nvlist_t *nvl)
2054 {
2055 nvpriv_t *priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv;
2056 i_nvp_t *curr;
2057
2058 /*
2059 * Walk nvpair in list and encode each nvpair
2060 */
2061 for (curr = priv->nvp_list; curr != NULL; curr = curr->nvi_next)
2062 if (nvs->nvs_ops->nvs_nvpair(nvs, &curr->nvi_nvp, NULL) != 0)
2063 return (EFAULT);
2064
2065 return (nvs->nvs_ops->nvs_nvl_fini(nvs));
2066 }
2067
2068 static int
nvs_decode_pairs(nvstream_t * nvs,nvlist_t * nvl)2069 nvs_decode_pairs(nvstream_t *nvs, nvlist_t *nvl)
2070 {
2071 nvpair_t *nvp;
2072 size_t nvsize;
2073 int err;
2074
2075 /*
2076 * Get decoded size of next pair in stream, alloc
2077 * memory for nvpair_t, then decode the nvpair
2078 */
2079 while ((err = nvs->nvs_ops->nvs_nvpair(nvs, NULL, &nvsize)) == 0) {
2080 if (nvsize == 0) /* end of list */
2081 break;
2082
2083 /* make sure len makes sense */
2084 if (nvsize < NVP_SIZE_CALC(1, 0))
2085 return (EFAULT);
2086
2087 if ((nvp = nvp_buf_alloc(nvl, nvsize)) == NULL)
2088 return (ENOMEM);
2089
2090 if ((err = nvs->nvs_ops->nvs_nvp_op(nvs, nvp)) != 0) {
2091 nvp_buf_free(nvl, nvp);
2092 return (err);
2093 }
2094
2095 if (i_validate_nvpair(nvp) != 0) {
2096 nvpair_free(nvp);
2097 nvp_buf_free(nvl, nvp);
2098 return (EFAULT);
2099 }
2100
2101 nvp_buf_link(nvl, nvp);
2102 }
2103 return (err);
2104 }
2105
2106 static int
nvs_getsize_pairs(nvstream_t * nvs,nvlist_t * nvl,size_t * buflen)2107 nvs_getsize_pairs(nvstream_t *nvs, nvlist_t *nvl, size_t *buflen)
2108 {
2109 nvpriv_t *priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv;
2110 i_nvp_t *curr;
2111 uint64_t nvsize = *buflen;
2112 size_t size;
2113
2114 /*
2115 * Get encoded size of nvpairs in nvlist
2116 */
2117 for (curr = priv->nvp_list; curr != NULL; curr = curr->nvi_next) {
2118 if (nvs->nvs_ops->nvs_nvp_size(nvs, &curr->nvi_nvp, &size) != 0)
2119 return (EINVAL);
2120
2121 if ((nvsize += size) > INT32_MAX)
2122 return (EINVAL);
2123 }
2124
2125 *buflen = nvsize;
2126 return (0);
2127 }
2128
2129 static int
nvs_operation(nvstream_t * nvs,nvlist_t * nvl,size_t * buflen)2130 nvs_operation(nvstream_t *nvs, nvlist_t *nvl, size_t *buflen)
2131 {
2132 int err;
2133
2134 if (nvl->nvl_priv == 0)
2135 return (EFAULT);
2136
2137 /*
2138 * Perform the operation, starting with header, then each nvpair
2139 */
2140 if ((err = nvs->nvs_ops->nvs_nvlist(nvs, nvl, buflen)) != 0)
2141 return (err);
2142
2143 switch (nvs->nvs_op) {
2144 case NVS_OP_ENCODE:
2145 err = nvs_encode_pairs(nvs, nvl);
2146 break;
2147
2148 case NVS_OP_DECODE:
2149 err = nvs_decode_pairs(nvs, nvl);
2150 break;
2151
2152 case NVS_OP_GETSIZE:
2153 err = nvs_getsize_pairs(nvs, nvl, buflen);
2154 break;
2155
2156 default:
2157 err = EINVAL;
2158 }
2159
2160 return (err);
2161 }
2162
2163 static int
nvs_embedded(nvstream_t * nvs,nvlist_t * embedded)2164 nvs_embedded(nvstream_t *nvs, nvlist_t *embedded)
2165 {
2166 switch (nvs->nvs_op) {
2167 case NVS_OP_ENCODE:
2168 return (nvs_operation(nvs, embedded, NULL));
2169
2170 case NVS_OP_DECODE: {
2171 nvpriv_t *priv;
2172 int err;
2173
2174 if (embedded->nvl_version != NV_VERSION)
2175 return (ENOTSUP);
2176
2177 if ((priv = nv_priv_alloc_embedded(nvs->nvs_priv)) == NULL)
2178 return (ENOMEM);
2179
2180 nvlist_init(embedded, embedded->nvl_nvflag, priv);
2181
2182 if ((err = nvs_operation(nvs, embedded, NULL)) != 0)
2183 nvlist_free(embedded);
2184 return (err);
2185 }
2186 default:
2187 break;
2188 }
2189
2190 return (EINVAL);
2191 }
2192
2193 static int
nvs_embedded_nvl_array(nvstream_t * nvs,nvpair_t * nvp,size_t * size)2194 nvs_embedded_nvl_array(nvstream_t *nvs, nvpair_t *nvp, size_t *size)
2195 {
2196 size_t nelem = NVP_NELEM(nvp);
2197 nvlist_t **nvlp = EMBEDDED_NVL_ARRAY(nvp);
2198 int i;
2199
2200 switch (nvs->nvs_op) {
2201 case NVS_OP_ENCODE:
2202 for (i = 0; i < nelem; i++)
2203 if (nvs_embedded(nvs, nvlp[i]) != 0)
2204 return (EFAULT);
2205 break;
2206
2207 case NVS_OP_DECODE: {
2208 size_t len = nelem * sizeof (uint64_t);
2209 nvlist_t *embedded = (nvlist_t *)((uintptr_t)nvlp + len);
2210
2211 bzero(nvlp, len); /* don't trust packed data */
2212 for (i = 0; i < nelem; i++) {
2213 if (nvs_embedded(nvs, embedded) != 0) {
2214 nvpair_free(nvp);
2215 return (EFAULT);
2216 }
2217
2218 nvlp[i] = embedded++;
2219 }
2220 break;
2221 }
2222 case NVS_OP_GETSIZE: {
2223 uint64_t nvsize = 0;
2224
2225 for (i = 0; i < nelem; i++) {
2226 size_t nvp_sz = 0;
2227
2228 if (nvs_operation(nvs, nvlp[i], &nvp_sz) != 0)
2229 return (EINVAL);
2230
2231 if ((nvsize += nvp_sz) > INT32_MAX)
2232 return (EINVAL);
2233 }
2234
2235 *size = nvsize;
2236 break;
2237 }
2238 default:
2239 return (EINVAL);
2240 }
2241
2242 return (0);
2243 }
2244
2245 static int nvs_native(nvstream_t *, nvlist_t *, char *, size_t *);
2246 static int nvs_xdr(nvstream_t *, nvlist_t *, char *, size_t *);
2247
2248 /*
2249 * Common routine for nvlist operations:
2250 * encode, decode, getsize (encoded size).
2251 */
2252 static int
nvlist_common(nvlist_t * nvl,char * buf,size_t * buflen,int encoding,int nvs_op)2253 nvlist_common(nvlist_t *nvl, char *buf, size_t *buflen, int encoding,
2254 int nvs_op)
2255 {
2256 int err = 0;
2257 nvstream_t nvs;
2258 int nvl_endian;
2259 #ifdef _LITTLE_ENDIAN
2260 int host_endian = 1;
2261 #else
2262 int host_endian = 0;
2263 #endif /* _LITTLE_ENDIAN */
2264 nvs_header_t *nvh = (void *)buf;
2265
2266 if (buflen == NULL || nvl == NULL ||
2267 (nvs.nvs_priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL)
2268 return (EINVAL);
2269
2270 nvs.nvs_op = nvs_op;
2271
2272 /*
2273 * For NVS_OP_ENCODE and NVS_OP_DECODE make sure an nvlist and
2274 * a buffer is allocated. The first 4 bytes in the buffer are
2275 * used for encoding method and host endian.
2276 */
2277 switch (nvs_op) {
2278 case NVS_OP_ENCODE:
2279 if (buf == NULL || *buflen < sizeof (nvs_header_t))
2280 return (EINVAL);
2281
2282 nvh->nvh_encoding = encoding;
2283 nvh->nvh_endian = nvl_endian = host_endian;
2284 nvh->nvh_reserved1 = 0;
2285 nvh->nvh_reserved2 = 0;
2286 break;
2287
2288 case NVS_OP_DECODE:
2289 if (buf == NULL || *buflen < sizeof (nvs_header_t))
2290 return (EINVAL);
2291
2292 /* get method of encoding from first byte */
2293 encoding = nvh->nvh_encoding;
2294 nvl_endian = nvh->nvh_endian;
2295 break;
2296
2297 case NVS_OP_GETSIZE:
2298 nvl_endian = host_endian;
2299
2300 /*
2301 * add the size for encoding
2302 */
2303 *buflen = sizeof (nvs_header_t);
2304 break;
2305
2306 default:
2307 return (ENOTSUP);
2308 }
2309
2310 /*
2311 * Create an nvstream with proper encoding method
2312 */
2313 switch (encoding) {
2314 case NV_ENCODE_NATIVE:
2315 /*
2316 * check endianness, in case we are unpacking
2317 * from a file
2318 */
2319 if (nvl_endian != host_endian)
2320 return (ENOTSUP);
2321 err = nvs_native(&nvs, nvl, buf, buflen);
2322 break;
2323 case NV_ENCODE_XDR:
2324 err = nvs_xdr(&nvs, nvl, buf, buflen);
2325 break;
2326 default:
2327 err = ENOTSUP;
2328 break;
2329 }
2330
2331 return (err);
2332 }
2333
2334 int
nvlist_size(nvlist_t * nvl,size_t * size,int encoding)2335 nvlist_size(nvlist_t *nvl, size_t *size, int encoding)
2336 {
2337 return (nvlist_common(nvl, NULL, size, encoding, NVS_OP_GETSIZE));
2338 }
2339
2340 /*
2341 * Pack nvlist into contiguous memory
2342 */
2343 /*ARGSUSED1*/
2344 int
nvlist_pack(nvlist_t * nvl,char ** bufp,size_t * buflen,int encoding,int kmflag)2345 nvlist_pack(nvlist_t *nvl, char **bufp, size_t *buflen, int encoding,
2346 int kmflag)
2347 {
2348 #if defined(_KERNEL) && !defined(_BOOT)
2349 return (nvlist_xpack(nvl, bufp, buflen, encoding,
2350 (kmflag == KM_SLEEP ? nv_alloc_sleep : nv_alloc_nosleep)));
2351 #else
2352 return (nvlist_xpack(nvl, bufp, buflen, encoding, nv_alloc_nosleep));
2353 #endif
2354 }
2355
2356 int
nvlist_xpack(nvlist_t * nvl,char ** bufp,size_t * buflen,int encoding,nv_alloc_t * nva)2357 nvlist_xpack(nvlist_t *nvl, char **bufp, size_t *buflen, int encoding,
2358 nv_alloc_t *nva)
2359 {
2360 nvpriv_t nvpriv;
2361 size_t alloc_size;
2362 char *buf;
2363 int err;
2364
2365 if (nva == NULL || nvl == NULL || bufp == NULL || buflen == NULL)
2366 return (EINVAL);
2367
2368 if (*bufp != NULL)
2369 return (nvlist_common(nvl, *bufp, buflen, encoding,
2370 NVS_OP_ENCODE));
2371
2372 /*
2373 * Here is a difficult situation:
2374 * 1. The nvlist has fixed allocator properties.
2375 * All other nvlist routines (like nvlist_add_*, ...) use
2376 * these properties.
2377 * 2. When using nvlist_pack() the user can specify his own
2378 * allocator properties (e.g. by using KM_NOSLEEP).
2379 *
2380 * We use the user specified properties (2). A clearer solution
2381 * will be to remove the kmflag from nvlist_pack(), but we will
2382 * not change the interface.
2383 */
2384 nv_priv_init(&nvpriv, nva, 0);
2385
2386 if ((err = nvlist_size(nvl, &alloc_size, encoding)))
2387 return (err);
2388
2389 if ((buf = nv_mem_zalloc(&nvpriv, alloc_size)) == NULL)
2390 return (ENOMEM);
2391
2392 if ((err = nvlist_common(nvl, buf, &alloc_size, encoding,
2393 NVS_OP_ENCODE)) != 0) {
2394 nv_mem_free(&nvpriv, buf, alloc_size);
2395 } else {
2396 *buflen = alloc_size;
2397 *bufp = buf;
2398 }
2399
2400 return (err);
2401 }
2402
2403 /*
2404 * Unpack buf into an nvlist_t
2405 */
2406 /*ARGSUSED1*/
2407 int
nvlist_unpack(char * buf,size_t buflen,nvlist_t ** nvlp,int kmflag)2408 nvlist_unpack(char *buf, size_t buflen, nvlist_t **nvlp, int kmflag)
2409 {
2410 #if defined(_KERNEL) && !defined(_BOOT)
2411 return (nvlist_xunpack(buf, buflen, nvlp,
2412 (kmflag == KM_SLEEP ? nv_alloc_sleep : nv_alloc_nosleep)));
2413 #else
2414 return (nvlist_xunpack(buf, buflen, nvlp, nv_alloc_nosleep));
2415 #endif
2416 }
2417
2418 int
nvlist_xunpack(char * buf,size_t buflen,nvlist_t ** nvlp,nv_alloc_t * nva)2419 nvlist_xunpack(char *buf, size_t buflen, nvlist_t **nvlp, nv_alloc_t *nva)
2420 {
2421 nvlist_t *nvl;
2422 int err;
2423
2424 if (nvlp == NULL)
2425 return (EINVAL);
2426
2427 if ((err = nvlist_xalloc(&nvl, 0, nva)) != 0)
2428 return (err);
2429
2430 if ((err = nvlist_common(nvl, buf, &buflen, 0, NVS_OP_DECODE)) != 0)
2431 nvlist_free(nvl);
2432 else
2433 *nvlp = nvl;
2434
2435 return (err);
2436 }
2437
2438 /*
2439 * Native encoding functions
2440 */
2441 typedef struct {
2442 /*
2443 * This structure is used when decoding a packed nvpair in
2444 * the native format. n_base points to a buffer containing the
2445 * packed nvpair. n_end is a pointer to the end of the buffer.
2446 * (n_end actually points to the first byte past the end of the
2447 * buffer.) n_curr is a pointer that lies between n_base and n_end.
2448 * It points to the current data that we are decoding.
2449 * The amount of data left in the buffer is equal to n_end - n_curr.
2450 * n_flag is used to recognize a packed embedded list.
2451 */
2452 caddr_t n_base;
2453 caddr_t n_end;
2454 caddr_t n_curr;
2455 uint_t n_flag;
2456 } nvs_native_t;
2457
2458 static int
nvs_native_create(nvstream_t * nvs,nvs_native_t * native,char * buf,size_t buflen)2459 nvs_native_create(nvstream_t *nvs, nvs_native_t *native, char *buf,
2460 size_t buflen)
2461 {
2462 switch (nvs->nvs_op) {
2463 case NVS_OP_ENCODE:
2464 case NVS_OP_DECODE:
2465 nvs->nvs_private = native;
2466 native->n_curr = native->n_base = buf;
2467 native->n_end = buf + buflen;
2468 native->n_flag = 0;
2469 return (0);
2470
2471 case NVS_OP_GETSIZE:
2472 nvs->nvs_private = native;
2473 native->n_curr = native->n_base = native->n_end = NULL;
2474 native->n_flag = 0;
2475 return (0);
2476 default:
2477 return (EINVAL);
2478 }
2479 }
2480
2481 /*ARGSUSED*/
2482 static void
nvs_native_destroy(nvstream_t * nvs)2483 nvs_native_destroy(nvstream_t *nvs)
2484 {
2485 }
2486
2487 static int
native_cp(nvstream_t * nvs,void * buf,size_t size)2488 native_cp(nvstream_t *nvs, void *buf, size_t size)
2489 {
2490 nvs_native_t *native = (nvs_native_t *)nvs->nvs_private;
2491
2492 if (native->n_curr + size > native->n_end)
2493 return (EFAULT);
2494
2495 /*
2496 * The bcopy() below eliminates alignment requirement
2497 * on the buffer (stream) and is preferred over direct access.
2498 */
2499 switch (nvs->nvs_op) {
2500 case NVS_OP_ENCODE:
2501 bcopy(buf, native->n_curr, size);
2502 break;
2503 case NVS_OP_DECODE:
2504 bcopy(native->n_curr, buf, size);
2505 break;
2506 default:
2507 return (EINVAL);
2508 }
2509
2510 native->n_curr += size;
2511 return (0);
2512 }
2513
2514 /*
2515 * operate on nvlist_t header
2516 */
2517 static int
nvs_native_nvlist(nvstream_t * nvs,nvlist_t * nvl,size_t * size)2518 nvs_native_nvlist(nvstream_t *nvs, nvlist_t *nvl, size_t *size)
2519 {
2520 nvs_native_t *native = nvs->nvs_private;
2521
2522 switch (nvs->nvs_op) {
2523 case NVS_OP_ENCODE:
2524 case NVS_OP_DECODE:
2525 if (native->n_flag)
2526 return (0); /* packed embedded list */
2527
2528 native->n_flag = 1;
2529
2530 /* copy version and nvflag of the nvlist_t */
2531 if (native_cp(nvs, &nvl->nvl_version, sizeof (int32_t)) != 0 ||
2532 native_cp(nvs, &nvl->nvl_nvflag, sizeof (int32_t)) != 0)
2533 return (EFAULT);
2534
2535 return (0);
2536
2537 case NVS_OP_GETSIZE:
2538 /*
2539 * if calculate for packed embedded list
2540 * 4 for end of the embedded list
2541 * else
2542 * 2 * sizeof (int32_t) for nvl_version and nvl_nvflag
2543 * and 4 for end of the entire list
2544 */
2545 if (native->n_flag) {
2546 *size += 4;
2547 } else {
2548 native->n_flag = 1;
2549 *size += 2 * sizeof (int32_t) + 4;
2550 }
2551
2552 return (0);
2553
2554 default:
2555 return (EINVAL);
2556 }
2557 }
2558
2559 static int
nvs_native_nvl_fini(nvstream_t * nvs)2560 nvs_native_nvl_fini(nvstream_t *nvs)
2561 {
2562 if (nvs->nvs_op == NVS_OP_ENCODE) {
2563 nvs_native_t *native = (nvs_native_t *)nvs->nvs_private;
2564 /*
2565 * Add 4 zero bytes at end of nvlist. They are used
2566 * for end detection by the decode routine.
2567 */
2568 if (native->n_curr + sizeof (int) > native->n_end)
2569 return (EFAULT);
2570
2571 bzero(native->n_curr, sizeof (int));
2572 native->n_curr += sizeof (int);
2573 }
2574
2575 return (0);
2576 }
2577
2578 static int
nvpair_native_embedded(nvstream_t * nvs,nvpair_t * nvp)2579 nvpair_native_embedded(nvstream_t *nvs, nvpair_t *nvp)
2580 {
2581 if (nvs->nvs_op == NVS_OP_ENCODE) {
2582 nvs_native_t *native = (nvs_native_t *)nvs->nvs_private;
2583 nvlist_t *packed = (void *)
2584 (native->n_curr - nvp->nvp_size + NVP_VALOFF(nvp));
2585 /*
2586 * Null out the pointer that is meaningless in the packed
2587 * structure. The address may not be aligned, so we have
2588 * to use bzero.
2589 */
2590 bzero(&packed->nvl_priv, sizeof (packed->nvl_priv));
2591 }
2592
2593 return (nvs_embedded(nvs, EMBEDDED_NVL(nvp)));
2594 }
2595
2596 static int
nvpair_native_embedded_array(nvstream_t * nvs,nvpair_t * nvp)2597 nvpair_native_embedded_array(nvstream_t *nvs, nvpair_t *nvp)
2598 {
2599 if (nvs->nvs_op == NVS_OP_ENCODE) {
2600 nvs_native_t *native = (nvs_native_t *)nvs->nvs_private;
2601 char *value = native->n_curr - nvp->nvp_size + NVP_VALOFF(nvp);
2602 size_t len = NVP_NELEM(nvp) * sizeof (uint64_t);
2603 nvlist_t *packed = (nvlist_t *)((uintptr_t)value + len);
2604 int i;
2605 /*
2606 * Null out pointers that are meaningless in the packed
2607 * structure. The addresses may not be aligned, so we have
2608 * to use bzero.
2609 */
2610 bzero(value, len);
2611
2612 for (i = 0; i < NVP_NELEM(nvp); i++, packed++)
2613 /*
2614 * Null out the pointer that is meaningless in the
2615 * packed structure. The address may not be aligned,
2616 * so we have to use bzero.
2617 */
2618 bzero(&packed->nvl_priv, sizeof (packed->nvl_priv));
2619 }
2620
2621 return (nvs_embedded_nvl_array(nvs, nvp, NULL));
2622 }
2623
2624 static void
nvpair_native_string_array(nvstream_t * nvs,nvpair_t * nvp)2625 nvpair_native_string_array(nvstream_t *nvs, nvpair_t *nvp)
2626 {
2627 switch (nvs->nvs_op) {
2628 case NVS_OP_ENCODE: {
2629 nvs_native_t *native = (nvs_native_t *)nvs->nvs_private;
2630 uint64_t *strp = (void *)
2631 (native->n_curr - nvp->nvp_size + NVP_VALOFF(nvp));
2632 /*
2633 * Null out pointers that are meaningless in the packed
2634 * structure. The addresses may not be aligned, so we have
2635 * to use bzero.
2636 */
2637 bzero(strp, NVP_NELEM(nvp) * sizeof (uint64_t));
2638 break;
2639 }
2640 case NVS_OP_DECODE: {
2641 char **strp = (void *)NVP_VALUE(nvp);
2642 char *buf = ((char *)strp + NVP_NELEM(nvp) * sizeof (uint64_t));
2643 int i;
2644
2645 for (i = 0; i < NVP_NELEM(nvp); i++) {
2646 strp[i] = buf;
2647 buf += strlen(buf) + 1;
2648 }
2649 break;
2650 }
2651 }
2652 }
2653
2654 static int
nvs_native_nvp_op(nvstream_t * nvs,nvpair_t * nvp)2655 nvs_native_nvp_op(nvstream_t *nvs, nvpair_t *nvp)
2656 {
2657 data_type_t type;
2658 int value_sz;
2659 int ret = 0;
2660
2661 /*
2662 * We do the initial bcopy of the data before we look at
2663 * the nvpair type, because when we're decoding, we won't
2664 * have the correct values for the pair until we do the bcopy.
2665 */
2666 switch (nvs->nvs_op) {
2667 case NVS_OP_ENCODE:
2668 case NVS_OP_DECODE:
2669 if (native_cp(nvs, nvp, nvp->nvp_size) != 0)
2670 return (EFAULT);
2671 break;
2672 default:
2673 return (EINVAL);
2674 }
2675
2676 /* verify nvp_name_sz, check the name string length */
2677 if (i_validate_nvpair_name(nvp) != 0)
2678 return (EFAULT);
2679
2680 type = NVP_TYPE(nvp);
2681
2682 /*
2683 * Verify type and nelem and get the value size.
2684 * In case of data types DATA_TYPE_STRING and DATA_TYPE_STRING_ARRAY
2685 * is the size of the string(s) excluded.
2686 */
2687 if ((value_sz = i_get_value_size(type, NULL, NVP_NELEM(nvp))) < 0)
2688 return (EFAULT);
2689
2690 if (NVP_SIZE_CALC(nvp->nvp_name_sz, value_sz) > nvp->nvp_size)
2691 return (EFAULT);
2692
2693 switch (type) {
2694 case DATA_TYPE_NVLIST:
2695 ret = nvpair_native_embedded(nvs, nvp);
2696 break;
2697 case DATA_TYPE_NVLIST_ARRAY:
2698 ret = nvpair_native_embedded_array(nvs, nvp);
2699 break;
2700 case DATA_TYPE_STRING_ARRAY:
2701 nvpair_native_string_array(nvs, nvp);
2702 break;
2703 default:
2704 break;
2705 }
2706
2707 return (ret);
2708 }
2709
2710 static int
nvs_native_nvp_size(nvstream_t * nvs,nvpair_t * nvp,size_t * size)2711 nvs_native_nvp_size(nvstream_t *nvs, nvpair_t *nvp, size_t *size)
2712 {
2713 uint64_t nvp_sz = nvp->nvp_size;
2714
2715 switch (NVP_TYPE(nvp)) {
2716 case DATA_TYPE_NVLIST: {
2717 size_t nvsize = 0;
2718
2719 if (nvs_operation(nvs, EMBEDDED_NVL(nvp), &nvsize) != 0)
2720 return (EINVAL);
2721
2722 nvp_sz += nvsize;
2723 break;
2724 }
2725 case DATA_TYPE_NVLIST_ARRAY: {
2726 size_t nvsize;
2727
2728 if (nvs_embedded_nvl_array(nvs, nvp, &nvsize) != 0)
2729 return (EINVAL);
2730
2731 nvp_sz += nvsize;
2732 break;
2733 }
2734 default:
2735 break;
2736 }
2737
2738 if (nvp_sz > INT32_MAX)
2739 return (EINVAL);
2740
2741 *size = nvp_sz;
2742
2743 return (0);
2744 }
2745
2746 static int
nvs_native_nvpair(nvstream_t * nvs,nvpair_t * nvp,size_t * size)2747 nvs_native_nvpair(nvstream_t *nvs, nvpair_t *nvp, size_t *size)
2748 {
2749 switch (nvs->nvs_op) {
2750 case NVS_OP_ENCODE:
2751 return (nvs_native_nvp_op(nvs, nvp));
2752
2753 case NVS_OP_DECODE: {
2754 nvs_native_t *native = (nvs_native_t *)nvs->nvs_private;
2755 int32_t decode_len;
2756
2757 /* try to read the size value from the stream */
2758 if (native->n_curr + sizeof (int32_t) > native->n_end)
2759 return (EFAULT);
2760 bcopy(native->n_curr, &decode_len, sizeof (int32_t));
2761
2762 /* sanity check the size value */
2763 if (decode_len < 0 ||
2764 decode_len > native->n_end - native->n_curr)
2765 return (EFAULT);
2766
2767 *size = decode_len;
2768
2769 /*
2770 * If at the end of the stream then move the cursor
2771 * forward, otherwise nvpair_native_op() will read
2772 * the entire nvpair at the same cursor position.
2773 */
2774 if (*size == 0)
2775 native->n_curr += sizeof (int32_t);
2776 break;
2777 }
2778
2779 default:
2780 return (EINVAL);
2781 }
2782
2783 return (0);
2784 }
2785
2786 static const nvs_ops_t nvs_native_ops = {
2787 nvs_native_nvlist,
2788 nvs_native_nvpair,
2789 nvs_native_nvp_op,
2790 nvs_native_nvp_size,
2791 nvs_native_nvl_fini
2792 };
2793
2794 static int
nvs_native(nvstream_t * nvs,nvlist_t * nvl,char * buf,size_t * buflen)2795 nvs_native(nvstream_t *nvs, nvlist_t *nvl, char *buf, size_t *buflen)
2796 {
2797 nvs_native_t native;
2798 int err;
2799
2800 nvs->nvs_ops = &nvs_native_ops;
2801
2802 if ((err = nvs_native_create(nvs, &native, buf + sizeof (nvs_header_t),
2803 *buflen - sizeof (nvs_header_t))) != 0)
2804 return (err);
2805
2806 err = nvs_operation(nvs, nvl, buflen);
2807
2808 nvs_native_destroy(nvs);
2809
2810 return (err);
2811 }
2812
2813 /*
2814 * XDR encoding functions
2815 *
2816 * An xdr packed nvlist is encoded as:
2817 *
2818 * - encoding methode and host endian (4 bytes)
2819 * - nvl_version (4 bytes)
2820 * - nvl_nvflag (4 bytes)
2821 *
2822 * - encoded nvpairs, the format of one xdr encoded nvpair is:
2823 * - encoded size of the nvpair (4 bytes)
2824 * - decoded size of the nvpair (4 bytes)
2825 * - name string, (4 + sizeof(NV_ALIGN4(string))
2826 * a string is coded as size (4 bytes) and data
2827 * - data type (4 bytes)
2828 * - number of elements in the nvpair (4 bytes)
2829 * - data
2830 *
2831 * - 2 zero's for end of the entire list (8 bytes)
2832 */
2833 static int
nvs_xdr_create(nvstream_t * nvs,XDR * xdr,char * buf,size_t buflen)2834 nvs_xdr_create(nvstream_t *nvs, XDR *xdr, char *buf, size_t buflen)
2835 {
2836 /* xdr data must be 4 byte aligned */
2837 if ((ulong_t)buf % 4 != 0)
2838 return (EFAULT);
2839
2840 switch (nvs->nvs_op) {
2841 case NVS_OP_ENCODE:
2842 xdrmem_create(xdr, buf, (uint_t)buflen, XDR_ENCODE);
2843 nvs->nvs_private = xdr;
2844 return (0);
2845 case NVS_OP_DECODE:
2846 xdrmem_create(xdr, buf, (uint_t)buflen, XDR_DECODE);
2847 nvs->nvs_private = xdr;
2848 return (0);
2849 case NVS_OP_GETSIZE:
2850 nvs->nvs_private = NULL;
2851 return (0);
2852 default:
2853 return (EINVAL);
2854 }
2855 }
2856
2857 static void
nvs_xdr_destroy(nvstream_t * nvs)2858 nvs_xdr_destroy(nvstream_t *nvs)
2859 {
2860 switch (nvs->nvs_op) {
2861 case NVS_OP_ENCODE:
2862 case NVS_OP_DECODE:
2863 xdr_destroy((XDR *)nvs->nvs_private);
2864 break;
2865 default:
2866 break;
2867 }
2868 }
2869
2870 static int
nvs_xdr_nvlist(nvstream_t * nvs,nvlist_t * nvl,size_t * size)2871 nvs_xdr_nvlist(nvstream_t *nvs, nvlist_t *nvl, size_t *size)
2872 {
2873 switch (nvs->nvs_op) {
2874 case NVS_OP_ENCODE:
2875 case NVS_OP_DECODE: {
2876 XDR *xdr = nvs->nvs_private;
2877
2878 if (!xdr_int(xdr, &nvl->nvl_version) ||
2879 !xdr_u_int(xdr, &nvl->nvl_nvflag))
2880 return (EFAULT);
2881 break;
2882 }
2883 case NVS_OP_GETSIZE: {
2884 /*
2885 * 2 * 4 for nvl_version + nvl_nvflag
2886 * and 8 for end of the entire list
2887 */
2888 *size += 2 * 4 + 8;
2889 break;
2890 }
2891 default:
2892 return (EINVAL);
2893 }
2894 return (0);
2895 }
2896
2897 static int
nvs_xdr_nvl_fini(nvstream_t * nvs)2898 nvs_xdr_nvl_fini(nvstream_t *nvs)
2899 {
2900 if (nvs->nvs_op == NVS_OP_ENCODE) {
2901 XDR *xdr = nvs->nvs_private;
2902 int zero = 0;
2903
2904 if (!xdr_int(xdr, &zero) || !xdr_int(xdr, &zero))
2905 return (EFAULT);
2906 }
2907
2908 return (0);
2909 }
2910
2911 /*
2912 * The format of xdr encoded nvpair is:
2913 * encode_size, decode_size, name string, data type, nelem, data
2914 */
2915 static int
nvs_xdr_nvp_op(nvstream_t * nvs,nvpair_t * nvp)2916 nvs_xdr_nvp_op(nvstream_t *nvs, nvpair_t *nvp)
2917 {
2918 data_type_t type;
2919 char *buf;
2920 char *buf_end = (char *)nvp + nvp->nvp_size;
2921 int value_sz;
2922 uint_t nelem, buflen;
2923 bool_t ret = FALSE;
2924 XDR *xdr = nvs->nvs_private;
2925
2926 ASSERT(xdr != NULL && nvp != NULL);
2927
2928 /* name string */
2929 if ((buf = NVP_NAME(nvp)) >= buf_end)
2930 return (EFAULT);
2931 buflen = buf_end - buf;
2932
2933 if (!xdr_string(xdr, &buf, buflen - 1))
2934 return (EFAULT);
2935 nvp->nvp_name_sz = strlen(buf) + 1;
2936
2937 /* type and nelem */
2938 if (!xdr_int(xdr, (int *)&nvp->nvp_type) ||
2939 !xdr_int(xdr, &nvp->nvp_value_elem))
2940 return (EFAULT);
2941
2942 type = NVP_TYPE(nvp);
2943 nelem = nvp->nvp_value_elem;
2944
2945 /*
2946 * Verify type and nelem and get the value size.
2947 * In case of data types DATA_TYPE_STRING and DATA_TYPE_STRING_ARRAY
2948 * is the size of the string(s) excluded.
2949 */
2950 if ((value_sz = i_get_value_size(type, NULL, nelem)) < 0)
2951 return (EFAULT);
2952
2953 /* if there is no data to extract then return */
2954 if (nelem == 0)
2955 return (0);
2956
2957 /* value */
2958 if ((buf = NVP_VALUE(nvp)) >= buf_end)
2959 return (EFAULT);
2960 buflen = buf_end - buf;
2961
2962 if (buflen < value_sz)
2963 return (EFAULT);
2964
2965 switch (type) {
2966 case DATA_TYPE_NVLIST:
2967 if (nvs_embedded(nvs, (void *)buf) == 0)
2968 return (0);
2969 break;
2970
2971 case DATA_TYPE_NVLIST_ARRAY:
2972 if (nvs_embedded_nvl_array(nvs, nvp, NULL) == 0)
2973 return (0);
2974 break;
2975
2976 case DATA_TYPE_BOOLEAN:
2977 ret = TRUE;
2978 break;
2979
2980 case DATA_TYPE_BYTE:
2981 case DATA_TYPE_INT8:
2982 case DATA_TYPE_UINT8:
2983 ret = xdr_char(xdr, buf);
2984 break;
2985
2986 case DATA_TYPE_INT16:
2987 ret = xdr_short(xdr, (void *)buf);
2988 break;
2989
2990 case DATA_TYPE_UINT16:
2991 ret = xdr_u_short(xdr, (void *)buf);
2992 break;
2993
2994 case DATA_TYPE_BOOLEAN_VALUE:
2995 case DATA_TYPE_INT32:
2996 ret = xdr_int(xdr, (void *)buf);
2997 break;
2998
2999 case DATA_TYPE_UINT32:
3000 ret = xdr_u_int(xdr, (void *)buf);
3001 break;
3002
3003 case DATA_TYPE_INT64:
3004 ret = xdr_longlong_t(xdr, (void *)buf);
3005 break;
3006
3007 case DATA_TYPE_UINT64:
3008 ret = xdr_u_longlong_t(xdr, (void *)buf);
3009 break;
3010
3011 case DATA_TYPE_HRTIME:
3012 /*
3013 * NOTE: must expose the definition of hrtime_t here
3014 */
3015 ret = xdr_longlong_t(xdr, (void *)buf);
3016 break;
3017 #if !defined(_KERNEL)
3018 case DATA_TYPE_DOUBLE:
3019 ret = xdr_double(xdr, (void *)buf);
3020 break;
3021 #endif
3022 case DATA_TYPE_STRING:
3023 ret = xdr_string(xdr, &buf, buflen - 1);
3024 break;
3025
3026 case DATA_TYPE_BYTE_ARRAY:
3027 ret = xdr_opaque(xdr, buf, nelem);
3028 break;
3029
3030 case DATA_TYPE_INT8_ARRAY:
3031 case DATA_TYPE_UINT8_ARRAY:
3032 ret = xdr_array(xdr, &buf, &nelem, buflen, sizeof (int8_t),
3033 (xdrproc_t)xdr_char);
3034 break;
3035
3036 case DATA_TYPE_INT16_ARRAY:
3037 ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (int16_t),
3038 sizeof (int16_t), (xdrproc_t)xdr_short);
3039 break;
3040
3041 case DATA_TYPE_UINT16_ARRAY:
3042 ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (uint16_t),
3043 sizeof (uint16_t), (xdrproc_t)xdr_u_short);
3044 break;
3045
3046 case DATA_TYPE_BOOLEAN_ARRAY:
3047 case DATA_TYPE_INT32_ARRAY:
3048 ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (int32_t),
3049 sizeof (int32_t), (xdrproc_t)xdr_int);
3050 break;
3051
3052 case DATA_TYPE_UINT32_ARRAY:
3053 ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (uint32_t),
3054 sizeof (uint32_t), (xdrproc_t)xdr_u_int);
3055 break;
3056
3057 case DATA_TYPE_INT64_ARRAY:
3058 ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (int64_t),
3059 sizeof (int64_t), (xdrproc_t)xdr_longlong_t);
3060 break;
3061
3062 case DATA_TYPE_UINT64_ARRAY:
3063 ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (uint64_t),
3064 sizeof (uint64_t), (xdrproc_t)xdr_u_longlong_t);
3065 break;
3066
3067 case DATA_TYPE_STRING_ARRAY: {
3068 size_t len = nelem * sizeof (uint64_t);
3069 char **strp = (void *)buf;
3070 int i;
3071
3072 if (nvs->nvs_op == NVS_OP_DECODE)
3073 bzero(buf, len); /* don't trust packed data */
3074
3075 for (i = 0; i < nelem; i++) {
3076 if (buflen <= len)
3077 return (EFAULT);
3078
3079 buf += len;
3080 buflen -= len;
3081
3082 if (xdr_string(xdr, &buf, buflen - 1) != TRUE)
3083 return (EFAULT);
3084
3085 if (nvs->nvs_op == NVS_OP_DECODE)
3086 strp[i] = buf;
3087 len = strlen(buf) + 1;
3088 }
3089 ret = TRUE;
3090 break;
3091 }
3092 default:
3093 break;
3094 }
3095
3096 return (ret == TRUE ? 0 : EFAULT);
3097 }
3098
3099 static int
nvs_xdr_nvp_size(nvstream_t * nvs,nvpair_t * nvp,size_t * size)3100 nvs_xdr_nvp_size(nvstream_t *nvs, nvpair_t *nvp, size_t *size)
3101 {
3102 data_type_t type = NVP_TYPE(nvp);
3103 /*
3104 * encode_size + decode_size + name string size + data type + nelem
3105 * where name string size = 4 + NV_ALIGN4(strlen(NVP_NAME(nvp)))
3106 */
3107 uint64_t nvp_sz = 4 + 4 + 4 + NV_ALIGN4(strlen(NVP_NAME(nvp))) + 4 + 4;
3108
3109 switch (type) {
3110 case DATA_TYPE_BOOLEAN:
3111 break;
3112
3113 case DATA_TYPE_BOOLEAN_VALUE:
3114 case DATA_TYPE_BYTE:
3115 case DATA_TYPE_INT8:
3116 case DATA_TYPE_UINT8:
3117 case DATA_TYPE_INT16:
3118 case DATA_TYPE_UINT16:
3119 case DATA_TYPE_INT32:
3120 case DATA_TYPE_UINT32:
3121 nvp_sz += 4; /* 4 is the minimum xdr unit */
3122 break;
3123
3124 case DATA_TYPE_INT64:
3125 case DATA_TYPE_UINT64:
3126 case DATA_TYPE_HRTIME:
3127 #if !defined(_KERNEL)
3128 case DATA_TYPE_DOUBLE:
3129 #endif
3130 nvp_sz += 8;
3131 break;
3132
3133 case DATA_TYPE_STRING:
3134 nvp_sz += 4 + NV_ALIGN4(strlen((char *)NVP_VALUE(nvp)));
3135 break;
3136
3137 case DATA_TYPE_BYTE_ARRAY:
3138 nvp_sz += NV_ALIGN4(NVP_NELEM(nvp));
3139 break;
3140
3141 case DATA_TYPE_BOOLEAN_ARRAY:
3142 case DATA_TYPE_INT8_ARRAY:
3143 case DATA_TYPE_UINT8_ARRAY:
3144 case DATA_TYPE_INT16_ARRAY:
3145 case DATA_TYPE_UINT16_ARRAY:
3146 case DATA_TYPE_INT32_ARRAY:
3147 case DATA_TYPE_UINT32_ARRAY:
3148 nvp_sz += 4 + 4 * (uint64_t)NVP_NELEM(nvp);
3149 break;
3150
3151 case DATA_TYPE_INT64_ARRAY:
3152 case DATA_TYPE_UINT64_ARRAY:
3153 nvp_sz += 4 + 8 * (uint64_t)NVP_NELEM(nvp);
3154 break;
3155
3156 case DATA_TYPE_STRING_ARRAY: {
3157 int i;
3158 char **strs = (void *)NVP_VALUE(nvp);
3159
3160 for (i = 0; i < NVP_NELEM(nvp); i++)
3161 nvp_sz += 4 + NV_ALIGN4(strlen(strs[i]));
3162
3163 break;
3164 }
3165
3166 case DATA_TYPE_NVLIST:
3167 case DATA_TYPE_NVLIST_ARRAY: {
3168 size_t nvsize = 0;
3169 int old_nvs_op = nvs->nvs_op;
3170 int err;
3171
3172 nvs->nvs_op = NVS_OP_GETSIZE;
3173 if (type == DATA_TYPE_NVLIST)
3174 err = nvs_operation(nvs, EMBEDDED_NVL(nvp), &nvsize);
3175 else
3176 err = nvs_embedded_nvl_array(nvs, nvp, &nvsize);
3177 nvs->nvs_op = old_nvs_op;
3178
3179 if (err != 0)
3180 return (EINVAL);
3181
3182 nvp_sz += nvsize;
3183 break;
3184 }
3185
3186 default:
3187 return (EINVAL);
3188 }
3189
3190 if (nvp_sz > INT32_MAX)
3191 return (EINVAL);
3192
3193 *size = nvp_sz;
3194
3195 return (0);
3196 }
3197
3198
3199 /*
3200 * The NVS_XDR_MAX_LEN macro takes a packed xdr buffer of size x and estimates
3201 * the largest nvpair that could be encoded in the buffer.
3202 *
3203 * See comments above nvpair_xdr_op() for the format of xdr encoding.
3204 * The size of a xdr packed nvpair without any data is 5 words.
3205 *
3206 * Using the size of the data directly as an estimate would be ok
3207 * in all cases except one. If the data type is of DATA_TYPE_STRING_ARRAY
3208 * then the actual nvpair has space for an array of pointers to index
3209 * the strings. These pointers are not encoded into the packed xdr buffer.
3210 *
3211 * If the data is of type DATA_TYPE_STRING_ARRAY and all the strings are
3212 * of length 0, then each string is endcoded in xdr format as a single word.
3213 * Therefore when expanded to an nvpair there will be 2.25 word used for
3214 * each string. (a int64_t allocated for pointer usage, and a single char
3215 * for the null termination.)
3216 *
3217 * This is the calculation performed by the NVS_XDR_MAX_LEN macro.
3218 */
3219 #define NVS_XDR_HDR_LEN ((size_t)(5 * 4))
3220 #define NVS_XDR_DATA_LEN(y) (((size_t)(y) <= NVS_XDR_HDR_LEN) ? \
3221 0 : ((size_t)(y) - NVS_XDR_HDR_LEN))
3222 #define NVS_XDR_MAX_LEN(x) (NVP_SIZE_CALC(1, 0) + \
3223 (NVS_XDR_DATA_LEN(x) * 2) + \
3224 NV_ALIGN4((NVS_XDR_DATA_LEN(x) / 4)))
3225
3226 static int
nvs_xdr_nvpair(nvstream_t * nvs,nvpair_t * nvp,size_t * size)3227 nvs_xdr_nvpair(nvstream_t *nvs, nvpair_t *nvp, size_t *size)
3228 {
3229 XDR *xdr = nvs->nvs_private;
3230 int32_t encode_len, decode_len;
3231
3232 switch (nvs->nvs_op) {
3233 case NVS_OP_ENCODE: {
3234 size_t nvsize;
3235
3236 if (nvs_xdr_nvp_size(nvs, nvp, &nvsize) != 0)
3237 return (EFAULT);
3238
3239 decode_len = nvp->nvp_size;
3240 encode_len = nvsize;
3241 if (!xdr_int(xdr, &encode_len) || !xdr_int(xdr, &decode_len))
3242 return (EFAULT);
3243
3244 return (nvs_xdr_nvp_op(nvs, nvp));
3245 }
3246 case NVS_OP_DECODE: {
3247 struct xdr_bytesrec bytesrec;
3248
3249 /* get the encode and decode size */
3250 if (!xdr_int(xdr, &encode_len) || !xdr_int(xdr, &decode_len))
3251 return (EFAULT);
3252 *size = decode_len;
3253
3254 /* are we at the end of the stream? */
3255 if (*size == 0)
3256 return (0);
3257
3258 /* sanity check the size parameter */
3259 if (!xdr_control(xdr, XDR_GET_BYTES_AVAIL, &bytesrec))
3260 return (EFAULT);
3261
3262 if (*size > NVS_XDR_MAX_LEN(bytesrec.xc_num_avail))
3263 return (EFAULT);
3264 break;
3265 }
3266
3267 default:
3268 return (EINVAL);
3269 }
3270 return (0);
3271 }
3272
3273 static const struct nvs_ops nvs_xdr_ops = {
3274 nvs_xdr_nvlist,
3275 nvs_xdr_nvpair,
3276 nvs_xdr_nvp_op,
3277 nvs_xdr_nvp_size,
3278 nvs_xdr_nvl_fini
3279 };
3280
3281 static int
nvs_xdr(nvstream_t * nvs,nvlist_t * nvl,char * buf,size_t * buflen)3282 nvs_xdr(nvstream_t *nvs, nvlist_t *nvl, char *buf, size_t *buflen)
3283 {
3284 XDR xdr;
3285 int err;
3286
3287 nvs->nvs_ops = &nvs_xdr_ops;
3288
3289 if ((err = nvs_xdr_create(nvs, &xdr, buf + sizeof (nvs_header_t),
3290 *buflen - sizeof (nvs_header_t))) != 0)
3291 return (err);
3292
3293 err = nvs_operation(nvs, nvl, buflen);
3294
3295 nvs_xdr_destroy(nvs);
3296
3297 return (err);
3298 }
3299