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/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 (tmp[len - 1] != '\0') { 992 ERRNO_SET(EINVAL); 993 return (NULL); 994 } 995 if (size < 0) { 996 ERRNO_SET(EINVAL); 997 return (NULL); 998 } 999 tmp += len; 1000 } 1001 if (size != 0) { 1002 ERRNO_SET(EINVAL); 1003 return (NULL); 1004 } 1005 1006 value = nv_calloc(nvp->nvp_nitems, sizeof(*value)); 1007 if (value == NULL) 1008 return (NULL); 1009 1010 for (ii = 0; ii < nvp->nvp_nitems; ii++) { 1011 value[ii] = nv_strdup((const char *)ptr); 1012 if (value[ii] == NULL) 1013 goto out; 1014 len = strlen(value[ii]) + 1; 1015 ptr += len; 1016 *leftp -= len; 1017 } 1018 nvp->nvp_data = (uint64_t)(uintptr_t)value; 1019 1020 return (ptr); 1021 out: 1022 for (j = 0; j < ii; j++) 1023 nv_free(value[j]); 1024 nv_free(value); 1025 return (NULL); 1026 } 1027 1028 #ifndef _KERNEL 1029 const unsigned char * 1030 nvpair_unpack_descriptor_array(bool isbe, nvpair_t *nvp, 1031 const unsigned char *ptr, size_t *leftp, const int *fds, size_t nfds) 1032 { 1033 int64_t idx; 1034 size_t size; 1035 unsigned int ii; 1036 int *array; 1037 1038 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR_ARRAY); 1039 1040 size = sizeof(idx) * nvp->nvp_nitems; 1041 if (nvp->nvp_datasize != size || *leftp < size || 1042 nvp->nvp_nitems == 0 || size < nvp->nvp_nitems) { 1043 ERRNO_SET(EINVAL); 1044 return (NULL); 1045 } 1046 1047 array = (int *)nv_malloc(size); 1048 if (array == NULL) 1049 return (NULL); 1050 1051 for (ii = 0; ii < nvp->nvp_nitems; ii++) { 1052 if (isbe) 1053 idx = be64dec(ptr); 1054 else 1055 idx = le64dec(ptr); 1056 1057 if (idx < 0) { 1058 ERRNO_SET(EINVAL); 1059 nv_free(array); 1060 return (NULL); 1061 } 1062 1063 if ((size_t)idx >= nfds) { 1064 ERRNO_SET(EINVAL); 1065 nv_free(array); 1066 return (NULL); 1067 } 1068 1069 array[ii] = (uint64_t)fds[idx]; 1070 1071 ptr += sizeof(idx); 1072 *leftp -= sizeof(idx); 1073 } 1074 1075 nvp->nvp_data = (uint64_t)(uintptr_t)array; 1076 1077 return (ptr); 1078 } 1079 #endif 1080 1081 const unsigned char * 1082 nvpair_unpack_nvlist_array(bool isbe __unused, nvpair_t *nvp, 1083 const unsigned char *ptr, size_t *leftp, nvlist_t **firstel) 1084 { 1085 nvlist_t **value; 1086 nvpair_t *tmpnvp; 1087 unsigned int ii, j; 1088 size_t sizeup; 1089 1090 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST_ARRAY); 1091 1092 sizeup = sizeof(struct nvpair_header) * nvp->nvp_nitems; 1093 if (nvp->nvp_nitems == 0 || sizeup < nvp->nvp_nitems || 1094 sizeup > *leftp) { 1095 ERRNO_SET(EINVAL); 1096 return (NULL); 1097 } 1098 1099 value = nv_calloc(nvp->nvp_nitems, sizeof(*value)); 1100 if (value == NULL) 1101 return (NULL); 1102 1103 for (ii = 0; ii < nvp->nvp_nitems; ii++) { 1104 value[ii] = nvlist_create(0); 1105 if (value[ii] == NULL) 1106 goto fail; 1107 if (ii > 0) { 1108 tmpnvp = nvpair_allocv(" ", NV_TYPE_NVLIST, 1109 (uint64_t)(uintptr_t)value[ii], 0, 0); 1110 if (tmpnvp == NULL) 1111 goto fail; 1112 nvlist_set_array_next(value[ii - 1], tmpnvp); 1113 } 1114 } 1115 nvlist_set_flags(value[nvp->nvp_nitems - 1], NV_FLAG_IN_ARRAY); 1116 1117 nvp->nvp_data = (uint64_t)(uintptr_t)value; 1118 *firstel = value[0]; 1119 1120 return (ptr); 1121 fail: 1122 ERRNO_SAVE(); 1123 for (j = 0; j <= ii; j++) 1124 nvlist_destroy(value[j]); 1125 nv_free(value); 1126 ERRNO_RESTORE(); 1127 1128 return (NULL); 1129 } 1130 1131 const unsigned char * 1132 nvpair_unpack(bool isbe, const unsigned char *ptr, size_t *leftp, 1133 nvpair_t **nvpp) 1134 { 1135 nvpair_t *nvp, *tmp; 1136 1137 nvp = nv_calloc(1, sizeof(*nvp) + NV_NAME_MAX); 1138 if (nvp == NULL) 1139 return (NULL); 1140 nvp->nvp_name = (char *)(nvp + 1); 1141 1142 ptr = nvpair_unpack_header(isbe, nvp, ptr, leftp); 1143 if (ptr == NULL) 1144 goto fail; 1145 tmp = nv_realloc(nvp, sizeof(*nvp) + strlen(nvp->nvp_name) + 1); 1146 if (tmp == NULL) 1147 goto fail; 1148 nvp = tmp; 1149 1150 /* Update nvp_name after realloc(). */ 1151 nvp->nvp_name = (char *)(nvp + 1); 1152 nvp->nvp_data = 0x00; 1153 nvp->nvp_magic = NVPAIR_MAGIC; 1154 *nvpp = nvp; 1155 return (ptr); 1156 fail: 1157 nv_free(nvp); 1158 return (NULL); 1159 } 1160 1161 int 1162 nvpair_type(const nvpair_t *nvp) 1163 { 1164 1165 NVPAIR_ASSERT(nvp); 1166 1167 return (nvp->nvp_type); 1168 } 1169 1170 const char * 1171 nvpair_name(const nvpair_t *nvp) 1172 { 1173 1174 NVPAIR_ASSERT(nvp); 1175 1176 return (nvp->nvp_name); 1177 } 1178 1179 nvpair_t * 1180 nvpair_create_stringf(const char *name, const char *valuefmt, ...) 1181 { 1182 va_list valueap; 1183 nvpair_t *nvp; 1184 1185 va_start(valueap, valuefmt); 1186 nvp = nvpair_create_stringv(name, valuefmt, valueap); 1187 va_end(valueap); 1188 1189 return (nvp); 1190 } 1191 1192 nvpair_t * 1193 nvpair_create_stringv(const char *name, const char *valuefmt, va_list valueap) 1194 { 1195 nvpair_t *nvp; 1196 char *str; 1197 int len; 1198 1199 len = nv_vasprintf(&str, valuefmt, valueap); 1200 if (len < 0) 1201 return (NULL); 1202 nvp = nvpair_create_string(name, str); 1203 nv_free(str); 1204 return (nvp); 1205 } 1206 1207 nvpair_t * 1208 nvpair_create_null(const char *name) 1209 { 1210 1211 return (nvpair_allocv(name, NV_TYPE_NULL, 0, 0, 0)); 1212 } 1213 1214 nvpair_t * 1215 nvpair_create_bool(const char *name, bool value) 1216 { 1217 1218 return (nvpair_allocv(name, NV_TYPE_BOOL, value ? 1 : 0, 1219 sizeof(uint8_t), 0)); 1220 } 1221 1222 nvpair_t * 1223 nvpair_create_number(const char *name, uint64_t value) 1224 { 1225 1226 return (nvpair_allocv(name, NV_TYPE_NUMBER, value, sizeof(value), 0)); 1227 } 1228 1229 nvpair_t * 1230 nvpair_create_string(const char *name, const char *value) 1231 { 1232 nvpair_t *nvp; 1233 size_t size; 1234 char *data; 1235 1236 if (value == NULL) { 1237 ERRNO_SET(EINVAL); 1238 return (NULL); 1239 } 1240 1241 data = nv_strdup(value); 1242 if (data == NULL) 1243 return (NULL); 1244 size = strlen(value) + 1; 1245 1246 nvp = nvpair_allocv(name, NV_TYPE_STRING, (uint64_t)(uintptr_t)data, 1247 size, 0); 1248 if (nvp == NULL) 1249 nv_free(data); 1250 1251 return (nvp); 1252 } 1253 1254 nvpair_t * 1255 nvpair_create_nvlist(const char *name, const nvlist_t *value) 1256 { 1257 nvlist_t *nvl; 1258 nvpair_t *nvp; 1259 1260 if (value == NULL) { 1261 ERRNO_SET(EINVAL); 1262 return (NULL); 1263 } 1264 1265 nvl = nvlist_clone(value); 1266 if (nvl == NULL) 1267 return (NULL); 1268 1269 nvp = nvpair_allocv(name, NV_TYPE_NVLIST, (uint64_t)(uintptr_t)nvl, 0, 1270 0); 1271 if (nvp == NULL) 1272 nvlist_destroy(nvl); 1273 else 1274 nvlist_set_parent(nvl, nvp); 1275 1276 return (nvp); 1277 } 1278 1279 #ifndef _KERNEL 1280 nvpair_t * 1281 nvpair_create_descriptor(const char *name, int value) 1282 { 1283 nvpair_t *nvp; 1284 1285 value = fcntl(value, F_DUPFD_CLOEXEC, 0); 1286 if (value < 0) 1287 return (NULL); 1288 1289 nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR, (uint64_t)value, 1290 sizeof(int64_t), 0); 1291 if (nvp == NULL) { 1292 ERRNO_SAVE(); 1293 close(value); 1294 ERRNO_RESTORE(); 1295 } 1296 1297 return (nvp); 1298 } 1299 #endif 1300 1301 nvpair_t * 1302 nvpair_create_binary(const char *name, const void *value, size_t size) 1303 { 1304 nvpair_t *nvp; 1305 void *data; 1306 1307 if (value == NULL || size == 0) { 1308 ERRNO_SET(EINVAL); 1309 return (NULL); 1310 } 1311 1312 data = nv_malloc(size); 1313 if (data == NULL) 1314 return (NULL); 1315 memcpy(data, value, size); 1316 1317 nvp = nvpair_allocv(name, NV_TYPE_BINARY, (uint64_t)(uintptr_t)data, 1318 size, 0); 1319 if (nvp == NULL) 1320 nv_free(data); 1321 1322 return (nvp); 1323 } 1324 1325 nvpair_t * 1326 nvpair_create_bool_array(const char *name, const bool *value, size_t nitems) 1327 { 1328 nvpair_t *nvp; 1329 size_t size; 1330 void *data; 1331 1332 if (value == NULL || nitems == 0) { 1333 ERRNO_SET(EINVAL); 1334 return (NULL); 1335 } 1336 1337 data = nv_calloc(nitems, sizeof(value[0])); 1338 if (data == NULL) 1339 return (NULL); 1340 size = sizeof(value[0]) * nitems; 1341 1342 memcpy(data, value, size); 1343 nvp = nvpair_allocv(name, NV_TYPE_BOOL_ARRAY, (uint64_t)(uintptr_t)data, 1344 size, nitems); 1345 if (nvp == NULL) { 1346 ERRNO_SAVE(); 1347 nv_free(data); 1348 ERRNO_RESTORE(); 1349 } 1350 1351 return (nvp); 1352 } 1353 1354 nvpair_t * 1355 nvpair_create_number_array(const char *name, const uint64_t *value, 1356 size_t nitems) 1357 { 1358 nvpair_t *nvp; 1359 size_t size; 1360 void *data; 1361 1362 if (value == NULL || nitems == 0) { 1363 ERRNO_SET(EINVAL); 1364 return (NULL); 1365 } 1366 1367 data = nv_calloc(nitems, sizeof(value[0])); 1368 if (data == NULL) 1369 return (NULL); 1370 size = sizeof(value[0]) * nitems; 1371 1372 memcpy(data, value, size); 1373 nvp = nvpair_allocv(name, NV_TYPE_NUMBER_ARRAY, 1374 (uint64_t)(uintptr_t)data, size, nitems); 1375 if (nvp == NULL) { 1376 ERRNO_SAVE(); 1377 nv_free(data); 1378 ERRNO_RESTORE(); 1379 } 1380 1381 return (nvp); 1382 } 1383 1384 nvpair_t * 1385 nvpair_create_string_array(const char *name, const char * const *value, 1386 size_t nitems) 1387 { 1388 nvpair_t *nvp; 1389 unsigned int ii; 1390 size_t datasize, size; 1391 char **data; 1392 1393 if (value == NULL || nitems == 0) { 1394 ERRNO_SET(EINVAL); 1395 return (NULL); 1396 } 1397 1398 nvp = NULL; 1399 datasize = 0; 1400 data = nv_calloc(nitems, sizeof(value[0])); 1401 if (data == NULL) 1402 return (NULL); 1403 1404 for (ii = 0; ii < nitems; ii++) { 1405 if (value[ii] == NULL) { 1406 ERRNO_SET(EINVAL); 1407 goto fail; 1408 } 1409 1410 size = strlen(value[ii]) + 1; 1411 datasize += size; 1412 data[ii] = nv_strdup(value[ii]); 1413 if (data[ii] == NULL) 1414 goto fail; 1415 } 1416 nvp = nvpair_allocv(name, NV_TYPE_STRING_ARRAY, 1417 (uint64_t)(uintptr_t)data, datasize, nitems); 1418 1419 fail: 1420 if (nvp == NULL) { 1421 ERRNO_SAVE(); 1422 for (; ii > 0; ii--) 1423 nv_free(data[ii - 1]); 1424 nv_free(data); 1425 ERRNO_RESTORE(); 1426 } 1427 1428 return (nvp); 1429 } 1430 1431 nvpair_t * 1432 nvpair_create_nvlist_array(const char *name, const nvlist_t * const *value, 1433 size_t nitems) 1434 { 1435 unsigned int ii; 1436 nvlist_t **nvls; 1437 nvpair_t *parent; 1438 int flags; 1439 1440 nvls = NULL; 1441 1442 if (value == NULL || nitems == 0) { 1443 ERRNO_SET(EINVAL); 1444 return (NULL); 1445 } 1446 1447 nvls = nv_calloc(nitems, sizeof(value[0])); 1448 if (nvls == NULL) 1449 return (NULL); 1450 1451 for (ii = 0; ii < nitems; ii++) { 1452 if (value[ii] == NULL) { 1453 ERRNO_SET(EINVAL); 1454 goto fail; 1455 } 1456 1457 nvls[ii] = nvlist_clone(value[ii]); 1458 if (nvls[ii] == NULL) 1459 goto fail; 1460 1461 if (ii > 0) { 1462 nvpair_t *nvp; 1463 1464 nvp = nvpair_allocv(" ", NV_TYPE_NVLIST, 1465 (uint64_t)(uintptr_t)nvls[ii], 0, 0); 1466 if (nvp == NULL) { 1467 ERRNO_SAVE(); 1468 nvlist_destroy(nvls[ii]); 1469 ERRNO_RESTORE(); 1470 goto fail; 1471 } 1472 nvlist_set_array_next(nvls[ii - 1], nvp); 1473 } 1474 } 1475 flags = nvlist_flags(nvls[nitems - 1]) | NV_FLAG_IN_ARRAY; 1476 nvlist_set_flags(nvls[nitems - 1], flags); 1477 1478 parent = nvpair_allocv(name, NV_TYPE_NVLIST_ARRAY, 1479 (uint64_t)(uintptr_t)nvls, 0, nitems); 1480 if (parent == NULL) 1481 goto fail; 1482 1483 for (ii = 0; ii < nitems; ii++) 1484 nvlist_set_parent(nvls[ii], parent); 1485 1486 return (parent); 1487 1488 fail: 1489 ERRNO_SAVE(); 1490 for (; ii > 0; ii--) 1491 nvlist_destroy(nvls[ii - 1]); 1492 nv_free(nvls); 1493 ERRNO_RESTORE(); 1494 1495 return (NULL); 1496 } 1497 1498 #ifndef _KERNEL 1499 nvpair_t * 1500 nvpair_create_descriptor_array(const char *name, const int *value, 1501 size_t nitems) 1502 { 1503 unsigned int ii; 1504 nvpair_t *nvp; 1505 int *fds; 1506 1507 if (value == NULL) { 1508 ERRNO_SET(EINVAL); 1509 return (NULL); 1510 } 1511 1512 nvp = NULL; 1513 1514 fds = nv_calloc(nitems, sizeof(value[0])); 1515 if (fds == NULL) 1516 return (NULL); 1517 for (ii = 0; ii < nitems; ii++) { 1518 if (value[ii] == -1) { 1519 fds[ii] = -1; 1520 } else { 1521 fds[ii] = fcntl(value[ii], F_DUPFD_CLOEXEC, 0); 1522 if (fds[ii] == -1) 1523 goto fail; 1524 } 1525 } 1526 1527 nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR_ARRAY, 1528 (uint64_t)(uintptr_t)fds, sizeof(int64_t) * nitems, nitems); 1529 1530 fail: 1531 if (nvp == NULL) { 1532 ERRNO_SAVE(); 1533 for (; ii > 0; ii--) { 1534 if (fds[ii - 1] != -1) 1535 close(fds[ii - 1]); 1536 } 1537 nv_free(fds); 1538 ERRNO_RESTORE(); 1539 } 1540 1541 return (nvp); 1542 } 1543 #endif 1544 1545 nvpair_t * 1546 nvpair_move_string(const char *name, char *value) 1547 { 1548 nvpair_t *nvp; 1549 1550 if (value == NULL) { 1551 ERRNO_SET(EINVAL); 1552 return (NULL); 1553 } 1554 1555 nvp = nvpair_allocv(name, NV_TYPE_STRING, (uint64_t)(uintptr_t)value, 1556 strlen(value) + 1, 0); 1557 if (nvp == NULL) { 1558 ERRNO_SAVE(); 1559 nv_free(value); 1560 ERRNO_RESTORE(); 1561 } 1562 1563 return (nvp); 1564 } 1565 1566 nvpair_t * 1567 nvpair_move_nvlist(const char *name, nvlist_t *value) 1568 { 1569 nvpair_t *nvp; 1570 1571 if (value == NULL || nvlist_get_nvpair_parent(value) != NULL) { 1572 ERRNO_SET(EINVAL); 1573 return (NULL); 1574 } 1575 1576 if (nvlist_error(value) != 0) { 1577 ERRNO_SET(nvlist_error(value)); 1578 nvlist_destroy(value); 1579 return (NULL); 1580 } 1581 1582 nvp = nvpair_allocv(name, NV_TYPE_NVLIST, (uint64_t)(uintptr_t)value, 1583 0, 0); 1584 if (nvp == NULL) 1585 nvlist_destroy(value); 1586 else 1587 nvlist_set_parent(value, nvp); 1588 1589 return (nvp); 1590 } 1591 1592 #ifndef _KERNEL 1593 nvpair_t * 1594 nvpair_move_descriptor(const char *name, int value) 1595 { 1596 nvpair_t *nvp; 1597 1598 if (value < 0 || !fd_is_valid(value)) { 1599 ERRNO_SET(EBADF); 1600 return (NULL); 1601 } 1602 1603 nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR, (uint64_t)value, 1604 sizeof(int64_t), 0); 1605 if (nvp == NULL) { 1606 ERRNO_SAVE(); 1607 close(value); 1608 ERRNO_RESTORE(); 1609 } 1610 1611 return (nvp); 1612 } 1613 #endif 1614 1615 nvpair_t * 1616 nvpair_move_binary(const char *name, void *value, size_t size) 1617 { 1618 nvpair_t *nvp; 1619 1620 if (value == NULL || size == 0) { 1621 ERRNO_SET(EINVAL); 1622 return (NULL); 1623 } 1624 1625 nvp = nvpair_allocv(name, NV_TYPE_BINARY, (uint64_t)(uintptr_t)value, 1626 size, 0); 1627 if (nvp == NULL) { 1628 ERRNO_SAVE(); 1629 nv_free(value); 1630 ERRNO_RESTORE(); 1631 } 1632 1633 return (nvp); 1634 } 1635 1636 nvpair_t * 1637 nvpair_move_bool_array(const char *name, bool *value, size_t nitems) 1638 { 1639 nvpair_t *nvp; 1640 1641 if (value == NULL || nitems == 0) { 1642 ERRNO_SET(EINVAL); 1643 return (NULL); 1644 } 1645 1646 nvp = nvpair_allocv(name, NV_TYPE_BOOL_ARRAY, 1647 (uint64_t)(uintptr_t)value, sizeof(value[0]) * nitems, nitems); 1648 if (nvp == NULL) { 1649 ERRNO_SAVE(); 1650 nv_free(value); 1651 ERRNO_RESTORE(); 1652 } 1653 1654 return (nvp); 1655 } 1656 1657 nvpair_t * 1658 nvpair_move_string_array(const char *name, char **value, size_t nitems) 1659 { 1660 nvpair_t *nvp; 1661 size_t i, size; 1662 1663 if (value == NULL || nitems == 0) { 1664 ERRNO_SET(EINVAL); 1665 return (NULL); 1666 } 1667 1668 size = 0; 1669 for (i = 0; i < nitems; i++) { 1670 if (value[i] == NULL) { 1671 ERRNO_SET(EINVAL); 1672 return (NULL); 1673 } 1674 1675 size += strlen(value[i]) + 1; 1676 } 1677 1678 nvp = nvpair_allocv(name, NV_TYPE_STRING_ARRAY, 1679 (uint64_t)(uintptr_t)value, size, nitems); 1680 if (nvp == NULL) { 1681 ERRNO_SAVE(); 1682 for (i = 0; i < nitems; i++) 1683 nv_free(value[i]); 1684 nv_free(value); 1685 ERRNO_RESTORE(); 1686 } 1687 1688 return (nvp); 1689 } 1690 1691 nvpair_t * 1692 nvpair_move_number_array(const char *name, uint64_t *value, size_t nitems) 1693 { 1694 nvpair_t *nvp; 1695 1696 if (value == NULL || nitems == 0) { 1697 ERRNO_SET(EINVAL); 1698 return (NULL); 1699 } 1700 1701 nvp = nvpair_allocv(name, NV_TYPE_NUMBER_ARRAY, 1702 (uint64_t)(uintptr_t)value, sizeof(value[0]) * nitems, nitems); 1703 if (nvp == NULL) { 1704 ERRNO_SAVE(); 1705 nv_free(value); 1706 ERRNO_RESTORE(); 1707 } 1708 1709 return (nvp); 1710 } 1711 1712 nvpair_t * 1713 nvpair_move_nvlist_array(const char *name, nvlist_t **value, size_t nitems) 1714 { 1715 nvpair_t *parent; 1716 unsigned int ii; 1717 int flags; 1718 1719 if (value == NULL || nitems == 0) { 1720 ERRNO_SET(EINVAL); 1721 return (NULL); 1722 } 1723 1724 for (ii = 0; ii < nitems; ii++) { 1725 if (value == NULL || nvlist_error(value[ii]) != 0 || 1726 nvlist_get_pararr(value[ii], NULL) != NULL) { 1727 ERRNO_SET(EINVAL); 1728 goto fail; 1729 } 1730 if (ii > 0) { 1731 nvpair_t *nvp; 1732 1733 nvp = nvpair_allocv(" ", NV_TYPE_NVLIST, 1734 (uint64_t)(uintptr_t)value[ii], 0, 0); 1735 if (nvp == NULL) 1736 goto fail; 1737 nvlist_set_array_next(value[ii - 1], nvp); 1738 } 1739 } 1740 flags = nvlist_flags(value[nitems - 1]) | NV_FLAG_IN_ARRAY; 1741 nvlist_set_flags(value[nitems - 1], flags); 1742 1743 parent = nvpair_allocv(name, NV_TYPE_NVLIST_ARRAY, 1744 (uint64_t)(uintptr_t)value, 0, nitems); 1745 if (parent == NULL) 1746 goto fail; 1747 1748 for (ii = 0; ii < nitems; ii++) 1749 nvlist_set_parent(value[ii], parent); 1750 1751 return (parent); 1752 fail: 1753 ERRNO_SAVE(); 1754 for (ii = 0; ii < nitems; ii++) { 1755 if (value[ii] != NULL && 1756 nvlist_get_pararr(value[ii], NULL) != NULL) { 1757 nvlist_destroy(value[ii]); 1758 } 1759 } 1760 nv_free(value); 1761 ERRNO_RESTORE(); 1762 1763 return (NULL); 1764 } 1765 1766 #ifndef _KERNEL 1767 nvpair_t * 1768 nvpair_move_descriptor_array(const char *name, int *value, size_t nitems) 1769 { 1770 nvpair_t *nvp; 1771 size_t i; 1772 1773 if (value == NULL || nitems == 0) { 1774 ERRNO_SET(EINVAL); 1775 return (NULL); 1776 } 1777 1778 for (i = 0; i < nitems; i++) { 1779 if (value[i] != -1 && !fd_is_valid(value[i])) { 1780 ERRNO_SET(EBADF); 1781 goto fail; 1782 } 1783 } 1784 1785 nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR_ARRAY, 1786 (uint64_t)(uintptr_t)value, sizeof(value[0]) * nitems, nitems); 1787 if (nvp == NULL) 1788 goto fail; 1789 1790 return (nvp); 1791 fail: 1792 ERRNO_SAVE(); 1793 for (i = 0; i < nitems; i++) { 1794 if (fd_is_valid(value[i])) 1795 close(value[i]); 1796 } 1797 nv_free(value); 1798 ERRNO_RESTORE(); 1799 1800 return (NULL); 1801 } 1802 #endif 1803 1804 bool 1805 nvpair_get_bool(const nvpair_t *nvp) 1806 { 1807 1808 NVPAIR_ASSERT(nvp); 1809 1810 return (nvp->nvp_data == 1); 1811 } 1812 1813 uint64_t 1814 nvpair_get_number(const nvpair_t *nvp) 1815 { 1816 1817 NVPAIR_ASSERT(nvp); 1818 1819 return (nvp->nvp_data); 1820 } 1821 1822 const char * 1823 nvpair_get_string(const nvpair_t *nvp) 1824 { 1825 1826 NVPAIR_ASSERT(nvp); 1827 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING); 1828 1829 return ((const char *)(intptr_t)nvp->nvp_data); 1830 } 1831 1832 const nvlist_t * 1833 nvpair_get_nvlist(const nvpair_t *nvp) 1834 { 1835 1836 NVPAIR_ASSERT(nvp); 1837 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST); 1838 1839 return ((const nvlist_t *)(intptr_t)nvp->nvp_data); 1840 } 1841 1842 #ifndef _KERNEL 1843 int 1844 nvpair_get_descriptor(const nvpair_t *nvp) 1845 { 1846 1847 NVPAIR_ASSERT(nvp); 1848 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR); 1849 1850 return ((int)nvp->nvp_data); 1851 } 1852 #endif 1853 1854 const void * 1855 nvpair_get_binary(const nvpair_t *nvp, size_t *sizep) 1856 { 1857 1858 NVPAIR_ASSERT(nvp); 1859 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY); 1860 1861 if (sizep != NULL) 1862 *sizep = nvp->nvp_datasize; 1863 1864 return ((const void *)(intptr_t)nvp->nvp_data); 1865 } 1866 1867 const bool * 1868 nvpair_get_bool_array(const nvpair_t *nvp, size_t *nitems) 1869 { 1870 1871 NVPAIR_ASSERT(nvp); 1872 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL_ARRAY); 1873 1874 if (nitems != NULL) 1875 *nitems = nvp->nvp_nitems; 1876 1877 return ((const bool *)(intptr_t)nvp->nvp_data); 1878 } 1879 1880 const uint64_t * 1881 nvpair_get_number_array(const nvpair_t *nvp, size_t *nitems) 1882 { 1883 1884 NVPAIR_ASSERT(nvp); 1885 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER_ARRAY); 1886 1887 if (nitems != NULL) 1888 *nitems = nvp->nvp_nitems; 1889 1890 return ((const uint64_t *)(intptr_t)nvp->nvp_data); 1891 } 1892 1893 const char * const * 1894 nvpair_get_string_array(const nvpair_t *nvp, size_t *nitems) 1895 { 1896 1897 NVPAIR_ASSERT(nvp); 1898 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING_ARRAY); 1899 1900 if (nitems != NULL) 1901 *nitems = nvp->nvp_nitems; 1902 1903 return ((const char * const *)(intptr_t)nvp->nvp_data); 1904 } 1905 1906 const nvlist_t * const * 1907 nvpair_get_nvlist_array(const nvpair_t *nvp, size_t *nitems) 1908 { 1909 1910 NVPAIR_ASSERT(nvp); 1911 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST_ARRAY); 1912 1913 if (nitems != NULL) 1914 *nitems = nvp->nvp_nitems; 1915 1916 return ((const nvlist_t * const *)((intptr_t)nvp->nvp_data)); 1917 } 1918 1919 #ifndef _KERNEL 1920 const int * 1921 nvpair_get_descriptor_array(const nvpair_t *nvp, size_t *nitems) 1922 { 1923 1924 NVPAIR_ASSERT(nvp); 1925 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR_ARRAY); 1926 1927 if (nitems != NULL) 1928 *nitems = nvp->nvp_nitems; 1929 1930 return ((const int *)(intptr_t)nvp->nvp_data); 1931 } 1932 #endif 1933 1934 int 1935 nvpair_append_bool_array(nvpair_t *nvp, const bool value) 1936 { 1937 1938 NVPAIR_ASSERT(nvp); 1939 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL_ARRAY); 1940 return (nvpair_append(nvp, &value, sizeof(value), sizeof(value))); 1941 } 1942 1943 int 1944 nvpair_append_number_array(nvpair_t *nvp, const uint64_t value) 1945 { 1946 1947 NVPAIR_ASSERT(nvp); 1948 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER_ARRAY); 1949 return (nvpair_append(nvp, &value, sizeof(value), sizeof(value))); 1950 } 1951 1952 int 1953 nvpair_append_string_array(nvpair_t *nvp, const char *value) 1954 { 1955 char *str; 1956 1957 NVPAIR_ASSERT(nvp); 1958 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING_ARRAY); 1959 if (value == NULL) { 1960 ERRNO_SET(EINVAL); 1961 return (-1); 1962 } 1963 str = nv_strdup(value); 1964 if (str == NULL) { 1965 return (-1); 1966 } 1967 if (nvpair_append(nvp, &str, sizeof(str), strlen(str) + 1) == -1) { 1968 nv_free(str); 1969 return (-1); 1970 } 1971 return (0); 1972 } 1973 1974 int 1975 nvpair_append_nvlist_array(nvpair_t *nvp, const nvlist_t *value) 1976 { 1977 nvpair_t *tmpnvp; 1978 nvlist_t *nvl, *prev; 1979 int flags; 1980 1981 NVPAIR_ASSERT(nvp); 1982 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST_ARRAY); 1983 if (value == NULL || nvlist_error(value) != 0 || 1984 nvlist_get_pararr(value, NULL) != NULL) { 1985 ERRNO_SET(EINVAL); 1986 return (-1); 1987 } 1988 nvl = nvlist_clone(value); 1989 if (nvl == NULL) { 1990 return (-1); 1991 } 1992 flags = nvlist_flags(nvl) | NV_FLAG_IN_ARRAY; 1993 nvlist_set_flags(nvl, flags); 1994 1995 tmpnvp = NULL; 1996 prev = NULL; 1997 if (nvp->nvp_nitems > 0) { 1998 nvlist_t **nvls = (void *)(uintptr_t)nvp->nvp_data; 1999 2000 prev = nvls[nvp->nvp_nitems - 1]; 2001 PJDLOG_ASSERT(prev != NULL); 2002 2003 tmpnvp = nvpair_allocv(" ", NV_TYPE_NVLIST, 2004 (uint64_t)(uintptr_t)nvl, 0, 0); 2005 if (tmpnvp == NULL) { 2006 goto fail; 2007 } 2008 } 2009 if (nvpair_append(nvp, &nvl, sizeof(nvl), 0) == -1) { 2010 goto fail; 2011 } 2012 if (tmpnvp) { 2013 NVPAIR_ASSERT(tmpnvp); 2014 nvlist_set_array_next(prev, tmpnvp); 2015 } 2016 nvlist_set_parent(nvl, nvp); 2017 return (0); 2018 fail: 2019 if (tmpnvp) { 2020 nvpair_free(tmpnvp); 2021 } 2022 nvlist_destroy(nvl); 2023 return (-1); 2024 } 2025 2026 #ifndef _KERNEL 2027 int 2028 nvpair_append_descriptor_array(nvpair_t *nvp, const int value) 2029 { 2030 int fd; 2031 2032 NVPAIR_ASSERT(nvp); 2033 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR_ARRAY); 2034 fd = fcntl(value, F_DUPFD_CLOEXEC, 0); 2035 if (fd == -1) { 2036 return (-1); 2037 } 2038 if (nvpair_append(nvp, &fd, sizeof(fd), sizeof(fd)) == -1) { 2039 close(fd); 2040 return (-1); 2041 } 2042 return (0); 2043 } 2044 #endif 2045 2046 void 2047 nvpair_free(nvpair_t *nvp) 2048 { 2049 size_t i; 2050 2051 NVPAIR_ASSERT(nvp); 2052 PJDLOG_ASSERT(nvp->nvp_list == NULL); 2053 2054 nvp->nvp_magic = 0; 2055 switch (nvp->nvp_type) { 2056 #ifndef _KERNEL 2057 case NV_TYPE_DESCRIPTOR: 2058 close((int)nvp->nvp_data); 2059 break; 2060 case NV_TYPE_DESCRIPTOR_ARRAY: 2061 for (i = 0; i < nvp->nvp_nitems; i++) 2062 close(((int *)(intptr_t)nvp->nvp_data)[i]); 2063 nv_free((int *)(intptr_t)nvp->nvp_data); 2064 break; 2065 #endif 2066 case NV_TYPE_NVLIST: 2067 nvlist_destroy((nvlist_t *)(intptr_t)nvp->nvp_data); 2068 break; 2069 case NV_TYPE_STRING: 2070 nv_free((char *)(intptr_t)nvp->nvp_data); 2071 break; 2072 case NV_TYPE_BINARY: 2073 nv_free((void *)(intptr_t)nvp->nvp_data); 2074 break; 2075 case NV_TYPE_NVLIST_ARRAY: 2076 for (i = 0; i < nvp->nvp_nitems; i++) { 2077 nvlist_destroy( 2078 ((nvlist_t **)(intptr_t)nvp->nvp_data)[i]); 2079 } 2080 nv_free(((nvlist_t **)(intptr_t)nvp->nvp_data)); 2081 break; 2082 case NV_TYPE_NUMBER_ARRAY: 2083 nv_free((uint64_t *)(intptr_t)nvp->nvp_data); 2084 break; 2085 case NV_TYPE_BOOL_ARRAY: 2086 nv_free((bool *)(intptr_t)nvp->nvp_data); 2087 break; 2088 case NV_TYPE_STRING_ARRAY: 2089 for (i = 0; i < nvp->nvp_nitems; i++) 2090 nv_free(((char **)(intptr_t)nvp->nvp_data)[i]); 2091 nv_free((char **)(intptr_t)nvp->nvp_data); 2092 break; 2093 } 2094 nv_free(nvp); 2095 } 2096 2097 void 2098 nvpair_free_structure(nvpair_t *nvp) 2099 { 2100 2101 NVPAIR_ASSERT(nvp); 2102 PJDLOG_ASSERT(nvp->nvp_list == NULL); 2103 2104 nvp->nvp_magic = 0; 2105 nv_free(nvp); 2106 } 2107 2108 const char * 2109 nvpair_type_string(int type) 2110 { 2111 2112 switch (type) { 2113 case NV_TYPE_NULL: 2114 return ("NULL"); 2115 case NV_TYPE_BOOL: 2116 return ("BOOL"); 2117 case NV_TYPE_NUMBER: 2118 return ("NUMBER"); 2119 case NV_TYPE_STRING: 2120 return ("STRING"); 2121 case NV_TYPE_NVLIST: 2122 return ("NVLIST"); 2123 case NV_TYPE_DESCRIPTOR: 2124 return ("DESCRIPTOR"); 2125 case NV_TYPE_BINARY: 2126 return ("BINARY"); 2127 case NV_TYPE_BOOL_ARRAY: 2128 return ("BOOL ARRAY"); 2129 case NV_TYPE_NUMBER_ARRAY: 2130 return ("NUMBER ARRAY"); 2131 case NV_TYPE_STRING_ARRAY: 2132 return ("STRING ARRAY"); 2133 case NV_TYPE_NVLIST_ARRAY: 2134 return ("NVLIST ARRAY"); 2135 case NV_TYPE_DESCRIPTOR_ARRAY: 2136 return ("DESCRIPTOR ARRAY"); 2137 default: 2138 return ("<UNKNOWN>"); 2139 } 2140 } 2141 2142