nvpair.c revision 258594
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 258594 2013-11-25 20:45:30Z 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 goto failed; 688 nvp = tmp; 689 /* Update nvp_name after realloc(). */ 690 nvp->nvp_name = (char *)(nvp + 1); 691 692 switch (nvp->nvp_type) { 693 case NV_TYPE_NULL: 694 ptr = nvpair_unpack_null(flags, nvp, ptr, leftp); 695 break; 696 case NV_TYPE_BOOL: 697 ptr = nvpair_unpack_bool(flags, nvp, ptr, leftp); 698 break; 699 case NV_TYPE_NUMBER: 700 ptr = nvpair_unpack_number(flags, nvp, ptr, leftp); 701 break; 702 case NV_TYPE_STRING: 703 ptr = nvpair_unpack_string(flags, nvp, ptr, leftp); 704 break; 705 case NV_TYPE_NVLIST: 706 ptr = nvpair_unpack_nvlist(flags, nvp, ptr, leftp, fds, 707 nfds); 708 break; 709 case NV_TYPE_DESCRIPTOR: 710 ptr = nvpair_unpack_descriptor(flags, nvp, ptr, leftp, fds, 711 nfds); 712 break; 713 case NV_TYPE_BINARY: 714 ptr = nvpair_unpack_binary(flags, nvp, ptr, leftp); 715 break; 716 default: 717 PJDLOG_ABORT("Invalid type (%d).", nvp->nvp_type); 718 } 719 720 if (ptr == NULL) 721 goto failed; 722 723 nvp->nvp_magic = NVPAIR_MAGIC; 724 *nvpp = nvp; 725 return (ptr); 726failed: 727 free(nvp); 728 return (NULL); 729} 730 731int 732nvpair_type(const nvpair_t *nvp) 733{ 734 735 NVPAIR_ASSERT(nvp); 736 737 return (nvp->nvp_type); 738} 739 740const char * 741nvpair_name(const nvpair_t *nvp) 742{ 743 744 NVPAIR_ASSERT(nvp); 745 746 return (nvp->nvp_name); 747} 748 749static nvpair_t * 750nvpair_allocv(int type, uint64_t data, size_t datasize, const char *namefmt, 751 va_list nameap) 752{ 753 nvpair_t *nvp; 754 char *name; 755 int namelen; 756 757 PJDLOG_ASSERT(type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST); 758 759 namelen = vasprintf(&name, namefmt, nameap); 760 if (namelen < 0) 761 return (NULL); 762 763 PJDLOG_ASSERT(namelen > 0); 764 if (namelen >= NV_NAME_MAX) { 765 free(name); 766 errno = ENAMETOOLONG; 767 return (NULL); 768 } 769 770 nvp = calloc(1, sizeof(*nvp) + namelen + 1); 771 if (nvp != NULL) { 772 nvp->nvp_name = (char *)(nvp + 1); 773 memcpy(nvp->nvp_name, name, namelen + 1); 774 nvp->nvp_type = type; 775 nvp->nvp_data = data; 776 nvp->nvp_datasize = datasize; 777 nvp->nvp_magic = NVPAIR_MAGIC; 778 } 779 free(name); 780 781 return (nvp); 782}; 783 784nvpair_t * 785nvpair_create_null(const char *name) 786{ 787 788 return (nvpair_createf_null("%s", name)); 789} 790 791nvpair_t * 792nvpair_create_bool(const char *name, bool value) 793{ 794 795 return (nvpair_createf_bool(value, "%s", name)); 796} 797 798nvpair_t * 799nvpair_create_number(const char *name, uint64_t value) 800{ 801 802 return (nvpair_createf_number(value, "%s", name)); 803} 804 805nvpair_t * 806nvpair_create_string(const char *name, const char *value) 807{ 808 809 return (nvpair_createf_string(value, "%s", name)); 810} 811 812nvpair_t * 813nvpair_create_stringf(const char *name, const char *valuefmt, ...) 814{ 815 va_list valueap; 816 nvpair_t *nvp; 817 818 va_start(valueap, valuefmt); 819 nvp = nvpair_create_stringv(name, valuefmt, valueap); 820 va_end(valueap); 821 822 return (nvp); 823} 824 825nvpair_t * 826nvpair_create_stringv(const char *name, const char *valuefmt, va_list valueap) 827{ 828 nvpair_t *nvp; 829 char *str; 830 int len; 831 832 len = vasprintf(&str, valuefmt, valueap); 833 if (len < 0) 834 return (NULL); 835 nvp = nvpair_create_string(name, str); 836 if (nvp == NULL) 837 free(str); 838 return (nvp); 839} 840 841nvpair_t * 842nvpair_create_nvlist(const char *name, const nvlist_t *value) 843{ 844 845 return (nvpair_createf_nvlist(value, "%s", name)); 846} 847 848nvpair_t * 849nvpair_create_descriptor(const char *name, int value) 850{ 851 852 return (nvpair_createf_descriptor(value, "%s", name)); 853} 854 855nvpair_t * 856nvpair_create_binary(const char *name, const void *value, size_t size) 857{ 858 859 return (nvpair_createf_binary(value, size, "%s", name)); 860} 861 862nvpair_t * 863nvpair_createf_null(const char *namefmt, ...) 864{ 865 va_list nameap; 866 nvpair_t *nvp; 867 868 va_start(nameap, namefmt); 869 nvp = nvpair_createv_null(namefmt, nameap); 870 va_end(nameap); 871 872 return (nvp); 873} 874 875nvpair_t * 876nvpair_createf_bool(bool value, const char *namefmt, ...) 877{ 878 va_list nameap; 879 nvpair_t *nvp; 880 881 va_start(nameap, namefmt); 882 nvp = nvpair_createv_bool(value, namefmt, nameap); 883 va_end(nameap); 884 885 return (nvp); 886} 887 888nvpair_t * 889nvpair_createf_number(uint64_t value, const char *namefmt, ...) 890{ 891 va_list nameap; 892 nvpair_t *nvp; 893 894 va_start(nameap, namefmt); 895 nvp = nvpair_createv_number(value, namefmt, nameap); 896 va_end(nameap); 897 898 return (nvp); 899} 900 901nvpair_t * 902nvpair_createf_string(const char *value, const char *namefmt, ...) 903{ 904 va_list nameap; 905 nvpair_t *nvp; 906 907 va_start(nameap, namefmt); 908 nvp = nvpair_createv_string(value, namefmt, nameap); 909 va_end(nameap); 910 911 return (nvp); 912} 913 914nvpair_t * 915nvpair_createf_nvlist(const nvlist_t *value, const char *namefmt, ...) 916{ 917 va_list nameap; 918 nvpair_t *nvp; 919 920 va_start(nameap, namefmt); 921 nvp = nvpair_createv_nvlist(value, namefmt, nameap); 922 va_end(nameap); 923 924 return (nvp); 925} 926 927nvpair_t * 928nvpair_createf_descriptor(int value, const char *namefmt, ...) 929{ 930 va_list nameap; 931 nvpair_t *nvp; 932 933 va_start(nameap, namefmt); 934 nvp = nvpair_createv_descriptor(value, namefmt, nameap); 935 va_end(nameap); 936 937 return (nvp); 938} 939 940nvpair_t * 941nvpair_createf_binary(const void *value, size_t size, const char *namefmt, ...) 942{ 943 va_list nameap; 944 nvpair_t *nvp; 945 946 va_start(nameap, namefmt); 947 nvp = nvpair_createv_binary(value, size, namefmt, nameap); 948 va_end(nameap); 949 950 return (nvp); 951} 952 953nvpair_t * 954nvpair_createv_null(const char *namefmt, va_list nameap) 955{ 956 957 return (nvpair_allocv(NV_TYPE_NULL, 0, 0, namefmt, nameap)); 958} 959 960nvpair_t * 961nvpair_createv_bool(bool value, const char *namefmt, va_list nameap) 962{ 963 964 return (nvpair_allocv(NV_TYPE_BOOL, value ? 1 : 0, sizeof(uint8_t), 965 namefmt, nameap)); 966} 967 968nvpair_t * 969nvpair_createv_number(uint64_t value, const char *namefmt, va_list nameap) 970{ 971 972 return (nvpair_allocv(NV_TYPE_NUMBER, value, sizeof(value), namefmt, 973 nameap)); 974} 975 976nvpair_t * 977nvpair_createv_string(const char *value, const char *namefmt, va_list nameap) 978{ 979 nvpair_t *nvp; 980 size_t size; 981 char *data; 982 983 if (value == NULL) { 984 errno = EINVAL; 985 return (NULL); 986 } 987 988 data = strdup(value); 989 if (data == NULL) 990 return (NULL); 991 size = strlen(value) + 1; 992 993 nvp = nvpair_allocv(NV_TYPE_STRING, (uint64_t)(uintptr_t)data, size, 994 namefmt, nameap); 995 if (nvp == NULL) 996 free(data); 997 998 return (nvp); 999} 1000 1001nvpair_t * 1002nvpair_createv_nvlist(const nvlist_t *value, const char *namefmt, 1003 va_list nameap) 1004{ 1005 nvlist_t *nvl; 1006 nvpair_t *nvp; 1007 1008 if (value == NULL) { 1009 errno = EINVAL; 1010 return (NULL); 1011 } 1012 1013 nvl = nvlist_clone(value); 1014 if (nvl == NULL) 1015 return (NULL); 1016 1017 nvp = nvpair_allocv(NV_TYPE_NVLIST, (uint64_t)(uintptr_t)nvl, 0, 1018 namefmt, nameap); 1019 if (nvp == NULL) 1020 nvlist_destroy(nvl); 1021 1022 return (nvp); 1023} 1024 1025nvpair_t * 1026nvpair_createv_descriptor(int value, const char *namefmt, va_list nameap) 1027{ 1028 nvpair_t *nvp; 1029 1030 if (value < 0 || !fd_is_valid(value)) { 1031 errno = EBADF; 1032 return (NULL); 1033 } 1034 1035 value = fcntl(value, F_DUPFD_CLOEXEC, 0); 1036 if (value < 0) 1037 return (NULL); 1038 1039 nvp = nvpair_allocv(NV_TYPE_DESCRIPTOR, (uint64_t)value, 1040 sizeof(int64_t), namefmt, nameap); 1041 if (nvp == NULL) 1042 close(value); 1043 1044 return (nvp); 1045} 1046 1047nvpair_t * 1048nvpair_createv_binary(const void *value, size_t size, const char *namefmt, 1049 va_list nameap) 1050{ 1051 nvpair_t *nvp; 1052 void *data; 1053 1054 if (value == NULL || size == 0) { 1055 errno = EINVAL; 1056 return (NULL); 1057 } 1058 1059 data = malloc(size); 1060 if (data == NULL) 1061 return (NULL); 1062 memcpy(data, value, size); 1063 1064 nvp = nvpair_allocv(NV_TYPE_BINARY, (uint64_t)(uintptr_t)data, size, 1065 namefmt, nameap); 1066 if (nvp == NULL) 1067 free(data); 1068 1069 return (nvp); 1070} 1071 1072nvpair_t * 1073nvpair_move_string(const char *name, char *value) 1074{ 1075 1076 return (nvpair_movef_string(value, "%s", name)); 1077} 1078 1079nvpair_t * 1080nvpair_move_nvlist(const char *name, nvlist_t *value) 1081{ 1082 1083 return (nvpair_movef_nvlist(value, "%s", name)); 1084} 1085 1086nvpair_t * 1087nvpair_move_descriptor(const char *name, int value) 1088{ 1089 1090 return (nvpair_movef_descriptor(value, "%s", name)); 1091} 1092 1093nvpair_t * 1094nvpair_move_binary(const char *name, void *value, size_t size) 1095{ 1096 1097 return (nvpair_movef_binary(value, size, "%s", name)); 1098} 1099 1100nvpair_t * 1101nvpair_movef_string(char *value, const char *namefmt, ...) 1102{ 1103 va_list nameap; 1104 nvpair_t *nvp; 1105 1106 va_start(nameap, namefmt); 1107 nvp = nvpair_movev_string(value, namefmt, nameap); 1108 va_end(nameap); 1109 1110 return (nvp); 1111} 1112 1113nvpair_t * 1114nvpair_movef_nvlist(nvlist_t *value, const char *namefmt, ...) 1115{ 1116 va_list nameap; 1117 nvpair_t *nvp; 1118 1119 va_start(nameap, namefmt); 1120 nvp = nvpair_movev_nvlist(value, namefmt, nameap); 1121 va_end(nameap); 1122 1123 return (nvp); 1124} 1125 1126nvpair_t * 1127nvpair_movef_descriptor(int value, const char *namefmt, ...) 1128{ 1129 va_list nameap; 1130 nvpair_t *nvp; 1131 1132 va_start(nameap, namefmt); 1133 nvp = nvpair_movev_descriptor(value, namefmt, nameap); 1134 va_end(nameap); 1135 1136 return (nvp); 1137} 1138 1139nvpair_t * 1140nvpair_movef_binary(void *value, size_t size, const char *namefmt, ...) 1141{ 1142 va_list nameap; 1143 nvpair_t *nvp; 1144 1145 va_start(nameap, namefmt); 1146 nvp = nvpair_movev_binary(value, size, namefmt, nameap); 1147 va_end(nameap); 1148 1149 return (nvp); 1150} 1151 1152nvpair_t * 1153nvpair_movev_string(char *value, const char *namefmt, va_list nameap) 1154{ 1155 nvpair_t *nvp; 1156 1157 if (value == NULL) { 1158 errno = EINVAL; 1159 return (NULL); 1160 } 1161 1162 nvp = nvpair_allocv(NV_TYPE_STRING, (uint64_t)(uintptr_t)value, 1163 strlen(value) + 1, namefmt, nameap); 1164 if (nvp == NULL) 1165 free(value); 1166 1167 return (nvp); 1168} 1169 1170nvpair_t * 1171nvpair_movev_nvlist(nvlist_t *value, const char *namefmt, va_list nameap) 1172{ 1173 nvpair_t *nvp; 1174 1175 if (value == NULL) { 1176 errno = EINVAL; 1177 return (NULL); 1178 } 1179 1180 nvp = nvpair_allocv(NV_TYPE_NVLIST, (uint64_t)(uintptr_t)value, 0, 1181 namefmt, nameap); 1182 if (nvp == NULL) 1183 nvlist_destroy(value); 1184 1185 return (nvp); 1186} 1187 1188nvpair_t * 1189nvpair_movev_descriptor(int value, const char *namefmt, va_list nameap) 1190{ 1191 1192 if (value < 0 || !fd_is_valid(value)) { 1193 errno = EBADF; 1194 return (NULL); 1195 } 1196 1197 return (nvpair_allocv(NV_TYPE_DESCRIPTOR, (uint64_t)value, 1198 sizeof(int64_t), namefmt, nameap)); 1199} 1200 1201nvpair_t * 1202nvpair_movev_binary(void *value, size_t size, const char *namefmt, 1203 va_list nameap) 1204{ 1205 1206 if (value == NULL || size == 0) { 1207 errno = EINVAL; 1208 return (NULL); 1209 } 1210 1211 return (nvpair_allocv(NV_TYPE_BINARY, (uint64_t)(uintptr_t)value, size, 1212 namefmt, nameap)); 1213} 1214 1215bool 1216nvpair_get_bool(const nvpair_t *nvp) 1217{ 1218 1219 NVPAIR_ASSERT(nvp); 1220 1221 return (nvp->nvp_data == 1); 1222} 1223 1224uint64_t 1225nvpair_get_number(const nvpair_t *nvp) 1226{ 1227 1228 NVPAIR_ASSERT(nvp); 1229 1230 return (nvp->nvp_data); 1231} 1232 1233const char * 1234nvpair_get_string(const nvpair_t *nvp) 1235{ 1236 1237 NVPAIR_ASSERT(nvp); 1238 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING); 1239 1240 return ((const char *)(intptr_t)nvp->nvp_data); 1241} 1242 1243const nvlist_t * 1244nvpair_get_nvlist(const nvpair_t *nvp) 1245{ 1246 1247 NVPAIR_ASSERT(nvp); 1248 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST); 1249 1250 return ((const nvlist_t *)(intptr_t)nvp->nvp_data); 1251} 1252 1253int 1254nvpair_get_descriptor(const nvpair_t *nvp) 1255{ 1256 1257 NVPAIR_ASSERT(nvp); 1258 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR); 1259 1260 return ((int)nvp->nvp_data); 1261} 1262 1263const void * 1264nvpair_get_binary(const nvpair_t *nvp, size_t *sizep) 1265{ 1266 1267 NVPAIR_ASSERT(nvp); 1268 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY); 1269 1270 if (sizep != NULL) 1271 *sizep = nvp->nvp_datasize; 1272 return ((const void *)(intptr_t)nvp->nvp_data); 1273} 1274 1275void 1276nvpair_free(nvpair_t *nvp) 1277{ 1278 1279 NVPAIR_ASSERT(nvp); 1280 PJDLOG_ASSERT(nvp->nvp_list == NULL); 1281 1282 nvp->nvp_magic = 0; 1283 switch (nvp->nvp_type) { 1284 case NV_TYPE_DESCRIPTOR: 1285 close((int)nvp->nvp_data); 1286 break; 1287 case NV_TYPE_NVLIST: 1288 nvlist_destroy((nvlist_t *)(intptr_t)nvp->nvp_data); 1289 break; 1290 case NV_TYPE_STRING: 1291 free((char *)(intptr_t)nvp->nvp_data); 1292 break; 1293 case NV_TYPE_BINARY: 1294 free((void *)(intptr_t)nvp->nvp_data); 1295 break; 1296 } 1297 free(nvp); 1298} 1299 1300void 1301nvpair_free_structure(nvpair_t *nvp) 1302{ 1303 1304 NVPAIR_ASSERT(nvp); 1305 PJDLOG_ASSERT(nvp->nvp_list == NULL); 1306 1307 nvp->nvp_magic = 0; 1308 free(nvp); 1309} 1310 1311const char * 1312nvpair_type_string(int type) 1313{ 1314 1315 switch (type) { 1316 case NV_TYPE_NULL: 1317 return ("NULL"); 1318 case NV_TYPE_BOOL: 1319 return ("BOOL"); 1320 case NV_TYPE_NUMBER: 1321 return ("NUMBER"); 1322 case NV_TYPE_STRING: 1323 return ("STRING"); 1324 case NV_TYPE_NVLIST: 1325 return ("NVLIST"); 1326 case NV_TYPE_DESCRIPTOR: 1327 return ("DESCRIPTOR"); 1328 case NV_TYPE_BINARY: 1329 return ("BINARY"); 1330 default: 1331 return ("<UNKNOWN>"); 1332 } 1333} 1334