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