subr_nvpair.c revision 258065
1/*- 2 * Copyright (c) 2009-2013 The FreeBSD Foundation 3 * All rights reserved. 4 * 5 * This software was developed by Pawel Jakub Dawidek under sponsorship from 6 * the FreeBSD Foundation. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30#include <sys/cdefs.h> 31__FBSDID("$FreeBSD: head/lib/libnv/nvpair.c 258065 2013-11-12 19:39:14Z pjd $"); 32 33#include <sys/param.h> 34#include <sys/endian.h> 35#include <sys/queue.h> 36 37#include <errno.h> 38#include <fcntl.h> 39#include <stdarg.h> 40#include <stdbool.h> 41#include <stdint.h> 42#include <stdlib.h> 43#include <string.h> 44#include <unistd.h> 45 46#ifdef HAVE_PJDLOG 47#include <pjdlog.h> 48#endif 49 50#include "common_impl.h" 51#include "nv.h" 52#include "nv_impl.h" 53#include "nvlist_impl.h" 54#include "nvpair_impl.h" 55 56#ifndef HAVE_PJDLOG 57#include <assert.h> 58#define PJDLOG_ASSERT(...) assert(__VA_ARGS__) 59#define PJDLOG_RASSERT(expr, ...) assert(expr) 60#define PJDLOG_ABORT(...) abort() 61#endif 62 63#define NVPAIR_MAGIC 0x6e7670 /* "nvp" */ 64struct nvpair { 65 int nvp_magic; 66 char *nvp_name; 67 int nvp_type; 68 uint64_t nvp_data; 69 size_t nvp_datasize; 70 nvlist_t *nvp_list; /* Used for sanity checks. */ 71 TAILQ_ENTRY(nvpair) nvp_next; 72}; 73 74#define NVPAIR_ASSERT(nvp) do { \ 75 PJDLOG_ASSERT((nvp) != NULL); \ 76 PJDLOG_ASSERT((nvp)->nvp_magic == NVPAIR_MAGIC); \ 77} while (0) 78 79struct nvpair_header { 80 uint8_t nvph_type; 81 uint16_t nvph_namesize; 82 uint64_t nvph_datasize; 83} __packed; 84 85 86void 87nvpair_assert(const nvpair_t *nvp) 88{ 89 90 NVPAIR_ASSERT(nvp); 91} 92 93const nvlist_t * 94nvpair_nvlist(const nvpair_t *nvp) 95{ 96 97 NVPAIR_ASSERT(nvp); 98 99 return (nvp->nvp_list); 100} 101 102nvpair_t * 103nvpair_next(const nvpair_t *nvp) 104{ 105 106 NVPAIR_ASSERT(nvp); 107 PJDLOG_ASSERT(nvp->nvp_list != NULL); 108 109 return (TAILQ_NEXT(nvp, nvp_next)); 110} 111 112nvpair_t * 113nvpair_prev(const nvpair_t *nvp) 114{ 115 116 NVPAIR_ASSERT(nvp); 117 PJDLOG_ASSERT(nvp->nvp_list != NULL); 118 119 return (TAILQ_PREV(nvp, nvl_head, nvp_next)); 120} 121 122void 123nvpair_insert(struct nvl_head *head, nvpair_t *nvp, nvlist_t *nvl) 124{ 125 126 NVPAIR_ASSERT(nvp); 127 PJDLOG_ASSERT(nvp->nvp_list == NULL); 128 PJDLOG_ASSERT(!nvlist_exists(nvl, nvpair_name(nvp))); 129 130 TAILQ_INSERT_TAIL(head, nvp, nvp_next); 131 nvp->nvp_list = nvl; 132} 133 134void 135nvpair_remove(struct nvl_head *head, nvpair_t *nvp, const nvlist_t *nvl) 136{ 137 138 NVPAIR_ASSERT(nvp); 139 PJDLOG_ASSERT(nvp->nvp_list == nvl); 140 141 TAILQ_REMOVE(head, nvp, nvp_next); 142 nvp->nvp_list = NULL; 143} 144 145nvpair_t * 146nvpair_clone(const nvpair_t *nvp) 147{ 148 nvpair_t *newnvp; 149 const char *name; 150 const void *data; 151 size_t datasize; 152 153 NVPAIR_ASSERT(nvp); 154 155 name = nvpair_name(nvp); 156 157 switch (nvpair_type(nvp)) { 158 case NV_TYPE_NULL: 159 newnvp = nvpair_create_null(name); 160 break; 161 case NV_TYPE_BOOL: 162 newnvp = nvpair_create_bool(name, nvpair_get_bool(nvp)); 163 break; 164 case NV_TYPE_NUMBER: 165 newnvp = nvpair_create_number(name, nvpair_get_number(nvp)); 166 break; 167 case NV_TYPE_STRING: 168 newnvp = nvpair_create_string(name, nvpair_get_string(nvp)); 169 break; 170 case NV_TYPE_NVLIST: 171 newnvp = nvpair_create_nvlist(name, nvpair_get_nvlist(nvp)); 172 break; 173 case NV_TYPE_DESCRIPTOR: 174 newnvp = nvpair_create_descriptor(name, 175 nvpair_get_descriptor(nvp)); 176 break; 177 case NV_TYPE_BINARY: 178 data = nvpair_get_binary(nvp, &datasize); 179 newnvp = nvpair_create_binary(name, data, datasize); 180 break; 181 default: 182 PJDLOG_ABORT("Unknown type: %d.", nvpair_type(nvp)); 183 } 184 185 return (newnvp); 186} 187 188size_t 189nvpair_header_size(void) 190{ 191 192 return (sizeof(struct nvpair_header)); 193} 194 195size_t 196nvpair_size(const nvpair_t *nvp) 197{ 198 199 NVPAIR_ASSERT(nvp); 200 201 return (nvp->nvp_datasize); 202} 203 204static unsigned char * 205nvpair_pack_header(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp) 206{ 207 struct nvpair_header nvphdr; 208 size_t namesize; 209 210 NVPAIR_ASSERT(nvp); 211 212 nvphdr.nvph_type = nvp->nvp_type; 213 namesize = strlen(nvp->nvp_name) + 1; 214 PJDLOG_ASSERT(namesize > 0 && namesize <= UINT16_MAX); 215 nvphdr.nvph_namesize = namesize; 216 nvphdr.nvph_datasize = nvp->nvp_datasize; 217 PJDLOG_ASSERT(*leftp >= sizeof(nvphdr)); 218 memcpy(ptr, &nvphdr, sizeof(nvphdr)); 219 ptr += sizeof(nvphdr); 220 *leftp -= sizeof(nvphdr); 221 222 PJDLOG_ASSERT(*leftp >= namesize); 223 memcpy(ptr, nvp->nvp_name, namesize); 224 ptr += namesize; 225 *leftp -= namesize; 226 227 return (ptr); 228} 229 230static unsigned char * 231nvpair_pack_null(const nvpair_t *nvp, unsigned char *ptr, 232 size_t *leftp __unused) 233{ 234 235 NVPAIR_ASSERT(nvp); 236 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NULL); 237 238 return (ptr); 239} 240 241static unsigned char * 242nvpair_pack_bool(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp) 243{ 244 uint8_t value; 245 246 NVPAIR_ASSERT(nvp); 247 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL); 248 249 value = (uint8_t)nvp->nvp_data; 250 251 PJDLOG_ASSERT(*leftp >= sizeof(value)); 252 memcpy(ptr, &value, sizeof(value)); 253 ptr += sizeof(value); 254 *leftp -= sizeof(value); 255 256 return (ptr); 257} 258 259static unsigned char * 260nvpair_pack_number(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp) 261{ 262 uint64_t value; 263 264 NVPAIR_ASSERT(nvp); 265 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER); 266 267 value = (uint64_t)nvp->nvp_data; 268 269 PJDLOG_ASSERT(*leftp >= sizeof(value)); 270 memcpy(ptr, &value, sizeof(value)); 271 ptr += sizeof(value); 272 *leftp -= sizeof(value); 273 274 return (ptr); 275} 276 277static unsigned char * 278nvpair_pack_string(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp) 279{ 280 281 NVPAIR_ASSERT(nvp); 282 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING); 283 284 PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize); 285 memcpy(ptr, (const void *)(intptr_t)nvp->nvp_data, nvp->nvp_datasize); 286 ptr += nvp->nvp_datasize; 287 *leftp -= nvp->nvp_datasize; 288 289 return (ptr); 290} 291 292static unsigned char * 293nvpair_pack_nvlist(const nvpair_t *nvp, unsigned char *ptr, int64_t *fdidxp, 294 size_t *leftp) 295{ 296 unsigned char *data; 297 size_t size; 298 299 NVPAIR_ASSERT(nvp); 300 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST); 301 302 if (nvp->nvp_datasize == 0) 303 return (ptr); 304 305 data = nvlist_xpack((const nvlist_t *)(intptr_t)nvp->nvp_data, fdidxp, 306 &size); 307 if (data == NULL) 308 return (NULL); 309 310 PJDLOG_ASSERT(size == nvp->nvp_datasize); 311 PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize); 312 313 memcpy(ptr, data, nvp->nvp_datasize); 314 free(data); 315 316 ptr += nvp->nvp_datasize; 317 *leftp -= nvp->nvp_datasize; 318 319 return (ptr); 320} 321 322static unsigned char * 323nvpair_pack_descriptor(const nvpair_t *nvp, unsigned char *ptr, int64_t *fdidxp, 324 size_t *leftp) 325{ 326 int64_t value; 327 328 NVPAIR_ASSERT(nvp); 329 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR); 330 331 value = (int64_t)nvp->nvp_data; 332 if (value != -1) { 333 /* 334 * If there is a real descriptor here, we change its number 335 * to position in the array of descriptors send via control 336 * message. 337 */ 338 PJDLOG_ASSERT(fdidxp != NULL); 339 340 value = *fdidxp; 341 (*fdidxp)++; 342 } 343 344 PJDLOG_ASSERT(*leftp >= sizeof(value)); 345 memcpy(ptr, &value, sizeof(value)); 346 ptr += sizeof(value); 347 *leftp -= sizeof(value); 348 349 return (ptr); 350} 351 352static unsigned char * 353nvpair_pack_binary(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp) 354{ 355 356 NVPAIR_ASSERT(nvp); 357 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY); 358 359 PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize); 360 memcpy(ptr, (const void *)(intptr_t)nvp->nvp_data, nvp->nvp_datasize); 361 ptr += nvp->nvp_datasize; 362 *leftp -= nvp->nvp_datasize; 363 364 return (ptr); 365} 366 367unsigned char * 368nvpair_pack(nvpair_t *nvp, unsigned char *ptr, int64_t *fdidxp, size_t *leftp) 369{ 370 371 NVPAIR_ASSERT(nvp); 372 373 /* 374 * We have to update datasize for NV_TYPE_NVLIST on every pack, 375 * so that proper datasize is placed into nvpair_header 376 * during the nvpair_pack_header() call below. 377 */ 378 if (nvp->nvp_type == NV_TYPE_NVLIST) { 379 if (nvp->nvp_data == 0) { 380 nvp->nvp_datasize = 0; 381 } else { 382 nvp->nvp_datasize = 383 nvlist_size((const nvlist_t *)(intptr_t)nvp->nvp_data); 384 } 385 } 386 387 ptr = nvpair_pack_header(nvp, ptr, leftp); 388 if (ptr == NULL) 389 return (NULL); 390 391 switch (nvp->nvp_type) { 392 case NV_TYPE_NULL: 393 ptr = nvpair_pack_null(nvp, ptr, leftp); 394 break; 395 case NV_TYPE_BOOL: 396 ptr = nvpair_pack_bool(nvp, ptr, leftp); 397 break; 398 case NV_TYPE_NUMBER: 399 ptr = nvpair_pack_number(nvp, ptr, leftp); 400 break; 401 case NV_TYPE_STRING: 402 ptr = nvpair_pack_string(nvp, ptr, leftp); 403 break; 404 case NV_TYPE_NVLIST: 405 ptr = nvpair_pack_nvlist(nvp, ptr, fdidxp, leftp); 406 break; 407 case NV_TYPE_DESCRIPTOR: 408 ptr = nvpair_pack_descriptor(nvp, ptr, fdidxp, leftp); 409 break; 410 case NV_TYPE_BINARY: 411 ptr = nvpair_pack_binary(nvp, ptr, leftp); 412 break; 413 default: 414 PJDLOG_ABORT("Invalid type (%d).", nvp->nvp_type); 415 } 416 417 return (ptr); 418} 419 420static const unsigned char * 421nvpair_unpack_header(int flags, nvpair_t *nvp, const unsigned char *ptr, 422 size_t *leftp) 423{ 424 struct nvpair_header nvphdr; 425 426 if (*leftp < sizeof(nvphdr)) 427 goto failed; 428 429 memcpy(&nvphdr, ptr, sizeof(nvphdr)); 430 ptr += sizeof(nvphdr); 431 *leftp -= sizeof(nvphdr); 432 433#if NV_TYPE_FIRST > 0 434 if (nvphdr.nvph_type < NV_TYPE_FIRST) 435 goto failed; 436#endif 437 if (nvphdr.nvph_type > NV_TYPE_LAST) 438 goto failed; 439 440#if BYTE_ORDER == BIG_ENDIAN 441 if ((flags & NV_FLAG_BIG_ENDIAN) == 0) { 442 nvphdr.nvph_namesize = le16toh(nvphdr.nvph_namesize); 443 nvphdr.nvph_datasize = le64toh(nvphdr.nvph_datasize); 444 } 445#else 446 if ((flags & NV_FLAG_BIG_ENDIAN) != 0) { 447 nvphdr.nvph_namesize = be16toh(nvphdr.nvph_namesize); 448 nvphdr.nvph_datasize = be64toh(nvphdr.nvph_datasize); 449 } 450#endif 451 452 if (nvphdr.nvph_namesize > NV_NAME_MAX) 453 goto failed; 454 if (*leftp < nvphdr.nvph_namesize) 455 goto failed; 456 if (nvphdr.nvph_namesize < 1) 457 goto failed; 458 if (strnlen((const char *)ptr, nvphdr.nvph_namesize) != 459 (size_t)(nvphdr.nvph_namesize - 1)) { 460 goto failed; 461 } 462 463 memcpy(nvp->nvp_name, ptr, nvphdr.nvph_namesize); 464 ptr += nvphdr.nvph_namesize; 465 *leftp -= nvphdr.nvph_namesize; 466 467 if (*leftp < nvphdr.nvph_datasize) 468 goto failed; 469 470 nvp->nvp_type = nvphdr.nvph_type; 471 nvp->nvp_data = 0; 472 nvp->nvp_datasize = nvphdr.nvph_datasize; 473 474 return (ptr); 475failed: 476 errno = EINVAL; 477 return (NULL); 478} 479 480static const unsigned char * 481nvpair_unpack_null(int flags __unused, nvpair_t *nvp, const unsigned char *ptr, 482 size_t *leftp __unused) 483{ 484 485 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NULL); 486 487 if (nvp->nvp_datasize != 0) { 488 errno = EINVAL; 489 return (NULL); 490 } 491 492 return (ptr); 493} 494 495static const unsigned char * 496nvpair_unpack_bool(int flags __unused, nvpair_t *nvp, const unsigned char *ptr, 497 size_t *leftp) 498{ 499 uint8_t value; 500 501 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL); 502 503 if (nvp->nvp_datasize != sizeof(value)) { 504 errno = EINVAL; 505 return (NULL); 506 } 507 if (*leftp < sizeof(value)) { 508 errno = EINVAL; 509 return (NULL); 510 } 511 512 memcpy(&value, ptr, sizeof(value)); 513 ptr += sizeof(value); 514 *leftp -= sizeof(value); 515 516 if (value != 0 && value != 1) { 517 errno = EINVAL; 518 return (NULL); 519 } 520 521 nvp->nvp_data = (uint64_t)value; 522 523 return (ptr); 524} 525 526static const unsigned char * 527nvpair_unpack_number(int flags, nvpair_t *nvp, const unsigned char *ptr, 528 size_t *leftp) 529{ 530 531 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER); 532 533 if (nvp->nvp_datasize != sizeof(uint64_t)) { 534 errno = EINVAL; 535 return (NULL); 536 } 537 if (*leftp < sizeof(uint64_t)) { 538 errno = EINVAL; 539 return (NULL); 540 } 541 542 if ((flags & NV_FLAG_BIG_ENDIAN) != 0) 543 nvp->nvp_data = be64dec(ptr); 544 else 545 nvp->nvp_data = le64dec(ptr); 546 ptr += sizeof(uint64_t); 547 *leftp -= sizeof(uint64_t); 548 549 return (ptr); 550} 551 552static const unsigned char * 553nvpair_unpack_string(int flags __unused, nvpair_t *nvp, 554 const unsigned char *ptr, size_t *leftp) 555{ 556 557 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING); 558 559 if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) { 560 errno = EINVAL; 561 return (NULL); 562 } 563 564 if (strnlen((const char *)ptr, nvp->nvp_datasize) != 565 nvp->nvp_datasize - 1) { 566 errno = EINVAL; 567 return (NULL); 568 } 569 570 nvp->nvp_data = (uint64_t)(uintptr_t)strdup((const char *)ptr); 571 if (nvp->nvp_data == 0) 572 return (NULL); 573 574 ptr += nvp->nvp_datasize; 575 *leftp -= nvp->nvp_datasize; 576 577 return (ptr); 578} 579 580static const unsigned char * 581nvpair_unpack_nvlist(int flags __unused, nvpair_t *nvp, 582 const unsigned char *ptr, size_t *leftp, const int *fds, size_t nfds) 583{ 584 nvlist_t *value; 585 586 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST); 587 588 if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) { 589 errno = EINVAL; 590 return (NULL); 591 } 592 593 value = nvlist_xunpack(ptr, nvp->nvp_datasize, fds, nfds); 594 if (value == NULL) 595 return (NULL); 596 597 nvp->nvp_data = (uint64_t)(uintptr_t)value; 598 599 ptr += nvp->nvp_datasize; 600 *leftp -= nvp->nvp_datasize; 601 602 return (ptr); 603} 604 605static const unsigned char * 606nvpair_unpack_descriptor(int flags, nvpair_t *nvp, const unsigned char *ptr, 607 size_t *leftp, const int *fds, size_t nfds) 608{ 609 int64_t idx; 610 611 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR); 612 613 if (nvp->nvp_datasize != sizeof(idx)) { 614 errno = EINVAL; 615 return (NULL); 616 } 617 if (*leftp < sizeof(idx)) { 618 errno = EINVAL; 619 return (NULL); 620 } 621 622 if ((flags & NV_FLAG_BIG_ENDIAN) != 0) 623 idx = be64dec(ptr); 624 else 625 idx = le64dec(ptr); 626 627 if (idx < 0) { 628 errno = EINVAL; 629 return (NULL); 630 } 631 632 if ((size_t)idx >= nfds) { 633 errno = EINVAL; 634 return (NULL); 635 } 636 637 nvp->nvp_data = (uint64_t)fds[idx]; 638 639 ptr += sizeof(idx); 640 *leftp -= sizeof(idx); 641 642 return (ptr); 643} 644 645static const unsigned char * 646nvpair_unpack_binary(int flags __unused, nvpair_t *nvp, 647 const unsigned char *ptr, size_t *leftp) 648{ 649 void *value; 650 651 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY); 652 653 if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) { 654 errno = EINVAL; 655 return (NULL); 656 } 657 658 value = malloc(nvp->nvp_datasize); 659 if (value == NULL) 660 return (NULL); 661 662 memcpy(value, ptr, nvp->nvp_datasize); 663 ptr += nvp->nvp_datasize; 664 *leftp -= nvp->nvp_datasize; 665 666 nvp->nvp_data = (uint64_t)(uintptr_t)value; 667 668 return (ptr); 669} 670 671const unsigned char * 672nvpair_unpack(int flags, const unsigned char *ptr, size_t *leftp, 673 const int *fds, size_t nfds, nvpair_t **nvpp) 674{ 675 nvpair_t *nvp, *tmp; 676 677 nvp = calloc(1, sizeof(*nvp) + NV_NAME_MAX); 678 if (nvp == NULL) 679 return (NULL); 680 nvp->nvp_name = (char *)(nvp + 1); 681 682 ptr = nvpair_unpack_header(flags, nvp, ptr, leftp); 683 if (ptr == NULL) 684 goto failed; 685 tmp = realloc(nvp, sizeof(*nvp) + strlen(nvp->nvp_name) + 1); 686 if (tmp == NULL) { 687 free(nvp); 688 goto failed; 689 } 690 nvp = tmp; 691 /* Update nvp_name after realloc(). */ 692 nvp->nvp_name = (char *)(nvp + 1); 693 694 switch (nvp->nvp_type) { 695 case NV_TYPE_NULL: 696 ptr = nvpair_unpack_null(flags, nvp, ptr, leftp); 697 break; 698 case NV_TYPE_BOOL: 699 ptr = nvpair_unpack_bool(flags, nvp, ptr, leftp); 700 break; 701 case NV_TYPE_NUMBER: 702 ptr = nvpair_unpack_number(flags, nvp, ptr, leftp); 703 break; 704 case NV_TYPE_STRING: 705 ptr = nvpair_unpack_string(flags, nvp, ptr, leftp); 706 break; 707 case NV_TYPE_NVLIST: 708 ptr = nvpair_unpack_nvlist(flags, nvp, ptr, leftp, fds, 709 nfds); 710 break; 711 case NV_TYPE_DESCRIPTOR: 712 ptr = nvpair_unpack_descriptor(flags, nvp, ptr, leftp, fds, 713 nfds); 714 break; 715 case NV_TYPE_BINARY: 716 ptr = nvpair_unpack_binary(flags, nvp, ptr, leftp); 717 break; 718 default: 719 PJDLOG_ABORT("Invalid type (%d).", nvp->nvp_type); 720 } 721 722 if (ptr == NULL) 723 goto failed; 724 725 nvp->nvp_magic = NVPAIR_MAGIC; 726 *nvpp = nvp; 727 return (ptr); 728failed: 729 free(nvp); 730 return (NULL); 731} 732 733int 734nvpair_type(const nvpair_t *nvp) 735{ 736 737 NVPAIR_ASSERT(nvp); 738 739 return (nvp->nvp_type); 740} 741 742const char * 743nvpair_name(const nvpair_t *nvp) 744{ 745 746 NVPAIR_ASSERT(nvp); 747 748 return (nvp->nvp_name); 749} 750 751static nvpair_t * 752nvpair_allocv(int type, uint64_t data, size_t datasize, const char *namefmt, 753 va_list nameap) 754{ 755 nvpair_t *nvp; 756 char *name; 757 int namelen; 758 759 PJDLOG_ASSERT(type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST); 760 761 namelen = vasprintf(&name, namefmt, nameap); 762 if (namelen < 0) 763 return (NULL); 764 765 PJDLOG_ASSERT(namelen > 0); 766 if (namelen >= NV_NAME_MAX) { 767 free(name); 768 errno = ENAMETOOLONG; 769 return (NULL); 770 } 771 772 nvp = calloc(1, sizeof(*nvp) + namelen + 1); 773 if (nvp != NULL) { 774 nvp->nvp_name = (char *)(nvp + 1); 775 memcpy(nvp->nvp_name, name, namelen + 1); 776 nvp->nvp_type = type; 777 nvp->nvp_data = data; 778 nvp->nvp_datasize = datasize; 779 nvp->nvp_magic = NVPAIR_MAGIC; 780 } 781 free(name); 782 783 return (nvp); 784}; 785 786nvpair_t * 787nvpair_create_null(const char *name) 788{ 789 790 return (nvpair_createf_null("%s", name)); 791} 792 793nvpair_t * 794nvpair_create_bool(const char *name, bool value) 795{ 796 797 return (nvpair_createf_bool(value, "%s", name)); 798} 799 800nvpair_t * 801nvpair_create_number(const char *name, uint64_t value) 802{ 803 804 return (nvpair_createf_number(value, "%s", name)); 805} 806 807nvpair_t * 808nvpair_create_string(const char *name, const char *value) 809{ 810 811 return (nvpair_createf_string(value, "%s", name)); 812} 813 814nvpair_t * 815nvpair_create_stringf(const char *name, const char *valuefmt, ...) 816{ 817 va_list valueap; 818 nvpair_t *nvp; 819 820 va_start(valueap, valuefmt); 821 nvp = nvpair_create_stringv(name, valuefmt, valueap); 822 va_end(valueap); 823 824 return (nvp); 825} 826 827nvpair_t * 828nvpair_create_stringv(const char *name, const char *valuefmt, va_list valueap) 829{ 830 nvpair_t *nvp; 831 char *str; 832 int len; 833 834 len = vasprintf(&str, valuefmt, valueap); 835 if (len < 0) 836 return (NULL); 837 nvp = nvpair_create_string(name, str); 838 if (nvp == NULL) 839 free(str); 840 return (nvp); 841} 842 843nvpair_t * 844nvpair_create_nvlist(const char *name, const nvlist_t *value) 845{ 846 847 return (nvpair_createf_nvlist(value, "%s", name)); 848} 849 850nvpair_t * 851nvpair_create_descriptor(const char *name, int value) 852{ 853 854 return (nvpair_createf_descriptor(value, "%s", name)); 855} 856 857nvpair_t * 858nvpair_create_binary(const char *name, const void *value, size_t size) 859{ 860 861 return (nvpair_createf_binary(value, size, "%s", name)); 862} 863 864nvpair_t * 865nvpair_createf_null(const char *namefmt, ...) 866{ 867 va_list nameap; 868 nvpair_t *nvp; 869 870 va_start(nameap, namefmt); 871 nvp = nvpair_createv_null(namefmt, nameap); 872 va_end(nameap); 873 874 return (nvp); 875} 876 877nvpair_t * 878nvpair_createf_bool(bool value, const char *namefmt, ...) 879{ 880 va_list nameap; 881 nvpair_t *nvp; 882 883 va_start(nameap, namefmt); 884 nvp = nvpair_createv_bool(value, namefmt, nameap); 885 va_end(nameap); 886 887 return (nvp); 888} 889 890nvpair_t * 891nvpair_createf_number(uint64_t value, const char *namefmt, ...) 892{ 893 va_list nameap; 894 nvpair_t *nvp; 895 896 va_start(nameap, namefmt); 897 nvp = nvpair_createv_number(value, namefmt, nameap); 898 va_end(nameap); 899 900 return (nvp); 901} 902 903nvpair_t * 904nvpair_createf_string(const char *value, const char *namefmt, ...) 905{ 906 va_list nameap; 907 nvpair_t *nvp; 908 909 va_start(nameap, namefmt); 910 nvp = nvpair_createv_string(value, namefmt, nameap); 911 va_end(nameap); 912 913 return (nvp); 914} 915 916nvpair_t * 917nvpair_createf_nvlist(const nvlist_t *value, const char *namefmt, ...) 918{ 919 va_list nameap; 920 nvpair_t *nvp; 921 922 va_start(nameap, namefmt); 923 nvp = nvpair_createv_nvlist(value, namefmt, nameap); 924 va_end(nameap); 925 926 return (nvp); 927} 928 929nvpair_t * 930nvpair_createf_descriptor(int value, const char *namefmt, ...) 931{ 932 va_list nameap; 933 nvpair_t *nvp; 934 935 va_start(nameap, namefmt); 936 nvp = nvpair_createv_descriptor(value, namefmt, nameap); 937 va_end(nameap); 938 939 return (nvp); 940} 941 942nvpair_t * 943nvpair_createf_binary(const void *value, size_t size, const char *namefmt, ...) 944{ 945 va_list nameap; 946 nvpair_t *nvp; 947 948 va_start(nameap, namefmt); 949 nvp = nvpair_createv_binary(value, size, namefmt, nameap); 950 va_end(nameap); 951 952 return (nvp); 953} 954 955nvpair_t * 956nvpair_createv_null(const char *namefmt, va_list nameap) 957{ 958 959 return (nvpair_allocv(NV_TYPE_NULL, 0, 0, namefmt, nameap)); 960} 961 962nvpair_t * 963nvpair_createv_bool(bool value, const char *namefmt, va_list nameap) 964{ 965 966 return (nvpair_allocv(NV_TYPE_BOOL, value ? 1 : 0, sizeof(uint8_t), 967 namefmt, nameap)); 968} 969 970nvpair_t * 971nvpair_createv_number(uint64_t value, const char *namefmt, va_list nameap) 972{ 973 974 return (nvpair_allocv(NV_TYPE_NUMBER, value, sizeof(value), namefmt, 975 nameap)); 976} 977 978nvpair_t * 979nvpair_createv_string(const char *value, const char *namefmt, va_list nameap) 980{ 981 nvpair_t *nvp; 982 size_t size; 983 char *data; 984 985 if (value == NULL) { 986 errno = EINVAL; 987 return (NULL); 988 } 989 990 data = strdup(value); 991 if (data == NULL) 992 return (NULL); 993 size = strlen(value) + 1; 994 995 nvp = nvpair_allocv(NV_TYPE_STRING, (uint64_t)(uintptr_t)data, size, 996 namefmt, nameap); 997 if (nvp == NULL) 998 free(data); 999 1000 return (nvp); 1001} 1002 1003nvpair_t * 1004nvpair_createv_nvlist(const nvlist_t *value, const char *namefmt, 1005 va_list nameap) 1006{ 1007 nvlist_t *nvl; 1008 nvpair_t *nvp; 1009 1010 if (value == NULL) { 1011 errno = EINVAL; 1012 return (NULL); 1013 } 1014 1015 nvl = nvlist_clone(value); 1016 if (nvl == NULL) 1017 return (NULL); 1018 1019 nvp = nvpair_allocv(NV_TYPE_NVLIST, (uint64_t)(uintptr_t)nvl, 0, 1020 namefmt, nameap); 1021 if (nvp == NULL) 1022 nvlist_destroy(nvl); 1023 1024 return (nvp); 1025} 1026 1027nvpair_t * 1028nvpair_createv_descriptor(int value, const char *namefmt, va_list nameap) 1029{ 1030 nvpair_t *nvp; 1031 1032 if (value < 0 || !fd_is_valid(value)) { 1033 errno = EBADF; 1034 return (NULL); 1035 } 1036 1037 value = fcntl(value, F_DUPFD_CLOEXEC, 0); 1038 if (value < 0) 1039 return (NULL); 1040 1041 nvp = nvpair_allocv(NV_TYPE_DESCRIPTOR, (uint64_t)value, 1042 sizeof(int64_t), namefmt, nameap); 1043 if (nvp == NULL) 1044 close(value); 1045 1046 return (nvp); 1047} 1048 1049nvpair_t * 1050nvpair_createv_binary(const void *value, size_t size, const char *namefmt, 1051 va_list nameap) 1052{ 1053 nvpair_t *nvp; 1054 void *data; 1055 1056 if (value == NULL || size == 0) { 1057 errno = EINVAL; 1058 return (NULL); 1059 } 1060 1061 data = malloc(size); 1062 if (data == NULL) 1063 return (NULL); 1064 memcpy(data, value, size); 1065 1066 nvp = nvpair_allocv(NV_TYPE_BINARY, (uint64_t)(uintptr_t)data, size, 1067 namefmt, nameap); 1068 if (nvp == NULL) 1069 free(data); 1070 1071 return (nvp); 1072} 1073 1074nvpair_t * 1075nvpair_move_string(const char *name, char *value) 1076{ 1077 1078 return (nvpair_movef_string(value, "%s", name)); 1079} 1080 1081nvpair_t * 1082nvpair_move_nvlist(const char *name, nvlist_t *value) 1083{ 1084 1085 return (nvpair_movef_nvlist(value, "%s", name)); 1086} 1087 1088nvpair_t * 1089nvpair_move_descriptor(const char *name, int value) 1090{ 1091 1092 return (nvpair_movef_descriptor(value, "%s", name)); 1093} 1094 1095nvpair_t * 1096nvpair_move_binary(const char *name, void *value, size_t size) 1097{ 1098 1099 return (nvpair_movef_binary(value, size, "%s", name)); 1100} 1101 1102nvpair_t * 1103nvpair_movef_string(char *value, const char *namefmt, ...) 1104{ 1105 va_list nameap; 1106 nvpair_t *nvp; 1107 1108 va_start(nameap, namefmt); 1109 nvp = nvpair_movev_string(value, namefmt, nameap); 1110 va_end(nameap); 1111 1112 return (nvp); 1113} 1114 1115nvpair_t * 1116nvpair_movef_nvlist(nvlist_t *value, const char *namefmt, ...) 1117{ 1118 va_list nameap; 1119 nvpair_t *nvp; 1120 1121 va_start(nameap, namefmt); 1122 nvp = nvpair_movev_nvlist(value, namefmt, nameap); 1123 va_end(nameap); 1124 1125 return (nvp); 1126} 1127 1128nvpair_t * 1129nvpair_movef_descriptor(int value, const char *namefmt, ...) 1130{ 1131 va_list nameap; 1132 nvpair_t *nvp; 1133 1134 va_start(nameap, namefmt); 1135 nvp = nvpair_movev_descriptor(value, namefmt, nameap); 1136 va_end(nameap); 1137 1138 return (nvp); 1139} 1140 1141nvpair_t * 1142nvpair_movef_binary(void *value, size_t size, const char *namefmt, ...) 1143{ 1144 va_list nameap; 1145 nvpair_t *nvp; 1146 1147 va_start(nameap, namefmt); 1148 nvp = nvpair_movev_binary(value, size, namefmt, nameap); 1149 va_end(nameap); 1150 1151 return (nvp); 1152} 1153 1154nvpair_t * 1155nvpair_movev_string(char *value, const char *namefmt, va_list nameap) 1156{ 1157 nvpair_t *nvp; 1158 1159 if (value == NULL) { 1160 errno = EINVAL; 1161 return (NULL); 1162 } 1163 1164 nvp = nvpair_allocv(NV_TYPE_STRING, (uint64_t)(uintptr_t)value, 1165 strlen(value) + 1, namefmt, nameap); 1166 if (nvp == NULL) 1167 free(value); 1168 1169 return (nvp); 1170} 1171 1172nvpair_t * 1173nvpair_movev_nvlist(nvlist_t *value, const char *namefmt, va_list nameap) 1174{ 1175 nvpair_t *nvp; 1176 1177 if (value == NULL) { 1178 errno = EINVAL; 1179 return (NULL); 1180 } 1181 1182 nvp = nvpair_allocv(NV_TYPE_NVLIST, (uint64_t)(uintptr_t)value, 0, 1183 namefmt, nameap); 1184 if (nvp == NULL) 1185 nvlist_destroy(value); 1186 1187 return (nvp); 1188} 1189 1190nvpair_t * 1191nvpair_movev_descriptor(int value, const char *namefmt, va_list nameap) 1192{ 1193 1194 if (value < 0 || !fd_is_valid(value)) { 1195 errno = EBADF; 1196 return (NULL); 1197 } 1198 1199 return (nvpair_allocv(NV_TYPE_DESCRIPTOR, (uint64_t)value, 1200 sizeof(int64_t), namefmt, nameap)); 1201} 1202 1203nvpair_t * 1204nvpair_movev_binary(void *value, size_t size, const char *namefmt, 1205 va_list nameap) 1206{ 1207 1208 if (value == NULL || size == 0) { 1209 errno = EINVAL; 1210 return (NULL); 1211 } 1212 1213 return (nvpair_allocv(NV_TYPE_BINARY, (uint64_t)(uintptr_t)value, size, 1214 namefmt, nameap)); 1215} 1216 1217bool 1218nvpair_get_bool(const nvpair_t *nvp) 1219{ 1220 1221 NVPAIR_ASSERT(nvp); 1222 1223 return (nvp->nvp_data == 1); 1224} 1225 1226uint64_t 1227nvpair_get_number(const nvpair_t *nvp) 1228{ 1229 1230 NVPAIR_ASSERT(nvp); 1231 1232 return (nvp->nvp_data); 1233} 1234 1235const char * 1236nvpair_get_string(const nvpair_t *nvp) 1237{ 1238 1239 NVPAIR_ASSERT(nvp); 1240 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING); 1241 1242 return ((const char *)(intptr_t)nvp->nvp_data); 1243} 1244 1245const nvlist_t * 1246nvpair_get_nvlist(const nvpair_t *nvp) 1247{ 1248 1249 NVPAIR_ASSERT(nvp); 1250 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST); 1251 1252 return ((const nvlist_t *)(intptr_t)nvp->nvp_data); 1253} 1254 1255int 1256nvpair_get_descriptor(const nvpair_t *nvp) 1257{ 1258 1259 NVPAIR_ASSERT(nvp); 1260 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR); 1261 1262 return ((int)nvp->nvp_data); 1263} 1264 1265const void * 1266nvpair_get_binary(const nvpair_t *nvp, size_t *sizep) 1267{ 1268 1269 NVPAIR_ASSERT(nvp); 1270 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY); 1271 1272 if (sizep != NULL) 1273 *sizep = nvp->nvp_datasize; 1274 return ((const void *)(intptr_t)nvp->nvp_data); 1275} 1276 1277void 1278nvpair_free(nvpair_t *nvp) 1279{ 1280 1281 NVPAIR_ASSERT(nvp); 1282 PJDLOG_ASSERT(nvp->nvp_list == NULL); 1283 1284 nvp->nvp_magic = 0; 1285 switch (nvp->nvp_type) { 1286 case NV_TYPE_DESCRIPTOR: 1287 close((int)nvp->nvp_data); 1288 break; 1289 case NV_TYPE_NVLIST: 1290 nvlist_destroy((nvlist_t *)(intptr_t)nvp->nvp_data); 1291 break; 1292 case NV_TYPE_STRING: 1293 free((char *)(intptr_t)nvp->nvp_data); 1294 break; 1295 case NV_TYPE_BINARY: 1296 free((void *)(intptr_t)nvp->nvp_data); 1297 break; 1298 } 1299 free(nvp); 1300} 1301 1302void 1303nvpair_free_structure(nvpair_t *nvp) 1304{ 1305 1306 NVPAIR_ASSERT(nvp); 1307 PJDLOG_ASSERT(nvp->nvp_list == NULL); 1308 1309 nvp->nvp_magic = 0; 1310 free(nvp); 1311} 1312 1313const char * 1314nvpair_type_string(int type) 1315{ 1316 1317 switch (type) { 1318 case NV_TYPE_NULL: 1319 return ("NULL"); 1320 case NV_TYPE_BOOL: 1321 return ("BOOL"); 1322 case NV_TYPE_NUMBER: 1323 return ("NUMBER"); 1324 case NV_TYPE_STRING: 1325 return ("STRING"); 1326 case NV_TYPE_NVLIST: 1327 return ("NVLIST"); 1328 case NV_TYPE_DESCRIPTOR: 1329 return ("DESCRIPTOR"); 1330 case NV_TYPE_BINARY: 1331 return ("BINARY"); 1332 default: 1333 return ("<UNKNOWN>"); 1334 } 1335} 1336