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