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