1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright (c) 2009-2013 The FreeBSD Foundation
5 * Copyright (c) 2013-2015 Mariusz Zaborski <oshogbo@FreeBSD.org>
6 * All rights reserved.
7 *
8 * This software was developed by Pawel Jakub Dawidek under sponsorship from
9 * the FreeBSD Foundation.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD$");
35
36 #include <sys/param.h>
37 #include <sys/endian.h>
38 #include <sys/queue.h>
39
40 #ifdef _KERNEL
41
42 #include <sys/errno.h>
43 #include <sys/lock.h>
44 #include <sys/malloc.h>
45 #include <sys/systm.h>
46
47 #include <machine/stdarg.h>
48
49 #else
50 #include <errno.h>
51 #include <fcntl.h>
52 #include <stdarg.h>
53 #include <stdbool.h>
54 #include <stdint.h>
55 #include <stdlib.h>
56 #include <string.h>
57 #include <unistd.h>
58
59 #include "common_impl.h"
60 #endif
61
62 #ifdef HAVE_PJDLOG
63 #include <pjdlog.h>
64 #endif
65
66 #include <sys/nv.h>
67
68 #include "nv_impl.h"
69 #include "nvlist_impl.h"
70 #include "nvpair_impl.h"
71
72 #ifndef HAVE_PJDLOG
73 #ifdef _KERNEL
74 #define PJDLOG_ASSERT(...) MPASS(__VA_ARGS__)
75 #define PJDLOG_RASSERT(expr, ...) KASSERT(expr, (__VA_ARGS__))
76 #define PJDLOG_ABORT(...) panic(__VA_ARGS__)
77 #else
78 #include <assert.h>
79 #define PJDLOG_ASSERT(...) assert(__VA_ARGS__)
80 #define PJDLOG_RASSERT(expr, ...) assert(expr)
81 #define PJDLOG_ABORT(...) abort()
82 #endif
83 #endif
84
85 #define NVPAIR_MAGIC 0x6e7670 /* "nvp" */
86 struct nvpair {
87 int nvp_magic;
88 char *nvp_name;
89 int nvp_type;
90 uint64_t nvp_data;
91 size_t nvp_datasize;
92 size_t nvp_nitems; /* Used only for array types. */
93 nvlist_t *nvp_list;
94 TAILQ_ENTRY(nvpair) nvp_next;
95 };
96
97 #define NVPAIR_ASSERT(nvp) do { \
98 PJDLOG_ASSERT((nvp) != NULL); \
99 PJDLOG_ASSERT((nvp)->nvp_magic == NVPAIR_MAGIC); \
100 } while (0)
101
102 struct nvpair_header {
103 uint8_t nvph_type;
104 uint16_t nvph_namesize;
105 uint64_t nvph_datasize;
106 uint64_t nvph_nitems;
107 } __packed;
108
109
110 void
111 nvpair_assert(const nvpair_t *nvp __unused)
112 {
113
114 NVPAIR_ASSERT(nvp);
115 }
116
117 static nvpair_t *
118 nvpair_allocv(const char *name, int type, uint64_t data, size_t datasize,
119 size_t nitems)
120 {
121 nvpair_t *nvp;
122 size_t namelen;
123
124 PJDLOG_ASSERT(type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST);
125
126 namelen = strlen(name);
127 if (namelen >= NV_NAME_MAX) {
128 ERRNO_SET(ENAMETOOLONG);
129 return (NULL);
130 }
131
132 nvp = nv_calloc(1, sizeof(*nvp) + namelen + 1);
133 if (nvp != NULL) {
134 nvp->nvp_name = (char *)(nvp + 1);
135 memcpy(nvp->nvp_name, name, namelen);
136 nvp->nvp_name[namelen] = '\0';
137 nvp->nvp_type = type;
138 nvp->nvp_data = data;
139 nvp->nvp_datasize = datasize;
140 nvp->nvp_nitems = nitems;
141 nvp->nvp_magic = NVPAIR_MAGIC;
142 }
143
144 return (nvp);
145 }
146
147 static int
148 nvpair_append(nvpair_t *nvp, const void *value, size_t valsize, size_t datasize)
149 {
150 void *olddata, *data, *valp;
151 size_t oldlen;
152
153 oldlen = nvp->nvp_nitems * valsize;
154 olddata = (void *)(uintptr_t)nvp->nvp_data;
155 data = nv_realloc(olddata, oldlen + valsize);
156 if (data == NULL) {
157 ERRNO_SET(ENOMEM);
158 return (-1);
159 }
160 valp = (unsigned char *)data + oldlen;
161 memcpy(valp, value, valsize);
162
163 nvp->nvp_data = (uint64_t)(uintptr_t)data;
164 nvp->nvp_datasize += datasize;
165 nvp->nvp_nitems++;
166 return (0);
167 }
168
169 nvlist_t *
170 nvpair_nvlist(const nvpair_t *nvp)
171 {
172
173 NVPAIR_ASSERT(nvp);
174
175 return (nvp->nvp_list);
176 }
177
178 nvpair_t *
179 nvpair_next(const nvpair_t *nvp)
180 {
181
182 NVPAIR_ASSERT(nvp);
183 PJDLOG_ASSERT(nvp->nvp_list != NULL);
184
185 return (TAILQ_NEXT(nvp, nvp_next));
186 }
187
188 nvpair_t *
189 nvpair_prev(const nvpair_t *nvp)
190 {
191
192 NVPAIR_ASSERT(nvp);
193 PJDLOG_ASSERT(nvp->nvp_list != NULL);
194
195 return (TAILQ_PREV(nvp, nvl_head, nvp_next));
196 }
197
198 void
199 nvpair_insert(struct nvl_head *head, nvpair_t *nvp, nvlist_t *nvl)
200 {
201
202 NVPAIR_ASSERT(nvp);
203 PJDLOG_ASSERT(nvp->nvp_list == NULL);
204 PJDLOG_ASSERT((nvlist_flags(nvl) & NV_FLAG_NO_UNIQUE) != 0 ||
205 !nvlist_exists(nvl, nvpair_name(nvp)));
206
207 TAILQ_INSERT_TAIL(head, nvp, nvp_next);
208 nvp->nvp_list = nvl;
209 }
210
211 static void
212 nvpair_remove_nvlist(nvpair_t *nvp)
213 {
214 nvlist_t *nvl;
215
216 /* XXX: DECONST is bad, mkay? */
217 nvl = __DECONST(nvlist_t *, nvpair_get_nvlist(nvp));
218 PJDLOG_ASSERT(nvl != NULL);
219 nvlist_set_parent(nvl, NULL);
220 }
221
222 static void
223 nvpair_remove_nvlist_array(nvpair_t *nvp)
224 {
225 nvlist_t **nvlarray;
226 size_t count, i;
227
228 /* XXX: DECONST is bad, mkay? */
229 nvlarray = __DECONST(nvlist_t **,
230 nvpair_get_nvlist_array(nvp, &count));
231 for (i = 0; i < count; i++) {
232 nvlist_set_array_next(nvlarray[i], NULL);
233 nvlist_set_parent(nvlarray[i], NULL);
234 }
235 }
236
237 void
238 nvpair_remove(struct nvl_head *head, nvpair_t *nvp,
239 const nvlist_t *nvl __unused)
240 {
241
242 NVPAIR_ASSERT(nvp);
243 PJDLOG_ASSERT(nvp->nvp_list == nvl);
244
245 if (nvpair_type(nvp) == NV_TYPE_NVLIST)
246 nvpair_remove_nvlist(nvp);
247 else if (nvpair_type(nvp) == NV_TYPE_NVLIST_ARRAY)
248 nvpair_remove_nvlist_array(nvp);
249
250 TAILQ_REMOVE(head, nvp, nvp_next);
251 nvp->nvp_list = NULL;
252 }
253
254 nvpair_t *
255 nvpair_clone(const nvpair_t *nvp)
256 {
257 nvpair_t *newnvp;
258 const char *name;
259 const void *data;
260 size_t datasize;
261
262 NVPAIR_ASSERT(nvp);
263
264 name = nvpair_name(nvp);
265
266 switch (nvpair_type(nvp)) {
267 case NV_TYPE_NULL:
268 newnvp = nvpair_create_null(name);
269 break;
270 case NV_TYPE_BOOL:
271 newnvp = nvpair_create_bool(name, nvpair_get_bool(nvp));
272 break;
273 case NV_TYPE_NUMBER:
274 newnvp = nvpair_create_number(name, nvpair_get_number(nvp));
275 break;
276 case NV_TYPE_STRING:
277 newnvp = nvpair_create_string(name, nvpair_get_string(nvp));
278 break;
279 case NV_TYPE_NVLIST:
280 newnvp = nvpair_create_nvlist(name, nvpair_get_nvlist(nvp));
281 break;
282 case NV_TYPE_BINARY:
283 data = nvpair_get_binary(nvp, &datasize);
284 newnvp = nvpair_create_binary(name, data, datasize);
285 break;
286 case NV_TYPE_BOOL_ARRAY:
287 data = nvpair_get_bool_array(nvp, &datasize);
288 newnvp = nvpair_create_bool_array(name, data, datasize);
289 break;
290 case NV_TYPE_NUMBER_ARRAY:
291 data = nvpair_get_number_array(nvp, &datasize);
292 newnvp = nvpair_create_number_array(name, data, datasize);
293 break;
294 case NV_TYPE_STRING_ARRAY:
295 data = nvpair_get_string_array(nvp, &datasize);
296 newnvp = nvpair_create_string_array(name, data, datasize);
297 break;
298 case NV_TYPE_NVLIST_ARRAY:
299 data = nvpair_get_nvlist_array(nvp, &datasize);
300 newnvp = nvpair_create_nvlist_array(name, data, datasize);
301 break;
302 #ifndef _KERNEL
303 case NV_TYPE_DESCRIPTOR:
304 newnvp = nvpair_create_descriptor(name,
305 nvpair_get_descriptor(nvp));
306 break;
307 case NV_TYPE_DESCRIPTOR_ARRAY:
308 data = nvpair_get_descriptor_array(nvp, &datasize);
309 newnvp = nvpair_create_descriptor_array(name, data, datasize);
310 break;
311 #endif
312 default:
313 PJDLOG_ABORT("Unknown type: %d.", nvpair_type(nvp));
314 }
315
316 return (newnvp);
317 }
318
319 size_t
320 nvpair_header_size(void)
321 {
322
323 return (sizeof(struct nvpair_header));
324 }
325
326 size_t
327 nvpair_size(const nvpair_t *nvp)
328 {
329
330 NVPAIR_ASSERT(nvp);
331
332 return (nvp->nvp_datasize);
333 }
334
335 unsigned char *
336 nvpair_pack_header(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
337 {
338 struct nvpair_header nvphdr;
339 size_t namesize;
340
341 NVPAIR_ASSERT(nvp);
342
343 nvphdr.nvph_type = nvp->nvp_type;
344 namesize = strlen(nvp->nvp_name) + 1;
345 PJDLOG_ASSERT(namesize > 0 && namesize <= UINT16_MAX);
346 nvphdr.nvph_namesize = namesize;
347 nvphdr.nvph_datasize = nvp->nvp_datasize;
348 nvphdr.nvph_nitems = nvp->nvp_nitems;
349 PJDLOG_ASSERT(*leftp >= sizeof(nvphdr));
350 memcpy(ptr, &nvphdr, sizeof(nvphdr));
351 ptr += sizeof(nvphdr);
352 *leftp -= sizeof(nvphdr);
353
354 PJDLOG_ASSERT(*leftp >= namesize);
355 memcpy(ptr, nvp->nvp_name, namesize);
356 ptr += namesize;
357 *leftp -= namesize;
358
359 return (ptr);
360 }
361
362 unsigned char *
363 nvpair_pack_null(const nvpair_t *nvp __unused, unsigned char *ptr,
364 size_t *leftp __unused)
365 {
366
367 NVPAIR_ASSERT(nvp);
368 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NULL);
369
370 return (ptr);
371 }
372
373 unsigned char *
374 nvpair_pack_bool(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
375 {
376 uint8_t value;
377
378 NVPAIR_ASSERT(nvp);
379 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL);
380
381 value = (uint8_t)nvp->nvp_data;
382
383 PJDLOG_ASSERT(*leftp >= sizeof(value));
384 memcpy(ptr, &value, sizeof(value));
385 ptr += sizeof(value);
386 *leftp -= sizeof(value);
387
388 return (ptr);
389 }
390
391 unsigned char *
392 nvpair_pack_number(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
393 {
394 uint64_t value;
395
396 NVPAIR_ASSERT(nvp);
397 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER);
398
399 value = (uint64_t)nvp->nvp_data;
400
401 PJDLOG_ASSERT(*leftp >= sizeof(value));
402 memcpy(ptr, &value, sizeof(value));
403 ptr += sizeof(value);
404 *leftp -= sizeof(value);
405
406 return (ptr);
407 }
408
409 unsigned char *
410 nvpair_pack_string(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
411 {
412
413 NVPAIR_ASSERT(nvp);
414 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING);
415
416 PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize);
417 memcpy(ptr, (const void *)(intptr_t)nvp->nvp_data, nvp->nvp_datasize);
418 ptr += nvp->nvp_datasize;
419 *leftp -= nvp->nvp_datasize;
420
421 return (ptr);
422 }
423
424 unsigned char *
425 nvpair_pack_nvlist_up(unsigned char *ptr, size_t *leftp)
426 {
427 struct nvpair_header nvphdr;
428 size_t namesize;
429 const char *name = "";
430
431 namesize = 1;
432 nvphdr.nvph_type = NV_TYPE_NVLIST_UP;
433 nvphdr.nvph_namesize = namesize;
434 nvphdr.nvph_datasize = 0;
435 nvphdr.nvph_nitems = 0;
436 PJDLOG_ASSERT(*leftp >= sizeof(nvphdr));
437 memcpy(ptr, &nvphdr, sizeof(nvphdr));
438 ptr += sizeof(nvphdr);
439 *leftp -= sizeof(nvphdr);
440
441 PJDLOG_ASSERT(*leftp >= namesize);
442 memcpy(ptr, name, namesize);
443 ptr += namesize;
444 *leftp -= namesize;
445
446 return (ptr);
447 }
448
449 unsigned char *
450 nvpair_pack_nvlist_array_next(unsigned char *ptr, size_t *leftp)
451 {
452 struct nvpair_header nvphdr;
453 size_t namesize;
454 const char *name = "";
455
456 namesize = 1;
457 nvphdr.nvph_type = NV_TYPE_NVLIST_ARRAY_NEXT;
458 nvphdr.nvph_namesize = namesize;
459 nvphdr.nvph_datasize = 0;
460 nvphdr.nvph_nitems = 0;
461 PJDLOG_ASSERT(*leftp >= sizeof(nvphdr));
462 memcpy(ptr, &nvphdr, sizeof(nvphdr));
463 ptr += sizeof(nvphdr);
464 *leftp -= sizeof(nvphdr);
465
466 PJDLOG_ASSERT(*leftp >= namesize);
467 memcpy(ptr, name, namesize);
468 ptr += namesize;
469 *leftp -= namesize;
470
471 return (ptr);
472 }
473
474 #ifndef _KERNEL
475 unsigned char *
476 nvpair_pack_descriptor(const nvpair_t *nvp, unsigned char *ptr, int64_t *fdidxp,
477 size_t *leftp)
478 {
479 int64_t value;
480
481 NVPAIR_ASSERT(nvp);
482 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR);
483
484 value = (int64_t)nvp->nvp_data;
485 if (value != -1) {
486 /*
487 * If there is a real descriptor here, we change its number
488 * to position in the array of descriptors send via control
489 * message.
490 */
491 PJDLOG_ASSERT(fdidxp != NULL);
492
493 value = *fdidxp;
494 (*fdidxp)++;
495 }
496
497 PJDLOG_ASSERT(*leftp >= sizeof(value));
498 memcpy(ptr, &value, sizeof(value));
499 ptr += sizeof(value);
500 *leftp -= sizeof(value);
501
502 return (ptr);
503 }
504 #endif
505
506 unsigned char *
507 nvpair_pack_binary(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
508 {
509
510 NVPAIR_ASSERT(nvp);
511 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY);
512
513 PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize);
514 memcpy(ptr, (const void *)(intptr_t)nvp->nvp_data, nvp->nvp_datasize);
515 ptr += nvp->nvp_datasize;
516 *leftp -= nvp->nvp_datasize;
517
518 return (ptr);
519 }
520
521 unsigned char *
522 nvpair_pack_bool_array(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
523 {
524
525 NVPAIR_ASSERT(nvp);
526 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL_ARRAY);
527 PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize);
528
529 memcpy(ptr, (const void *)(intptr_t)nvp->nvp_data, nvp->nvp_datasize);
530 ptr += nvp->nvp_datasize;
531 *leftp -= nvp->nvp_datasize;
532
533 return (ptr);
534 }
535
536 unsigned char *
537 nvpair_pack_number_array(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
538 {
539
540 NVPAIR_ASSERT(nvp);
541 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER_ARRAY);
542 PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize);
543
544 memcpy(ptr, (const void *)(intptr_t)nvp->nvp_data, nvp->nvp_datasize);
545 ptr += nvp->nvp_datasize;
546 *leftp -= nvp->nvp_datasize;
547
548 return (ptr);
549 }
550
551 unsigned char *
552 nvpair_pack_string_array(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
553 {
554 unsigned int ii;
555 size_t size __unused, len;
556 const char * const *array;
557
558 NVPAIR_ASSERT(nvp);
559 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING_ARRAY);
560 PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize);
561
562 size = 0;
563 array = nvpair_get_string_array(nvp, NULL);
564 PJDLOG_ASSERT(array != NULL);
565
566 for (ii = 0; ii < nvp->nvp_nitems; ii++) {
567 len = strlen(array[ii]) + 1;
568 PJDLOG_ASSERT(*leftp >= len);
569
570 memcpy(ptr, (const void *)array[ii], len);
571 size += len;
572 ptr += len;
573 *leftp -= len;
574 }
575
576 PJDLOG_ASSERT(size == nvp->nvp_datasize);
577
578 return (ptr);
579 }
580
581 #ifndef _KERNEL
582 unsigned char *
583 nvpair_pack_descriptor_array(const nvpair_t *nvp, unsigned char *ptr,
584 int64_t *fdidxp, size_t *leftp)
585 {
586 int64_t value;
587 const int *array;
588 unsigned int ii;
589
590 NVPAIR_ASSERT(nvp);
591 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR_ARRAY);
592 PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize);
593
594 array = nvpair_get_descriptor_array(nvp, NULL);
595 PJDLOG_ASSERT(array != NULL);
596
597 for (ii = 0; ii < nvp->nvp_nitems; ii++) {
598 PJDLOG_ASSERT(*leftp >= sizeof(value));
599
600 value = array[ii];
601 if (value != -1) {
602 /*
603 * If there is a real descriptor here, we change its
604 * number to position in the array of descriptors send
605 * via control message.
606 */
607 PJDLOG_ASSERT(fdidxp != NULL);
608
609 value = *fdidxp;
610 (*fdidxp)++;
611 }
612 memcpy(ptr, &value, sizeof(value));
613 ptr += sizeof(value);
614 *leftp -= sizeof(value);
615 }
616
617 return (ptr);
618 }
619 #endif
620
621 void
622 nvpair_init_datasize(nvpair_t *nvp)
623 {
624
625 NVPAIR_ASSERT(nvp);
626
627 if (nvp->nvp_type == NV_TYPE_NVLIST) {
628 if (nvp->nvp_data == 0) {
629 nvp->nvp_datasize = 0;
630 } else {
631 nvp->nvp_datasize =
632 nvlist_size((const nvlist_t *)(intptr_t)nvp->nvp_data);
633 }
634 }
635 }
636
637 const unsigned char *
638 nvpair_unpack_header(bool isbe, nvpair_t *nvp, const unsigned char *ptr,
639 size_t *leftp)
640 {
641 struct nvpair_header nvphdr;
642
643 if (*leftp < sizeof(nvphdr))
644 goto fail;
645
646 memcpy(&nvphdr, ptr, sizeof(nvphdr));
647 ptr += sizeof(nvphdr);
648 *leftp -= sizeof(nvphdr);
649
650 #if NV_TYPE_FIRST > 0
651 if (nvphdr.nvph_type < NV_TYPE_FIRST)
652 goto fail;
653 #endif
654 if (nvphdr.nvph_type > NV_TYPE_LAST &&
655 nvphdr.nvph_type != NV_TYPE_NVLIST_UP &&
656 nvphdr.nvph_type != NV_TYPE_NVLIST_ARRAY_NEXT) {
657 goto fail;
658 }
659
660 #if BYTE_ORDER == BIG_ENDIAN
661 if (!isbe) {
662 nvphdr.nvph_namesize = le16toh(nvphdr.nvph_namesize);
663 nvphdr.nvph_datasize = le64toh(nvphdr.nvph_datasize);
664 nvphdr.nvph_nitems = le64toh(nvphdr.nvph_nitems);
665 }
666 #else
667 if (isbe) {
668 nvphdr.nvph_namesize = be16toh(nvphdr.nvph_namesize);
669 nvphdr.nvph_datasize = be64toh(nvphdr.nvph_datasize);
670 nvphdr.nvph_nitems = be64toh(nvphdr.nvph_nitems);
671 }
672 #endif
673
674 if (nvphdr.nvph_namesize > NV_NAME_MAX)
675 goto fail;
676 if (*leftp < nvphdr.nvph_namesize)
677 goto fail;
678 if (nvphdr.nvph_namesize < 1)
679 goto fail;
680 if (strnlen((const char *)ptr, nvphdr.nvph_namesize) !=
681 (size_t)(nvphdr.nvph_namesize - 1)) {
682 goto fail;
683 }
684
685 memcpy(nvp->nvp_name, ptr, nvphdr.nvph_namesize);
686 ptr += nvphdr.nvph_namesize;
687 *leftp -= nvphdr.nvph_namesize;
688
689 if (*leftp < nvphdr.nvph_datasize)
690 goto fail;
691
692 nvp->nvp_type = nvphdr.nvph_type;
693 nvp->nvp_data = 0;
694 nvp->nvp_datasize = nvphdr.nvph_datasize;
695 nvp->nvp_nitems = nvphdr.nvph_nitems;
696
697 return (ptr);
698 fail:
699 ERRNO_SET(EINVAL);
700 return (NULL);
701 }
702
703 const unsigned char *
704 nvpair_unpack_null(bool isbe __unused, nvpair_t *nvp, const unsigned char *ptr,
705 size_t *leftp __unused)
706 {
707
708 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NULL);
709
710 if (nvp->nvp_datasize != 0) {
711 ERRNO_SET(EINVAL);
712 return (NULL);
713 }
714
715 return (ptr);
716 }
717
718 const unsigned char *
719 nvpair_unpack_bool(bool isbe __unused, nvpair_t *nvp, const unsigned char *ptr,
720 size_t *leftp)
721 {
722 uint8_t value;
723
724 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL);
725
726 if (nvp->nvp_datasize != sizeof(value)) {
727 ERRNO_SET(EINVAL);
728 return (NULL);
729 }
730 if (*leftp < sizeof(value)) {
731 ERRNO_SET(EINVAL);
732 return (NULL);
733 }
734
735 memcpy(&value, ptr, sizeof(value));
736 ptr += sizeof(value);
737 *leftp -= sizeof(value);
738
739 if (value != 0 && value != 1) {
740 ERRNO_SET(EINVAL);
741 return (NULL);
742 }
743
744 nvp->nvp_data = (uint64_t)value;
745
746 return (ptr);
747 }
748
749 const unsigned char *
750 nvpair_unpack_number(bool isbe, nvpair_t *nvp, const unsigned char *ptr,
751 size_t *leftp)
752 {
753
754 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER);
755
756 if (nvp->nvp_datasize != sizeof(uint64_t)) {
757 ERRNO_SET(EINVAL);
758 return (NULL);
759 }
760 if (*leftp < sizeof(uint64_t)) {
761 ERRNO_SET(EINVAL);
762 return (NULL);
763 }
764
765 if (isbe)
766 nvp->nvp_data = be64dec(ptr);
767 else
768 nvp->nvp_data = le64dec(ptr);
769
770 ptr += sizeof(uint64_t);
771 *leftp -= sizeof(uint64_t);
772
773 return (ptr);
774 }
775
776 const unsigned char *
777 nvpair_unpack_string(bool isbe __unused, nvpair_t *nvp,
778 const unsigned char *ptr, size_t *leftp)
779 {
780
781 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING);
782
783 if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) {
784 ERRNO_SET(EINVAL);
785 return (NULL);
786 }
787
788 if (strnlen((const char *)ptr, nvp->nvp_datasize) !=
789 nvp->nvp_datasize - 1) {
790 ERRNO_SET(EINVAL);
791 return (NULL);
792 }
793
794 nvp->nvp_data = (uint64_t)(uintptr_t)nv_strdup((const char *)ptr);
795 if (nvp->nvp_data == 0)
796 return (NULL);
797
798 ptr += nvp->nvp_datasize;
799 *leftp -= nvp->nvp_datasize;
800
801 return (ptr);
802 }
803
804 const unsigned char *
805 nvpair_unpack_nvlist(bool isbe __unused, nvpair_t *nvp,
806 const unsigned char *ptr, size_t *leftp, size_t nfds, nvlist_t **child)
807 {
808 nvlist_t *value;
809
810 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST);
811
812 if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) {
813 ERRNO_SET(EINVAL);
814 return (NULL);
815 }
816
817 value = nvlist_create(0);
818 if (value == NULL)
819 return (NULL);
820
821 ptr = nvlist_unpack_header(value, ptr, nfds, NULL, leftp);
822 if (ptr == NULL)
823 return (NULL);
824
825 nvp->nvp_data = (uint64_t)(uintptr_t)value;
826 *child = value;
827
828 return (ptr);
829 }
830
831 #ifndef _KERNEL
832 const unsigned char *
833 nvpair_unpack_descriptor(bool isbe, nvpair_t *nvp, const unsigned char *ptr,
834 size_t *leftp, const int *fds, size_t nfds)
835 {
836 int64_t idx;
837
838 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR);
839
840 if (nvp->nvp_datasize != sizeof(idx)) {
841 ERRNO_SET(EINVAL);
842 return (NULL);
843 }
844 if (*leftp < sizeof(idx)) {
845 ERRNO_SET(EINVAL);
846 return (NULL);
847 }
848
849 if (isbe)
850 idx = be64dec(ptr);
851 else
852 idx = le64dec(ptr);
853
854 if (idx < 0) {
855 ERRNO_SET(EINVAL);
856 return (NULL);
857 }
858
859 if ((size_t)idx >= nfds) {
860 ERRNO_SET(EINVAL);
861 return (NULL);
862 }
863
864 nvp->nvp_data = (uint64_t)fds[idx];
865
866 ptr += sizeof(idx);
867 *leftp -= sizeof(idx);
868
869 return (ptr);
870 }
871 #endif
872
873 const unsigned char *
874 nvpair_unpack_binary(bool isbe __unused, nvpair_t *nvp,
875 const unsigned char *ptr, size_t *leftp)
876 {
877 void *value;
878
879 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY);
880
881 if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) {
882 ERRNO_SET(EINVAL);
883 return (NULL);
884 }
885
886 value = nv_malloc(nvp->nvp_datasize);
887 if (value == NULL)
888 return (NULL);
889
890 memcpy(value, ptr, nvp->nvp_datasize);
891 ptr += nvp->nvp_datasize;
892 *leftp -= nvp->nvp_datasize;
893
894 nvp->nvp_data = (uint64_t)(uintptr_t)value;
895
896 return (ptr);
897 }
898
899 const unsigned char *
900 nvpair_unpack_bool_array(bool isbe __unused, nvpair_t *nvp,
901 const unsigned char *ptr, size_t *leftp)
902 {
903 uint8_t *value;
904 size_t size;
905 unsigned int i;
906
907 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL_ARRAY);
908
909 size = sizeof(*value) * nvp->nvp_nitems;
910 if (nvp->nvp_datasize != size || *leftp < size ||
911 nvp->nvp_nitems == 0 || size < nvp->nvp_nitems) {
912 ERRNO_SET(EINVAL);
913 return (NULL);
914 }
915
916 value = nv_malloc(size);
917 if (value == NULL)
918 return (NULL);
919
920 for (i = 0; i < nvp->nvp_nitems; i++) {
921 value[i] = *(const uint8_t *)ptr;
922
923 ptr += sizeof(*value);
924 *leftp -= sizeof(*value);
925 }
926
927 nvp->nvp_data = (uint64_t)(uintptr_t)value;
928
929 return (ptr);
930 }
931
932 const unsigned char *
933 nvpair_unpack_number_array(bool isbe, nvpair_t *nvp, const unsigned char *ptr,
934 size_t *leftp)
935 {
936 uint64_t *value;
937 size_t size;
938 unsigned int i;
939
940 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER_ARRAY);
941
942 size = sizeof(*value) * nvp->nvp_nitems;
943 if (nvp->nvp_datasize != size || *leftp < size ||
944 nvp->nvp_nitems == 0 || size < nvp->nvp_nitems) {
945 ERRNO_SET(EINVAL);
946 return (NULL);
947 }
948
949 value = nv_malloc(size);
950 if (value == NULL)
951 return (NULL);
952
953 for (i = 0; i < nvp->nvp_nitems; i++) {
954 if (isbe)
955 value[i] = be64dec(ptr);
956 else
957 value[i] = le64dec(ptr);
958
959 ptr += sizeof(*value);
960 *leftp -= sizeof(*value);
961 }
962
963 nvp->nvp_data = (uint64_t)(uintptr_t)value;
964
965 return (ptr);
966 }
967
968 const unsigned char *
969 nvpair_unpack_string_array(bool isbe __unused, nvpair_t *nvp,
970 const unsigned char *ptr, size_t *leftp)
971 {
972 ssize_t size;
973 size_t len;
974 const char *tmp;
975 char **value;
976 unsigned int ii, j;
977
978 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING_ARRAY);
979
980 if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0 ||
981 nvp->nvp_nitems == 0) {
982 ERRNO_SET(EINVAL);
983 return (NULL);
984 }
985
986 size = nvp->nvp_datasize;
987 tmp = (const char *)ptr;
988 for (ii = 0; ii < nvp->nvp_nitems; ii++) {
989 len = strnlen(tmp, size - 1) + 1;
990 size -= len;
991 if (size < 0) {
992 ERRNO_SET(EINVAL);
993 return (NULL);
994 }
995 tmp += len;
996 }
997 if (size != 0) {
998 ERRNO_SET(EINVAL);
999 return (NULL);
1000 }
1001
1002 value = nv_malloc(sizeof(*value) * nvp->nvp_nitems);
1003 if (value == NULL)
1004 return (NULL);
1005
1006 for (ii = 0; ii < nvp->nvp_nitems; ii++) {
1007 value[ii] = nv_strdup((const char *)ptr);
1008 if (value[ii] == NULL)
1009 goto out;
1010 len = strlen(value[ii]) + 1;
1011 ptr += len;
1012 *leftp -= len;
1013 }
1014 nvp->nvp_data = (uint64_t)(uintptr_t)value;
1015
1016 return (ptr);
1017 out:
1018 for (j = 0; j < ii; j++)
1019 nv_free(value[j]);
1020 nv_free(value);
1021 return (NULL);
1022 }
1023
1024 #ifndef _KERNEL
1025 const unsigned char *
1026 nvpair_unpack_descriptor_array(bool isbe, nvpair_t *nvp,
1027 const unsigned char *ptr, size_t *leftp, const int *fds, size_t nfds)
1028 {
1029 int64_t idx;
1030 size_t size;
1031 unsigned int ii;
1032 int *array;
1033
1034 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR_ARRAY);
1035
1036 size = sizeof(idx) * nvp->nvp_nitems;
1037 if (nvp->nvp_datasize != size || *leftp < size ||
1038 nvp->nvp_nitems == 0 || size < nvp->nvp_nitems) {
1039 ERRNO_SET(EINVAL);
1040 return (NULL);
1041 }
1042
1043 array = (int *)nv_malloc(size);
1044 if (array == NULL)
1045 return (NULL);
1046
1047 for (ii = 0; ii < nvp->nvp_nitems; ii++) {
1048 if (isbe)
1049 idx = be64dec(ptr);
1050 else
1051 idx = le64dec(ptr);
1052
1053 if (idx < 0) {
1054 ERRNO_SET(EINVAL);
1055 nv_free(array);
1056 return (NULL);
1057 }
1058
1059 if ((size_t)idx >= nfds) {
1060 ERRNO_SET(EINVAL);
1061 nv_free(array);
1062 return (NULL);
1063 }
1064
1065 array[ii] = (uint64_t)fds[idx];
1066
1067 ptr += sizeof(idx);
1068 *leftp -= sizeof(idx);
1069 }
1070
1071 nvp->nvp_data = (uint64_t)(uintptr_t)array;
1072
1073 return (ptr);
1074 }
1075 #endif
1076
1077 const unsigned char *
1078 nvpair_unpack_nvlist_array(bool isbe __unused, nvpair_t *nvp,
1079 const unsigned char *ptr, size_t *leftp, nvlist_t **firstel)
1080 {
1081 nvlist_t **value;
1082 nvpair_t *tmpnvp;
1083 unsigned int ii, j;
1084 size_t sizeup;
1085
1086 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST_ARRAY);
1087
1088 sizeup = sizeof(struct nvpair_header) * nvp->nvp_nitems;
1089 if (nvp->nvp_nitems == 0 || sizeup < nvp->nvp_nitems ||
1090 sizeup > *leftp) {
1091 ERRNO_SET(EINVAL);
1092 return (NULL);
1093 }
1094
1095 value = nv_malloc(nvp->nvp_nitems * sizeof(*value));
1096 if (value == NULL)
1097 return (NULL);
1098
1099 for (ii = 0; ii < nvp->nvp_nitems; ii++) {
1100 value[ii] = nvlist_create(0);
1101 if (value[ii] == NULL)
1102 goto fail;
1103 if (ii > 0) {
1104 tmpnvp = nvpair_allocv(" ", NV_TYPE_NVLIST,
1105 (uint64_t)(uintptr_t)value[ii], 0, 0);
1106 if (tmpnvp == NULL)
1107 goto fail;
1108 nvlist_set_array_next(value[ii - 1], tmpnvp);
1109 }
1110 }
1111 nvlist_set_flags(value[nvp->nvp_nitems - 1], NV_FLAG_IN_ARRAY);
1112
1113 nvp->nvp_data = (uint64_t)(uintptr_t)value;
1114 *firstel = value[0];
1115
1116 return (ptr);
1117 fail:
1118 ERRNO_SAVE();
1119 for (j = 0; j <= ii; j++)
1120 nvlist_destroy(value[j]);
1121 nv_free(value);
1122 ERRNO_RESTORE();
1123
1124 return (NULL);
1125 }
1126
1127 const unsigned char *
1128 nvpair_unpack(bool isbe, const unsigned char *ptr, size_t *leftp,
1129 nvpair_t **nvpp)
1130 {
1131 nvpair_t *nvp, *tmp;
1132
1133 nvp = nv_calloc(1, sizeof(*nvp) + NV_NAME_MAX);
1134 if (nvp == NULL)
1135 return (NULL);
1136 nvp->nvp_name = (char *)(nvp + 1);
1137
1138 ptr = nvpair_unpack_header(isbe, nvp, ptr, leftp);
1139 if (ptr == NULL)
1140 goto fail;
1141 tmp = nv_realloc(nvp, sizeof(*nvp) + strlen(nvp->nvp_name) + 1);
1142 if (tmp == NULL)
1143 goto fail;
1144 nvp = tmp;
1145
1146 /* Update nvp_name after realloc(). */
1147 nvp->nvp_name = (char *)(nvp + 1);
1148 nvp->nvp_data = 0x00;
1149 nvp->nvp_magic = NVPAIR_MAGIC;
1150 *nvpp = nvp;
1151 return (ptr);
1152 fail:
1153 nv_free(nvp);
1154 return (NULL);
1155 }
1156
1157 int
1158 nvpair_type(const nvpair_t *nvp)
1159 {
1160
1161 NVPAIR_ASSERT(nvp);
1162
1163 return (nvp->nvp_type);
1164 }
1165
1166 const char *
1167 nvpair_name(const nvpair_t *nvp)
1168 {
1169
1170 NVPAIR_ASSERT(nvp);
1171
1172 return (nvp->nvp_name);
1173 }
1174
1175 nvpair_t *
1176 nvpair_create_stringf(const char *name, const char *valuefmt, ...)
1177 {
1178 va_list valueap;
1179 nvpair_t *nvp;
1180
1181 va_start(valueap, valuefmt);
1182 nvp = nvpair_create_stringv(name, valuefmt, valueap);
1183 va_end(valueap);
1184
1185 return (nvp);
1186 }
1187
1188 nvpair_t *
1189 nvpair_create_stringv(const char *name, const char *valuefmt, va_list valueap)
1190 {
1191 nvpair_t *nvp;
1192 char *str;
1193 int len;
1194
1195 len = nv_vasprintf(&str, valuefmt, valueap);
1196 if (len < 0)
1197 return (NULL);
1198 nvp = nvpair_create_string(name, str);
1199 nv_free(str);
1200 return (nvp);
1201 }
1202
1203 nvpair_t *
1204 nvpair_create_null(const char *name)
1205 {
1206
1207 return (nvpair_allocv(name, NV_TYPE_NULL, 0, 0, 0));
1208 }
1209
1210 nvpair_t *
1211 nvpair_create_bool(const char *name, bool value)
1212 {
1213
1214 return (nvpair_allocv(name, NV_TYPE_BOOL, value ? 1 : 0,
1215 sizeof(uint8_t), 0));
1216 }
1217
1218 nvpair_t *
1219 nvpair_create_number(const char *name, uint64_t value)
1220 {
1221
1222 return (nvpair_allocv(name, NV_TYPE_NUMBER, value, sizeof(value), 0));
1223 }
1224
1225 nvpair_t *
1226 nvpair_create_string(const char *name, const char *value)
1227 {
1228 nvpair_t *nvp;
1229 size_t size;
1230 char *data;
1231
1232 if (value == NULL) {
1233 ERRNO_SET(EINVAL);
1234 return (NULL);
1235 }
1236
1237 data = nv_strdup(value);
1238 if (data == NULL)
1239 return (NULL);
1240 size = strlen(value) + 1;
1241
1242 nvp = nvpair_allocv(name, NV_TYPE_STRING, (uint64_t)(uintptr_t)data,
1243 size, 0);
1244 if (nvp == NULL)
1245 nv_free(data);
1246
1247 return (nvp);
1248 }
1249
1250 nvpair_t *
1251 nvpair_create_nvlist(const char *name, const nvlist_t *value)
1252 {
1253 nvlist_t *nvl;
1254 nvpair_t *nvp;
1255
1256 if (value == NULL) {
1257 ERRNO_SET(EINVAL);
1258 return (NULL);
1259 }
1260
1261 nvl = nvlist_clone(value);
1262 if (nvl == NULL)
1263 return (NULL);
1264
1265 nvp = nvpair_allocv(name, NV_TYPE_NVLIST, (uint64_t)(uintptr_t)nvl, 0,
1266 0);
1267 if (nvp == NULL)
1268 nvlist_destroy(nvl);
1269 else
1270 nvlist_set_parent(nvl, nvp);
1271
1272 return (nvp);
1273 }
1274
1275 #ifndef _KERNEL
1276 nvpair_t *
1277 nvpair_create_descriptor(const char *name, int value)
1278 {
1279 nvpair_t *nvp;
1280
1281 value = fcntl(value, F_DUPFD_CLOEXEC, 0);
1282 if (value < 0)
1283 return (NULL);
1284
1285 nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR, (uint64_t)value,
1286 sizeof(int64_t), 0);
1287 if (nvp == NULL) {
1288 ERRNO_SAVE();
1289 close(value);
1290 ERRNO_RESTORE();
1291 }
1292
1293 return (nvp);
1294 }
1295 #endif
1296
1297 nvpair_t *
1298 nvpair_create_binary(const char *name, const void *value, size_t size)
1299 {
1300 nvpair_t *nvp;
1301 void *data;
1302
1303 if (value == NULL || size == 0) {
1304 ERRNO_SET(EINVAL);
1305 return (NULL);
1306 }
1307
1308 data = nv_malloc(size);
1309 if (data == NULL)
1310 return (NULL);
1311 memcpy(data, value, size);
1312
1313 nvp = nvpair_allocv(name, NV_TYPE_BINARY, (uint64_t)(uintptr_t)data,
1314 size, 0);
1315 if (nvp == NULL)
1316 nv_free(data);
1317
1318 return (nvp);
1319 }
1320
1321 nvpair_t *
1322 nvpair_create_bool_array(const char *name, const bool *value, size_t nitems)
1323 {
1324 nvpair_t *nvp;
1325 size_t size;
1326 void *data;
1327
1328 if (value == NULL || nitems == 0) {
1329 ERRNO_SET(EINVAL);
1330 return (NULL);
1331 }
1332
1333 size = sizeof(value[0]) * nitems;
1334 data = nv_malloc(size);
1335 if (data == NULL)
1336 return (NULL);
1337
1338 memcpy(data, value, size);
1339 nvp = nvpair_allocv(name, NV_TYPE_BOOL_ARRAY, (uint64_t)(uintptr_t)data,
1340 size, nitems);
1341 if (nvp == NULL) {
1342 ERRNO_SAVE();
1343 nv_free(data);
1344 ERRNO_RESTORE();
1345 }
1346
1347 return (nvp);
1348 }
1349
1350 nvpair_t *
1351 nvpair_create_number_array(const char *name, const uint64_t *value,
1352 size_t nitems)
1353 {
1354 nvpair_t *nvp;
1355 size_t size;
1356 void *data;
1357
1358 if (value == NULL || nitems == 0) {
1359 ERRNO_SET(EINVAL);
1360 return (NULL);
1361 }
1362
1363 size = sizeof(value[0]) * nitems;
1364 data = nv_malloc(size);
1365 if (data == NULL)
1366 return (NULL);
1367
1368 memcpy(data, value, size);
1369 nvp = nvpair_allocv(name, NV_TYPE_NUMBER_ARRAY,
1370 (uint64_t)(uintptr_t)data, size, nitems);
1371 if (nvp == NULL) {
1372 ERRNO_SAVE();
1373 nv_free(data);
1374 ERRNO_RESTORE();
1375 }
1376
1377 return (nvp);
1378 }
1379
1380 nvpair_t *
1381 nvpair_create_string_array(const char *name, const char * const *value,
1382 size_t nitems)
1383 {
1384 nvpair_t *nvp;
1385 unsigned int ii;
1386 size_t datasize, size;
1387 char **data;
1388
1389 if (value == NULL || nitems == 0) {
1390 ERRNO_SET(EINVAL);
1391 return (NULL);
1392 }
1393
1394 nvp = NULL;
1395 datasize = 0;
1396 data = nv_malloc(sizeof(value[0]) * nitems);
1397 if (data == NULL)
1398 return (NULL);
1399
1400 for (ii = 0; ii < nitems; ii++) {
1401 if (value[ii] == NULL) {
1402 ERRNO_SET(EINVAL);
1403 goto fail;
1404 }
1405
1406 size = strlen(value[ii]) + 1;
1407 datasize += size;
1408 data[ii] = nv_strdup(value[ii]);
1409 if (data[ii] == NULL)
1410 goto fail;
1411 }
1412 nvp = nvpair_allocv(name, NV_TYPE_STRING_ARRAY,
1413 (uint64_t)(uintptr_t)data, datasize, nitems);
1414
1415 fail:
1416 if (nvp == NULL) {
1417 ERRNO_SAVE();
1418 for (; ii > 0; ii--)
1419 nv_free(data[ii - 1]);
1420 nv_free(data);
1421 ERRNO_RESTORE();
1422 }
1423
1424 return (nvp);
1425 }
1426
1427 nvpair_t *
1428 nvpair_create_nvlist_array(const char *name, const nvlist_t * const *value,
1429 size_t nitems)
1430 {
1431 unsigned int ii;
1432 nvlist_t **nvls;
1433 nvpair_t *parent;
1434 int flags;
1435
1436 nvls = NULL;
1437
1438 if (value == NULL || nitems == 0) {
1439 ERRNO_SET(EINVAL);
1440 return (NULL);
1441 }
1442
1443 nvls = nv_malloc(sizeof(value[0]) * nitems);
1444 if (nvls == NULL)
1445 return (NULL);
1446
1447 for (ii = 0; ii < nitems; ii++) {
1448 if (value[ii] == NULL) {
1449 ERRNO_SET(EINVAL);
1450 goto fail;
1451 }
1452
1453 nvls[ii] = nvlist_clone(value[ii]);
1454 if (nvls[ii] == NULL)
1455 goto fail;
1456
1457 if (ii > 0) {
1458 nvpair_t *nvp;
1459
1460 nvp = nvpair_allocv(" ", NV_TYPE_NVLIST,
1461 (uint64_t)(uintptr_t)nvls[ii], 0, 0);
1462 if (nvp == NULL) {
1463 ERRNO_SAVE();
1464 nvlist_destroy(nvls[ii]);
1465 ERRNO_RESTORE();
1466 goto fail;
1467 }
1468 nvlist_set_array_next(nvls[ii - 1], nvp);
1469 }
1470 }
1471 flags = nvlist_flags(nvls[nitems - 1]) | NV_FLAG_IN_ARRAY;
1472 nvlist_set_flags(nvls[nitems - 1], flags);
1473
1474 parent = nvpair_allocv(name, NV_TYPE_NVLIST_ARRAY,
1475 (uint64_t)(uintptr_t)nvls, 0, nitems);
1476 if (parent == NULL)
1477 goto fail;
1478
1479 for (ii = 0; ii < nitems; ii++)
1480 nvlist_set_parent(nvls[ii], parent);
1481
1482 return (parent);
1483
1484 fail:
1485 ERRNO_SAVE();
1486 for (; ii > 0; ii--)
1487 nvlist_destroy(nvls[ii - 1]);
1488 nv_free(nvls);
1489 ERRNO_RESTORE();
1490
1491 return (NULL);
1492 }
1493
1494 #ifndef _KERNEL
1495 nvpair_t *
1496 nvpair_create_descriptor_array(const char *name, const int *value,
1497 size_t nitems)
1498 {
1499 unsigned int ii;
1500 nvpair_t *nvp;
1501 int *fds;
1502
1503 if (value == NULL) {
1504 ERRNO_SET(EINVAL);
1505 return (NULL);
1506 }
1507
1508 nvp = NULL;
1509
1510 fds = nv_malloc(sizeof(value[0]) * nitems);
1511 if (fds == NULL)
1512 return (NULL);
1513 for (ii = 0; ii < nitems; ii++) {
1514 if (value[ii] == -1) {
1515 fds[ii] = -1;
1516 } else {
1517 fds[ii] = fcntl(value[ii], F_DUPFD_CLOEXEC, 0);
1518 if (fds[ii] == -1)
1519 goto fail;
1520 }
1521 }
1522
1523 nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR_ARRAY,
1524 (uint64_t)(uintptr_t)fds, sizeof(int64_t) * nitems, nitems);
1525
1526 fail:
1527 if (nvp == NULL) {
1528 ERRNO_SAVE();
1529 for (; ii > 0; ii--) {
1530 if (fds[ii - 1] != -1)
1531 close(fds[ii - 1]);
1532 }
1533 nv_free(fds);
1534 ERRNO_RESTORE();
1535 }
1536
1537 return (nvp);
1538 }
1539 #endif
1540
1541 nvpair_t *
1542 nvpair_move_string(const char *name, char *value)
1543 {
1544 nvpair_t *nvp;
1545
1546 if (value == NULL) {
1547 ERRNO_SET(EINVAL);
1548 return (NULL);
1549 }
1550
1551 nvp = nvpair_allocv(name, NV_TYPE_STRING, (uint64_t)(uintptr_t)value,
1552 strlen(value) + 1, 0);
1553 if (nvp == NULL) {
1554 ERRNO_SAVE();
1555 nv_free(value);
1556 ERRNO_RESTORE();
1557 }
1558
1559 return (nvp);
1560 }
1561
1562 nvpair_t *
1563 nvpair_move_nvlist(const char *name, nvlist_t *value)
1564 {
1565 nvpair_t *nvp;
1566
1567 if (value == NULL || nvlist_get_nvpair_parent(value) != NULL) {
1568 ERRNO_SET(EINVAL);
1569 return (NULL);
1570 }
1571
1572 if (nvlist_error(value) != 0) {
1573 ERRNO_SET(nvlist_error(value));
1574 nvlist_destroy(value);
1575 return (NULL);
1576 }
1577
1578 nvp = nvpair_allocv(name, NV_TYPE_NVLIST, (uint64_t)(uintptr_t)value,
1579 0, 0);
1580 if (nvp == NULL)
1581 nvlist_destroy(value);
1582 else
1583 nvlist_set_parent(value, nvp);
1584
1585 return (nvp);
1586 }
1587
1588 #ifndef _KERNEL
1589 nvpair_t *
1590 nvpair_move_descriptor(const char *name, int value)
1591 {
1592 nvpair_t *nvp;
1593
1594 if (value < 0 || !fd_is_valid(value)) {
1595 ERRNO_SET(EBADF);
1596 return (NULL);
1597 }
1598
1599 nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR, (uint64_t)value,
1600 sizeof(int64_t), 0);
1601 if (nvp == NULL) {
1602 ERRNO_SAVE();
1603 close(value);
1604 ERRNO_RESTORE();
1605 }
1606
1607 return (nvp);
1608 }
1609 #endif
1610
1611 nvpair_t *
1612 nvpair_move_binary(const char *name, void *value, size_t size)
1613 {
1614 nvpair_t *nvp;
1615
1616 if (value == NULL || size == 0) {
1617 ERRNO_SET(EINVAL);
1618 return (NULL);
1619 }
1620
1621 nvp = nvpair_allocv(name, NV_TYPE_BINARY, (uint64_t)(uintptr_t)value,
1622 size, 0);
1623 if (nvp == NULL) {
1624 ERRNO_SAVE();
1625 nv_free(value);
1626 ERRNO_RESTORE();
1627 }
1628
1629 return (nvp);
1630 }
1631
1632 nvpair_t *
1633 nvpair_move_bool_array(const char *name, bool *value, size_t nitems)
1634 {
1635 nvpair_t *nvp;
1636
1637 if (value == NULL || nitems == 0) {
1638 ERRNO_SET(EINVAL);
1639 return (NULL);
1640 }
1641
1642 nvp = nvpair_allocv(name, NV_TYPE_BOOL_ARRAY,
1643 (uint64_t)(uintptr_t)value, sizeof(value[0]) * nitems, nitems);
1644 if (nvp == NULL) {
1645 ERRNO_SAVE();
1646 nv_free(value);
1647 ERRNO_RESTORE();
1648 }
1649
1650 return (nvp);
1651 }
1652
1653 nvpair_t *
1654 nvpair_move_string_array(const char *name, char **value, size_t nitems)
1655 {
1656 nvpair_t *nvp;
1657 size_t i, size;
1658
1659 if (value == NULL || nitems == 0) {
1660 ERRNO_SET(EINVAL);
1661 return (NULL);
1662 }
1663
1664 size = 0;
1665 for (i = 0; i < nitems; i++) {
1666 if (value[i] == NULL) {
1667 ERRNO_SET(EINVAL);
1668 return (NULL);
1669 }
1670
1671 size += strlen(value[i]) + 1;
1672 }
1673
1674 nvp = nvpair_allocv(name, NV_TYPE_STRING_ARRAY,
1675 (uint64_t)(uintptr_t)value, size, nitems);
1676 if (nvp == NULL) {
1677 ERRNO_SAVE();
1678 for (i = 0; i < nitems; i++)
1679 nv_free(value[i]);
1680 nv_free(value);
1681 ERRNO_RESTORE();
1682 }
1683
1684 return (nvp);
1685 }
1686
1687 nvpair_t *
1688 nvpair_move_number_array(const char *name, uint64_t *value, size_t nitems)
1689 {
1690 nvpair_t *nvp;
1691
1692 if (value == NULL || nitems == 0) {
1693 ERRNO_SET(EINVAL);
1694 return (NULL);
1695 }
1696
1697 nvp = nvpair_allocv(name, NV_TYPE_NUMBER_ARRAY,
1698 (uint64_t)(uintptr_t)value, sizeof(value[0]) * nitems, nitems);
1699 if (nvp == NULL) {
1700 ERRNO_SAVE();
1701 nv_free(value);
1702 ERRNO_RESTORE();
1703 }
1704
1705 return (nvp);
1706 }
1707
1708 nvpair_t *
1709 nvpair_move_nvlist_array(const char *name, nvlist_t **value, size_t nitems)
1710 {
1711 nvpair_t *parent;
1712 unsigned int ii;
1713 int flags;
1714
1715 if (value == NULL || nitems == 0) {
1716 ERRNO_SET(EINVAL);
1717 return (NULL);
1718 }
1719
1720 for (ii = 0; ii < nitems; ii++) {
1721 if (value == NULL || nvlist_error(value[ii]) != 0 ||
1722 nvlist_get_pararr(value[ii], NULL) != NULL) {
1723 ERRNO_SET(EINVAL);
1724 goto fail;
1725 }
1726 if (ii > 0) {
1727 nvpair_t *nvp;
1728
1729 nvp = nvpair_allocv(" ", NV_TYPE_NVLIST,
1730 (uint64_t)(uintptr_t)value[ii], 0, 0);
1731 if (nvp == NULL)
1732 goto fail;
1733 nvlist_set_array_next(value[ii - 1], nvp);
1734 }
1735 }
1736 flags = nvlist_flags(value[nitems - 1]) | NV_FLAG_IN_ARRAY;
1737 nvlist_set_flags(value[nitems - 1], flags);
1738
1739 parent = nvpair_allocv(name, NV_TYPE_NVLIST_ARRAY,
1740 (uint64_t)(uintptr_t)value, 0, nitems);
1741 if (parent == NULL)
1742 goto fail;
1743
1744 for (ii = 0; ii < nitems; ii++)
1745 nvlist_set_parent(value[ii], parent);
1746
1747 return (parent);
1748 fail:
1749 ERRNO_SAVE();
1750 for (ii = 0; ii < nitems; ii++) {
1751 if (value[ii] != NULL &&
1752 nvlist_get_pararr(value[ii], NULL) != NULL) {
1753 nvlist_destroy(value[ii]);
1754 }
1755 }
1756 nv_free(value);
1757 ERRNO_RESTORE();
1758
1759 return (NULL);
1760 }
1761
1762 #ifndef _KERNEL
1763 nvpair_t *
1764 nvpair_move_descriptor_array(const char *name, int *value, size_t nitems)
1765 {
1766 nvpair_t *nvp;
1767 size_t i;
1768
1769 if (value == NULL || nitems == 0) {
1770 ERRNO_SET(EINVAL);
1771 return (NULL);
1772 }
1773
1774 for (i = 0; i < nitems; i++) {
1775 if (value[i] != -1 && !fd_is_valid(value[i])) {
1776 ERRNO_SET(EBADF);
1777 goto fail;
1778 }
1779 }
1780
1781 nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR_ARRAY,
1782 (uint64_t)(uintptr_t)value, sizeof(value[0]) * nitems, nitems);
1783 if (nvp == NULL)
1784 goto fail;
1785
1786 return (nvp);
1787 fail:
1788 ERRNO_SAVE();
1789 for (i = 0; i < nitems; i++) {
1790 if (fd_is_valid(value[i]))
1791 close(value[i]);
1792 }
1793 nv_free(value);
1794 ERRNO_RESTORE();
1795
1796 return (NULL);
1797 }
1798 #endif
1799
1800 bool
1801 nvpair_get_bool(const nvpair_t *nvp)
1802 {
1803
1804 NVPAIR_ASSERT(nvp);
1805
1806 return (nvp->nvp_data == 1);
1807 }
1808
1809 uint64_t
1810 nvpair_get_number(const nvpair_t *nvp)
1811 {
1812
1813 NVPAIR_ASSERT(nvp);
1814
1815 return (nvp->nvp_data);
1816 }
1817
1818 const char *
1819 nvpair_get_string(const nvpair_t *nvp)
1820 {
1821
1822 NVPAIR_ASSERT(nvp);
1823 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING);
1824
1825 return ((const char *)(intptr_t)nvp->nvp_data);
1826 }
1827
1828 const nvlist_t *
1829 nvpair_get_nvlist(const nvpair_t *nvp)
1830 {
1831
1832 NVPAIR_ASSERT(nvp);
1833 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST);
1834
1835 return ((const nvlist_t *)(intptr_t)nvp->nvp_data);
1836 }
1837
1838 #ifndef _KERNEL
1839 int
1840 nvpair_get_descriptor(const nvpair_t *nvp)
1841 {
1842
1843 NVPAIR_ASSERT(nvp);
1844 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR);
1845
1846 return ((int)nvp->nvp_data);
1847 }
1848 #endif
1849
1850 const void *
1851 nvpair_get_binary(const nvpair_t *nvp, size_t *sizep)
1852 {
1853
1854 NVPAIR_ASSERT(nvp);
1855 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY);
1856
1857 if (sizep != NULL)
1858 *sizep = nvp->nvp_datasize;
1859
1860 return ((const void *)(intptr_t)nvp->nvp_data);
1861 }
1862
1863 const bool *
1864 nvpair_get_bool_array(const nvpair_t *nvp, size_t *nitems)
1865 {
1866
1867 NVPAIR_ASSERT(nvp);
1868 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL_ARRAY);
1869
1870 if (nitems != NULL)
1871 *nitems = nvp->nvp_nitems;
1872
1873 return ((const bool *)(intptr_t)nvp->nvp_data);
1874 }
1875
1876 const uint64_t *
1877 nvpair_get_number_array(const nvpair_t *nvp, size_t *nitems)
1878 {
1879
1880 NVPAIR_ASSERT(nvp);
1881 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER_ARRAY);
1882
1883 if (nitems != NULL)
1884 *nitems = nvp->nvp_nitems;
1885
1886 return ((const uint64_t *)(intptr_t)nvp->nvp_data);
1887 }
1888
1889 const char * const *
1890 nvpair_get_string_array(const nvpair_t *nvp, size_t *nitems)
1891 {
1892
1893 NVPAIR_ASSERT(nvp);
1894 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING_ARRAY);
1895
1896 if (nitems != NULL)
1897 *nitems = nvp->nvp_nitems;
1898
1899 return ((const char * const *)(intptr_t)nvp->nvp_data);
1900 }
1901
1902 const nvlist_t * const *
1903 nvpair_get_nvlist_array(const nvpair_t *nvp, size_t *nitems)
1904 {
1905
1906 NVPAIR_ASSERT(nvp);
1907 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST_ARRAY);
1908
1909 if (nitems != NULL)
1910 *nitems = nvp->nvp_nitems;
1911
1912 return ((const nvlist_t * const *)((intptr_t)nvp->nvp_data));
1913 }
1914
1915 #ifndef _KERNEL
1916 const int *
1917 nvpair_get_descriptor_array(const nvpair_t *nvp, size_t *nitems)
1918 {
1919
1920 NVPAIR_ASSERT(nvp);
1921 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR_ARRAY);
1922
1923 if (nitems != NULL)
1924 *nitems = nvp->nvp_nitems;
1925
1926 return ((const int *)(intptr_t)nvp->nvp_data);
1927 }
1928 #endif
1929
1930 int
1931 nvpair_append_bool_array(nvpair_t *nvp, const bool value)
1932 {
1933
1934 NVPAIR_ASSERT(nvp);
1935 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL_ARRAY);
1936 return (nvpair_append(nvp, &value, sizeof(value), sizeof(value)));
1937 }
1938
1939 int
1940 nvpair_append_number_array(nvpair_t *nvp, const uint64_t value)
1941 {
1942
1943 NVPAIR_ASSERT(nvp);
1944 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER_ARRAY);
1945 return (nvpair_append(nvp, &value, sizeof(value), sizeof(value)));
1946 }
1947
1948 int
1949 nvpair_append_string_array(nvpair_t *nvp, const char *value)
1950 {
1951 char *str;
1952
1953 NVPAIR_ASSERT(nvp);
1954 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING_ARRAY);
1955 if (value == NULL) {
1956 ERRNO_SET(EINVAL);
1957 return (-1);
1958 }
1959 str = nv_strdup(value);
1960 if (str == NULL) {
1961 return (-1);
1962 }
1963 if (nvpair_append(nvp, &str, sizeof(str), strlen(str) + 1) == -1) {
1964 nv_free(str);
1965 return (-1);
1966 }
1967 return (0);
1968 }
1969
1970 int
1971 nvpair_append_nvlist_array(nvpair_t *nvp, const nvlist_t *value)
1972 {
1973 nvpair_t *tmpnvp;
1974 nvlist_t *nvl, *prev;
1975 int flags;
1976
1977 NVPAIR_ASSERT(nvp);
1978 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST_ARRAY);
1979 if (value == NULL || nvlist_error(value) != 0 ||
1980 nvlist_get_pararr(value, NULL) != NULL) {
1981 ERRNO_SET(EINVAL);
1982 return (-1);
1983 }
1984 nvl = nvlist_clone(value);
1985 if (nvl == NULL) {
1986 return (-1);
1987 }
1988 flags = nvlist_flags(nvl) | NV_FLAG_IN_ARRAY;
1989 nvlist_set_flags(nvl, flags);
1990
1991 tmpnvp = NULL;
1992 prev = NULL;
1993 if (nvp->nvp_nitems > 0) {
1994 nvlist_t **nvls = (void *)(uintptr_t)nvp->nvp_data;
1995
1996 prev = nvls[nvp->nvp_nitems - 1];
1997 PJDLOG_ASSERT(prev != NULL);
1998
1999 tmpnvp = nvpair_allocv(" ", NV_TYPE_NVLIST,
2000 (uint64_t)(uintptr_t)nvl, 0, 0);
2001 if (tmpnvp == NULL) {
2002 goto fail;
2003 }
2004 }
2005 if (nvpair_append(nvp, &nvl, sizeof(nvl), 0) == -1) {
2006 goto fail;
2007 }
2008 if (tmpnvp) {
2009 NVPAIR_ASSERT(tmpnvp);
2010 nvlist_set_array_next(prev, tmpnvp);
2011 }
2012 nvlist_set_parent(nvl, nvp);
2013 return (0);
2014 fail:
2015 if (tmpnvp) {
2016 nvpair_free(tmpnvp);
2017 }
2018 nvlist_destroy(nvl);
2019 return (-1);
2020 }
2021
2022 #ifndef _KERNEL
2023 int
2024 nvpair_append_descriptor_array(nvpair_t *nvp, const int value)
2025 {
2026 int fd;
2027
2028 NVPAIR_ASSERT(nvp);
2029 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR_ARRAY);
2030 fd = fcntl(value, F_DUPFD_CLOEXEC, 0);
2031 if (fd == -1) {
2032 return (-1);
2033 }
2034 if (nvpair_append(nvp, &fd, sizeof(fd), sizeof(fd)) == -1) {
2035 close(fd);
2036 return (-1);
2037 }
2038 return (0);
2039 }
2040 #endif
2041
2042 void
2043 nvpair_free(nvpair_t *nvp)
2044 {
2045 size_t i;
2046
2047 NVPAIR_ASSERT(nvp);
2048 PJDLOG_ASSERT(nvp->nvp_list == NULL);
2049
2050 nvp->nvp_magic = 0;
2051 switch (nvp->nvp_type) {
2052 #ifndef _KERNEL
2053 case NV_TYPE_DESCRIPTOR:
2054 close((int)nvp->nvp_data);
2055 break;
2056 case NV_TYPE_DESCRIPTOR_ARRAY:
2057 for (i = 0; i < nvp->nvp_nitems; i++)
2058 close(((int *)(intptr_t)nvp->nvp_data)[i]);
2059 nv_free((int *)(intptr_t)nvp->nvp_data);
2060 break;
2061 #endif
2062 case NV_TYPE_NVLIST:
2063 nvlist_destroy((nvlist_t *)(intptr_t)nvp->nvp_data);
2064 break;
2065 case NV_TYPE_STRING:
2066 nv_free((char *)(intptr_t)nvp->nvp_data);
2067 break;
2068 case NV_TYPE_BINARY:
2069 nv_free((void *)(intptr_t)nvp->nvp_data);
2070 break;
2071 case NV_TYPE_NVLIST_ARRAY:
2072 for (i = 0; i < nvp->nvp_nitems; i++) {
2073 nvlist_destroy(
2074 ((nvlist_t **)(intptr_t)nvp->nvp_data)[i]);
2075 }
2076 nv_free(((nvlist_t **)(intptr_t)nvp->nvp_data));
2077 break;
2078 case NV_TYPE_NUMBER_ARRAY:
2079 nv_free((uint64_t *)(intptr_t)nvp->nvp_data);
2080 break;
2081 case NV_TYPE_BOOL_ARRAY:
2082 nv_free((bool *)(intptr_t)nvp->nvp_data);
2083 break;
2084 case NV_TYPE_STRING_ARRAY:
2085 for (i = 0; i < nvp->nvp_nitems; i++)
2086 nv_free(((char **)(intptr_t)nvp->nvp_data)[i]);
2087 nv_free((char **)(intptr_t)nvp->nvp_data);
2088 break;
2089 }
2090 nv_free(nvp);
2091 }
2092
2093 void
2094 nvpair_free_structure(nvpair_t *nvp)
2095 {
2096
2097 NVPAIR_ASSERT(nvp);
2098 PJDLOG_ASSERT(nvp->nvp_list == NULL);
2099
2100 nvp->nvp_magic = 0;
2101 nv_free(nvp);
2102 }
2103
2104 const char *
2105 nvpair_type_string(int type)
2106 {
2107
2108 switch (type) {
2109 case NV_TYPE_NULL:
2110 return ("NULL");
2111 case NV_TYPE_BOOL:
2112 return ("BOOL");
2113 case NV_TYPE_NUMBER:
2114 return ("NUMBER");
2115 case NV_TYPE_STRING:
2116 return ("STRING");
2117 case NV_TYPE_NVLIST:
2118 return ("NVLIST");
2119 case NV_TYPE_DESCRIPTOR:
2120 return ("DESCRIPTOR");
2121 case NV_TYPE_BINARY:
2122 return ("BINARY");
2123 case NV_TYPE_BOOL_ARRAY:
2124 return ("BOOL ARRAY");
2125 case NV_TYPE_NUMBER_ARRAY:
2126 return ("NUMBER ARRAY");
2127 case NV_TYPE_STRING_ARRAY:
2128 return ("STRING ARRAY");
2129 case NV_TYPE_NVLIST_ARRAY:
2130 return ("NVLIST ARRAY");
2131 case NV_TYPE_DESCRIPTOR_ARRAY:
2132 return ("DESCRIPTOR ARRAY");
2133 default:
2134 return ("<UNKNOWN>");
2135 }
2136 }
2137
Cache object: 2ebf25d6a5e2e2dcfb573425d2ec5226
|