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, 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 } 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); 696 fail: 697 ERRNO_SET(EINVAL); 698 return (NULL); 699 } 700 701 const unsigned char * 702 nvpair_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 716 const unsigned char * 717 nvpair_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 747 const unsigned char * 748 nvpair_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 774 const unsigned char * 775 nvpair_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 802 const unsigned char * 803 nvpair_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 830 const unsigned char * 831 nvpair_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 871 const unsigned char * 872 nvpair_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 897 const unsigned char * 898 nvpair_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 930 const unsigned char * 931 nvpair_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 966 const unsigned char * 967 nvpair_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); 1015 out: 1016 for (j = 0; j < ii; j++) 1017 nv_free(value[j]); 1018 nv_free(value); 1019 return (NULL); 1020 } 1021 1022 #ifndef _KERNEL 1023 const unsigned char * 1024 nvpair_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 1075 const unsigned char * 1076 nvpair_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); 1115 fail: 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 1125 const unsigned char * 1126 nvpair_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); 1150 fail: 1151 nv_free(nvp); 1152 return (NULL); 1153 } 1154 1155 int 1156 nvpair_type(const nvpair_t *nvp) 1157 { 1158 1159 NVPAIR_ASSERT(nvp); 1160 1161 return (nvp->nvp_type); 1162 } 1163 1164 const char * 1165 nvpair_name(const nvpair_t *nvp) 1166 { 1167 1168 NVPAIR_ASSERT(nvp); 1169 1170 return (nvp->nvp_name); 1171 } 1172 1173 nvpair_t * 1174 nvpair_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 1186 nvpair_t * 1187 nvpair_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 nv_free(str); 1198 return (nvp); 1199 } 1200 1201 nvpair_t * 1202 nvpair_create_null(const char *name) 1203 { 1204 1205 return (nvpair_allocv(name, NV_TYPE_NULL, 0, 0, 0)); 1206 } 1207 1208 nvpair_t * 1209 nvpair_create_bool(const char *name, bool value) 1210 { 1211 1212 return (nvpair_allocv(name, NV_TYPE_BOOL, value ? 1 : 0, 1213 sizeof(uint8_t), 0)); 1214 } 1215 1216 nvpair_t * 1217 nvpair_create_number(const char *name, uint64_t value) 1218 { 1219 1220 return (nvpair_allocv(name, NV_TYPE_NUMBER, value, sizeof(value), 0)); 1221 } 1222 1223 nvpair_t * 1224 nvpair_create_string(const char *name, const char *value) 1225 { 1226 nvpair_t *nvp; 1227 size_t size; 1228 char *data; 1229 1230 if (value == NULL) { 1231 ERRNO_SET(EINVAL); 1232 return (NULL); 1233 } 1234 1235 data = nv_strdup(value); 1236 if (data == NULL) 1237 return (NULL); 1238 size = strlen(value) + 1; 1239 1240 nvp = nvpair_allocv(name, NV_TYPE_STRING, (uint64_t)(uintptr_t)data, 1241 size, 0); 1242 if (nvp == NULL) 1243 nv_free(data); 1244 1245 return (nvp); 1246 } 1247 1248 nvpair_t * 1249 nvpair_create_nvlist(const char *name, const nvlist_t *value) 1250 { 1251 nvlist_t *nvl; 1252 nvpair_t *nvp; 1253 1254 if (value == NULL) { 1255 ERRNO_SET(EINVAL); 1256 return (NULL); 1257 } 1258 1259 nvl = nvlist_clone(value); 1260 if (nvl == NULL) 1261 return (NULL); 1262 1263 nvp = nvpair_allocv(name, NV_TYPE_NVLIST, (uint64_t)(uintptr_t)nvl, 0, 1264 0); 1265 if (nvp == NULL) 1266 nvlist_destroy(nvl); 1267 else 1268 nvlist_set_parent(nvl, nvp); 1269 1270 return (nvp); 1271 } 1272 1273 #ifndef _KERNEL 1274 nvpair_t * 1275 nvpair_create_descriptor(const char *name, int value) 1276 { 1277 nvpair_t *nvp; 1278 1279 value = fcntl(value, F_DUPFD_CLOEXEC, 0); 1280 if (value < 0) 1281 return (NULL); 1282 1283 nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR, (uint64_t)value, 1284 sizeof(int64_t), 0); 1285 if (nvp == NULL) { 1286 ERRNO_SAVE(); 1287 close(value); 1288 ERRNO_RESTORE(); 1289 } 1290 1291 return (nvp); 1292 } 1293 #endif 1294 1295 nvpair_t * 1296 nvpair_create_binary(const char *name, const void *value, size_t size) 1297 { 1298 nvpair_t *nvp; 1299 void *data; 1300 1301 if (value == NULL || size == 0) { 1302 ERRNO_SET(EINVAL); 1303 return (NULL); 1304 } 1305 1306 data = nv_malloc(size); 1307 if (data == NULL) 1308 return (NULL); 1309 memcpy(data, value, size); 1310 1311 nvp = nvpair_allocv(name, NV_TYPE_BINARY, (uint64_t)(uintptr_t)data, 1312 size, 0); 1313 if (nvp == NULL) 1314 nv_free(data); 1315 1316 return (nvp); 1317 } 1318 1319 nvpair_t * 1320 nvpair_create_bool_array(const char *name, const bool *value, size_t nitems) 1321 { 1322 nvpair_t *nvp; 1323 size_t size; 1324 void *data; 1325 1326 if (value == NULL || nitems == 0) { 1327 ERRNO_SET(EINVAL); 1328 return (NULL); 1329 } 1330 1331 size = sizeof(value[0]) * nitems; 1332 data = nv_malloc(size); 1333 if (data == NULL) 1334 return (NULL); 1335 1336 memcpy(data, value, size); 1337 nvp = nvpair_allocv(name, NV_TYPE_BOOL_ARRAY, (uint64_t)(uintptr_t)data, 1338 size, nitems); 1339 if (nvp == NULL) { 1340 ERRNO_SAVE(); 1341 nv_free(data); 1342 ERRNO_RESTORE(); 1343 } 1344 1345 return (nvp); 1346 } 1347 1348 nvpair_t * 1349 nvpair_create_number_array(const char *name, const uint64_t *value, 1350 size_t nitems) 1351 { 1352 nvpair_t *nvp; 1353 size_t size; 1354 void *data; 1355 1356 if (value == NULL || nitems == 0) { 1357 ERRNO_SET(EINVAL); 1358 return (NULL); 1359 } 1360 1361 size = sizeof(value[0]) * nitems; 1362 data = nv_malloc(size); 1363 if (data == NULL) 1364 return (NULL); 1365 1366 memcpy(data, value, size); 1367 nvp = nvpair_allocv(name, NV_TYPE_NUMBER_ARRAY, 1368 (uint64_t)(uintptr_t)data, size, nitems); 1369 if (nvp == NULL) { 1370 ERRNO_SAVE(); 1371 nv_free(data); 1372 ERRNO_RESTORE(); 1373 } 1374 1375 return (nvp); 1376 } 1377 1378 nvpair_t * 1379 nvpair_create_string_array(const char *name, const char * const *value, 1380 size_t nitems) 1381 { 1382 nvpair_t *nvp; 1383 unsigned int ii; 1384 size_t datasize, size; 1385 char **data; 1386 1387 if (value == NULL || nitems == 0) { 1388 ERRNO_SET(EINVAL); 1389 return (NULL); 1390 } 1391 1392 nvp = NULL; 1393 datasize = 0; 1394 data = nv_malloc(sizeof(value[0]) * nitems); 1395 if (data == NULL) 1396 return (NULL); 1397 1398 for (ii = 0; ii < nitems; ii++) { 1399 if (value[ii] == NULL) { 1400 ERRNO_SET(EINVAL); 1401 goto fail; 1402 } 1403 1404 size = strlen(value[ii]) + 1; 1405 datasize += size; 1406 data[ii] = nv_strdup(value[ii]); 1407 if (data[ii] == NULL) 1408 goto fail; 1409 } 1410 nvp = nvpair_allocv(name, NV_TYPE_STRING_ARRAY, 1411 (uint64_t)(uintptr_t)data, datasize, nitems); 1412 1413 fail: 1414 if (nvp == NULL) { 1415 ERRNO_SAVE(); 1416 for (; ii > 0; ii--) 1417 nv_free(data[ii - 1]); 1418 nv_free(data); 1419 ERRNO_RESTORE(); 1420 } 1421 1422 return (nvp); 1423 } 1424 1425 nvpair_t * 1426 nvpair_create_nvlist_array(const char *name, const nvlist_t * const *value, 1427 size_t nitems) 1428 { 1429 unsigned int ii; 1430 nvlist_t **nvls; 1431 nvpair_t *parent; 1432 int flags; 1433 1434 nvls = NULL; 1435 1436 if (value == NULL || nitems == 0) { 1437 ERRNO_SET(EINVAL); 1438 return (NULL); 1439 } 1440 1441 nvls = nv_malloc(sizeof(value[0]) * nitems); 1442 if (nvls == NULL) 1443 return (NULL); 1444 1445 for (ii = 0; ii < nitems; ii++) { 1446 if (value[ii] == NULL) { 1447 ERRNO_SET(EINVAL); 1448 goto fail; 1449 } 1450 1451 nvls[ii] = nvlist_clone(value[ii]); 1452 if (nvls[ii] == NULL) 1453 goto fail; 1454 1455 if (ii > 0) { 1456 nvpair_t *nvp; 1457 1458 nvp = nvpair_allocv(" ", NV_TYPE_NVLIST, 1459 (uint64_t)(uintptr_t)nvls[ii], 0, 0); 1460 if (nvp == NULL) { 1461 ERRNO_SAVE(); 1462 nvlist_destroy(nvls[ii]); 1463 ERRNO_RESTORE(); 1464 goto fail; 1465 } 1466 nvlist_set_array_next(nvls[ii - 1], nvp); 1467 } 1468 } 1469 flags = nvlist_flags(nvls[nitems - 1]) | NV_FLAG_IN_ARRAY; 1470 nvlist_set_flags(nvls[nitems - 1], flags); 1471 1472 parent = nvpair_allocv(name, NV_TYPE_NVLIST_ARRAY, 1473 (uint64_t)(uintptr_t)nvls, 0, nitems); 1474 if (parent == NULL) 1475 goto fail; 1476 1477 for (ii = 0; ii < nitems; ii++) 1478 nvlist_set_parent(nvls[ii], parent); 1479 1480 return (parent); 1481 1482 fail: 1483 ERRNO_SAVE(); 1484 for (; ii > 0; ii--) 1485 nvlist_destroy(nvls[ii - 1]); 1486 nv_free(nvls); 1487 ERRNO_RESTORE(); 1488 1489 return (NULL); 1490 } 1491 1492 #ifndef _KERNEL 1493 nvpair_t * 1494 nvpair_create_descriptor_array(const char *name, const int *value, 1495 size_t nitems) 1496 { 1497 unsigned int ii; 1498 nvpair_t *nvp; 1499 int *fds; 1500 1501 if (value == NULL) { 1502 ERRNO_SET(EINVAL); 1503 return (NULL); 1504 } 1505 1506 nvp = NULL; 1507 1508 fds = nv_malloc(sizeof(value[0]) * nitems); 1509 if (fds == NULL) 1510 return (NULL); 1511 for (ii = 0; ii < nitems; ii++) { 1512 if (value[ii] == -1) { 1513 fds[ii] = -1; 1514 } else { 1515 fds[ii] = fcntl(value[ii], F_DUPFD_CLOEXEC, 0); 1516 if (fds[ii] == -1) 1517 goto fail; 1518 } 1519 } 1520 1521 nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR_ARRAY, 1522 (uint64_t)(uintptr_t)fds, sizeof(int64_t) * nitems, nitems); 1523 1524 fail: 1525 if (nvp == NULL) { 1526 ERRNO_SAVE(); 1527 for (; ii > 0; ii--) { 1528 if (fds[ii - 1] != -1) 1529 close(fds[ii - 1]); 1530 } 1531 nv_free(fds); 1532 ERRNO_RESTORE(); 1533 } 1534 1535 return (nvp); 1536 } 1537 #endif 1538 1539 nvpair_t * 1540 nvpair_move_string(const char *name, char *value) 1541 { 1542 nvpair_t *nvp; 1543 1544 if (value == NULL) { 1545 ERRNO_SET(EINVAL); 1546 return (NULL); 1547 } 1548 1549 nvp = nvpair_allocv(name, NV_TYPE_STRING, (uint64_t)(uintptr_t)value, 1550 strlen(value) + 1, 0); 1551 if (nvp == NULL) { 1552 ERRNO_SAVE(); 1553 nv_free(value); 1554 ERRNO_RESTORE(); 1555 } 1556 1557 return (nvp); 1558 } 1559 1560 nvpair_t * 1561 nvpair_move_nvlist(const char *name, nvlist_t *value) 1562 { 1563 nvpair_t *nvp; 1564 1565 if (value == NULL || nvlist_get_nvpair_parent(value) != NULL) { 1566 ERRNO_SET(EINVAL); 1567 return (NULL); 1568 } 1569 1570 if (nvlist_error(value) != 0) { 1571 ERRNO_SET(nvlist_error(value)); 1572 nvlist_destroy(value); 1573 return (NULL); 1574 } 1575 1576 nvp = nvpair_allocv(name, NV_TYPE_NVLIST, (uint64_t)(uintptr_t)value, 1577 0, 0); 1578 if (nvp == NULL) 1579 nvlist_destroy(value); 1580 else 1581 nvlist_set_parent(value, nvp); 1582 1583 return (nvp); 1584 } 1585 1586 #ifndef _KERNEL 1587 nvpair_t * 1588 nvpair_move_descriptor(const char *name, int value) 1589 { 1590 nvpair_t *nvp; 1591 1592 if (value < 0 || !fd_is_valid(value)) { 1593 ERRNO_SET(EBADF); 1594 return (NULL); 1595 } 1596 1597 nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR, (uint64_t)value, 1598 sizeof(int64_t), 0); 1599 if (nvp == NULL) { 1600 ERRNO_SAVE(); 1601 close(value); 1602 ERRNO_RESTORE(); 1603 } 1604 1605 return (nvp); 1606 } 1607 #endif 1608 1609 nvpair_t * 1610 nvpair_move_binary(const char *name, void *value, size_t size) 1611 { 1612 nvpair_t *nvp; 1613 1614 if (value == NULL || size == 0) { 1615 ERRNO_SET(EINVAL); 1616 return (NULL); 1617 } 1618 1619 nvp = nvpair_allocv(name, NV_TYPE_BINARY, (uint64_t)(uintptr_t)value, 1620 size, 0); 1621 if (nvp == NULL) { 1622 ERRNO_SAVE(); 1623 nv_free(value); 1624 ERRNO_RESTORE(); 1625 } 1626 1627 return (nvp); 1628 } 1629 1630 nvpair_t * 1631 nvpair_move_bool_array(const char *name, bool *value, size_t nitems) 1632 { 1633 nvpair_t *nvp; 1634 1635 if (value == NULL || nitems == 0) { 1636 ERRNO_SET(EINVAL); 1637 return (NULL); 1638 } 1639 1640 nvp = nvpair_allocv(name, NV_TYPE_BOOL_ARRAY, 1641 (uint64_t)(uintptr_t)value, sizeof(value[0]) * nitems, nitems); 1642 if (nvp == NULL) { 1643 ERRNO_SAVE(); 1644 nv_free(value); 1645 ERRNO_RESTORE(); 1646 } 1647 1648 return (nvp); 1649 } 1650 1651 nvpair_t * 1652 nvpair_move_string_array(const char *name, char **value, size_t nitems) 1653 { 1654 nvpair_t *nvp; 1655 size_t i, size; 1656 1657 if (value == NULL || nitems == 0) { 1658 ERRNO_SET(EINVAL); 1659 return (NULL); 1660 } 1661 1662 size = 0; 1663 for (i = 0; i < nitems; i++) { 1664 if (value[i] == NULL) { 1665 ERRNO_SET(EINVAL); 1666 return (NULL); 1667 } 1668 1669 size += strlen(value[i]) + 1; 1670 } 1671 1672 nvp = nvpair_allocv(name, NV_TYPE_STRING_ARRAY, 1673 (uint64_t)(uintptr_t)value, size, nitems); 1674 if (nvp == NULL) { 1675 ERRNO_SAVE(); 1676 for (i = 0; i < nitems; i++) 1677 nv_free(value[i]); 1678 nv_free(value); 1679 ERRNO_RESTORE(); 1680 } 1681 1682 return (nvp); 1683 } 1684 1685 nvpair_t * 1686 nvpair_move_number_array(const char *name, uint64_t *value, size_t nitems) 1687 { 1688 nvpair_t *nvp; 1689 1690 if (value == NULL || nitems == 0) { 1691 ERRNO_SET(EINVAL); 1692 return (NULL); 1693 } 1694 1695 nvp = nvpair_allocv(name, NV_TYPE_NUMBER_ARRAY, 1696 (uint64_t)(uintptr_t)value, sizeof(value[0]) * nitems, nitems); 1697 if (nvp == NULL) { 1698 ERRNO_SAVE(); 1699 nv_free(value); 1700 ERRNO_RESTORE(); 1701 } 1702 1703 return (nvp); 1704 } 1705 1706 nvpair_t * 1707 nvpair_move_nvlist_array(const char *name, nvlist_t **value, size_t nitems) 1708 { 1709 nvpair_t *parent; 1710 unsigned int ii; 1711 int flags; 1712 1713 if (value == NULL || nitems == 0) { 1714 ERRNO_SET(EINVAL); 1715 return (NULL); 1716 } 1717 1718 for (ii = 0; ii < nitems; ii++) { 1719 if (value == NULL || nvlist_error(value[ii]) != 0 || 1720 nvlist_get_pararr(value[ii], NULL) != NULL) { 1721 ERRNO_SET(EINVAL); 1722 goto fail; 1723 } 1724 if (ii > 0) { 1725 nvpair_t *nvp; 1726 1727 nvp = nvpair_allocv(" ", NV_TYPE_NVLIST, 1728 (uint64_t)(uintptr_t)value[ii], 0, 0); 1729 if (nvp == NULL) 1730 goto fail; 1731 nvlist_set_array_next(value[ii - 1], nvp); 1732 } 1733 } 1734 flags = nvlist_flags(value[nitems - 1]) | NV_FLAG_IN_ARRAY; 1735 nvlist_set_flags(value[nitems - 1], flags); 1736 1737 parent = nvpair_allocv(name, NV_TYPE_NVLIST_ARRAY, 1738 (uint64_t)(uintptr_t)value, 0, nitems); 1739 if (parent == NULL) 1740 goto fail; 1741 1742 for (ii = 0; ii < nitems; ii++) 1743 nvlist_set_parent(value[ii], parent); 1744 1745 return (parent); 1746 fail: 1747 ERRNO_SAVE(); 1748 for (ii = 0; ii < nitems; ii++) { 1749 if (value[ii] != NULL && 1750 nvlist_get_pararr(value[ii], NULL) != NULL) { 1751 nvlist_destroy(value[ii]); 1752 } 1753 } 1754 nv_free(value); 1755 ERRNO_RESTORE(); 1756 1757 return (NULL); 1758 } 1759 1760 #ifndef _KERNEL 1761 nvpair_t * 1762 nvpair_move_descriptor_array(const char *name, int *value, size_t nitems) 1763 { 1764 nvpair_t *nvp; 1765 size_t i; 1766 1767 if (value == NULL || nitems == 0) { 1768 ERRNO_SET(EINVAL); 1769 return (NULL); 1770 } 1771 1772 for (i = 0; i < nitems; i++) { 1773 if (value[i] != -1 && !fd_is_valid(value[i])) { 1774 ERRNO_SET(EBADF); 1775 goto fail; 1776 } 1777 } 1778 1779 nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR_ARRAY, 1780 (uint64_t)(uintptr_t)value, sizeof(value[0]) * nitems, nitems); 1781 if (nvp == NULL) 1782 goto fail; 1783 1784 return (nvp); 1785 fail: 1786 ERRNO_SAVE(); 1787 for (i = 0; i < nitems; i++) { 1788 if (fd_is_valid(value[i])) 1789 close(value[i]); 1790 } 1791 nv_free(value); 1792 ERRNO_RESTORE(); 1793 1794 return (NULL); 1795 } 1796 #endif 1797 1798 bool 1799 nvpair_get_bool(const nvpair_t *nvp) 1800 { 1801 1802 NVPAIR_ASSERT(nvp); 1803 1804 return (nvp->nvp_data == 1); 1805 } 1806 1807 uint64_t 1808 nvpair_get_number(const nvpair_t *nvp) 1809 { 1810 1811 NVPAIR_ASSERT(nvp); 1812 1813 return (nvp->nvp_data); 1814 } 1815 1816 const char * 1817 nvpair_get_string(const nvpair_t *nvp) 1818 { 1819 1820 NVPAIR_ASSERT(nvp); 1821 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING); 1822 1823 return ((const char *)(intptr_t)nvp->nvp_data); 1824 } 1825 1826 const nvlist_t * 1827 nvpair_get_nvlist(const nvpair_t *nvp) 1828 { 1829 1830 NVPAIR_ASSERT(nvp); 1831 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST); 1832 1833 return ((const nvlist_t *)(intptr_t)nvp->nvp_data); 1834 } 1835 1836 #ifndef _KERNEL 1837 int 1838 nvpair_get_descriptor(const nvpair_t *nvp) 1839 { 1840 1841 NVPAIR_ASSERT(nvp); 1842 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR); 1843 1844 return ((int)nvp->nvp_data); 1845 } 1846 #endif 1847 1848 const void * 1849 nvpair_get_binary(const nvpair_t *nvp, size_t *sizep) 1850 { 1851 1852 NVPAIR_ASSERT(nvp); 1853 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY); 1854 1855 if (sizep != NULL) 1856 *sizep = nvp->nvp_datasize; 1857 1858 return ((const void *)(intptr_t)nvp->nvp_data); 1859 } 1860 1861 const bool * 1862 nvpair_get_bool_array(const nvpair_t *nvp, size_t *nitems) 1863 { 1864 1865 NVPAIR_ASSERT(nvp); 1866 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL_ARRAY); 1867 1868 if (nitems != NULL) 1869 *nitems = nvp->nvp_nitems; 1870 1871 return ((const bool *)(intptr_t)nvp->nvp_data); 1872 } 1873 1874 const uint64_t * 1875 nvpair_get_number_array(const nvpair_t *nvp, size_t *nitems) 1876 { 1877 1878 NVPAIR_ASSERT(nvp); 1879 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER_ARRAY); 1880 1881 if (nitems != NULL) 1882 *nitems = nvp->nvp_nitems; 1883 1884 return ((const uint64_t *)(intptr_t)nvp->nvp_data); 1885 } 1886 1887 const char * const * 1888 nvpair_get_string_array(const nvpair_t *nvp, size_t *nitems) 1889 { 1890 1891 NVPAIR_ASSERT(nvp); 1892 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING_ARRAY); 1893 1894 if (nitems != NULL) 1895 *nitems = nvp->nvp_nitems; 1896 1897 return ((const char * const *)(intptr_t)nvp->nvp_data); 1898 } 1899 1900 const nvlist_t * const * 1901 nvpair_get_nvlist_array(const nvpair_t *nvp, size_t *nitems) 1902 { 1903 1904 NVPAIR_ASSERT(nvp); 1905 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST_ARRAY); 1906 1907 if (nitems != NULL) 1908 *nitems = nvp->nvp_nitems; 1909 1910 return ((const nvlist_t * const *)((intptr_t)nvp->nvp_data)); 1911 } 1912 1913 #ifndef _KERNEL 1914 const int * 1915 nvpair_get_descriptor_array(const nvpair_t *nvp, size_t *nitems) 1916 { 1917 1918 NVPAIR_ASSERT(nvp); 1919 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR_ARRAY); 1920 1921 if (nitems != NULL) 1922 *nitems = nvp->nvp_nitems; 1923 1924 return ((const int *)(intptr_t)nvp->nvp_data); 1925 } 1926 #endif 1927 1928 int 1929 nvpair_append_bool_array(nvpair_t *nvp, const bool value) 1930 { 1931 1932 NVPAIR_ASSERT(nvp); 1933 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL_ARRAY); 1934 return (nvpair_append(nvp, &value, sizeof(value), sizeof(value))); 1935 } 1936 1937 int 1938 nvpair_append_number_array(nvpair_t *nvp, const uint64_t value) 1939 { 1940 1941 NVPAIR_ASSERT(nvp); 1942 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER_ARRAY); 1943 return (nvpair_append(nvp, &value, sizeof(value), sizeof(value))); 1944 } 1945 1946 int 1947 nvpair_append_string_array(nvpair_t *nvp, const char *value) 1948 { 1949 char *str; 1950 1951 NVPAIR_ASSERT(nvp); 1952 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING_ARRAY); 1953 if (value == NULL) { 1954 ERRNO_SET(EINVAL); 1955 return (-1); 1956 } 1957 str = nv_strdup(value); 1958 if (str == NULL) { 1959 return (-1); 1960 } 1961 if (nvpair_append(nvp, &str, sizeof(str), strlen(str) + 1) == -1) { 1962 nv_free(str); 1963 return (-1); 1964 } 1965 return (0); 1966 } 1967 1968 int 1969 nvpair_append_nvlist_array(nvpair_t *nvp, const nvlist_t *value) 1970 { 1971 nvpair_t *tmpnvp; 1972 nvlist_t *nvl, *prev; 1973 int flags; 1974 1975 NVPAIR_ASSERT(nvp); 1976 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST_ARRAY); 1977 if (value == NULL || nvlist_error(value) != 0 || 1978 nvlist_get_pararr(value, NULL) != NULL) { 1979 ERRNO_SET(EINVAL); 1980 return (-1); 1981 } 1982 nvl = nvlist_clone(value); 1983 if (nvl == NULL) { 1984 return (-1); 1985 } 1986 flags = nvlist_flags(nvl) | NV_FLAG_IN_ARRAY; 1987 nvlist_set_flags(nvl, flags); 1988 1989 tmpnvp = NULL; 1990 prev = NULL; 1991 if (nvp->nvp_nitems > 0) { 1992 nvlist_t **nvls = (void *)(uintptr_t)nvp->nvp_data; 1993 1994 prev = nvls[nvp->nvp_nitems - 1]; 1995 PJDLOG_ASSERT(prev != NULL); 1996 1997 tmpnvp = nvpair_allocv(" ", NV_TYPE_NVLIST, 1998 (uint64_t)(uintptr_t)nvl, 0, 0); 1999 if (tmpnvp == NULL) { 2000 goto fail; 2001 } 2002 } 2003 if (nvpair_append(nvp, &nvl, sizeof(nvl), 0) == -1) { 2004 goto fail; 2005 } 2006 if (tmpnvp) { 2007 NVPAIR_ASSERT(tmpnvp); 2008 nvlist_set_array_next(prev, tmpnvp); 2009 } 2010 nvlist_set_parent(nvl, nvp); 2011 return (0); 2012 fail: 2013 if (tmpnvp) { 2014 nvpair_free(tmpnvp); 2015 } 2016 nvlist_destroy(nvl); 2017 return (-1); 2018 } 2019 2020 #ifndef _KERNEL 2021 int 2022 nvpair_append_descriptor_array(nvpair_t *nvp, const int value) 2023 { 2024 int fd; 2025 2026 NVPAIR_ASSERT(nvp); 2027 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR_ARRAY); 2028 fd = fcntl(value, F_DUPFD_CLOEXEC, 0); 2029 if (fd == -1) { 2030 return (-1); 2031 } 2032 if (nvpair_append(nvp, &fd, sizeof(fd), sizeof(fd)) == -1) { 2033 close(fd); 2034 return (-1); 2035 } 2036 return (0); 2037 } 2038 #endif 2039 2040 void 2041 nvpair_free(nvpair_t *nvp) 2042 { 2043 size_t i; 2044 2045 NVPAIR_ASSERT(nvp); 2046 PJDLOG_ASSERT(nvp->nvp_list == NULL); 2047 2048 nvp->nvp_magic = 0; 2049 switch (nvp->nvp_type) { 2050 #ifndef _KERNEL 2051 case NV_TYPE_DESCRIPTOR: 2052 close((int)nvp->nvp_data); 2053 break; 2054 case NV_TYPE_DESCRIPTOR_ARRAY: 2055 for (i = 0; i < nvp->nvp_nitems; i++) 2056 close(((int *)(intptr_t)nvp->nvp_data)[i]); 2057 nv_free((int *)(intptr_t)nvp->nvp_data); 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 2091 void 2092 nvpair_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 2102 const char * 2103 nvpair_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