2 * Copyright (c) 2009-2013 The FreeBSD Foundation
5 * This software was developed by Pawel Jakub Dawidek under sponsorship from
6 * the FreeBSD Foundation.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
33 #include <sys/param.h>
34 #include <sys/endian.h>
35 #include <sys/queue.h>
39 #include <sys/errno.h>
41 #include <sys/malloc.h>
42 #include <sys/systm.h>
44 #include <machine/stdarg.h>
56 #include "common_impl.h"
64 #include <sys/nv_impl.h>
65 #include <sys/nvlist_impl.h>
66 #include <sys/nvpair_impl.h>
70 #define PJDLOG_ASSERT(...) MPASS(__VA_ARGS__)
71 #define PJDLOG_RASSERT(expr, ...) KASSERT(expr, (__VA_ARGS__))
72 #define PJDLOG_ABORT(...) panic(__VA_ARGS__)
75 #define PJDLOG_ASSERT(...) assert(__VA_ARGS__)
76 #define PJDLOG_RASSERT(expr, ...) assert(expr)
77 #define PJDLOG_ABORT(...) abort()
81 #define NVPAIR_MAGIC 0x6e7670 /* "nvp" */
89 TAILQ_ENTRY(nvpair) nvp_next;
92 #define NVPAIR_ASSERT(nvp) do { \
93 PJDLOG_ASSERT((nvp) != NULL); \
94 PJDLOG_ASSERT((nvp)->nvp_magic == NVPAIR_MAGIC); \
97 struct nvpair_header {
99 uint16_t nvph_namesize;
100 uint64_t nvph_datasize;
105 nvpair_assert(const nvpair_t *nvp)
112 nvpair_nvlist(const nvpair_t *nvp)
117 return (nvp->nvp_list);
121 nvpair_next(const nvpair_t *nvp)
125 PJDLOG_ASSERT(nvp->nvp_list != NULL);
127 return (TAILQ_NEXT(nvp, nvp_next));
131 nvpair_prev(const nvpair_t *nvp)
135 PJDLOG_ASSERT(nvp->nvp_list != NULL);
137 return (TAILQ_PREV(nvp, nvl_head, nvp_next));
141 nvpair_insert(struct nvl_head *head, nvpair_t *nvp, nvlist_t *nvl)
145 PJDLOG_ASSERT(nvp->nvp_list == NULL);
146 PJDLOG_ASSERT(!nvlist_exists(nvl, nvpair_name(nvp)));
148 TAILQ_INSERT_TAIL(head, nvp, nvp_next);
153 nvpair_remove_nvlist(nvpair_t *nvp)
157 /* XXX: DECONST is bad, mkay? */
158 nvl = __DECONST(nvlist_t *, nvpair_get_nvlist(nvp));
159 PJDLOG_ASSERT(nvl != NULL);
160 nvlist_set_parent(nvl, NULL);
164 nvpair_remove(struct nvl_head *head, nvpair_t *nvp, const nvlist_t *nvl)
168 PJDLOG_ASSERT(nvp->nvp_list == nvl);
170 if (nvpair_type(nvp) == NV_TYPE_NVLIST)
171 nvpair_remove_nvlist(nvp);
173 TAILQ_REMOVE(head, nvp, nvp_next);
174 nvp->nvp_list = NULL;
178 nvpair_clone(const nvpair_t *nvp)
187 name = nvpair_name(nvp);
189 switch (nvpair_type(nvp)) {
191 newnvp = nvpair_create_null(name);
194 newnvp = nvpair_create_bool(name, nvpair_get_bool(nvp));
197 newnvp = nvpair_create_number(name, nvpair_get_number(nvp));
200 newnvp = nvpair_create_string(name, nvpair_get_string(nvp));
203 newnvp = nvpair_create_nvlist(name, nvpair_get_nvlist(nvp));
206 case NV_TYPE_DESCRIPTOR:
207 newnvp = nvpair_create_descriptor(name,
208 nvpair_get_descriptor(nvp));
212 data = nvpair_get_binary(nvp, &datasize);
213 newnvp = nvpair_create_binary(name, data, datasize);
216 PJDLOG_ABORT("Unknown type: %d.", nvpair_type(nvp));
223 nvpair_header_size(void)
226 return (sizeof(struct nvpair_header));
230 nvpair_size(const nvpair_t *nvp)
235 return (nvp->nvp_datasize);
239 nvpair_pack_header(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
241 struct nvpair_header nvphdr;
246 nvphdr.nvph_type = nvp->nvp_type;
247 namesize = strlen(nvp->nvp_name) + 1;
248 PJDLOG_ASSERT(namesize > 0 && namesize <= UINT16_MAX);
249 nvphdr.nvph_namesize = namesize;
250 nvphdr.nvph_datasize = nvp->nvp_datasize;
251 PJDLOG_ASSERT(*leftp >= sizeof(nvphdr));
252 memcpy(ptr, &nvphdr, sizeof(nvphdr));
253 ptr += sizeof(nvphdr);
254 *leftp -= sizeof(nvphdr);
256 PJDLOG_ASSERT(*leftp >= namesize);
257 memcpy(ptr, nvp->nvp_name, namesize);
265 nvpair_pack_null(const nvpair_t *nvp, unsigned char *ptr,
266 size_t *leftp __unused)
270 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NULL);
276 nvpair_pack_bool(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
281 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL);
283 value = (uint8_t)nvp->nvp_data;
285 PJDLOG_ASSERT(*leftp >= sizeof(value));
286 memcpy(ptr, &value, sizeof(value));
287 ptr += sizeof(value);
288 *leftp -= sizeof(value);
294 nvpair_pack_number(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
299 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER);
301 value = (uint64_t)nvp->nvp_data;
303 PJDLOG_ASSERT(*leftp >= sizeof(value));
304 memcpy(ptr, &value, sizeof(value));
305 ptr += sizeof(value);
306 *leftp -= sizeof(value);
312 nvpair_pack_string(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
316 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING);
318 PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize);
319 memcpy(ptr, (const void *)(intptr_t)nvp->nvp_data, nvp->nvp_datasize);
320 ptr += nvp->nvp_datasize;
321 *leftp -= nvp->nvp_datasize;
327 nvpair_pack_nvlist_up(unsigned char *ptr, size_t *leftp)
329 struct nvpair_header nvphdr;
331 const char *name = "";
334 nvphdr.nvph_type = NV_TYPE_NVLIST_UP;
335 nvphdr.nvph_namesize = namesize;
336 nvphdr.nvph_datasize = 0;
337 PJDLOG_ASSERT(*leftp >= sizeof(nvphdr));
338 memcpy(ptr, &nvphdr, sizeof(nvphdr));
339 ptr += sizeof(nvphdr);
340 *leftp -= sizeof(nvphdr);
342 PJDLOG_ASSERT(*leftp >= namesize);
343 memcpy(ptr, name, namesize);
352 nvpair_pack_descriptor(const nvpair_t *nvp, unsigned char *ptr, int64_t *fdidxp,
358 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR);
360 value = (int64_t)nvp->nvp_data;
363 * If there is a real descriptor here, we change its number
364 * to position in the array of descriptors send via control
367 PJDLOG_ASSERT(fdidxp != NULL);
373 PJDLOG_ASSERT(*leftp >= sizeof(value));
374 memcpy(ptr, &value, sizeof(value));
375 ptr += sizeof(value);
376 *leftp -= sizeof(value);
383 nvpair_pack_binary(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
387 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY);
389 PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize);
390 memcpy(ptr, (const void *)(intptr_t)nvp->nvp_data, nvp->nvp_datasize);
391 ptr += nvp->nvp_datasize;
392 *leftp -= nvp->nvp_datasize;
398 nvpair_init_datasize(nvpair_t *nvp)
403 if (nvp->nvp_type == NV_TYPE_NVLIST) {
404 if (nvp->nvp_data == 0) {
405 nvp->nvp_datasize = 0;
408 nvlist_size((const nvlist_t *)(intptr_t)nvp->nvp_data);
413 const unsigned char *
414 nvpair_unpack_header(bool isbe, nvpair_t *nvp, const unsigned char *ptr,
417 struct nvpair_header nvphdr;
419 if (*leftp < sizeof(nvphdr))
422 memcpy(&nvphdr, ptr, sizeof(nvphdr));
423 ptr += sizeof(nvphdr);
424 *leftp -= sizeof(nvphdr);
426 #if NV_TYPE_FIRST > 0
427 if (nvphdr.nvph_type < NV_TYPE_FIRST)
430 if (nvphdr.nvph_type > NV_TYPE_LAST &&
431 nvphdr.nvph_type != NV_TYPE_NVLIST_UP) {
435 #if BYTE_ORDER == BIG_ENDIAN
437 nvphdr.nvph_namesize = le16toh(nvphdr.nvph_namesize);
438 nvphdr.nvph_datasize = le64toh(nvphdr.nvph_datasize);
442 nvphdr.nvph_namesize = be16toh(nvphdr.nvph_namesize);
443 nvphdr.nvph_datasize = be64toh(nvphdr.nvph_datasize);
447 if (nvphdr.nvph_namesize > NV_NAME_MAX)
449 if (*leftp < nvphdr.nvph_namesize)
451 if (nvphdr.nvph_namesize < 1)
453 if (strnlen((const char *)ptr, nvphdr.nvph_namesize) !=
454 (size_t)(nvphdr.nvph_namesize - 1)) {
458 memcpy(nvp->nvp_name, ptr, nvphdr.nvph_namesize);
459 ptr += nvphdr.nvph_namesize;
460 *leftp -= nvphdr.nvph_namesize;
462 if (*leftp < nvphdr.nvph_datasize)
465 nvp->nvp_type = nvphdr.nvph_type;
467 nvp->nvp_datasize = nvphdr.nvph_datasize;
471 RESTORE_ERRNO(EINVAL);
475 const unsigned char *
476 nvpair_unpack_null(bool isbe __unused, nvpair_t *nvp, const unsigned char *ptr,
477 size_t *leftp __unused)
480 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NULL);
482 if (nvp->nvp_datasize != 0) {
483 RESTORE_ERRNO(EINVAL);
490 const unsigned char *
491 nvpair_unpack_bool(bool isbe __unused, nvpair_t *nvp, const unsigned char *ptr,
496 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL);
498 if (nvp->nvp_datasize != sizeof(value)) {
499 RESTORE_ERRNO(EINVAL);
502 if (*leftp < sizeof(value)) {
503 RESTORE_ERRNO(EINVAL);
507 memcpy(&value, ptr, sizeof(value));
508 ptr += sizeof(value);
509 *leftp -= sizeof(value);
511 if (value != 0 && value != 1) {
512 RESTORE_ERRNO(EINVAL);
516 nvp->nvp_data = (uint64_t)value;
521 const unsigned char *
522 nvpair_unpack_number(bool isbe, nvpair_t *nvp, const unsigned char *ptr,
526 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER);
528 if (nvp->nvp_datasize != sizeof(uint64_t)) {
529 RESTORE_ERRNO(EINVAL);
532 if (*leftp < sizeof(uint64_t)) {
533 RESTORE_ERRNO(EINVAL);
538 nvp->nvp_data = be64dec(ptr);
540 nvp->nvp_data = le64dec(ptr);
541 ptr += sizeof(uint64_t);
542 *leftp -= sizeof(uint64_t);
547 const unsigned char *
548 nvpair_unpack_string(bool isbe __unused, nvpair_t *nvp,
549 const unsigned char *ptr, size_t *leftp)
552 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING);
554 if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) {
555 RESTORE_ERRNO(EINVAL);
559 if (strnlen((const char *)ptr, nvp->nvp_datasize) !=
560 nvp->nvp_datasize - 1) {
561 RESTORE_ERRNO(EINVAL);
565 nvp->nvp_data = (uint64_t)(uintptr_t)nv_strdup((const char *)ptr);
566 if (nvp->nvp_data == 0)
569 ptr += nvp->nvp_datasize;
570 *leftp -= nvp->nvp_datasize;
575 const unsigned char *
576 nvpair_unpack_nvlist(bool isbe __unused, nvpair_t *nvp,
577 const unsigned char *ptr, size_t *leftp, size_t nfds, nvlist_t **child)
581 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST);
583 if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) {
584 RESTORE_ERRNO(EINVAL);
588 value = nvlist_create(0);
592 ptr = nvlist_unpack_header(value, ptr, nfds, NULL, leftp);
596 nvp->nvp_data = (uint64_t)(uintptr_t)value;
603 const unsigned char *
604 nvpair_unpack_descriptor(bool isbe, nvpair_t *nvp, const unsigned char *ptr,
605 size_t *leftp, const int *fds, size_t nfds)
609 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR);
611 if (nvp->nvp_datasize != sizeof(idx)) {
615 if (*leftp < sizeof(idx)) {
630 if ((size_t)idx >= nfds) {
635 nvp->nvp_data = (uint64_t)fds[idx];
638 *leftp -= sizeof(idx);
644 const unsigned char *
645 nvpair_unpack_binary(bool isbe __unused, nvpair_t *nvp,
646 const unsigned char *ptr, size_t *leftp)
650 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY);
652 if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) {
653 RESTORE_ERRNO(EINVAL);
657 value = nv_malloc(nvp->nvp_datasize);
661 memcpy(value, ptr, nvp->nvp_datasize);
662 ptr += nvp->nvp_datasize;
663 *leftp -= nvp->nvp_datasize;
665 nvp->nvp_data = (uint64_t)(uintptr_t)value;
670 const unsigned char *
671 nvpair_unpack(bool isbe, const unsigned char *ptr, size_t *leftp,
676 nvp = nv_calloc(1, sizeof(*nvp) + NV_NAME_MAX);
679 nvp->nvp_name = (char *)(nvp + 1);
681 ptr = nvpair_unpack_header(isbe, nvp, ptr, leftp);
684 tmp = nv_realloc(nvp, sizeof(*nvp) + strlen(nvp->nvp_name) + 1);
689 /* Update nvp_name after realloc(). */
690 nvp->nvp_name = (char *)(nvp + 1);
691 nvp->nvp_data = 0x00;
692 nvp->nvp_magic = NVPAIR_MAGIC;
701 nvpair_type(const nvpair_t *nvp)
706 return (nvp->nvp_type);
710 nvpair_name(const nvpair_t *nvp)
715 return (nvp->nvp_name);
719 nvpair_allocv(const char *name, int type, uint64_t data, size_t datasize)
724 PJDLOG_ASSERT(type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST);
726 namelen = strlen(name);
727 if (namelen >= NV_NAME_MAX) {
728 RESTORE_ERRNO(ENAMETOOLONG);
732 nvp = nv_calloc(1, sizeof(*nvp) + namelen + 1);
734 nvp->nvp_name = (char *)(nvp + 1);
735 memcpy(nvp->nvp_name, name, namelen);
736 nvp->nvp_name[namelen + 1] = '\0';
737 nvp->nvp_type = type;
738 nvp->nvp_data = data;
739 nvp->nvp_datasize = datasize;
740 nvp->nvp_magic = NVPAIR_MAGIC;
747 nvpair_create_stringf(const char *name, const char *valuefmt, ...)
752 va_start(valueap, valuefmt);
753 nvp = nvpair_create_stringv(name, valuefmt, valueap);
760 nvpair_create_stringv(const char *name, const char *valuefmt, va_list valueap)
766 len = nv_vasprintf(&str, valuefmt, valueap);
769 nvp = nvpair_create_string(name, str);
776 nvpair_create_null(const char *name)
779 return (nvpair_allocv(name, NV_TYPE_NULL, 0, 0));
783 nvpair_create_bool(const char *name, bool value)
786 return (nvpair_allocv(name, NV_TYPE_BOOL, value ? 1 : 0,
791 nvpair_create_number(const char *name, uint64_t value)
794 return (nvpair_allocv(name, NV_TYPE_NUMBER, value, sizeof(value)));
798 nvpair_create_string(const char *name, const char *value)
805 RESTORE_ERRNO(EINVAL);
809 data = nv_strdup(value);
812 size = strlen(value) + 1;
814 nvp = nvpair_allocv(name, NV_TYPE_STRING, (uint64_t)(uintptr_t)data,
823 nvpair_create_nvlist(const char *name, const nvlist_t *value)
829 RESTORE_ERRNO(EINVAL);
833 nvl = nvlist_clone(value);
837 nvp = nvpair_allocv(name, NV_TYPE_NVLIST, (uint64_t)(uintptr_t)nvl, 0);
841 nvlist_set_parent(nvl, nvp);
848 nvpair_create_descriptor(const char *name, int value)
852 if (value < 0 || !fd_is_valid(value)) {
857 value = fcntl(value, F_DUPFD_CLOEXEC, 0);
861 nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR, (uint64_t)value,
871 nvpair_create_binary(const char *name, const void *value, size_t size)
876 if (value == NULL || size == 0) {
877 RESTORE_ERRNO(EINVAL);
881 data = nv_malloc(size);
884 memcpy(data, value, size);
886 nvp = nvpair_allocv(name, NV_TYPE_BINARY, (uint64_t)(uintptr_t)data,
895 nvpair_move_string(const char *name, char *value)
901 RESTORE_ERRNO(EINVAL);
905 nvp = nvpair_allocv(name, NV_TYPE_STRING, (uint64_t)(uintptr_t)value,
910 RESTORE_ERRNO(serrno);
917 nvpair_move_nvlist(const char *name, nvlist_t *value)
921 if (value == NULL || nvlist_get_nvpair_parent(value) != NULL) {
922 RESTORE_ERRNO(EINVAL);
926 if (nvlist_error(value) != 0) {
927 RESTORE_ERRNO(nvlist_error(value));
928 nvlist_destroy(value);
932 nvp = nvpair_allocv(name, NV_TYPE_NVLIST, (uint64_t)(uintptr_t)value,
935 nvlist_destroy(value);
937 nvlist_set_parent(value, nvp);
944 nvpair_move_descriptor(const char *name, int value)
949 if (value < 0 || !fd_is_valid(value)) {
954 nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR, (uint64_t)value,
967 nvpair_move_binary(const char *name, void *value, size_t size)
972 if (value == NULL || size == 0) {
973 RESTORE_ERRNO(EINVAL);
977 nvp = nvpair_allocv(name, NV_TYPE_BINARY, (uint64_t)(uintptr_t)value,
982 RESTORE_ERRNO(serrno);
989 nvpair_get_bool(const nvpair_t *nvp)
994 return (nvp->nvp_data == 1);
998 nvpair_get_number(const nvpair_t *nvp)
1003 return (nvp->nvp_data);
1007 nvpair_get_string(const nvpair_t *nvp)
1011 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING);
1013 return ((const char *)(intptr_t)nvp->nvp_data);
1017 nvpair_get_nvlist(const nvpair_t *nvp)
1021 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST);
1023 return ((const nvlist_t *)(intptr_t)nvp->nvp_data);
1028 nvpair_get_descriptor(const nvpair_t *nvp)
1032 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR);
1034 return ((int)nvp->nvp_data);
1039 nvpair_get_binary(const nvpair_t *nvp, size_t *sizep)
1043 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY);
1046 *sizep = nvp->nvp_datasize;
1047 return ((const void *)(intptr_t)nvp->nvp_data);
1051 nvpair_free(nvpair_t *nvp)
1055 PJDLOG_ASSERT(nvp->nvp_list == NULL);
1058 switch (nvp->nvp_type) {
1060 case NV_TYPE_DESCRIPTOR:
1061 close((int)nvp->nvp_data);
1064 case NV_TYPE_NVLIST:
1065 nvlist_destroy((nvlist_t *)(intptr_t)nvp->nvp_data);
1067 case NV_TYPE_STRING:
1068 nv_free((char *)(intptr_t)nvp->nvp_data);
1070 case NV_TYPE_BINARY:
1071 nv_free((void *)(intptr_t)nvp->nvp_data);
1078 nvpair_free_structure(nvpair_t *nvp)
1082 PJDLOG_ASSERT(nvp->nvp_list == NULL);
1089 nvpair_type_string(int type)
1097 case NV_TYPE_NUMBER:
1099 case NV_TYPE_STRING:
1101 case NV_TYPE_NVLIST:
1103 case NV_TYPE_DESCRIPTOR:
1104 return ("DESCRIPTOR");
1105 case NV_TYPE_BINARY:
1108 return ("<UNKNOWN>");