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" */ 86struct 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 102struct 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 110void 111nvpair_assert(const nvpair_t *nvp __unused) 112{ 113 114 NVPAIR_ASSERT(nvp); 115} 116 117static nvpair_t * 118nvpair_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 147static int 148nvpair_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 169nvlist_t * 170nvpair_nvlist(const nvpair_t *nvp) 171{ 172 173 NVPAIR_ASSERT(nvp); 174 175 return (nvp->nvp_list); 176} 177 178nvpair_t * 179nvpair_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 188nvpair_t * 189nvpair_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 198void 199nvpair_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 211static void 212nvpair_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 222static void 223nvpair_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 237void 238nvpair_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 254nvpair_t * 255nvpair_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 319size_t 320nvpair_header_size(void) 321{ 322 323 return (sizeof(struct nvpair_header)); 324} 325 326size_t 327nvpair_size(const nvpair_t *nvp) 328{ 329 330 NVPAIR_ASSERT(nvp); 331 332 return (nvp->nvp_datasize); 333} 334 335unsigned char * 336nvpair_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 362unsigned char * 363nvpair_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 373unsigned char * 374nvpair_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 391unsigned char * 392nvpair_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 409unsigned char * 410nvpair_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 424unsigned char * 425nvpair_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 449unsigned char * 450nvpair_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 475unsigned char * 476nvpair_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 506unsigned char * 507nvpair_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 521unsigned char * 522nvpair_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 536unsigned char * 537nvpair_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 551unsigned char * 552nvpair_pack_string_array(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp) 553{ 554 unsigned int ii; 555 size_t size, 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 582unsigned char * 583nvpair_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 621void 622nvpair_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 637const unsigned char * 638nvpair_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 } 665#else 666 if (isbe) { 667 nvphdr.nvph_namesize = be16toh(nvphdr.nvph_namesize); 668 nvphdr.nvph_datasize = be64toh(nvphdr.nvph_datasize); 669 } 670#endif 671 672 if (nvphdr.nvph_namesize > NV_NAME_MAX) 673 goto fail; 674 if (*leftp < nvphdr.nvph_namesize) 675 goto fail; 676 if (nvphdr.nvph_namesize < 1) 677 goto fail; 678 if (strnlen((const char *)ptr, nvphdr.nvph_namesize) != 679 (size_t)(nvphdr.nvph_namesize - 1)) { 680 goto fail; 681 } 682 683 memcpy(nvp->nvp_name, ptr, nvphdr.nvph_namesize); 684 ptr += nvphdr.nvph_namesize; 685 *leftp -= nvphdr.nvph_namesize; 686 687 if (*leftp < nvphdr.nvph_datasize) 688 goto fail; 689 690 nvp->nvp_type = nvphdr.nvph_type; 691 nvp->nvp_data = 0; 692 nvp->nvp_datasize = nvphdr.nvph_datasize; 693 nvp->nvp_nitems = nvphdr.nvph_nitems; 694 695 return (ptr); 696fail: 697 ERRNO_SET(EINVAL); 698 return (NULL); 699} 700 701const unsigned char * 702nvpair_unpack_null(bool isbe __unused, nvpair_t *nvp, const unsigned char *ptr, 703 size_t *leftp __unused) 704{ 705 706 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NULL); 707 708 if (nvp->nvp_datasize != 0) { 709 ERRNO_SET(EINVAL); 710 return (NULL); 711 } 712 713 return (ptr); 714} 715 716const unsigned char * 717nvpair_unpack_bool(bool isbe __unused, nvpair_t *nvp, const unsigned char *ptr, 718 size_t *leftp) 719{ 720 uint8_t value; 721 722 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL); 723 724 if (nvp->nvp_datasize != sizeof(value)) { 725 ERRNO_SET(EINVAL); 726 return (NULL); 727 } 728 if (*leftp < sizeof(value)) { 729 ERRNO_SET(EINVAL); 730 return (NULL); 731 } 732 733 memcpy(&value, ptr, sizeof(value)); 734 ptr += sizeof(value); 735 *leftp -= sizeof(value); 736 737 if (value != 0 && value != 1) { 738 ERRNO_SET(EINVAL); 739 return (NULL); 740 } 741 742 nvp->nvp_data = (uint64_t)value; 743 744 return (ptr); 745} 746 747const unsigned char * 748nvpair_unpack_number(bool isbe, nvpair_t *nvp, const unsigned char *ptr, 749 size_t *leftp) 750{ 751 752 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER); 753 754 if (nvp->nvp_datasize != sizeof(uint64_t)) { 755 ERRNO_SET(EINVAL); 756 return (NULL); 757 } 758 if (*leftp < sizeof(uint64_t)) { 759 ERRNO_SET(EINVAL); 760 return (NULL); 761 } 762 763 if (isbe) 764 nvp->nvp_data = be64dec(ptr); 765 else 766 nvp->nvp_data = le64dec(ptr); 767 768 ptr += sizeof(uint64_t); 769 *leftp -= sizeof(uint64_t); 770 771 return (ptr); 772} 773 774const unsigned char * 775nvpair_unpack_string(bool isbe __unused, nvpair_t *nvp, 776 const unsigned char *ptr, size_t *leftp) 777{ 778 779 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING); 780 781 if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) { 782 ERRNO_SET(EINVAL); 783 return (NULL); 784 } 785 786 if (strnlen((const char *)ptr, nvp->nvp_datasize) != 787 nvp->nvp_datasize - 1) { 788 ERRNO_SET(EINVAL); 789 return (NULL); 790 } 791 792 nvp->nvp_data = (uint64_t)(uintptr_t)nv_strdup((const char *)ptr); 793 if (nvp->nvp_data == 0) 794 return (NULL); 795 796 ptr += nvp->nvp_datasize; 797 *leftp -= nvp->nvp_datasize; 798 799 return (ptr); 800} 801 802const unsigned char * 803nvpair_unpack_nvlist(bool isbe __unused, nvpair_t *nvp, 804 const unsigned char *ptr, size_t *leftp, size_t nfds, nvlist_t **child) 805{ 806 nvlist_t *value; 807 808 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST); 809 810 if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) { 811 ERRNO_SET(EINVAL); 812 return (NULL); 813 } 814 815 value = nvlist_create(0); 816 if (value == NULL) 817 return (NULL); 818 819 ptr = nvlist_unpack_header(value, ptr, nfds, NULL, leftp); 820 if (ptr == NULL) 821 return (NULL); 822 823 nvp->nvp_data = (uint64_t)(uintptr_t)value; 824 *child = value; 825 826 return (ptr); 827} 828 829#ifndef _KERNEL 830const unsigned char * 831nvpair_unpack_descriptor(bool isbe, nvpair_t *nvp, const unsigned char *ptr, 832 size_t *leftp, const int *fds, size_t nfds) 833{ 834 int64_t idx; 835 836 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR); 837 838 if (nvp->nvp_datasize != sizeof(idx)) { 839 ERRNO_SET(EINVAL); 840 return (NULL); 841 } 842 if (*leftp < sizeof(idx)) { 843 ERRNO_SET(EINVAL); 844 return (NULL); 845 } 846 847 if (isbe) 848 idx = be64dec(ptr); 849 else 850 idx = le64dec(ptr); 851 852 if (idx < 0) { 853 ERRNO_SET(EINVAL); 854 return (NULL); 855 } 856 857 if ((size_t)idx >= nfds) { 858 ERRNO_SET(EINVAL); 859 return (NULL); 860 } 861 862 nvp->nvp_data = (uint64_t)fds[idx]; 863 864 ptr += sizeof(idx); 865 *leftp -= sizeof(idx); 866 867 return (ptr); 868} 869#endif 870 871const unsigned char * 872nvpair_unpack_binary(bool isbe __unused, nvpair_t *nvp, 873 const unsigned char *ptr, size_t *leftp) 874{ 875 void *value; 876 877 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY); 878 879 if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) { 880 ERRNO_SET(EINVAL); 881 return (NULL); 882 } 883 884 value = nv_malloc(nvp->nvp_datasize); 885 if (value == NULL) 886 return (NULL); 887 888 memcpy(value, ptr, nvp->nvp_datasize); 889 ptr += nvp->nvp_datasize; 890 *leftp -= nvp->nvp_datasize; 891 892 nvp->nvp_data = (uint64_t)(uintptr_t)value; 893 894 return (ptr); 895} 896 897const unsigned char * 898nvpair_unpack_bool_array(bool isbe __unused, nvpair_t *nvp, 899 const unsigned char *ptr, size_t *leftp) 900{ 901 uint8_t *value; 902 size_t size; 903 unsigned int i; 904 905 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL_ARRAY); 906 907 size = sizeof(*value) * nvp->nvp_nitems; 908 if (nvp->nvp_datasize != size || *leftp < size || 909 nvp->nvp_nitems == 0 || size < nvp->nvp_nitems) { 910 ERRNO_SET(EINVAL); 911 return (NULL); 912 } 913 914 value = nv_malloc(size); 915 if (value == NULL) 916 return (NULL); 917 918 for (i = 0; i < nvp->nvp_nitems; i++) { 919 value[i] = *(const uint8_t *)ptr; 920 921 ptr += sizeof(*value); 922 *leftp -= sizeof(*value); 923 } 924 925 nvp->nvp_data = (uint64_t)(uintptr_t)value; 926 927 return (ptr); 928} 929 930const unsigned char * 931nvpair_unpack_number_array(bool isbe, nvpair_t *nvp, const unsigned char *ptr, 932 size_t *leftp) 933{ 934 uint64_t *value; 935 size_t size; 936 unsigned int i; 937 938 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER_ARRAY); 939 940 size = sizeof(*value) * nvp->nvp_nitems; 941 if (nvp->nvp_datasize != size || *leftp < size || 942 nvp->nvp_nitems == 0 || size < nvp->nvp_nitems) { 943 ERRNO_SET(EINVAL); 944 return (NULL); 945 } 946 947 value = nv_malloc(size); 948 if (value == NULL) 949 return (NULL); 950 951 for (i = 0; i < nvp->nvp_nitems; i++) { 952 if (isbe) 953 value[i] = be64dec(ptr); 954 else 955 value[i] = le64dec(ptr); 956 957 ptr += sizeof(*value); 958 *leftp -= sizeof(*value); 959 } 960 961 nvp->nvp_data = (uint64_t)(uintptr_t)value; 962 963 return (ptr); 964} 965 966const unsigned char * 967nvpair_unpack_string_array(bool isbe __unused, nvpair_t *nvp, 968 const unsigned char *ptr, size_t *leftp) 969{ 970 ssize_t size; 971 size_t len; 972 const char *tmp; 973 char **value; 974 unsigned int ii, j; 975 976 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING_ARRAY); 977 978 if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0 || 979 nvp->nvp_nitems == 0) { 980 ERRNO_SET(EINVAL); 981 return (NULL); 982 } 983 984 size = nvp->nvp_datasize; 985 tmp = (const char *)ptr; 986 for (ii = 0; ii < nvp->nvp_nitems; ii++) { 987 len = strnlen(tmp, size - 1) + 1; 988 size -= len; 989 if (size < 0) { 990 ERRNO_SET(EINVAL); 991 return (NULL); 992 } 993 tmp += len; 994 } 995 if (size != 0) { 996 ERRNO_SET(EINVAL); 997 return (NULL); 998 } 999 1000 value = nv_malloc(sizeof(*value) * nvp->nvp_nitems); 1001 if (value == NULL) 1002 return (NULL); 1003 1004 for (ii = 0; ii < nvp->nvp_nitems; ii++) { 1005 value[ii] = nv_strdup((const char *)ptr); 1006 if (value[ii] == NULL) 1007 goto out; 1008 len = strlen(value[ii]) + 1; 1009 ptr += len; 1010 *leftp -= len; 1011 } 1012 nvp->nvp_data = (uint64_t)(uintptr_t)value; 1013 1014 return (ptr); 1015out: 1016 for (j = 0; j < ii; j++) 1017 nv_free(value[j]); 1018 nv_free(value); 1019 return (NULL); 1020} 1021 1022#ifndef _KERNEL 1023const unsigned char * 1024nvpair_unpack_descriptor_array(bool isbe, nvpair_t *nvp, 1025 const unsigned char *ptr, size_t *leftp, const int *fds, size_t nfds) 1026{ 1027 int64_t idx; 1028 size_t size; 1029 unsigned int ii; 1030 int *array; 1031 1032 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR_ARRAY); 1033 1034 size = sizeof(idx) * nvp->nvp_nitems; 1035 if (nvp->nvp_datasize != size || *leftp < size || 1036 nvp->nvp_nitems == 0 || size < nvp->nvp_nitems) { 1037 ERRNO_SET(EINVAL); 1038 return (NULL); 1039 } 1040 1041 array = (int *)nv_malloc(size); 1042 if (array == NULL) 1043 return (NULL); 1044 1045 for (ii = 0; ii < nvp->nvp_nitems; ii++) { 1046 if (isbe) 1047 idx = be64dec(ptr); 1048 else 1049 idx = le64dec(ptr); 1050 1051 if (idx < 0) { 1052 ERRNO_SET(EINVAL); 1053 nv_free(array); 1054 return (NULL); 1055 } 1056 1057 if ((size_t)idx >= nfds) { 1058 ERRNO_SET(EINVAL); 1059 nv_free(array); 1060 return (NULL); 1061 } 1062 1063 array[ii] = (uint64_t)fds[idx]; 1064 1065 ptr += sizeof(idx); 1066 *leftp -= sizeof(idx); 1067 } 1068 1069 nvp->nvp_data = (uint64_t)(uintptr_t)array; 1070 1071 return (ptr); 1072} 1073#endif 1074 1075const unsigned char * 1076nvpair_unpack_nvlist_array(bool isbe __unused, nvpair_t *nvp, 1077 const unsigned char *ptr, size_t *leftp, nvlist_t **firstel) 1078{ 1079 nvlist_t **value; 1080 nvpair_t *tmpnvp; 1081 unsigned int ii, j; 1082 size_t sizeup; 1083 1084 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST_ARRAY); 1085 1086 sizeup = sizeof(struct nvpair_header) * nvp->nvp_nitems; 1087 if (nvp->nvp_nitems == 0 || sizeup < nvp->nvp_nitems || 1088 sizeup > *leftp) { 1089 ERRNO_SET(EINVAL); 1090 return (NULL); 1091 } 1092 1093 value = nv_malloc(nvp->nvp_nitems * sizeof(*value)); 1094 if (value == NULL) 1095 return (NULL); 1096 1097 for (ii = 0; ii < nvp->nvp_nitems; ii++) { 1098 value[ii] = nvlist_create(0); 1099 if (value[ii] == NULL) 1100 goto fail; 1101 if (ii > 0) { 1102 tmpnvp = nvpair_allocv(" ", NV_TYPE_NVLIST, 1103 (uint64_t)(uintptr_t)value[ii], 0, 0); 1104 if (tmpnvp == NULL) 1105 goto fail; 1106 nvlist_set_array_next(value[ii - 1], tmpnvp); 1107 } 1108 } 1109 nvlist_set_flags(value[nvp->nvp_nitems - 1], NV_FLAG_IN_ARRAY); 1110 1111 nvp->nvp_data = (uint64_t)(uintptr_t)value; 1112 *firstel = value[0]; 1113 1114 return (ptr); 1115fail: 1116 ERRNO_SAVE(); 1117 for (j = 0; j <= ii; j++) 1118 nvlist_destroy(value[j]); 1119 nv_free(value); 1120 ERRNO_RESTORE(); 1121 1122 return (NULL); 1123} 1124 1125const unsigned char * 1126nvpair_unpack(bool isbe, const unsigned char *ptr, size_t *leftp, 1127 nvpair_t **nvpp) 1128{ 1129 nvpair_t *nvp, *tmp; 1130 1131 nvp = nv_calloc(1, sizeof(*nvp) + NV_NAME_MAX); 1132 if (nvp == NULL) 1133 return (NULL); 1134 nvp->nvp_name = (char *)(nvp + 1); 1135 1136 ptr = nvpair_unpack_header(isbe, nvp, ptr, leftp); 1137 if (ptr == NULL) 1138 goto fail; 1139 tmp = nv_realloc(nvp, sizeof(*nvp) + strlen(nvp->nvp_name) + 1); 1140 if (tmp == NULL) 1141 goto fail; 1142 nvp = tmp; 1143 1144 /* Update nvp_name after realloc(). */ 1145 nvp->nvp_name = (char *)(nvp + 1); 1146 nvp->nvp_data = 0x00; 1147 nvp->nvp_magic = NVPAIR_MAGIC; 1148 *nvpp = nvp; 1149 return (ptr); 1150fail: 1151 nv_free(nvp); 1152 return (NULL); 1153} 1154 1155int 1156nvpair_type(const nvpair_t *nvp) 1157{ 1158 1159 NVPAIR_ASSERT(nvp); 1160 1161 return (nvp->nvp_type); 1162} 1163 1164const char * 1165nvpair_name(const nvpair_t *nvp) 1166{ 1167 1168 NVPAIR_ASSERT(nvp); 1169 1170 return (nvp->nvp_name); 1171} 1172 1173nvpair_t * 1174nvpair_create_stringf(const char *name, const char *valuefmt, ...) 1175{ 1176 va_list valueap; 1177 nvpair_t *nvp; 1178 1179 va_start(valueap, valuefmt); 1180 nvp = nvpair_create_stringv(name, valuefmt, valueap); 1181 va_end(valueap); 1182 1183 return (nvp); 1184} 1185 1186nvpair_t * 1187nvpair_create_stringv(const char *name, const char *valuefmt, va_list valueap) 1188{ 1189 nvpair_t *nvp; 1190 char *str; 1191 int len; 1192 1193 len = nv_vasprintf(&str, valuefmt, valueap); 1194 if (len < 0) 1195 return (NULL); 1196 nvp = nvpair_create_string(name, str); 1197 if (nvp == NULL) 1198 nv_free(str); 1199 return (nvp); 1200} 1201 1202nvpair_t * 1203nvpair_create_null(const char *name) 1204{ 1205 1206 return (nvpair_allocv(name, NV_TYPE_NULL, 0, 0, 0)); 1207} 1208 1209nvpair_t * 1210nvpair_create_bool(const char *name, bool value) 1211{ 1212 1213 return (nvpair_allocv(name, NV_TYPE_BOOL, value ? 1 : 0, 1214 sizeof(uint8_t), 0)); 1215} 1216 1217nvpair_t * 1218nvpair_create_number(const char *name, uint64_t value) 1219{ 1220 1221 return (nvpair_allocv(name, NV_TYPE_NUMBER, value, sizeof(value), 0)); 1222} 1223 1224nvpair_t * 1225nvpair_create_string(const char *name, const char *value) 1226{ 1227 nvpair_t *nvp; 1228 size_t size; 1229 char *data; 1230 1231 if (value == NULL) { 1232 ERRNO_SET(EINVAL); 1233 return (NULL); 1234 } 1235 1236 data = nv_strdup(value); 1237 if (data == NULL) 1238 return (NULL); 1239 size = strlen(value) + 1; 1240 1241 nvp = nvpair_allocv(name, NV_TYPE_STRING, (uint64_t)(uintptr_t)data, 1242 size, 0); 1243 if (nvp == NULL) 1244 nv_free(data); 1245 1246 return (nvp); 1247} 1248 1249nvpair_t * 1250nvpair_create_nvlist(const char *name, const nvlist_t *value) 1251{ 1252 nvlist_t *nvl; 1253 nvpair_t *nvp; 1254 1255 if (value == NULL) { 1256 ERRNO_SET(EINVAL); 1257 return (NULL); 1258 } 1259 1260 nvl = nvlist_clone(value); 1261 if (nvl == NULL) 1262 return (NULL); 1263 1264 nvp = nvpair_allocv(name, NV_TYPE_NVLIST, (uint64_t)(uintptr_t)nvl, 0, 1265 0); 1266 if (nvp == NULL) 1267 nvlist_destroy(nvl); 1268 else 1269 nvlist_set_parent(nvl, nvp); 1270 1271 return (nvp); 1272} 1273 1274#ifndef _KERNEL 1275nvpair_t * 1276nvpair_create_descriptor(const char *name, int value) 1277{ 1278 nvpair_t *nvp; 1279 1280 value = fcntl(value, F_DUPFD_CLOEXEC, 0); 1281 if (value < 0) 1282 return (NULL); 1283 1284 nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR, (uint64_t)value, 1285 sizeof(int64_t), 0); 1286 if (nvp == NULL) { 1287 ERRNO_SAVE(); 1288 close(value); 1289 ERRNO_RESTORE(); 1290 } 1291 1292 return (nvp); 1293} 1294#endif 1295 1296nvpair_t * 1297nvpair_create_binary(const char *name, const void *value, size_t size) 1298{ 1299 nvpair_t *nvp; 1300 void *data; 1301 1302 if (value == NULL || size == 0) { 1303 ERRNO_SET(EINVAL); 1304 return (NULL); 1305 } 1306 1307 data = nv_malloc(size); 1308 if (data == NULL) 1309 return (NULL); 1310 memcpy(data, value, size); 1311 1312 nvp = nvpair_allocv(name, NV_TYPE_BINARY, (uint64_t)(uintptr_t)data, 1313 size, 0); 1314 if (nvp == NULL) 1315 nv_free(data); 1316 1317 return (nvp); 1318} 1319 1320nvpair_t * 1321nvpair_create_bool_array(const char *name, const bool *value, size_t nitems) 1322{ 1323 nvpair_t *nvp; 1324 size_t size; 1325 void *data; 1326 1327 if (value == NULL || nitems == 0) { 1328 ERRNO_SET(EINVAL); 1329 return (NULL); 1330 } 1331 1332 size = sizeof(value[0]) * nitems; 1333 data = nv_malloc(size); 1334 if (data == NULL) 1335 return (NULL); 1336 1337 memcpy(data, value, size); 1338 nvp = nvpair_allocv(name, NV_TYPE_BOOL_ARRAY, (uint64_t)(uintptr_t)data, 1339 size, nitems); 1340 if (nvp == NULL) { 1341 ERRNO_SAVE(); 1342 nv_free(data); 1343 ERRNO_RESTORE(); 1344 } 1345 1346 return (nvp); 1347} 1348 1349nvpair_t * 1350nvpair_create_number_array(const char *name, const uint64_t *value, 1351 size_t nitems) 1352{ 1353 nvpair_t *nvp; 1354 size_t size; 1355 void *data; 1356 1357 if (value == NULL || nitems == 0) { 1358 ERRNO_SET(EINVAL); 1359 return (NULL); 1360 } 1361 1362 size = sizeof(value[0]) * nitems; 1363 data = nv_malloc(size); 1364 if (data == NULL) 1365 return (NULL); 1366 1367 memcpy(data, value, size); 1368 nvp = nvpair_allocv(name, NV_TYPE_NUMBER_ARRAY, 1369 (uint64_t)(uintptr_t)data, size, nitems); 1370 if (nvp == NULL) { 1371 ERRNO_SAVE(); 1372 nv_free(data); 1373 ERRNO_RESTORE(); 1374 } 1375 1376 return (nvp); 1377} 1378 1379nvpair_t * 1380nvpair_create_string_array(const char *name, const char * const *value, 1381 size_t nitems) 1382{ 1383 nvpair_t *nvp; 1384 unsigned int ii; 1385 size_t datasize, size; 1386 char **data; 1387 1388 if (value == NULL || nitems == 0) { 1389 ERRNO_SET(EINVAL); 1390 return (NULL); 1391 } 1392 1393 nvp = NULL; 1394 datasize = 0; 1395 data = nv_malloc(sizeof(value[0]) * nitems); 1396 if (data == NULL) 1397 return (NULL); 1398 1399 for (ii = 0; ii < nitems; ii++) { 1400 if (value[ii] == NULL) { 1401 ERRNO_SET(EINVAL); 1402 goto fail; 1403 } 1404 1405 size = strlen(value[ii]) + 1; 1406 datasize += size; 1407 data[ii] = nv_strdup(value[ii]); 1408 if (data[ii] == NULL) 1409 goto fail; 1410 } 1411 nvp = nvpair_allocv(name, NV_TYPE_STRING_ARRAY, 1412 (uint64_t)(uintptr_t)data, datasize, nitems); 1413 1414fail: 1415 if (nvp == NULL) { 1416 ERRNO_SAVE(); 1417 for (; ii > 0; ii--) 1418 nv_free(data[ii - 1]); 1419 nv_free(data); 1420 ERRNO_RESTORE(); 1421 } 1422 1423 return (nvp); 1424} 1425 1426nvpair_t * 1427nvpair_create_nvlist_array(const char *name, const nvlist_t * const *value, 1428 size_t nitems) 1429{ 1430 unsigned int ii; 1431 nvlist_t **nvls; 1432 nvpair_t *parent; 1433 int flags; 1434 1435 nvls = NULL; 1436 1437 if (value == NULL || nitems == 0) { 1438 ERRNO_SET(EINVAL); 1439 return (NULL); 1440 } 1441 1442 nvls = nv_malloc(sizeof(value[0]) * nitems); 1443 if (nvls == NULL) 1444 return (NULL); 1445 1446 for (ii = 0; ii < nitems; ii++) { 1447 if (value[ii] == NULL) { 1448 ERRNO_SET(EINVAL); 1449 goto fail; 1450 } 1451 1452 nvls[ii] = nvlist_clone(value[ii]); 1453 if (nvls[ii] == NULL) 1454 goto fail; 1455 1456 if (ii > 0) { 1457 nvpair_t *nvp; 1458 1459 nvp = nvpair_allocv(" ", NV_TYPE_NVLIST, 1460 (uint64_t)(uintptr_t)nvls[ii], 0, 0); 1461 if (nvp == NULL) { 1462 ERRNO_SAVE(); 1463 nvlist_destroy(nvls[ii]); 1464 ERRNO_RESTORE(); 1465 goto fail; 1466 } 1467 nvlist_set_array_next(nvls[ii - 1], nvp); 1468 } 1469 } 1470 flags = nvlist_flags(nvls[nitems - 1]) | NV_FLAG_IN_ARRAY; 1471 nvlist_set_flags(nvls[nitems - 1], flags); 1472 1473 parent = nvpair_allocv(name, NV_TYPE_NVLIST_ARRAY, 1474 (uint64_t)(uintptr_t)nvls, 0, nitems); 1475 if (parent == NULL) 1476 goto fail; 1477 1478 for (ii = 0; ii < nitems; ii++) 1479 nvlist_set_parent(nvls[ii], parent); 1480 1481 return (parent); 1482 1483fail: 1484 ERRNO_SAVE(); 1485 for (; ii > 0; ii--) 1486 nvlist_destroy(nvls[ii - 1]); 1487 nv_free(nvls); 1488 ERRNO_RESTORE(); 1489 1490 return (NULL); 1491} 1492 1493#ifndef _KERNEL 1494nvpair_t * 1495nvpair_create_descriptor_array(const char *name, const int *value, 1496 size_t nitems) 1497{ 1498 unsigned int ii; 1499 nvpair_t *nvp; 1500 int *fds; 1501 1502 if (value == NULL) { 1503 ERRNO_SET(EINVAL); 1504 return (NULL); 1505 } 1506 1507 nvp = NULL; 1508 1509 fds = nv_malloc(sizeof(value[0]) * nitems); 1510 if (fds == NULL) 1511 return (NULL); 1512 for (ii = 0; ii < nitems; ii++) { 1513 if (value[ii] == -1) { 1514 fds[ii] = -1; 1515 } else { 1516 fds[ii] = fcntl(value[ii], F_DUPFD_CLOEXEC, 0); 1517 if (fds[ii] == -1) 1518 goto fail; 1519 } 1520 } 1521 1522 nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR_ARRAY, 1523 (uint64_t)(uintptr_t)fds, sizeof(int64_t) * nitems, nitems); 1524 1525fail: 1526 if (nvp == NULL) { 1527 ERRNO_SAVE(); 1528 for (; ii > 0; ii--) { 1529 if (fds[ii - 1] != -1) 1530 close(fds[ii - 1]); 1531 } 1532 nv_free(fds); 1533 ERRNO_RESTORE(); 1534 } 1535 1536 return (nvp); 1537} 1538#endif 1539 1540nvpair_t * 1541nvpair_move_string(const char *name, char *value) 1542{ 1543 nvpair_t *nvp; 1544 1545 if (value == NULL) { 1546 ERRNO_SET(EINVAL); 1547 return (NULL); 1548 } 1549 1550 nvp = nvpair_allocv(name, NV_TYPE_STRING, (uint64_t)(uintptr_t)value, 1551 strlen(value) + 1, 0); 1552 if (nvp == NULL) { 1553 ERRNO_SAVE(); 1554 nv_free(value); 1555 ERRNO_RESTORE(); 1556 } 1557 1558 return (nvp); 1559} 1560 1561nvpair_t * 1562nvpair_move_nvlist(const char *name, nvlist_t *value) 1563{ 1564 nvpair_t *nvp; 1565 1566 if (value == NULL || nvlist_get_nvpair_parent(value) != NULL) { 1567 ERRNO_SET(EINVAL); 1568 return (NULL); 1569 } 1570 1571 if (nvlist_error(value) != 0) { 1572 ERRNO_SET(nvlist_error(value)); 1573 nvlist_destroy(value); 1574 return (NULL); 1575 } 1576 1577 nvp = nvpair_allocv(name, NV_TYPE_NVLIST, (uint64_t)(uintptr_t)value, 1578 0, 0); 1579 if (nvp == NULL) 1580 nvlist_destroy(value); 1581 else 1582 nvlist_set_parent(value, nvp); 1583 1584 return (nvp); 1585} 1586 1587#ifndef _KERNEL 1588nvpair_t * 1589nvpair_move_descriptor(const char *name, int value) 1590{ 1591 nvpair_t *nvp; 1592 1593 if (value < 0 || !fd_is_valid(value)) { 1594 ERRNO_SET(EBADF); 1595 return (NULL); 1596 } 1597 1598 nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR, (uint64_t)value, 1599 sizeof(int64_t), 0); 1600 if (nvp == NULL) { 1601 ERRNO_SAVE(); 1602 close(value); 1603 ERRNO_RESTORE(); 1604 } 1605 1606 return (nvp); 1607} 1608#endif 1609 1610nvpair_t * 1611nvpair_move_binary(const char *name, void *value, size_t size) 1612{ 1613 nvpair_t *nvp; 1614 1615 if (value == NULL || size == 0) { 1616 ERRNO_SET(EINVAL); 1617 return (NULL); 1618 } 1619 1620 nvp = nvpair_allocv(name, NV_TYPE_BINARY, (uint64_t)(uintptr_t)value, 1621 size, 0); 1622 if (nvp == NULL) { 1623 ERRNO_SAVE(); 1624 nv_free(value); 1625 ERRNO_RESTORE(); 1626 } 1627 1628 return (nvp); 1629} 1630 1631nvpair_t * 1632nvpair_move_bool_array(const char *name, bool *value, size_t nitems) 1633{ 1634 nvpair_t *nvp; 1635 1636 if (value == NULL || nitems == 0) { 1637 ERRNO_SET(EINVAL); 1638 return (NULL); 1639 } 1640 1641 nvp = nvpair_allocv(name, NV_TYPE_BOOL_ARRAY, 1642 (uint64_t)(uintptr_t)value, sizeof(value[0]) * nitems, nitems); 1643 if (nvp == NULL) { 1644 ERRNO_SAVE(); 1645 nv_free(value); 1646 ERRNO_RESTORE(); 1647 } 1648 1649 return (nvp); 1650} 1651 1652nvpair_t * 1653nvpair_move_string_array(const char *name, char **value, size_t nitems) 1654{ 1655 nvpair_t *nvp; 1656 size_t i, size; 1657 1658 if (value == NULL || nitems == 0) { 1659 ERRNO_SET(EINVAL); 1660 return (NULL); 1661 } 1662 1663 size = 0; 1664 for (i = 0; i < nitems; i++) { 1665 if (value[i] == NULL) { 1666 ERRNO_SET(EINVAL); 1667 return (NULL); 1668 } 1669 1670 size += strlen(value[i]) + 1; 1671 } 1672 1673 nvp = nvpair_allocv(name, NV_TYPE_STRING_ARRAY, 1674 (uint64_t)(uintptr_t)value, size, nitems); 1675 if (nvp == NULL) { 1676 ERRNO_SAVE(); 1677 for (i = 0; i < nitems; i++) 1678 nv_free(value[i]); 1679 nv_free(value); 1680 ERRNO_RESTORE(); 1681 } 1682 1683 return (nvp); 1684} 1685 1686nvpair_t * 1687nvpair_move_number_array(const char *name, uint64_t *value, size_t nitems) 1688{ 1689 nvpair_t *nvp; 1690 1691 if (value == NULL || nitems == 0) { 1692 ERRNO_SET(EINVAL); 1693 return (NULL); 1694 } 1695 1696 nvp = nvpair_allocv(name, NV_TYPE_NUMBER_ARRAY, 1697 (uint64_t)(uintptr_t)value, sizeof(value[0]) * nitems, nitems); 1698 if (nvp == NULL) { 1699 ERRNO_SAVE(); 1700 nv_free(value); 1701 ERRNO_RESTORE(); 1702 } 1703 1704 return (nvp); 1705} 1706 1707nvpair_t * 1708nvpair_move_nvlist_array(const char *name, nvlist_t **value, size_t nitems) 1709{ 1710 nvpair_t *parent; 1711 unsigned int ii; 1712 int flags; 1713 1714 if (value == NULL || nitems == 0) { 1715 ERRNO_SET(EINVAL); 1716 return (NULL); 1717 } 1718 1719 for (ii = 0; ii < nitems; ii++) { 1720 if (value == NULL || nvlist_error(value[ii]) != 0 || 1721 nvlist_get_pararr(value[ii], NULL) != NULL) { 1722 ERRNO_SET(EINVAL); 1723 goto fail; 1724 } 1725 if (ii > 0) { 1726 nvpair_t *nvp; 1727 1728 nvp = nvpair_allocv(" ", NV_TYPE_NVLIST, 1729 (uint64_t)(uintptr_t)value[ii], 0, 0); 1730 if (nvp == NULL) 1731 goto fail; 1732 nvlist_set_array_next(value[ii - 1], nvp); 1733 } 1734 } 1735 flags = nvlist_flags(value[nitems - 1]) | NV_FLAG_IN_ARRAY; 1736 nvlist_set_flags(value[nitems - 1], flags); 1737 1738 parent = nvpair_allocv(name, NV_TYPE_NVLIST_ARRAY, 1739 (uint64_t)(uintptr_t)value, 0, nitems); 1740 if (parent == NULL) 1741 goto fail; 1742 1743 for (ii = 0; ii < nitems; ii++) 1744 nvlist_set_parent(value[ii], parent); 1745 1746 return (parent); 1747fail: 1748 ERRNO_SAVE(); 1749 for (ii = 0; ii < nitems; ii++) { 1750 if (value[ii] != NULL && 1751 nvlist_get_pararr(value[ii], NULL) != NULL) { 1752 nvlist_destroy(value[ii]); 1753 } 1754 } 1755 nv_free(value); 1756 ERRNO_RESTORE(); 1757 1758 return (NULL); 1759} 1760 1761#ifndef _KERNEL 1762nvpair_t * 1763nvpair_move_descriptor_array(const char *name, int *value, size_t nitems) 1764{ 1765 nvpair_t *nvp; 1766 size_t i; 1767 1768 if (value == NULL || nitems == 0) { 1769 ERRNO_SET(EINVAL); 1770 return (NULL); 1771 } 1772 1773 for (i = 0; i < nitems; i++) { 1774 if (value[i] != -1 && !fd_is_valid(value[i])) { 1775 ERRNO_SET(EBADF); 1776 goto fail; 1777 } 1778 } 1779 1780 nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR_ARRAY, 1781 (uint64_t)(uintptr_t)value, sizeof(value[0]) * nitems, nitems); 1782 if (nvp == NULL) 1783 goto fail; 1784 1785 return (nvp); 1786fail: 1787 ERRNO_SAVE(); 1788 for (i = 0; i < nitems; i++) { 1789 if (fd_is_valid(value[i])) 1790 close(value[i]); 1791 } 1792 nv_free(value); 1793 ERRNO_RESTORE(); 1794 1795 return (NULL); 1796} 1797#endif 1798 1799bool 1800nvpair_get_bool(const nvpair_t *nvp) 1801{ 1802 1803 NVPAIR_ASSERT(nvp); 1804 1805 return (nvp->nvp_data == 1); 1806} 1807 1808uint64_t 1809nvpair_get_number(const nvpair_t *nvp) 1810{ 1811 1812 NVPAIR_ASSERT(nvp); 1813 1814 return (nvp->nvp_data); 1815} 1816 1817const char * 1818nvpair_get_string(const nvpair_t *nvp) 1819{ 1820 1821 NVPAIR_ASSERT(nvp); 1822 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING); 1823 1824 return ((const char *)(intptr_t)nvp->nvp_data); 1825} 1826 1827const nvlist_t * 1828nvpair_get_nvlist(const nvpair_t *nvp) 1829{ 1830 1831 NVPAIR_ASSERT(nvp); 1832 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST); 1833 1834 return ((const nvlist_t *)(intptr_t)nvp->nvp_data); 1835} 1836 1837#ifndef _KERNEL 1838int 1839nvpair_get_descriptor(const nvpair_t *nvp) 1840{ 1841 1842 NVPAIR_ASSERT(nvp); 1843 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR); 1844 1845 return ((int)nvp->nvp_data); 1846} 1847#endif 1848 1849const void * 1850nvpair_get_binary(const nvpair_t *nvp, size_t *sizep) 1851{ 1852 1853 NVPAIR_ASSERT(nvp); 1854 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY); 1855 1856 if (sizep != NULL) 1857 *sizep = nvp->nvp_datasize; 1858 1859 return ((const void *)(intptr_t)nvp->nvp_data); 1860} 1861 1862const bool * 1863nvpair_get_bool_array(const nvpair_t *nvp, size_t *nitems) 1864{ 1865 1866 NVPAIR_ASSERT(nvp); 1867 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL_ARRAY); 1868 1869 if (nitems != NULL) 1870 *nitems = nvp->nvp_nitems; 1871 1872 return ((const bool *)(intptr_t)nvp->nvp_data); 1873} 1874 1875const uint64_t * 1876nvpair_get_number_array(const nvpair_t *nvp, size_t *nitems) 1877{ 1878 1879 NVPAIR_ASSERT(nvp); 1880 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER_ARRAY); 1881 1882 if (nitems != NULL) 1883 *nitems = nvp->nvp_nitems; 1884 1885 return ((const uint64_t *)(intptr_t)nvp->nvp_data); 1886} 1887 1888const char * const * 1889nvpair_get_string_array(const nvpair_t *nvp, size_t *nitems) 1890{ 1891 1892 NVPAIR_ASSERT(nvp); 1893 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING_ARRAY); 1894 1895 if (nitems != NULL) 1896 *nitems = nvp->nvp_nitems; 1897 1898 return ((const char * const *)(intptr_t)nvp->nvp_data); 1899} 1900 1901const nvlist_t * const * 1902nvpair_get_nvlist_array(const nvpair_t *nvp, size_t *nitems) 1903{ 1904 1905 NVPAIR_ASSERT(nvp); 1906 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST_ARRAY); 1907 1908 if (nitems != NULL) 1909 *nitems = nvp->nvp_nitems; 1910 1911 return ((const nvlist_t * const *)((intptr_t)nvp->nvp_data)); 1912} 1913 1914#ifndef _KERNEL 1915const int * 1916nvpair_get_descriptor_array(const nvpair_t *nvp, size_t *nitems) 1917{ 1918 1919 NVPAIR_ASSERT(nvp); 1920 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR_ARRAY); 1921 1922 if (nitems != NULL) 1923 *nitems = nvp->nvp_nitems; 1924 1925 return ((const int *)(intptr_t)nvp->nvp_data); 1926} 1927#endif 1928 1929int 1930nvpair_append_bool_array(nvpair_t *nvp, const bool value) 1931{ 1932 1933 NVPAIR_ASSERT(nvp); 1934 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL_ARRAY); 1935 return (nvpair_append(nvp, &value, sizeof(value), sizeof(value))); 1936} 1937 1938int 1939nvpair_append_number_array(nvpair_t *nvp, const uint64_t value) 1940{ 1941 1942 NVPAIR_ASSERT(nvp); 1943 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER_ARRAY); 1944 return (nvpair_append(nvp, &value, sizeof(value), sizeof(value))); 1945} 1946 1947int 1948nvpair_append_string_array(nvpair_t *nvp, const char *value) 1949{ 1950 char *str; 1951 1952 NVPAIR_ASSERT(nvp); 1953 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING_ARRAY); 1954 if (value == NULL) { 1955 ERRNO_SET(EINVAL); 1956 return (-1); 1957 } 1958 str = nv_strdup(value); 1959 if (str == NULL) { 1960 return (-1); 1961 } 1962 if (nvpair_append(nvp, &str, sizeof(str), strlen(str) + 1) == -1) { 1963 nv_free(str); 1964 return (-1); 1965 } 1966 return (0); 1967} 1968 1969int 1970nvpair_append_nvlist_array(nvpair_t *nvp, const nvlist_t *value) 1971{ 1972 nvpair_t *tmpnvp; 1973 nvlist_t *nvl, *prev; 1974 int flags; 1975 1976 NVPAIR_ASSERT(nvp); 1977 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST_ARRAY); 1978 if (value == NULL || nvlist_error(value) != 0 || 1979 nvlist_get_pararr(value, NULL) != NULL) { 1980 ERRNO_SET(EINVAL); 1981 return (-1); 1982 } 1983 nvl = nvlist_clone(value); 1984 if (nvl == NULL) { 1985 return (-1); 1986 } 1987 flags = nvlist_flags(nvl) | NV_FLAG_IN_ARRAY; 1988 nvlist_set_flags(nvl, flags); 1989 1990 tmpnvp = NULL; 1991 prev = NULL; 1992 if (nvp->nvp_nitems > 0) { 1993 nvlist_t **nvls = (void *)(uintptr_t)nvp->nvp_data; 1994 1995 prev = nvls[nvp->nvp_nitems - 1]; 1996 PJDLOG_ASSERT(prev != NULL); 1997 1998 tmpnvp = nvpair_allocv(" ", NV_TYPE_NVLIST, 1999 (uint64_t)(uintptr_t)nvl, 0, 0); 2000 if (tmpnvp == NULL) { 2001 goto fail; 2002 } 2003 } 2004 if (nvpair_append(nvp, &nvl, sizeof(nvl), 0) == -1) { 2005 goto fail; 2006 } 2007 if (tmpnvp) { 2008 NVPAIR_ASSERT(tmpnvp); 2009 nvlist_set_array_next(prev, tmpnvp); 2010 } 2011 nvlist_set_parent(nvl, nvp); 2012 return (0); 2013fail: 2014 if (tmpnvp) { 2015 nvpair_free(tmpnvp); 2016 } 2017 nvlist_destroy(nvl); 2018 return (-1); 2019} 2020 2021#ifndef _KERNEL 2022int 2023nvpair_append_descriptor_array(nvpair_t *nvp, const int value) 2024{ 2025 int fd; 2026 2027 NVPAIR_ASSERT(nvp); 2028 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR_ARRAY); 2029 fd = fcntl(value, F_DUPFD_CLOEXEC, 0); 2030 if (fd == -1) { 2031 return (-1); 2032 } 2033 if (nvpair_append(nvp, &fd, sizeof(fd), sizeof(fd)) == -1) { 2034 close(fd); 2035 return (-1); 2036 } 2037 return (0); 2038} 2039#endif 2040 2041void 2042nvpair_free(nvpair_t *nvp) 2043{ 2044 size_t i; 2045 2046 NVPAIR_ASSERT(nvp); 2047 PJDLOG_ASSERT(nvp->nvp_list == NULL); 2048 2049 nvp->nvp_magic = 0; 2050 switch (nvp->nvp_type) { 2051#ifndef _KERNEL 2052 case NV_TYPE_DESCRIPTOR: 2053 close((int)nvp->nvp_data); 2054 break; 2055 case NV_TYPE_DESCRIPTOR_ARRAY: 2056 for (i = 0; i < nvp->nvp_nitems; i++) 2057 close(((int *)(intptr_t)nvp->nvp_data)[i]); 2058 break; 2059#endif 2060 case NV_TYPE_NVLIST: 2061 nvlist_destroy((nvlist_t *)(intptr_t)nvp->nvp_data); 2062 break; 2063 case NV_TYPE_STRING: 2064 nv_free((char *)(intptr_t)nvp->nvp_data); 2065 break; 2066 case NV_TYPE_BINARY: 2067 nv_free((void *)(intptr_t)nvp->nvp_data); 2068 break; 2069 case NV_TYPE_NVLIST_ARRAY: 2070 for (i = 0; i < nvp->nvp_nitems; i++) { 2071 nvlist_destroy( 2072 ((nvlist_t **)(intptr_t)nvp->nvp_data)[i]); 2073 } 2074 nv_free(((nvlist_t **)(intptr_t)nvp->nvp_data)); 2075 break; 2076 case NV_TYPE_NUMBER_ARRAY: 2077 nv_free((uint64_t *)(intptr_t)nvp->nvp_data); 2078 break; 2079 case NV_TYPE_BOOL_ARRAY: 2080 nv_free((bool *)(intptr_t)nvp->nvp_data); 2081 break; 2082 case NV_TYPE_STRING_ARRAY: 2083 for (i = 0; i < nvp->nvp_nitems; i++) 2084 nv_free(((char **)(intptr_t)nvp->nvp_data)[i]); 2085 nv_free((char **)(intptr_t)nvp->nvp_data); 2086 break; 2087 } 2088 nv_free(nvp); 2089} 2090 2091void 2092nvpair_free_structure(nvpair_t *nvp) 2093{ 2094 2095 NVPAIR_ASSERT(nvp); 2096 PJDLOG_ASSERT(nvp->nvp_list == NULL); 2097 2098 nvp->nvp_magic = 0; 2099 nv_free(nvp); 2100} 2101 2102const char * 2103nvpair_type_string(int type) 2104{ 2105 2106 switch (type) { 2107 case NV_TYPE_NULL: 2108 return ("NULL"); 2109 case NV_TYPE_BOOL: 2110 return ("BOOL"); 2111 case NV_TYPE_NUMBER: 2112 return ("NUMBER"); 2113 case NV_TYPE_STRING: 2114 return ("STRING"); 2115 case NV_TYPE_NVLIST: 2116 return ("NVLIST"); 2117 case NV_TYPE_DESCRIPTOR: 2118 return ("DESCRIPTOR"); 2119 case NV_TYPE_BINARY: 2120 return ("BINARY"); 2121 case NV_TYPE_BOOL_ARRAY: 2122 return ("BOOL ARRAY"); 2123 case NV_TYPE_NUMBER_ARRAY: 2124 return ("NUMBER ARRAY"); 2125 case NV_TYPE_STRING_ARRAY: 2126 return ("STRING ARRAY"); 2127 case NV_TYPE_NVLIST_ARRAY: 2128 return ("NVLIST ARRAY"); 2129 case NV_TYPE_DESCRIPTOR_ARRAY: 2130 return ("DESCRIPTOR ARRAY"); 2131 default: 2132 return ("<UNKNOWN>"); 2133 } 2134} 2135 2136