1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <sys/stropts.h> 30 #include <sys/debug.h> 31 #include <sys/isa_defs.h> 32 #include <sys/int_limits.h> 33 #include <sys/nvpair.h> 34 #include <sys/nvpair_impl.h> 35 #include <rpc/types.h> 36 #include <rpc/xdr.h> 37 38 #if defined(_KERNEL) && !defined(_BOOT) 39 #include <sys/varargs.h> 40 #else 41 #include <stdarg.h> 42 #include <strings.h> 43 #endif 44 45 #ifndef offsetof 46 #define offsetof(s, m) ((size_t)(&(((s *)0)->m))) 47 #endif 48 49 50 /* 51 * nvpair.c - Provides kernel & userland interfaces for manipulating 52 * name-value pairs. 53 * 54 * Overview Diagram 55 * 56 * +--------------+ 57 * | nvlist_t | 58 * |--------------| 59 * | nvl_version | 60 * | nvl_nvflag | 61 * | nvl_priv -+-+ 62 * | nvl_flag | | 63 * | nvl_pad | | 64 * +--------------+ | 65 * V 66 * +--------------+ last i_nvp in list 67 * | nvpriv_t | +---------------------> 68 * |--------------| | 69 * +--+- nvp_list | | +------------+ 70 * | | nvp_last -+--+ + nv_alloc_t | 71 * | | nvp_curr | |------------| 72 * | | nvp_nva -+----> | nva_ops | 73 * | | nvp_stat | | nva_arg | 74 * | +--------------+ +------------+ 75 * | 76 * +-------+ 77 * V 78 * +---------------------+ +-------------------+ 79 * | i_nvp_t | +-->| i_nvp_t | +--> 80 * |---------------------| | |-------------------| | 81 * | nvi_next -+--+ | nvi_next -+--+ 82 * | nvi_prev (NULL) | <----+ nvi_prev | 83 * | . . . . . . . . . . | | . . . . . . . . . | 84 * | nvp (nvpair_t) | | nvp (nvpair_t) | 85 * | - nvp_size | | - nvp_size | 86 * | - nvp_name_sz | | - nvp_name_sz | 87 * | - nvp_value_elem | | - nvp_value_elem | 88 * | - nvp_type | | - nvp_type | 89 * | - data ... | | - data ... | 90 * +---------------------+ +-------------------+ 91 * 92 * 93 * 94 * +---------------------+ +---------------------+ 95 * | i_nvp_t | +--> +-->| i_nvp_t (last) | 96 * |---------------------| | | |---------------------| 97 * | nvi_next -+--+ ... --+ | nvi_next (NULL) | 98 * <-+- nvi_prev |<-- ... <----+ nvi_prev | 99 * | . . . . . . . . . | | . . . . . . . . . | 100 * | nvp (nvpair_t) | | nvp (nvpair_t) | 101 * | - nvp_size | | - nvp_size | 102 * | - nvp_name_sz | | - nvp_name_sz | 103 * | - nvp_value_elem | | - nvp_value_elem | 104 * | - DATA_TYPE_NVLIST | | - nvp_type | 105 * | - data (embedded) | | - data ... | 106 * | nvlist name | +---------------------+ 107 * | +--------------+ | 108 * | | nvlist_t | | 109 * | |--------------| | 110 * | | nvl_version | | 111 * | | nvl_nvflag | | 112 * | | nvl_priv --+---+----> 113 * | | nvl_flag | | 114 * | | nvl_pad | | 115 * | +--------------+ | 116 * +---------------------+ 117 * 118 * 119 * N.B. nvpair_t may be aligned on 4 byte boundary, so +4 will 120 * allow value to be aligned on 8 byte boundary 121 * 122 * name_len is the length of the name string including the null terminator 123 * so it must be >= 1 124 */ 125 #define NVP_SIZE_CALC(name_len, data_len) \ 126 (NV_ALIGN((sizeof (nvpair_t)) + name_len) + NV_ALIGN(data_len)) 127 128 static int i_get_value_size(data_type_t type, const void *data, uint_t nelem); 129 static int nvlist_add_common(nvlist_t *nvl, const char *name, data_type_t type, 130 uint_t nelem, const void *data); 131 132 #define NV_STAT_EMBEDDED 0x1 133 #define EMBEDDED_NVL(nvp) ((nvlist_t *)(void *)NVP_VALUE(nvp)) 134 #define EMBEDDED_NVL_ARRAY(nvp) ((nvlist_t **)(void *)NVP_VALUE(nvp)) 135 136 #define NVP_VALOFF(nvp) (NV_ALIGN(sizeof (nvpair_t) + (nvp)->nvp_name_sz)) 137 #define NVPAIR2I_NVP(nvp) \ 138 ((i_nvp_t *)((size_t)(nvp) - offsetof(i_nvp_t, nvi_nvp))) 139 140 141 int 142 nv_alloc_init(nv_alloc_t *nva, const nv_alloc_ops_t *nvo, /* args */ ...) 143 { 144 va_list valist; 145 int err = 0; 146 147 nva->nva_ops = nvo; 148 nva->nva_arg = NULL; 149 150 va_start(valist, nvo); 151 if (nva->nva_ops->nv_ao_init != NULL) 152 err = nva->nva_ops->nv_ao_init(nva, valist); 153 va_end(valist); 154 155 return (err); 156 } 157 158 void 159 nv_alloc_reset(nv_alloc_t *nva) 160 { 161 if (nva->nva_ops->nv_ao_reset != NULL) 162 nva->nva_ops->nv_ao_reset(nva); 163 } 164 165 void 166 nv_alloc_fini(nv_alloc_t *nva) 167 { 168 if (nva->nva_ops->nv_ao_fini != NULL) 169 nva->nva_ops->nv_ao_fini(nva); 170 } 171 172 nv_alloc_t * 173 nvlist_lookup_nv_alloc(nvlist_t *nvl) 174 { 175 nvpriv_t *priv; 176 177 if (nvl == NULL || 178 (priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL) 179 return (NULL); 180 181 return (priv->nvp_nva); 182 } 183 184 static void * 185 nv_mem_zalloc(nvpriv_t *nvp, size_t size) 186 { 187 nv_alloc_t *nva = nvp->nvp_nva; 188 void *buf; 189 190 if ((buf = nva->nva_ops->nv_ao_alloc(nva, size)) != NULL) 191 bzero(buf, size); 192 193 return (buf); 194 } 195 196 static void 197 nv_mem_free(nvpriv_t *nvp, void *buf, size_t size) 198 { 199 nv_alloc_t *nva = nvp->nvp_nva; 200 201 nva->nva_ops->nv_ao_free(nva, buf, size); 202 } 203 204 static void 205 nv_priv_init(nvpriv_t *priv, nv_alloc_t *nva, uint32_t stat) 206 { 207 bzero(priv, sizeof (priv)); 208 209 priv->nvp_nva = nva; 210 priv->nvp_stat = stat; 211 } 212 213 static nvpriv_t * 214 nv_priv_alloc(nv_alloc_t *nva) 215 { 216 nvpriv_t *priv; 217 218 /* 219 * nv_mem_alloc() cannot called here because it needs the priv 220 * argument. 221 */ 222 if ((priv = nva->nva_ops->nv_ao_alloc(nva, sizeof (nvpriv_t))) == NULL) 223 return (NULL); 224 225 nv_priv_init(priv, nva, 0); 226 227 return (priv); 228 } 229 230 /* 231 * Embedded lists need their own nvpriv_t's. We create a new 232 * nvpriv_t using the parameters and allocator from the parent 233 * list's nvpriv_t. 234 */ 235 static nvpriv_t * 236 nv_priv_alloc_embedded(nvpriv_t *priv) 237 { 238 nvpriv_t *emb_priv; 239 240 if ((emb_priv = nv_mem_zalloc(priv, sizeof (nvpriv_t))) == NULL) 241 return (NULL); 242 243 nv_priv_init(emb_priv, priv->nvp_nva, NV_STAT_EMBEDDED); 244 245 return (emb_priv); 246 } 247 248 static void 249 nvlist_init(nvlist_t *nvl, uint32_t nvflag, nvpriv_t *priv) 250 { 251 nvl->nvl_version = NV_VERSION; 252 nvl->nvl_nvflag = nvflag & (NV_UNIQUE_NAME|NV_UNIQUE_NAME_TYPE); 253 nvl->nvl_priv = (uint64_t)(uintptr_t)priv; 254 nvl->nvl_flag = 0; 255 nvl->nvl_pad = 0; 256 } 257 258 /* 259 * nvlist_alloc - Allocate nvlist. 260 */ 261 /*ARGSUSED1*/ 262 int 263 nvlist_alloc(nvlist_t **nvlp, uint_t nvflag, int kmflag) 264 { 265 #if defined(_KERNEL) && !defined(_BOOT) 266 return (nvlist_xalloc(nvlp, nvflag, 267 (kmflag == KM_SLEEP ? nv_alloc_sleep : nv_alloc_nosleep))); 268 #else 269 return (nvlist_xalloc(nvlp, nvflag, nv_alloc_nosleep)); 270 #endif 271 } 272 273 int 274 nvlist_xalloc(nvlist_t **nvlp, uint_t nvflag, nv_alloc_t *nva) 275 { 276 nvpriv_t *priv; 277 278 if (nvlp == NULL || nva == NULL) 279 return (EINVAL); 280 281 if ((priv = nv_priv_alloc(nva)) == NULL) 282 return (ENOMEM); 283 284 if ((*nvlp = nv_mem_zalloc(priv, 285 NV_ALIGN(sizeof (nvlist_t)))) == NULL) { 286 nv_mem_free(priv, priv, sizeof (nvpriv_t)); 287 return (ENOMEM); 288 } 289 290 nvlist_init(*nvlp, nvflag, priv); 291 292 return (0); 293 } 294 295 /* 296 * nvp_buf_alloc - Allocate i_nvp_t for storing a new nv pair. 297 */ 298 static nvpair_t * 299 nvp_buf_alloc(nvlist_t *nvl, size_t len) 300 { 301 nvpriv_t *priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv; 302 i_nvp_t *buf; 303 nvpair_t *nvp; 304 size_t nvsize; 305 306 /* 307 * Allocate the buffer 308 */ 309 nvsize = len + offsetof(i_nvp_t, nvi_nvp); 310 311 if ((buf = nv_mem_zalloc(priv, nvsize)) == NULL) 312 return (NULL); 313 314 nvp = &buf->nvi_nvp; 315 nvp->nvp_size = len; 316 317 return (nvp); 318 } 319 320 /* 321 * nvp_buf_free - de-Allocate an i_nvp_t. 322 */ 323 static void 324 nvp_buf_free(nvlist_t *nvl, nvpair_t *nvp) 325 { 326 nvpriv_t *priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv; 327 size_t nvsize = nvp->nvp_size + offsetof(i_nvp_t, nvi_nvp); 328 329 nv_mem_free(priv, NVPAIR2I_NVP(nvp), nvsize); 330 } 331 332 /* 333 * nvp_buf_link - link a new nv pair into the nvlist. 334 */ 335 static void 336 nvp_buf_link(nvlist_t *nvl, nvpair_t *nvp) 337 { 338 nvpriv_t *priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv; 339 i_nvp_t *curr = NVPAIR2I_NVP(nvp); 340 341 /* Put element at end of nvlist */ 342 if (priv->nvp_list == NULL) { 343 priv->nvp_list = priv->nvp_last = curr; 344 } else { 345 curr->nvi_prev = priv->nvp_last; 346 priv->nvp_last->nvi_next = curr; 347 priv->nvp_last = curr; 348 } 349 } 350 351 /* 352 * nvp_buf_unlink - unlink an removed nvpair out of the nvlist. 353 */ 354 static void 355 nvp_buf_unlink(nvlist_t *nvl, nvpair_t *nvp) 356 { 357 nvpriv_t *priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv; 358 i_nvp_t *curr = NVPAIR2I_NVP(nvp); 359 360 /* 361 * protect nvlist_next_nvpair() against walking on freed memory. 362 */ 363 if (priv->nvp_curr == curr) 364 priv->nvp_curr = curr->nvi_next; 365 366 if (curr == priv->nvp_list) 367 priv->nvp_list = curr->nvi_next; 368 else 369 curr->nvi_prev->nvi_next = curr->nvi_next; 370 371 if (curr == priv->nvp_last) 372 priv->nvp_last = curr->nvi_prev; 373 else 374 curr->nvi_next->nvi_prev = curr->nvi_prev; 375 } 376 377 /* 378 * take a nvpair type and number of elements and make sure the are valid 379 */ 380 static int 381 i_validate_type_nelem(data_type_t type, uint_t nelem) 382 { 383 switch (type) { 384 case DATA_TYPE_BOOLEAN: 385 if (nelem != 0) 386 return (EINVAL); 387 break; 388 case DATA_TYPE_BOOLEAN_VALUE: 389 case DATA_TYPE_BYTE: 390 case DATA_TYPE_INT8: 391 case DATA_TYPE_UINT8: 392 case DATA_TYPE_INT16: 393 case DATA_TYPE_UINT16: 394 case DATA_TYPE_INT32: 395 case DATA_TYPE_UINT32: 396 case DATA_TYPE_INT64: 397 case DATA_TYPE_UINT64: 398 case DATA_TYPE_STRING: 399 case DATA_TYPE_HRTIME: 400 case DATA_TYPE_NVLIST: 401 if (nelem != 1) 402 return (EINVAL); 403 break; 404 case DATA_TYPE_BOOLEAN_ARRAY: 405 case DATA_TYPE_BYTE_ARRAY: 406 case DATA_TYPE_INT8_ARRAY: 407 case DATA_TYPE_UINT8_ARRAY: 408 case DATA_TYPE_INT16_ARRAY: 409 case DATA_TYPE_UINT16_ARRAY: 410 case DATA_TYPE_INT32_ARRAY: 411 case DATA_TYPE_UINT32_ARRAY: 412 case DATA_TYPE_INT64_ARRAY: 413 case DATA_TYPE_UINT64_ARRAY: 414 case DATA_TYPE_STRING_ARRAY: 415 case DATA_TYPE_NVLIST_ARRAY: 416 /* we allow arrays with 0 elements */ 417 break; 418 default: 419 return (EINVAL); 420 } 421 return (0); 422 } 423 424 /* 425 * Verify nvp_name_sz and check the name string length. 426 */ 427 static int 428 i_validate_nvpair_name(nvpair_t *nvp) 429 { 430 if ((nvp->nvp_name_sz <= 0) || 431 (nvp->nvp_size < NVP_SIZE_CALC(nvp->nvp_name_sz, 0))) 432 return (EFAULT); 433 434 /* verify the name string, make sure its terminated */ 435 if (NVP_NAME(nvp)[nvp->nvp_name_sz - 1] != '\0') 436 return (EFAULT); 437 438 return (strlen(NVP_NAME(nvp)) == nvp->nvp_name_sz - 1 ? 0 : EFAULT); 439 } 440 441 static int 442 i_validate_nvpair_value(data_type_t type, uint_t nelem, const void *data) 443 { 444 switch (type) { 445 case DATA_TYPE_BOOLEAN_VALUE: 446 if (*(boolean_t *)data != B_TRUE && 447 *(boolean_t *)data != B_FALSE) 448 return (EINVAL); 449 break; 450 case DATA_TYPE_BOOLEAN_ARRAY: { 451 int i; 452 453 for (i = 0; i < nelem; i++) 454 if (((boolean_t *)data)[i] != B_TRUE && 455 ((boolean_t *)data)[i] != B_FALSE) 456 return (EINVAL); 457 break; 458 } 459 default: 460 break; 461 } 462 463 return (0); 464 } 465 466 /* 467 * This function takes a pointer to what should be a nvpair and it's size 468 * and then verifies that all the nvpair fields make sense and can be 469 * trusted. This function is used when decoding packed nvpairs. 470 */ 471 static int 472 i_validate_nvpair(nvpair_t *nvp) 473 { 474 data_type_t type = NVP_TYPE(nvp); 475 int size1, size2; 476 477 /* verify nvp_name_sz, check the name string length */ 478 if (i_validate_nvpair_name(nvp) != 0) 479 return (EFAULT); 480 481 if (i_validate_nvpair_value(type, NVP_NELEM(nvp), NVP_VALUE(nvp)) != 0) 482 return (EFAULT); 483 484 /* 485 * verify nvp_type, nvp_value_elem, and also possibly 486 * verify string values and get the value size. 487 */ 488 size2 = i_get_value_size(type, NVP_VALUE(nvp), NVP_NELEM(nvp)); 489 size1 = nvp->nvp_size - NVP_VALOFF(nvp); 490 if (size2 < 0 || size1 != NV_ALIGN(size2)) 491 return (EFAULT); 492 493 return (0); 494 } 495 496 static int 497 nvlist_copy_pairs(nvlist_t *snvl, nvlist_t *dnvl) 498 { 499 nvpriv_t *priv; 500 i_nvp_t *curr; 501 502 if ((priv = (nvpriv_t *)(uintptr_t)snvl->nvl_priv) == NULL) 503 return (EINVAL); 504 505 for (curr = priv->nvp_list; curr != NULL; curr = curr->nvi_next) { 506 nvpair_t *nvp = &curr->nvi_nvp; 507 int err; 508 509 if ((err = nvlist_add_common(dnvl, NVP_NAME(nvp), NVP_TYPE(nvp), 510 NVP_NELEM(nvp), NVP_VALUE(nvp))) != 0) 511 return (err); 512 } 513 514 return (0); 515 } 516 517 /* 518 * Frees all memory allocated for an nvpair (like embedded lists) with 519 * the exception of the nvpair buffer itself. 520 */ 521 static void 522 nvpair_free(nvpair_t *nvp) 523 { 524 switch (NVP_TYPE(nvp)) { 525 case DATA_TYPE_NVLIST: 526 nvlist_free(EMBEDDED_NVL(nvp)); 527 break; 528 case DATA_TYPE_NVLIST_ARRAY: { 529 nvlist_t **nvlp = EMBEDDED_NVL_ARRAY(nvp); 530 int i; 531 532 for (i = 0; i < NVP_NELEM(nvp); i++) 533 if (nvlp[i] != NULL) 534 nvlist_free(nvlp[i]); 535 break; 536 } 537 default: 538 break; 539 } 540 } 541 542 /* 543 * nvlist_free - free an unpacked nvlist 544 */ 545 void 546 nvlist_free(nvlist_t *nvl) 547 { 548 nvpriv_t *priv; 549 i_nvp_t *curr; 550 551 if (nvl == NULL || 552 (priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL) 553 return; 554 555 /* 556 * Unpacked nvlist are linked through i_nvp_t 557 */ 558 curr = priv->nvp_list; 559 while (curr != NULL) { 560 nvpair_t *nvp = &curr->nvi_nvp; 561 curr = curr->nvi_next; 562 563 nvpair_free(nvp); 564 nvp_buf_free(nvl, nvp); 565 } 566 567 if (!(priv->nvp_stat & NV_STAT_EMBEDDED)) 568 nv_mem_free(priv, nvl, NV_ALIGN(sizeof (nvlist_t))); 569 else 570 nvl->nvl_priv = 0; 571 572 nv_mem_free(priv, priv, sizeof (nvpriv_t)); 573 } 574 575 static int 576 nvlist_contains_nvp(nvlist_t *nvl, nvpair_t *nvp) 577 { 578 nvpriv_t *priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv; 579 i_nvp_t *curr; 580 581 if (nvp == NULL) 582 return (0); 583 584 for (curr = priv->nvp_list; curr != NULL; curr = curr->nvi_next) 585 if (&curr->nvi_nvp == nvp) 586 return (1); 587 588 return (0); 589 } 590 591 /* 592 * Make a copy of nvlist 593 */ 594 /*ARGSUSED1*/ 595 int 596 nvlist_dup(nvlist_t *nvl, nvlist_t **nvlp, int kmflag) 597 { 598 #if defined(_KERNEL) && !defined(_BOOT) 599 return (nvlist_xdup(nvl, nvlp, 600 (kmflag == KM_SLEEP ? nv_alloc_sleep : nv_alloc_nosleep))); 601 #else 602 return (nvlist_xdup(nvl, nvlp, nv_alloc_nosleep)); 603 #endif 604 } 605 606 int 607 nvlist_xdup(nvlist_t *nvl, nvlist_t **nvlp, nv_alloc_t *nva) 608 { 609 int err; 610 nvlist_t *ret; 611 612 if (nvl == NULL || nvlp == NULL) 613 return (EINVAL); 614 615 if ((err = nvlist_xalloc(&ret, nvl->nvl_nvflag, nva)) != 0) 616 return (err); 617 618 if ((err = nvlist_copy_pairs(nvl, ret)) != 0) 619 nvlist_free(ret); 620 else 621 *nvlp = ret; 622 623 return (err); 624 } 625 626 /* 627 * Remove all with matching name 628 */ 629 int 630 nvlist_remove_all(nvlist_t *nvl, const char *name) 631 { 632 nvpriv_t *priv; 633 i_nvp_t *curr; 634 int error = ENOENT; 635 636 if (nvl == NULL || name == NULL || 637 (priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL) 638 return (EINVAL); 639 640 curr = priv->nvp_list; 641 while (curr != NULL) { 642 nvpair_t *nvp = &curr->nvi_nvp; 643 644 curr = curr->nvi_next; 645 if (strcmp(name, NVP_NAME(nvp)) != 0) 646 continue; 647 648 nvp_buf_unlink(nvl, nvp); 649 nvpair_free(nvp); 650 nvp_buf_free(nvl, nvp); 651 652 error = 0; 653 } 654 655 return (error); 656 } 657 658 /* 659 * Remove first one with matching name and type 660 */ 661 int 662 nvlist_remove(nvlist_t *nvl, const char *name, data_type_t type) 663 { 664 nvpriv_t *priv; 665 i_nvp_t *curr; 666 667 if (nvl == NULL || name == NULL || 668 (priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL) 669 return (EINVAL); 670 671 curr = priv->nvp_list; 672 while (curr != NULL) { 673 nvpair_t *nvp = &curr->nvi_nvp; 674 675 if (strcmp(name, NVP_NAME(nvp)) == 0 && NVP_TYPE(nvp) == type) { 676 nvp_buf_unlink(nvl, nvp); 677 nvpair_free(nvp); 678 nvp_buf_free(nvl, nvp); 679 680 return (0); 681 } 682 curr = curr->nvi_next; 683 } 684 685 return (ENOENT); 686 } 687 688 /* 689 * This function calculates the size of an nvpair value. 690 * 691 * The data argument controls the behavior in case of the data types 692 * DATA_TYPE_STRING and 693 * DATA_TYPE_STRING_ARRAY 694 * Is data == NULL then the size of the string(s) is excluded. 695 */ 696 static int 697 i_get_value_size(data_type_t type, const void *data, uint_t nelem) 698 { 699 uint64_t value_sz; 700 701 if (i_validate_type_nelem(type, nelem) != 0) 702 return (-1); 703 704 /* Calculate required size for holding value */ 705 switch (type) { 706 case DATA_TYPE_BOOLEAN: 707 value_sz = 0; 708 break; 709 case DATA_TYPE_BOOLEAN_VALUE: 710 value_sz = sizeof (boolean_t); 711 break; 712 case DATA_TYPE_BYTE: 713 value_sz = sizeof (uchar_t); 714 break; 715 case DATA_TYPE_INT8: 716 value_sz = sizeof (int8_t); 717 break; 718 case DATA_TYPE_UINT8: 719 value_sz = sizeof (uint8_t); 720 break; 721 case DATA_TYPE_INT16: 722 value_sz = sizeof (int16_t); 723 break; 724 case DATA_TYPE_UINT16: 725 value_sz = sizeof (uint16_t); 726 break; 727 case DATA_TYPE_INT32: 728 value_sz = sizeof (int32_t); 729 break; 730 case DATA_TYPE_UINT32: 731 value_sz = sizeof (uint32_t); 732 break; 733 case DATA_TYPE_INT64: 734 value_sz = sizeof (int64_t); 735 break; 736 case DATA_TYPE_UINT64: 737 value_sz = sizeof (uint64_t); 738 break; 739 case DATA_TYPE_STRING: 740 if (data == NULL) 741 value_sz = 0; 742 else 743 value_sz = strlen(data) + 1; 744 break; 745 case DATA_TYPE_BOOLEAN_ARRAY: 746 value_sz = (uint64_t)nelem * sizeof (boolean_t); 747 break; 748 case DATA_TYPE_BYTE_ARRAY: 749 value_sz = (uint64_t)nelem * sizeof (uchar_t); 750 break; 751 case DATA_TYPE_INT8_ARRAY: 752 value_sz = (uint64_t)nelem * sizeof (int8_t); 753 break; 754 case DATA_TYPE_UINT8_ARRAY: 755 value_sz = (uint64_t)nelem * sizeof (uint8_t); 756 break; 757 case DATA_TYPE_INT16_ARRAY: 758 value_sz = (uint64_t)nelem * sizeof (int16_t); 759 break; 760 case DATA_TYPE_UINT16_ARRAY: 761 value_sz = (uint64_t)nelem * sizeof (uint16_t); 762 break; 763 case DATA_TYPE_INT32_ARRAY: 764 value_sz = (uint64_t)nelem * sizeof (int32_t); 765 break; 766 case DATA_TYPE_UINT32_ARRAY: 767 value_sz = (uint64_t)nelem * sizeof (uint32_t); 768 break; 769 case DATA_TYPE_INT64_ARRAY: 770 value_sz = (uint64_t)nelem * sizeof (int64_t); 771 break; 772 case DATA_TYPE_UINT64_ARRAY: 773 value_sz = (uint64_t)nelem * sizeof (uint64_t); 774 break; 775 case DATA_TYPE_STRING_ARRAY: 776 value_sz = (uint64_t)nelem * sizeof (uint64_t); 777 778 if (data != NULL) { 779 char *const *strs = data; 780 uint_t i; 781 782 /* no alignment requirement for strings */ 783 for (i = 0; i < nelem; i++) { 784 if (strs[i] == NULL) 785 return (-1); 786 value_sz += strlen(strs[i]) + 1; 787 } 788 } 789 break; 790 case DATA_TYPE_HRTIME: 791 value_sz = sizeof (hrtime_t); 792 break; 793 case DATA_TYPE_NVLIST: 794 value_sz = NV_ALIGN(sizeof (nvlist_t)); 795 break; 796 case DATA_TYPE_NVLIST_ARRAY: 797 value_sz = (uint64_t)nelem * sizeof (uint64_t) + 798 (uint64_t)nelem * NV_ALIGN(sizeof (nvlist_t)); 799 break; 800 default: 801 return (-1); 802 } 803 804 return (value_sz > INT32_MAX ? -1 : (int)value_sz); 805 } 806 807 static int 808 nvlist_copy_embedded(nvlist_t *nvl, nvlist_t *onvl, nvlist_t *emb_nvl) 809 { 810 nvpriv_t *priv; 811 int err; 812 813 if ((priv = nv_priv_alloc_embedded((nvpriv_t *)(uintptr_t) 814 nvl->nvl_priv)) == NULL) 815 return (ENOMEM); 816 817 nvlist_init(emb_nvl, onvl->nvl_nvflag, priv); 818 819 if ((err = nvlist_copy_pairs(onvl, emb_nvl)) != 0) { 820 nvlist_free(emb_nvl); 821 emb_nvl->nvl_priv = 0; 822 } 823 824 return (err); 825 } 826 827 /* 828 * nvlist_add_common - Add new <name,value> pair to nvlist 829 */ 830 static int 831 nvlist_add_common(nvlist_t *nvl, const char *name, 832 data_type_t type, uint_t nelem, const void *data) 833 { 834 nvpair_t *nvp; 835 uint_t i; 836 837 int nvp_sz, name_sz, value_sz; 838 int err = 0; 839 840 if (name == NULL || nvl == NULL || nvl->nvl_priv == 0) 841 return (EINVAL); 842 843 if (nelem != 0 && data == NULL) 844 return (EINVAL); 845 846 /* 847 * Verify type and nelem and get the value size. 848 * In case of data types DATA_TYPE_STRING and DATA_TYPE_STRING_ARRAY 849 * is the size of the string(s) included. 850 */ 851 if ((value_sz = i_get_value_size(type, data, nelem)) < 0) 852 return (EINVAL); 853 854 if (i_validate_nvpair_value(type, nelem, data) != 0) 855 return (EINVAL); 856 857 /* 858 * If we're adding an nvlist or nvlist array, ensure that we are not 859 * adding the input nvlist to itself, which would cause recursion, 860 * and ensure that no NULL nvlist pointers are present. 861 */ 862 switch (type) { 863 case DATA_TYPE_NVLIST: 864 if (data == nvl || data == NULL) 865 return (EINVAL); 866 break; 867 case DATA_TYPE_NVLIST_ARRAY: { 868 nvlist_t **onvlp = (nvlist_t **)data; 869 for (i = 0; i < nelem; i++) { 870 if (onvlp[i] == nvl || onvlp[i] == NULL) 871 return (EINVAL); 872 } 873 break; 874 } 875 default: 876 break; 877 } 878 879 /* calculate sizes of the nvpair elements and the nvpair itself */ 880 name_sz = strlen(name) + 1; 881 882 nvp_sz = NVP_SIZE_CALC(name_sz, value_sz); 883 884 if ((nvp = nvp_buf_alloc(nvl, nvp_sz)) == NULL) 885 return (ENOMEM); 886 887 ASSERT(nvp->nvp_size == nvp_sz); 888 nvp->nvp_name_sz = name_sz; 889 nvp->nvp_value_elem = nelem; 890 nvp->nvp_type = type; 891 bcopy(name, NVP_NAME(nvp), name_sz); 892 893 switch (type) { 894 case DATA_TYPE_BOOLEAN: 895 break; 896 case DATA_TYPE_STRING_ARRAY: { 897 char *const *strs = data; 898 char *buf = NVP_VALUE(nvp); 899 char **cstrs = (void *)buf; 900 901 /* skip pre-allocated space for pointer array */ 902 buf += nelem * sizeof (uint64_t); 903 for (i = 0; i < nelem; i++) { 904 int slen = strlen(strs[i]) + 1; 905 bcopy(strs[i], buf, slen); 906 cstrs[i] = buf; 907 buf += slen; 908 } 909 break; 910 } 911 case DATA_TYPE_NVLIST: { 912 nvlist_t *nnvl = EMBEDDED_NVL(nvp); 913 nvlist_t *onvl = (nvlist_t *)data; 914 915 if ((err = nvlist_copy_embedded(nvl, onvl, nnvl)) != 0) { 916 nvp_buf_free(nvl, nvp); 917 return (err); 918 } 919 break; 920 } 921 case DATA_TYPE_NVLIST_ARRAY: { 922 nvlist_t **onvlp = (nvlist_t **)data; 923 nvlist_t **nvlp = EMBEDDED_NVL_ARRAY(nvp); 924 nvlist_t *embedded = (nvlist_t *) 925 ((uintptr_t)nvlp + nelem * sizeof (uint64_t)); 926 927 for (i = 0; i < nelem; i++) { 928 if ((err = nvlist_copy_embedded(nvl, 929 onvlp[i], embedded)) != 0) { 930 /* 931 * Free any successfully created lists 932 */ 933 nvpair_free(nvp); 934 nvp_buf_free(nvl, nvp); 935 return (err); 936 } 937 938 nvlp[i] = embedded++; 939 } 940 break; 941 } 942 default: 943 bcopy(data, NVP_VALUE(nvp), value_sz); 944 } 945 946 /* if unique name, remove before add */ 947 if (nvl->nvl_nvflag & NV_UNIQUE_NAME) 948 (void) nvlist_remove_all(nvl, name); 949 else if (nvl->nvl_nvflag & NV_UNIQUE_NAME_TYPE) 950 (void) nvlist_remove(nvl, name, type); 951 952 nvp_buf_link(nvl, nvp); 953 954 return (0); 955 } 956 957 int 958 nvlist_add_boolean(nvlist_t *nvl, const char *name) 959 { 960 return (nvlist_add_common(nvl, name, DATA_TYPE_BOOLEAN, 0, NULL)); 961 } 962 963 int 964 nvlist_add_boolean_value(nvlist_t *nvl, const char *name, boolean_t val) 965 { 966 return (nvlist_add_common(nvl, name, DATA_TYPE_BOOLEAN_VALUE, 1, &val)); 967 } 968 969 int 970 nvlist_add_byte(nvlist_t *nvl, const char *name, uchar_t val) 971 { 972 return (nvlist_add_common(nvl, name, DATA_TYPE_BYTE, 1, &val)); 973 } 974 975 int 976 nvlist_add_int8(nvlist_t *nvl, const char *name, int8_t val) 977 { 978 return (nvlist_add_common(nvl, name, DATA_TYPE_INT8, 1, &val)); 979 } 980 981 int 982 nvlist_add_uint8(nvlist_t *nvl, const char *name, uint8_t val) 983 { 984 return (nvlist_add_common(nvl, name, DATA_TYPE_UINT8, 1, &val)); 985 } 986 987 int 988 nvlist_add_int16(nvlist_t *nvl, const char *name, int16_t val) 989 { 990 return (nvlist_add_common(nvl, name, DATA_TYPE_INT16, 1, &val)); 991 } 992 993 int 994 nvlist_add_uint16(nvlist_t *nvl, const char *name, uint16_t val) 995 { 996 return (nvlist_add_common(nvl, name, DATA_TYPE_UINT16, 1, &val)); 997 } 998 999 int 1000 nvlist_add_int32(nvlist_t *nvl, const char *name, int32_t val) 1001 { 1002 return (nvlist_add_common(nvl, name, DATA_TYPE_INT32, 1, &val)); 1003 } 1004 1005 int 1006 nvlist_add_uint32(nvlist_t *nvl, const char *name, uint32_t val) 1007 { 1008 return (nvlist_add_common(nvl, name, DATA_TYPE_UINT32, 1, &val)); 1009 } 1010 1011 int 1012 nvlist_add_int64(nvlist_t *nvl, const char *name, int64_t val) 1013 { 1014 return (nvlist_add_common(nvl, name, DATA_TYPE_INT64, 1, &val)); 1015 } 1016 1017 int 1018 nvlist_add_uint64(nvlist_t *nvl, const char *name, uint64_t val) 1019 { 1020 return (nvlist_add_common(nvl, name, DATA_TYPE_UINT64, 1, &val)); 1021 } 1022 1023 int 1024 nvlist_add_string(nvlist_t *nvl, const char *name, const char *val) 1025 { 1026 return (nvlist_add_common(nvl, name, DATA_TYPE_STRING, 1, (void *)val)); 1027 } 1028 1029 int 1030 nvlist_add_boolean_array(nvlist_t *nvl, const char *name, 1031 boolean_t *a, uint_t n) 1032 { 1033 return (nvlist_add_common(nvl, name, DATA_TYPE_BOOLEAN_ARRAY, n, a)); 1034 } 1035 1036 int 1037 nvlist_add_byte_array(nvlist_t *nvl, const char *name, uchar_t *a, uint_t n) 1038 { 1039 return (nvlist_add_common(nvl, name, DATA_TYPE_BYTE_ARRAY, n, a)); 1040 } 1041 1042 int 1043 nvlist_add_int8_array(nvlist_t *nvl, const char *name, int8_t *a, uint_t n) 1044 { 1045 return (nvlist_add_common(nvl, name, DATA_TYPE_INT8_ARRAY, n, a)); 1046 } 1047 1048 int 1049 nvlist_add_uint8_array(nvlist_t *nvl, const char *name, uint8_t *a, uint_t n) 1050 { 1051 return (nvlist_add_common(nvl, name, DATA_TYPE_UINT8_ARRAY, n, a)); 1052 } 1053 1054 int 1055 nvlist_add_int16_array(nvlist_t *nvl, const char *name, int16_t *a, uint_t n) 1056 { 1057 return (nvlist_add_common(nvl, name, DATA_TYPE_INT16_ARRAY, n, a)); 1058 } 1059 1060 int 1061 nvlist_add_uint16_array(nvlist_t *nvl, const char *name, uint16_t *a, uint_t n) 1062 { 1063 return (nvlist_add_common(nvl, name, DATA_TYPE_UINT16_ARRAY, n, a)); 1064 } 1065 1066 int 1067 nvlist_add_int32_array(nvlist_t *nvl, const char *name, int32_t *a, uint_t n) 1068 { 1069 return (nvlist_add_common(nvl, name, DATA_TYPE_INT32_ARRAY, n, a)); 1070 } 1071 1072 int 1073 nvlist_add_uint32_array(nvlist_t *nvl, const char *name, uint32_t *a, uint_t n) 1074 { 1075 return (nvlist_add_common(nvl, name, DATA_TYPE_UINT32_ARRAY, n, a)); 1076 } 1077 1078 int 1079 nvlist_add_int64_array(nvlist_t *nvl, const char *name, int64_t *a, uint_t n) 1080 { 1081 return (nvlist_add_common(nvl, name, DATA_TYPE_INT64_ARRAY, n, a)); 1082 } 1083 1084 int 1085 nvlist_add_uint64_array(nvlist_t *nvl, const char *name, uint64_t *a, uint_t n) 1086 { 1087 return (nvlist_add_common(nvl, name, DATA_TYPE_UINT64_ARRAY, n, a)); 1088 } 1089 1090 int 1091 nvlist_add_string_array(nvlist_t *nvl, const char *name, 1092 char *const *a, uint_t n) 1093 { 1094 return (nvlist_add_common(nvl, name, DATA_TYPE_STRING_ARRAY, n, a)); 1095 } 1096 1097 int 1098 nvlist_add_hrtime(nvlist_t *nvl, const char *name, hrtime_t val) 1099 { 1100 return (nvlist_add_common(nvl, name, DATA_TYPE_HRTIME, 1, &val)); 1101 } 1102 1103 int 1104 nvlist_add_nvlist(nvlist_t *nvl, const char *name, nvlist_t *val) 1105 { 1106 return (nvlist_add_common(nvl, name, DATA_TYPE_NVLIST, 1, val)); 1107 } 1108 1109 int 1110 nvlist_add_nvlist_array(nvlist_t *nvl, const char *name, nvlist_t **a, uint_t n) 1111 { 1112 return (nvlist_add_common(nvl, name, DATA_TYPE_NVLIST_ARRAY, n, a)); 1113 } 1114 1115 /* reading name-value pairs */ 1116 nvpair_t * 1117 nvlist_next_nvpair(nvlist_t *nvl, nvpair_t *nvp) 1118 { 1119 nvpriv_t *priv; 1120 i_nvp_t *curr; 1121 1122 if (nvl == NULL || 1123 (priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL) 1124 return (NULL); 1125 1126 curr = NVPAIR2I_NVP(nvp); 1127 1128 /* 1129 * Ensure that nvp is a valid nvpair on this nvlist. 1130 * NB: nvp_curr is used only as a hint so that we don't always 1131 * have to walk the list to determine if nvp is still on the list. 1132 */ 1133 if (nvp == NULL) 1134 curr = priv->nvp_list; 1135 else if (priv->nvp_curr == curr || nvlist_contains_nvp(nvl, nvp)) 1136 curr = curr->nvi_next; 1137 else 1138 curr = NULL; 1139 1140 priv->nvp_curr = curr; 1141 1142 return (curr != NULL ? &curr->nvi_nvp : NULL); 1143 } 1144 1145 char * 1146 nvpair_name(nvpair_t *nvp) 1147 { 1148 return (NVP_NAME(nvp)); 1149 } 1150 1151 data_type_t 1152 nvpair_type(nvpair_t *nvp) 1153 { 1154 return (NVP_TYPE(nvp)); 1155 } 1156 1157 static int 1158 nvpair_value_common(nvpair_t *nvp, data_type_t type, uint_t *nelem, void *data) 1159 { 1160 if (nvp == NULL || nvpair_type(nvp) != type) 1161 return (EINVAL); 1162 1163 /* 1164 * For non-array types, we copy the data. 1165 * For array types (including string), we set a pointer. 1166 */ 1167 switch (type) { 1168 case DATA_TYPE_BOOLEAN: 1169 if (nelem != NULL) 1170 *nelem = 0; 1171 break; 1172 1173 case DATA_TYPE_BOOLEAN_VALUE: 1174 case DATA_TYPE_BYTE: 1175 case DATA_TYPE_INT8: 1176 case DATA_TYPE_UINT8: 1177 case DATA_TYPE_INT16: 1178 case DATA_TYPE_UINT16: 1179 case DATA_TYPE_INT32: 1180 case DATA_TYPE_UINT32: 1181 case DATA_TYPE_INT64: 1182 case DATA_TYPE_UINT64: 1183 case DATA_TYPE_HRTIME: 1184 if (data == NULL) 1185 return (EINVAL); 1186 bcopy(NVP_VALUE(nvp), data, 1187 (size_t)i_get_value_size(type, NULL, 1)); 1188 if (nelem != NULL) 1189 *nelem = 1; 1190 break; 1191 1192 case DATA_TYPE_NVLIST: 1193 case DATA_TYPE_STRING: 1194 if (data == NULL) 1195 return (EINVAL); 1196 *(void **)data = (void *)NVP_VALUE(nvp); 1197 if (nelem != NULL) 1198 *nelem = 1; 1199 break; 1200 1201 case DATA_TYPE_BOOLEAN_ARRAY: 1202 case DATA_TYPE_BYTE_ARRAY: 1203 case DATA_TYPE_INT8_ARRAY: 1204 case DATA_TYPE_UINT8_ARRAY: 1205 case DATA_TYPE_INT16_ARRAY: 1206 case DATA_TYPE_UINT16_ARRAY: 1207 case DATA_TYPE_INT32_ARRAY: 1208 case DATA_TYPE_UINT32_ARRAY: 1209 case DATA_TYPE_INT64_ARRAY: 1210 case DATA_TYPE_UINT64_ARRAY: 1211 case DATA_TYPE_STRING_ARRAY: 1212 case DATA_TYPE_NVLIST_ARRAY: 1213 if (nelem == NULL || data == NULL) 1214 return (EINVAL); 1215 if ((*nelem = NVP_NELEM(nvp)) != 0) 1216 *(void **)data = (void *)NVP_VALUE(nvp); 1217 else 1218 *(void **)data = NULL; 1219 break; 1220 1221 default: 1222 return (ENOTSUP); 1223 } 1224 1225 return (0); 1226 } 1227 1228 static int 1229 nvlist_lookup_common(nvlist_t *nvl, const char *name, data_type_t type, 1230 uint_t *nelem, void *data) 1231 { 1232 nvpriv_t *priv; 1233 nvpair_t *nvp; 1234 i_nvp_t *curr; 1235 1236 if (name == NULL || nvl == NULL || 1237 (priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL) 1238 return (EINVAL); 1239 1240 if (!(nvl->nvl_nvflag & (NV_UNIQUE_NAME | NV_UNIQUE_NAME_TYPE))) 1241 return (ENOTSUP); 1242 1243 for (curr = priv->nvp_list; curr != NULL; curr = curr->nvi_next) { 1244 nvp = &curr->nvi_nvp; 1245 1246 if (strcmp(name, NVP_NAME(nvp)) == 0 && NVP_TYPE(nvp) == type) 1247 return (nvpair_value_common(nvp, type, nelem, data)); 1248 } 1249 1250 return (ENOENT); 1251 } 1252 1253 int 1254 nvlist_lookup_boolean(nvlist_t *nvl, const char *name) 1255 { 1256 return (nvlist_lookup_common(nvl, name, DATA_TYPE_BOOLEAN, NULL, NULL)); 1257 } 1258 1259 int 1260 nvlist_lookup_boolean_value(nvlist_t *nvl, const char *name, boolean_t *val) 1261 { 1262 return (nvlist_lookup_common(nvl, name, 1263 DATA_TYPE_BOOLEAN_VALUE, NULL, val)); 1264 } 1265 1266 int 1267 nvlist_lookup_byte(nvlist_t *nvl, const char *name, uchar_t *val) 1268 { 1269 return (nvlist_lookup_common(nvl, name, DATA_TYPE_BYTE, NULL, val)); 1270 } 1271 1272 int 1273 nvlist_lookup_int8(nvlist_t *nvl, const char *name, int8_t *val) 1274 { 1275 return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT8, NULL, val)); 1276 } 1277 1278 int 1279 nvlist_lookup_uint8(nvlist_t *nvl, const char *name, uint8_t *val) 1280 { 1281 return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT8, NULL, val)); 1282 } 1283 1284 int 1285 nvlist_lookup_int16(nvlist_t *nvl, const char *name, int16_t *val) 1286 { 1287 return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT16, NULL, val)); 1288 } 1289 1290 int 1291 nvlist_lookup_uint16(nvlist_t *nvl, const char *name, uint16_t *val) 1292 { 1293 return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT16, NULL, val)); 1294 } 1295 1296 int 1297 nvlist_lookup_int32(nvlist_t *nvl, const char *name, int32_t *val) 1298 { 1299 return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT32, NULL, val)); 1300 } 1301 1302 int 1303 nvlist_lookup_uint32(nvlist_t *nvl, const char *name, uint32_t *val) 1304 { 1305 return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT32, NULL, val)); 1306 } 1307 1308 int 1309 nvlist_lookup_int64(nvlist_t *nvl, const char *name, int64_t *val) 1310 { 1311 return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT64, NULL, val)); 1312 } 1313 1314 int 1315 nvlist_lookup_uint64(nvlist_t *nvl, const char *name, uint64_t *val) 1316 { 1317 return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT64, NULL, val)); 1318 } 1319 1320 int 1321 nvlist_lookup_string(nvlist_t *nvl, const char *name, char **val) 1322 { 1323 return (nvlist_lookup_common(nvl, name, DATA_TYPE_STRING, NULL, val)); 1324 } 1325 1326 int 1327 nvlist_lookup_nvlist(nvlist_t *nvl, const char *name, nvlist_t **val) 1328 { 1329 return (nvlist_lookup_common(nvl, name, DATA_TYPE_NVLIST, NULL, val)); 1330 } 1331 1332 int 1333 nvlist_lookup_boolean_array(nvlist_t *nvl, const char *name, 1334 boolean_t **a, uint_t *n) 1335 { 1336 return (nvlist_lookup_common(nvl, name, 1337 DATA_TYPE_BOOLEAN_ARRAY, n, a)); 1338 } 1339 1340 int 1341 nvlist_lookup_byte_array(nvlist_t *nvl, const char *name, 1342 uchar_t **a, uint_t *n) 1343 { 1344 return (nvlist_lookup_common(nvl, name, DATA_TYPE_BYTE_ARRAY, n, a)); 1345 } 1346 1347 int 1348 nvlist_lookup_int8_array(nvlist_t *nvl, const char *name, int8_t **a, uint_t *n) 1349 { 1350 return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT8_ARRAY, n, a)); 1351 } 1352 1353 int 1354 nvlist_lookup_uint8_array(nvlist_t *nvl, const char *name, 1355 uint8_t **a, uint_t *n) 1356 { 1357 return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT8_ARRAY, n, a)); 1358 } 1359 1360 int 1361 nvlist_lookup_int16_array(nvlist_t *nvl, const char *name, 1362 int16_t **a, uint_t *n) 1363 { 1364 return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT16_ARRAY, n, a)); 1365 } 1366 1367 int 1368 nvlist_lookup_uint16_array(nvlist_t *nvl, const char *name, 1369 uint16_t **a, uint_t *n) 1370 { 1371 return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT16_ARRAY, n, a)); 1372 } 1373 1374 int 1375 nvlist_lookup_int32_array(nvlist_t *nvl, const char *name, 1376 int32_t **a, uint_t *n) 1377 { 1378 return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT32_ARRAY, n, a)); 1379 } 1380 1381 int 1382 nvlist_lookup_uint32_array(nvlist_t *nvl, const char *name, 1383 uint32_t **a, uint_t *n) 1384 { 1385 return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT32_ARRAY, n, a)); 1386 } 1387 1388 int 1389 nvlist_lookup_int64_array(nvlist_t *nvl, const char *name, 1390 int64_t **a, uint_t *n) 1391 { 1392 return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT64_ARRAY, n, a)); 1393 } 1394 1395 int 1396 nvlist_lookup_uint64_array(nvlist_t *nvl, const char *name, 1397 uint64_t **a, uint_t *n) 1398 { 1399 return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT64_ARRAY, n, a)); 1400 } 1401 1402 int 1403 nvlist_lookup_string_array(nvlist_t *nvl, const char *name, 1404 char ***a, uint_t *n) 1405 { 1406 return (nvlist_lookup_common(nvl, name, DATA_TYPE_STRING_ARRAY, n, a)); 1407 } 1408 1409 int 1410 nvlist_lookup_nvlist_array(nvlist_t *nvl, const char *name, 1411 nvlist_t ***a, uint_t *n) 1412 { 1413 return (nvlist_lookup_common(nvl, name, DATA_TYPE_NVLIST_ARRAY, n, a)); 1414 } 1415 1416 int 1417 nvlist_lookup_hrtime(nvlist_t *nvl, const char *name, hrtime_t *val) 1418 { 1419 return (nvlist_lookup_common(nvl, name, DATA_TYPE_HRTIME, NULL, val)); 1420 } 1421 1422 int 1423 nvlist_lookup_pairs(nvlist_t *nvl, int flag, ...) 1424 { 1425 va_list ap; 1426 char *name; 1427 int noentok = (flag & NV_FLAG_NOENTOK ? 1 : 0); 1428 int ret = 0; 1429 1430 va_start(ap, flag); 1431 while (ret == 0 && (name = va_arg(ap, char *)) != NULL) { 1432 data_type_t type; 1433 void *val; 1434 uint_t *nelem; 1435 1436 switch (type = va_arg(ap, data_type_t)) { 1437 case DATA_TYPE_BOOLEAN: 1438 ret = nvlist_lookup_common(nvl, name, type, NULL, NULL); 1439 break; 1440 1441 case DATA_TYPE_BOOLEAN_VALUE: 1442 case DATA_TYPE_BYTE: 1443 case DATA_TYPE_INT8: 1444 case DATA_TYPE_UINT8: 1445 case DATA_TYPE_INT16: 1446 case DATA_TYPE_UINT16: 1447 case DATA_TYPE_INT32: 1448 case DATA_TYPE_UINT32: 1449 case DATA_TYPE_INT64: 1450 case DATA_TYPE_UINT64: 1451 case DATA_TYPE_HRTIME: 1452 case DATA_TYPE_STRING: 1453 case DATA_TYPE_NVLIST: 1454 val = va_arg(ap, void *); 1455 ret = nvlist_lookup_common(nvl, name, type, NULL, val); 1456 break; 1457 1458 case DATA_TYPE_BYTE_ARRAY: 1459 case DATA_TYPE_BOOLEAN_ARRAY: 1460 case DATA_TYPE_INT8_ARRAY: 1461 case DATA_TYPE_UINT8_ARRAY: 1462 case DATA_TYPE_INT16_ARRAY: 1463 case DATA_TYPE_UINT16_ARRAY: 1464 case DATA_TYPE_INT32_ARRAY: 1465 case DATA_TYPE_UINT32_ARRAY: 1466 case DATA_TYPE_INT64_ARRAY: 1467 case DATA_TYPE_UINT64_ARRAY: 1468 case DATA_TYPE_STRING_ARRAY: 1469 case DATA_TYPE_NVLIST_ARRAY: 1470 val = va_arg(ap, void *); 1471 nelem = va_arg(ap, uint_t *); 1472 ret = nvlist_lookup_common(nvl, name, type, nelem, val); 1473 break; 1474 1475 default: 1476 ret = EINVAL; 1477 } 1478 1479 if (ret == ENOENT && noentok) 1480 ret = 0; 1481 } 1482 va_end(ap); 1483 1484 return (ret); 1485 } 1486 1487 int 1488 nvlist_lookup_nvpair(nvlist_t *nvl, const char *name, nvpair_t **ret) 1489 { 1490 nvpriv_t *priv; 1491 nvpair_t *nvp; 1492 i_nvp_t *curr; 1493 1494 if (name == NULL || nvl == NULL || 1495 (priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL) 1496 return (EINVAL); 1497 1498 if (!(nvl->nvl_nvflag & NV_UNIQUE_NAME)) 1499 return (ENOTSUP); 1500 1501 for (curr = priv->nvp_list; curr != NULL; curr = curr->nvi_next) { 1502 nvp = &curr->nvi_nvp; 1503 1504 if (strcmp(name, NVP_NAME(nvp)) == 0) { 1505 *ret = nvp; 1506 return (0); 1507 } 1508 } 1509 1510 return (ENOENT); 1511 } 1512 1513 boolean_t 1514 nvlist_exists(nvlist_t *nvl, const char *name) 1515 { 1516 nvpriv_t *priv; 1517 nvpair_t *nvp; 1518 i_nvp_t *curr; 1519 1520 if (name == NULL || nvl == NULL || 1521 (priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL) 1522 return (B_FALSE); 1523 1524 for (curr = priv->nvp_list; curr != NULL; curr = curr->nvi_next) { 1525 nvp = &curr->nvi_nvp; 1526 1527 if (strcmp(name, NVP_NAME(nvp)) == 0) 1528 return (B_TRUE); 1529 } 1530 1531 return (B_FALSE); 1532 } 1533 1534 int 1535 nvpair_value_boolean_value(nvpair_t *nvp, boolean_t *val) 1536 { 1537 return (nvpair_value_common(nvp, DATA_TYPE_BOOLEAN_VALUE, NULL, val)); 1538 } 1539 1540 int 1541 nvpair_value_byte(nvpair_t *nvp, uchar_t *val) 1542 { 1543 return (nvpair_value_common(nvp, DATA_TYPE_BYTE, NULL, val)); 1544 } 1545 1546 int 1547 nvpair_value_int8(nvpair_t *nvp, int8_t *val) 1548 { 1549 return (nvpair_value_common(nvp, DATA_TYPE_INT8, NULL, val)); 1550 } 1551 1552 int 1553 nvpair_value_uint8(nvpair_t *nvp, uint8_t *val) 1554 { 1555 return (nvpair_value_common(nvp, DATA_TYPE_UINT8, NULL, val)); 1556 } 1557 1558 int 1559 nvpair_value_int16(nvpair_t *nvp, int16_t *val) 1560 { 1561 return (nvpair_value_common(nvp, DATA_TYPE_INT16, NULL, val)); 1562 } 1563 1564 int 1565 nvpair_value_uint16(nvpair_t *nvp, uint16_t *val) 1566 { 1567 return (nvpair_value_common(nvp, DATA_TYPE_UINT16, NULL, val)); 1568 } 1569 1570 int 1571 nvpair_value_int32(nvpair_t *nvp, int32_t *val) 1572 { 1573 return (nvpair_value_common(nvp, DATA_TYPE_INT32, NULL, val)); 1574 } 1575 1576 int 1577 nvpair_value_uint32(nvpair_t *nvp, uint32_t *val) 1578 { 1579 return (nvpair_value_common(nvp, DATA_TYPE_UINT32, NULL, val)); 1580 } 1581 1582 int 1583 nvpair_value_int64(nvpair_t *nvp, int64_t *val) 1584 { 1585 return (nvpair_value_common(nvp, DATA_TYPE_INT64, NULL, val)); 1586 } 1587 1588 int 1589 nvpair_value_uint64(nvpair_t *nvp, uint64_t *val) 1590 { 1591 return (nvpair_value_common(nvp, DATA_TYPE_UINT64, NULL, val)); 1592 } 1593 1594 int 1595 nvpair_value_string(nvpair_t *nvp, char **val) 1596 { 1597 return (nvpair_value_common(nvp, DATA_TYPE_STRING, NULL, val)); 1598 } 1599 1600 int 1601 nvpair_value_nvlist(nvpair_t *nvp, nvlist_t **val) 1602 { 1603 return (nvpair_value_common(nvp, DATA_TYPE_NVLIST, NULL, val)); 1604 } 1605 1606 int 1607 nvpair_value_boolean_array(nvpair_t *nvp, boolean_t **val, uint_t *nelem) 1608 { 1609 return (nvpair_value_common(nvp, DATA_TYPE_BOOLEAN_ARRAY, nelem, val)); 1610 } 1611 1612 int 1613 nvpair_value_byte_array(nvpair_t *nvp, uchar_t **val, uint_t *nelem) 1614 { 1615 return (nvpair_value_common(nvp, DATA_TYPE_BYTE_ARRAY, nelem, val)); 1616 } 1617 1618 int 1619 nvpair_value_int8_array(nvpair_t *nvp, int8_t **val, uint_t *nelem) 1620 { 1621 return (nvpair_value_common(nvp, DATA_TYPE_INT8_ARRAY, nelem, val)); 1622 } 1623 1624 int 1625 nvpair_value_uint8_array(nvpair_t *nvp, uint8_t **val, uint_t *nelem) 1626 { 1627 return (nvpair_value_common(nvp, DATA_TYPE_UINT8_ARRAY, nelem, val)); 1628 } 1629 1630 int 1631 nvpair_value_int16_array(nvpair_t *nvp, int16_t **val, uint_t *nelem) 1632 { 1633 return (nvpair_value_common(nvp, DATA_TYPE_INT16_ARRAY, nelem, val)); 1634 } 1635 1636 int 1637 nvpair_value_uint16_array(nvpair_t *nvp, uint16_t **val, uint_t *nelem) 1638 { 1639 return (nvpair_value_common(nvp, DATA_TYPE_UINT16_ARRAY, nelem, val)); 1640 } 1641 1642 int 1643 nvpair_value_int32_array(nvpair_t *nvp, int32_t **val, uint_t *nelem) 1644 { 1645 return (nvpair_value_common(nvp, DATA_TYPE_INT32_ARRAY, nelem, val)); 1646 } 1647 1648 int 1649 nvpair_value_uint32_array(nvpair_t *nvp, uint32_t **val, uint_t *nelem) 1650 { 1651 return (nvpair_value_common(nvp, DATA_TYPE_UINT32_ARRAY, nelem, val)); 1652 } 1653 1654 int 1655 nvpair_value_int64_array(nvpair_t *nvp, int64_t **val, uint_t *nelem) 1656 { 1657 return (nvpair_value_common(nvp, DATA_TYPE_INT64_ARRAY, nelem, val)); 1658 } 1659 1660 int 1661 nvpair_value_uint64_array(nvpair_t *nvp, uint64_t **val, uint_t *nelem) 1662 { 1663 return (nvpair_value_common(nvp, DATA_TYPE_UINT64_ARRAY, nelem, val)); 1664 } 1665 1666 int 1667 nvpair_value_string_array(nvpair_t *nvp, char ***val, uint_t *nelem) 1668 { 1669 return (nvpair_value_common(nvp, DATA_TYPE_STRING_ARRAY, nelem, val)); 1670 } 1671 1672 int 1673 nvpair_value_nvlist_array(nvpair_t *nvp, nvlist_t ***val, uint_t *nelem) 1674 { 1675 return (nvpair_value_common(nvp, DATA_TYPE_NVLIST_ARRAY, nelem, val)); 1676 } 1677 1678 int 1679 nvpair_value_hrtime(nvpair_t *nvp, hrtime_t *val) 1680 { 1681 return (nvpair_value_common(nvp, DATA_TYPE_HRTIME, NULL, val)); 1682 } 1683 1684 /* 1685 * Add specified pair to the list. 1686 */ 1687 int 1688 nvlist_add_nvpair(nvlist_t *nvl, nvpair_t *nvp) 1689 { 1690 if (nvl == NULL || nvp == NULL) 1691 return (EINVAL); 1692 1693 return (nvlist_add_common(nvl, NVP_NAME(nvp), NVP_TYPE(nvp), 1694 NVP_NELEM(nvp), NVP_VALUE(nvp))); 1695 } 1696 1697 /* 1698 * Merge the supplied nvlists and put the result in dst. 1699 * The merged list will contain all names specified in both lists, 1700 * the values are taken from nvl in the case of duplicates. 1701 * Return 0 on success. 1702 */ 1703 /*ARGSUSED*/ 1704 int 1705 nvlist_merge(nvlist_t *dst, nvlist_t *nvl, int flag) 1706 { 1707 if (nvl == NULL || dst == NULL) 1708 return (EINVAL); 1709 1710 if (dst != nvl) 1711 return (nvlist_copy_pairs(nvl, dst)); 1712 1713 return (0); 1714 } 1715 1716 /* 1717 * Encoding related routines 1718 */ 1719 #define NVS_OP_ENCODE 0 1720 #define NVS_OP_DECODE 1 1721 #define NVS_OP_GETSIZE 2 1722 1723 typedef struct nvs_ops nvs_ops_t; 1724 1725 typedef struct { 1726 int nvs_op; 1727 const nvs_ops_t *nvs_ops; 1728 void *nvs_private; 1729 nvpriv_t *nvs_priv; 1730 } nvstream_t; 1731 1732 /* 1733 * nvs operations are: 1734 * - nvs_nvlist 1735 * encoding / decoding of a nvlist header (nvlist_t) 1736 * calculates the size used for header and end detection 1737 * 1738 * - nvs_nvpair 1739 * responsible for the first part of encoding / decoding of an nvpair 1740 * calculates the decoded size of an nvpair 1741 * 1742 * - nvs_nvp_op 1743 * second part of encoding / decoding of an nvpair 1744 * 1745 * - nvs_nvp_size 1746 * calculates the encoding size of an nvpair 1747 * 1748 * - nvs_nvl_fini 1749 * encodes the end detection mark (zeros). 1750 */ 1751 struct nvs_ops { 1752 int (*nvs_nvlist)(nvstream_t *, nvlist_t *, size_t *); 1753 int (*nvs_nvpair)(nvstream_t *, nvpair_t *, size_t *); 1754 int (*nvs_nvp_op)(nvstream_t *, nvpair_t *); 1755 int (*nvs_nvp_size)(nvstream_t *, nvpair_t *, size_t *); 1756 int (*nvs_nvl_fini)(nvstream_t *); 1757 }; 1758 1759 typedef struct { 1760 char nvh_encoding; /* nvs encoding method */ 1761 char nvh_endian; /* nvs endian */ 1762 char nvh_reserved1; /* reserved for future use */ 1763 char nvh_reserved2; /* reserved for future use */ 1764 } nvs_header_t; 1765 1766 static int 1767 nvs_encode_pairs(nvstream_t *nvs, nvlist_t *nvl) 1768 { 1769 nvpriv_t *priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv; 1770 i_nvp_t *curr; 1771 1772 /* 1773 * Walk nvpair in list and encode each nvpair 1774 */ 1775 for (curr = priv->nvp_list; curr != NULL; curr = curr->nvi_next) 1776 if (nvs->nvs_ops->nvs_nvpair(nvs, &curr->nvi_nvp, NULL) != 0) 1777 return (EFAULT); 1778 1779 return (nvs->nvs_ops->nvs_nvl_fini(nvs)); 1780 } 1781 1782 static int 1783 nvs_decode_pairs(nvstream_t *nvs, nvlist_t *nvl) 1784 { 1785 nvpair_t *nvp; 1786 size_t nvsize; 1787 int err; 1788 1789 /* 1790 * Get decoded size of next pair in stream, alloc 1791 * memory for nvpair_t, then decode the nvpair 1792 */ 1793 while ((err = nvs->nvs_ops->nvs_nvpair(nvs, NULL, &nvsize)) == 0) { 1794 if (nvsize == 0) /* end of list */ 1795 break; 1796 1797 /* make sure len makes sense */ 1798 if (nvsize < NVP_SIZE_CALC(1, 0)) 1799 return (EFAULT); 1800 1801 if ((nvp = nvp_buf_alloc(nvl, nvsize)) == NULL) 1802 return (ENOMEM); 1803 1804 if ((err = nvs->nvs_ops->nvs_nvp_op(nvs, nvp)) != 0) { 1805 nvp_buf_free(nvl, nvp); 1806 return (err); 1807 } 1808 1809 if (i_validate_nvpair(nvp) != 0) { 1810 nvpair_free(nvp); 1811 nvp_buf_free(nvl, nvp); 1812 return (EFAULT); 1813 } 1814 1815 nvp_buf_link(nvl, nvp); 1816 } 1817 return (err); 1818 } 1819 1820 static int 1821 nvs_getsize_pairs(nvstream_t *nvs, nvlist_t *nvl, size_t *buflen) 1822 { 1823 nvpriv_t *priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv; 1824 i_nvp_t *curr; 1825 uint64_t nvsize = *buflen; 1826 size_t size; 1827 1828 /* 1829 * Get encoded size of nvpairs in nvlist 1830 */ 1831 for (curr = priv->nvp_list; curr != NULL; curr = curr->nvi_next) { 1832 if (nvs->nvs_ops->nvs_nvp_size(nvs, &curr->nvi_nvp, &size) != 0) 1833 return (EINVAL); 1834 1835 if ((nvsize += size) > INT32_MAX) 1836 return (EINVAL); 1837 } 1838 1839 *buflen = nvsize; 1840 return (0); 1841 } 1842 1843 static int 1844 nvs_operation(nvstream_t *nvs, nvlist_t *nvl, size_t *buflen) 1845 { 1846 int err; 1847 1848 if (nvl->nvl_priv == 0) 1849 return (EFAULT); 1850 1851 /* 1852 * Perform the operation, starting with header, then each nvpair 1853 */ 1854 if ((err = nvs->nvs_ops->nvs_nvlist(nvs, nvl, buflen)) != 0) 1855 return (err); 1856 1857 switch (nvs->nvs_op) { 1858 case NVS_OP_ENCODE: 1859 err = nvs_encode_pairs(nvs, nvl); 1860 break; 1861 1862 case NVS_OP_DECODE: 1863 err = nvs_decode_pairs(nvs, nvl); 1864 break; 1865 1866 case NVS_OP_GETSIZE: 1867 err = nvs_getsize_pairs(nvs, nvl, buflen); 1868 break; 1869 1870 default: 1871 err = EINVAL; 1872 } 1873 1874 return (err); 1875 } 1876 1877 static int 1878 nvs_embedded(nvstream_t *nvs, nvlist_t *embedded) 1879 { 1880 switch (nvs->nvs_op) { 1881 case NVS_OP_ENCODE: 1882 return (nvs_operation(nvs, embedded, NULL)); 1883 1884 case NVS_OP_DECODE: { 1885 nvpriv_t *priv; 1886 int err; 1887 1888 if (embedded->nvl_version != NV_VERSION) 1889 return (ENOTSUP); 1890 1891 if ((priv = nv_priv_alloc_embedded(nvs->nvs_priv)) == NULL) 1892 return (ENOMEM); 1893 1894 nvlist_init(embedded, embedded->nvl_nvflag, priv); 1895 1896 if ((err = nvs_operation(nvs, embedded, NULL)) != 0) 1897 nvlist_free(embedded); 1898 return (err); 1899 } 1900 default: 1901 break; 1902 } 1903 1904 return (EINVAL); 1905 } 1906 1907 static int 1908 nvs_embedded_nvl_array(nvstream_t *nvs, nvpair_t *nvp, size_t *size) 1909 { 1910 size_t nelem = NVP_NELEM(nvp); 1911 nvlist_t **nvlp = EMBEDDED_NVL_ARRAY(nvp); 1912 int i; 1913 1914 switch (nvs->nvs_op) { 1915 case NVS_OP_ENCODE: 1916 for (i = 0; i < nelem; i++) 1917 if (nvs_embedded(nvs, nvlp[i]) != 0) 1918 return (EFAULT); 1919 break; 1920 1921 case NVS_OP_DECODE: { 1922 size_t len = nelem * sizeof (uint64_t); 1923 nvlist_t *embedded = (nvlist_t *)((uintptr_t)nvlp + len); 1924 1925 bzero(nvlp, len); /* don't trust packed data */ 1926 for (i = 0; i < nelem; i++) { 1927 if (nvs_embedded(nvs, embedded) != 0) { 1928 nvpair_free(nvp); 1929 return (EFAULT); 1930 } 1931 1932 nvlp[i] = embedded++; 1933 } 1934 break; 1935 } 1936 case NVS_OP_GETSIZE: { 1937 uint64_t nvsize = 0; 1938 1939 for (i = 0; i < nelem; i++) { 1940 size_t nvp_sz = 0; 1941 1942 if (nvs_operation(nvs, nvlp[i], &nvp_sz) != 0) 1943 return (EINVAL); 1944 1945 if ((nvsize += nvp_sz) > INT32_MAX) 1946 return (EINVAL); 1947 } 1948 1949 *size = nvsize; 1950 break; 1951 } 1952 default: 1953 return (EINVAL); 1954 } 1955 1956 return (0); 1957 } 1958 1959 static int nvs_native(nvstream_t *, nvlist_t *, char *, size_t *); 1960 static int nvs_xdr(nvstream_t *, nvlist_t *, char *, size_t *); 1961 1962 /* 1963 * Common routine for nvlist operations: 1964 * encode, decode, getsize (encoded size). 1965 */ 1966 static int 1967 nvlist_common(nvlist_t *nvl, char *buf, size_t *buflen, int encoding, 1968 int nvs_op) 1969 { 1970 int err = 0; 1971 nvstream_t nvs; 1972 int nvl_endian; 1973 #ifdef _LITTLE_ENDIAN 1974 int host_endian = 1; 1975 #else 1976 int host_endian = 0; 1977 #endif /* _LITTLE_ENDIAN */ 1978 nvs_header_t *nvh = (void *)buf; 1979 1980 if (buflen == NULL || nvl == NULL || 1981 (nvs.nvs_priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL) 1982 return (EINVAL); 1983 1984 nvs.nvs_op = nvs_op; 1985 1986 /* 1987 * For NVS_OP_ENCODE and NVS_OP_DECODE make sure an nvlist and 1988 * a buffer is allocated. The first 4 bytes in the buffer are 1989 * used for encoding method and host endian. 1990 */ 1991 switch (nvs_op) { 1992 case NVS_OP_ENCODE: 1993 if (buf == NULL || *buflen < sizeof (nvs_header_t)) 1994 return (EINVAL); 1995 1996 nvh->nvh_encoding = encoding; 1997 nvh->nvh_endian = nvl_endian = host_endian; 1998 nvh->nvh_reserved1 = 0; 1999 nvh->nvh_reserved2 = 0; 2000 break; 2001 2002 case NVS_OP_DECODE: 2003 if (buf == NULL || *buflen < sizeof (nvs_header_t)) 2004 return (EINVAL); 2005 2006 /* get method of encoding from first byte */ 2007 encoding = nvh->nvh_encoding; 2008 nvl_endian = nvh->nvh_endian; 2009 break; 2010 2011 case NVS_OP_GETSIZE: 2012 nvl_endian = host_endian; 2013 2014 /* 2015 * add the size for encoding 2016 */ 2017 *buflen = sizeof (nvs_header_t); 2018 break; 2019 2020 default: 2021 return (ENOTSUP); 2022 } 2023 2024 /* 2025 * Create an nvstream with proper encoding method 2026 */ 2027 switch (encoding) { 2028 case NV_ENCODE_NATIVE: 2029 /* 2030 * check endianness, in case we are unpacking 2031 * from a file 2032 */ 2033 if (nvl_endian != host_endian) 2034 return (ENOTSUP); 2035 err = nvs_native(&nvs, nvl, buf, buflen); 2036 break; 2037 case NV_ENCODE_XDR: 2038 err = nvs_xdr(&nvs, nvl, buf, buflen); 2039 break; 2040 default: 2041 err = ENOTSUP; 2042 break; 2043 } 2044 2045 return (err); 2046 } 2047 2048 int 2049 nvlist_size(nvlist_t *nvl, size_t *size, int encoding) 2050 { 2051 return (nvlist_common(nvl, NULL, size, encoding, NVS_OP_GETSIZE)); 2052 } 2053 2054 /* 2055 * Pack nvlist into contiguous memory 2056 */ 2057 /*ARGSUSED1*/ 2058 int 2059 nvlist_pack(nvlist_t *nvl, char **bufp, size_t *buflen, int encoding, 2060 int kmflag) 2061 { 2062 #if defined(_KERNEL) && !defined(_BOOT) 2063 return (nvlist_xpack(nvl, bufp, buflen, encoding, 2064 (kmflag == KM_SLEEP ? nv_alloc_sleep : nv_alloc_nosleep))); 2065 #else 2066 return (nvlist_xpack(nvl, bufp, buflen, encoding, nv_alloc_nosleep)); 2067 #endif 2068 } 2069 2070 int 2071 nvlist_xpack(nvlist_t *nvl, char **bufp, size_t *buflen, int encoding, 2072 nv_alloc_t *nva) 2073 { 2074 nvpriv_t nvpriv; 2075 size_t alloc_size; 2076 char *buf; 2077 int err; 2078 2079 if (nva == NULL || nvl == NULL || bufp == NULL || buflen == NULL) 2080 return (EINVAL); 2081 2082 if (*bufp != NULL) 2083 return (nvlist_common(nvl, *bufp, buflen, encoding, 2084 NVS_OP_ENCODE)); 2085 2086 /* 2087 * Here is a difficult situation: 2088 * 1. The nvlist has fixed allocator properties. 2089 * All other nvlist routines (like nvlist_add_*, ...) use 2090 * these properties. 2091 * 2. When using nvlist_pack() the user can specify his own 2092 * allocator properties (e.g. by using KM_NOSLEEP). 2093 * 2094 * We use the user specified properties (2). A clearer solution 2095 * will be to remove the kmflag from nvlist_pack(), but we will 2096 * not change the interface. 2097 */ 2098 nv_priv_init(&nvpriv, nva, 0); 2099 2100 if (err = nvlist_size(nvl, &alloc_size, encoding)) 2101 return (err); 2102 2103 if ((buf = nv_mem_zalloc(&nvpriv, alloc_size)) == NULL) 2104 return (ENOMEM); 2105 2106 if ((err = nvlist_common(nvl, buf, &alloc_size, encoding, 2107 NVS_OP_ENCODE)) != 0) { 2108 nv_mem_free(&nvpriv, buf, alloc_size); 2109 } else { 2110 *buflen = alloc_size; 2111 *bufp = buf; 2112 } 2113 2114 return (err); 2115 } 2116 2117 /* 2118 * Unpack buf into an nvlist_t 2119 */ 2120 /*ARGSUSED1*/ 2121 int 2122 nvlist_unpack(char *buf, size_t buflen, nvlist_t **nvlp, int kmflag) 2123 { 2124 #if defined(_KERNEL) && !defined(_BOOT) 2125 return (nvlist_xunpack(buf, buflen, nvlp, 2126 (kmflag == KM_SLEEP ? nv_alloc_sleep : nv_alloc_nosleep))); 2127 #else 2128 return (nvlist_xunpack(buf, buflen, nvlp, nv_alloc_nosleep)); 2129 #endif 2130 } 2131 2132 int 2133 nvlist_xunpack(char *buf, size_t buflen, nvlist_t **nvlp, nv_alloc_t *nva) 2134 { 2135 nvlist_t *nvl; 2136 int err; 2137 2138 if (nvlp == NULL) 2139 return (EINVAL); 2140 2141 if ((err = nvlist_xalloc(&nvl, 0, nva)) != 0) 2142 return (err); 2143 2144 if ((err = nvlist_common(nvl, buf, &buflen, 0, NVS_OP_DECODE)) != 0) 2145 nvlist_free(nvl); 2146 else 2147 *nvlp = nvl; 2148 2149 return (err); 2150 } 2151 2152 /* 2153 * Native encoding functions 2154 */ 2155 typedef struct { 2156 /* 2157 * This structure is used when decoding a packed nvpair in 2158 * the native format. n_base points to a buffer containing the 2159 * packed nvpair. n_end is a pointer to the end of the buffer. 2160 * (n_end actually points to the first byte past the end of the 2161 * buffer.) n_curr is a pointer that lies between n_base and n_end. 2162 * It points to the current data that we are decoding. 2163 * The amount of data left in the buffer is equal to n_end - n_curr. 2164 * n_flag is used to recognize a packed embedded list. 2165 */ 2166 caddr_t n_base; 2167 caddr_t n_end; 2168 caddr_t n_curr; 2169 uint_t n_flag; 2170 } nvs_native_t; 2171 2172 static int 2173 nvs_native_create(nvstream_t *nvs, nvs_native_t *native, char *buf, 2174 size_t buflen) 2175 { 2176 switch (nvs->nvs_op) { 2177 case NVS_OP_ENCODE: 2178 case NVS_OP_DECODE: 2179 nvs->nvs_private = native; 2180 native->n_curr = native->n_base = buf; 2181 native->n_end = buf + buflen; 2182 native->n_flag = 0; 2183 return (0); 2184 2185 case NVS_OP_GETSIZE: 2186 nvs->nvs_private = native; 2187 native->n_curr = native->n_base = native->n_end = NULL; 2188 native->n_flag = 0; 2189 return (0); 2190 default: 2191 return (EINVAL); 2192 } 2193 } 2194 2195 /*ARGSUSED*/ 2196 static void 2197 nvs_native_destroy(nvstream_t *nvs) 2198 { 2199 } 2200 2201 static int 2202 native_cp(nvstream_t *nvs, void *buf, size_t size) 2203 { 2204 nvs_native_t *native = (nvs_native_t *)nvs->nvs_private; 2205 2206 if (native->n_curr + size > native->n_end) 2207 return (EFAULT); 2208 2209 /* 2210 * The bcopy() below eliminates alignment requirement 2211 * on the buffer (stream) and is preferred over direct access. 2212 */ 2213 switch (nvs->nvs_op) { 2214 case NVS_OP_ENCODE: 2215 bcopy(buf, native->n_curr, size); 2216 break; 2217 case NVS_OP_DECODE: 2218 bcopy(native->n_curr, buf, size); 2219 break; 2220 default: 2221 return (EINVAL); 2222 } 2223 2224 native->n_curr += size; 2225 return (0); 2226 } 2227 2228 /* 2229 * operate on nvlist_t header 2230 */ 2231 static int 2232 nvs_native_nvlist(nvstream_t *nvs, nvlist_t *nvl, size_t *size) 2233 { 2234 nvs_native_t *native = nvs->nvs_private; 2235 2236 switch (nvs->nvs_op) { 2237 case NVS_OP_ENCODE: 2238 case NVS_OP_DECODE: 2239 if (native->n_flag) 2240 return (0); /* packed embedded list */ 2241 2242 native->n_flag = 1; 2243 2244 /* copy version and nvflag of the nvlist_t */ 2245 if (native_cp(nvs, &nvl->nvl_version, sizeof (int32_t)) != 0 || 2246 native_cp(nvs, &nvl->nvl_nvflag, sizeof (int32_t)) != 0) 2247 return (EFAULT); 2248 2249 return (0); 2250 2251 case NVS_OP_GETSIZE: 2252 /* 2253 * if calculate for packed embedded list 2254 * 4 for end of the embedded list 2255 * else 2256 * 2 * sizeof (int32_t) for nvl_version and nvl_nvflag 2257 * and 4 for end of the entire list 2258 */ 2259 if (native->n_flag) { 2260 *size += 4; 2261 } else { 2262 native->n_flag = 1; 2263 *size += 2 * sizeof (int32_t) + 4; 2264 } 2265 2266 return (0); 2267 2268 default: 2269 return (EINVAL); 2270 } 2271 } 2272 2273 static int 2274 nvs_native_nvl_fini(nvstream_t *nvs) 2275 { 2276 if (nvs->nvs_op == NVS_OP_ENCODE) { 2277 nvs_native_t *native = (nvs_native_t *)nvs->nvs_private; 2278 /* 2279 * Add 4 zero bytes at end of nvlist. They are used 2280 * for end detection by the decode routine. 2281 */ 2282 if (native->n_curr + sizeof (int) > native->n_end) 2283 return (EFAULT); 2284 2285 bzero(native->n_curr, sizeof (int)); 2286 native->n_curr += sizeof (int); 2287 } 2288 2289 return (0); 2290 } 2291 2292 static int 2293 nvpair_native_embedded(nvstream_t *nvs, nvpair_t *nvp) 2294 { 2295 if (nvs->nvs_op == NVS_OP_ENCODE) { 2296 nvs_native_t *native = (nvs_native_t *)nvs->nvs_private; 2297 nvlist_t *packed = (void *) 2298 (native->n_curr - nvp->nvp_size + NVP_VALOFF(nvp)); 2299 /* 2300 * Null out the pointer that is meaningless in the packed 2301 * structure. The address may not be aligned, so we have 2302 * to use bzero. 2303 */ 2304 bzero(&packed->nvl_priv, sizeof (packed->nvl_priv)); 2305 } 2306 2307 return (nvs_embedded(nvs, EMBEDDED_NVL(nvp))); 2308 } 2309 2310 static int 2311 nvpair_native_embedded_array(nvstream_t *nvs, nvpair_t *nvp) 2312 { 2313 if (nvs->nvs_op == NVS_OP_ENCODE) { 2314 nvs_native_t *native = (nvs_native_t *)nvs->nvs_private; 2315 char *value = native->n_curr - nvp->nvp_size + NVP_VALOFF(nvp); 2316 size_t len = NVP_NELEM(nvp) * sizeof (uint64_t); 2317 nvlist_t *packed = (nvlist_t *)((uintptr_t)value + len); 2318 int i; 2319 /* 2320 * Null out pointers that are meaningless in the packed 2321 * structure. The addresses may not be aligned, so we have 2322 * to use bzero. 2323 */ 2324 bzero(value, len); 2325 2326 for (i = 0; i < NVP_NELEM(nvp); i++, packed++) 2327 /* 2328 * Null out the pointer that is meaningless in the 2329 * packed structure. The address may not be aligned, 2330 * so we have to use bzero. 2331 */ 2332 bzero(&packed->nvl_priv, sizeof (packed->nvl_priv)); 2333 } 2334 2335 return (nvs_embedded_nvl_array(nvs, nvp, NULL)); 2336 } 2337 2338 static void 2339 nvpair_native_string_array(nvstream_t *nvs, nvpair_t *nvp) 2340 { 2341 switch (nvs->nvs_op) { 2342 case NVS_OP_ENCODE: { 2343 nvs_native_t *native = (nvs_native_t *)nvs->nvs_private; 2344 uint64_t *strp = (void *) 2345 (native->n_curr - nvp->nvp_size + NVP_VALOFF(nvp)); 2346 /* 2347 * Null out pointers that are meaningless in the packed 2348 * structure. The addresses may not be aligned, so we have 2349 * to use bzero. 2350 */ 2351 bzero(strp, NVP_NELEM(nvp) * sizeof (uint64_t)); 2352 break; 2353 } 2354 case NVS_OP_DECODE: { 2355 char **strp = (void *)NVP_VALUE(nvp); 2356 char *buf = ((char *)strp + NVP_NELEM(nvp) * sizeof (uint64_t)); 2357 int i; 2358 2359 for (i = 0; i < NVP_NELEM(nvp); i++) { 2360 strp[i] = buf; 2361 buf += strlen(buf) + 1; 2362 } 2363 break; 2364 } 2365 } 2366 } 2367 2368 static int 2369 nvs_native_nvp_op(nvstream_t *nvs, nvpair_t *nvp) 2370 { 2371 data_type_t type; 2372 int value_sz; 2373 int ret = 0; 2374 2375 /* 2376 * We do the initial bcopy of the data before we look at 2377 * the nvpair type, because when we're decoding, we won't 2378 * have the correct values for the pair until we do the bcopy. 2379 */ 2380 switch (nvs->nvs_op) { 2381 case NVS_OP_ENCODE: 2382 case NVS_OP_DECODE: 2383 if (native_cp(nvs, nvp, nvp->nvp_size) != 0) 2384 return (EFAULT); 2385 break; 2386 default: 2387 return (EINVAL); 2388 } 2389 2390 /* verify nvp_name_sz, check the name string length */ 2391 if (i_validate_nvpair_name(nvp) != 0) 2392 return (EFAULT); 2393 2394 type = NVP_TYPE(nvp); 2395 2396 /* 2397 * Verify type and nelem and get the value size. 2398 * In case of data types DATA_TYPE_STRING and DATA_TYPE_STRING_ARRAY 2399 * is the size of the string(s) excluded. 2400 */ 2401 if ((value_sz = i_get_value_size(type, NULL, NVP_NELEM(nvp))) < 0) 2402 return (EFAULT); 2403 2404 if (NVP_SIZE_CALC(nvp->nvp_name_sz, value_sz) > nvp->nvp_size) 2405 return (EFAULT); 2406 2407 switch (type) { 2408 case DATA_TYPE_NVLIST: 2409 ret = nvpair_native_embedded(nvs, nvp); 2410 break; 2411 case DATA_TYPE_NVLIST_ARRAY: 2412 ret = nvpair_native_embedded_array(nvs, nvp); 2413 break; 2414 case DATA_TYPE_STRING_ARRAY: 2415 nvpair_native_string_array(nvs, nvp); 2416 break; 2417 default: 2418 break; 2419 } 2420 2421 return (ret); 2422 } 2423 2424 static int 2425 nvs_native_nvp_size(nvstream_t *nvs, nvpair_t *nvp, size_t *size) 2426 { 2427 uint64_t nvp_sz = nvp->nvp_size; 2428 2429 switch (NVP_TYPE(nvp)) { 2430 case DATA_TYPE_NVLIST: { 2431 size_t nvsize = 0; 2432 2433 if (nvs_operation(nvs, EMBEDDED_NVL(nvp), &nvsize) != 0) 2434 return (EINVAL); 2435 2436 nvp_sz += nvsize; 2437 break; 2438 } 2439 case DATA_TYPE_NVLIST_ARRAY: { 2440 size_t nvsize; 2441 2442 if (nvs_embedded_nvl_array(nvs, nvp, &nvsize) != 0) 2443 return (EINVAL); 2444 2445 nvp_sz += nvsize; 2446 break; 2447 } 2448 default: 2449 break; 2450 } 2451 2452 if (nvp_sz > INT32_MAX) 2453 return (EINVAL); 2454 2455 *size = nvp_sz; 2456 2457 return (0); 2458 } 2459 2460 static int 2461 nvs_native_nvpair(nvstream_t *nvs, nvpair_t *nvp, size_t *size) 2462 { 2463 switch (nvs->nvs_op) { 2464 case NVS_OP_ENCODE: 2465 return (nvs_native_nvp_op(nvs, nvp)); 2466 2467 case NVS_OP_DECODE: { 2468 nvs_native_t *native = (nvs_native_t *)nvs->nvs_private; 2469 int32_t decode_len; 2470 2471 /* try to read the size value from the stream */ 2472 if (native->n_curr + sizeof (int32_t) > native->n_end) 2473 return (EFAULT); 2474 bcopy(native->n_curr, &decode_len, sizeof (int32_t)); 2475 2476 /* sanity check the size value */ 2477 if (decode_len < 0 || 2478 decode_len > native->n_end - native->n_curr) 2479 return (EFAULT); 2480 2481 *size = decode_len; 2482 2483 /* 2484 * If at the end of the stream then move the cursor 2485 * forward, otherwise nvpair_native_op() will read 2486 * the entire nvpair at the same cursor position. 2487 */ 2488 if (*size == 0) 2489 native->n_curr += sizeof (int32_t); 2490 break; 2491 } 2492 2493 default: 2494 return (EINVAL); 2495 } 2496 2497 return (0); 2498 } 2499 2500 static const nvs_ops_t nvs_native_ops = { 2501 nvs_native_nvlist, 2502 nvs_native_nvpair, 2503 nvs_native_nvp_op, 2504 nvs_native_nvp_size, 2505 nvs_native_nvl_fini 2506 }; 2507 2508 static int 2509 nvs_native(nvstream_t *nvs, nvlist_t *nvl, char *buf, size_t *buflen) 2510 { 2511 nvs_native_t native; 2512 int err; 2513 2514 nvs->nvs_ops = &nvs_native_ops; 2515 2516 if ((err = nvs_native_create(nvs, &native, buf + sizeof (nvs_header_t), 2517 *buflen - sizeof (nvs_header_t))) != 0) 2518 return (err); 2519 2520 err = nvs_operation(nvs, nvl, buflen); 2521 2522 nvs_native_destroy(nvs); 2523 2524 return (err); 2525 } 2526 2527 /* 2528 * XDR encoding functions 2529 * 2530 * An xdr packed nvlist is encoded as: 2531 * 2532 * - encoding methode and host endian (4 bytes) 2533 * - nvl_version (4 bytes) 2534 * - nvl_nvflag (4 bytes) 2535 * 2536 * - encoded nvpairs, the format of one xdr encoded nvpair is: 2537 * - encoded size of the nvpair (4 bytes) 2538 * - decoded size of the nvpair (4 bytes) 2539 * - name string, (4 + sizeof(NV_ALIGN4(string)) 2540 * a string is coded as size (4 bytes) and data 2541 * - data type (4 bytes) 2542 * - number of elements in the nvpair (4 bytes) 2543 * - data 2544 * 2545 * - 2 zero's for end of the entire list (8 bytes) 2546 */ 2547 static int 2548 nvs_xdr_create(nvstream_t *nvs, XDR *xdr, char *buf, size_t buflen) 2549 { 2550 /* xdr data must be 4 byte aligned */ 2551 if ((ulong_t)buf % 4 != 0) 2552 return (EFAULT); 2553 2554 switch (nvs->nvs_op) { 2555 case NVS_OP_ENCODE: 2556 xdrmem_create(xdr, buf, (uint_t)buflen, XDR_ENCODE); 2557 nvs->nvs_private = xdr; 2558 return (0); 2559 case NVS_OP_DECODE: 2560 xdrmem_create(xdr, buf, (uint_t)buflen, XDR_DECODE); 2561 nvs->nvs_private = xdr; 2562 return (0); 2563 case NVS_OP_GETSIZE: 2564 nvs->nvs_private = NULL; 2565 return (0); 2566 default: 2567 return (EINVAL); 2568 } 2569 } 2570 2571 static void 2572 nvs_xdr_destroy(nvstream_t *nvs) 2573 { 2574 switch (nvs->nvs_op) { 2575 case NVS_OP_ENCODE: 2576 case NVS_OP_DECODE: 2577 xdr_destroy((XDR *)nvs->nvs_private); 2578 break; 2579 default: 2580 break; 2581 } 2582 } 2583 2584 static int 2585 nvs_xdr_nvlist(nvstream_t *nvs, nvlist_t *nvl, size_t *size) 2586 { 2587 switch (nvs->nvs_op) { 2588 case NVS_OP_ENCODE: 2589 case NVS_OP_DECODE: { 2590 XDR *xdr = nvs->nvs_private; 2591 2592 if (!xdr_int(xdr, &nvl->nvl_version) || 2593 !xdr_u_int(xdr, &nvl->nvl_nvflag)) 2594 return (EFAULT); 2595 break; 2596 } 2597 case NVS_OP_GETSIZE: { 2598 /* 2599 * 2 * 4 for nvl_version + nvl_nvflag 2600 * and 8 for end of the entire list 2601 */ 2602 *size += 2 * 4 + 8; 2603 break; 2604 } 2605 default: 2606 return (EINVAL); 2607 } 2608 return (0); 2609 } 2610 2611 static int 2612 nvs_xdr_nvl_fini(nvstream_t *nvs) 2613 { 2614 if (nvs->nvs_op == NVS_OP_ENCODE) { 2615 XDR *xdr = nvs->nvs_private; 2616 int zero = 0; 2617 2618 if (!xdr_int(xdr, &zero) || !xdr_int(xdr, &zero)) 2619 return (EFAULT); 2620 } 2621 2622 return (0); 2623 } 2624 2625 /* 2626 * The format of xdr encoded nvpair is: 2627 * encode_size, decode_size, name string, data type, nelem, data 2628 */ 2629 static int 2630 nvs_xdr_nvp_op(nvstream_t *nvs, nvpair_t *nvp) 2631 { 2632 data_type_t type; 2633 char *buf; 2634 char *buf_end = (char *)nvp + nvp->nvp_size; 2635 int value_sz; 2636 uint_t nelem, buflen; 2637 bool_t ret = FALSE; 2638 XDR *xdr = nvs->nvs_private; 2639 2640 ASSERT(xdr != NULL && nvp != NULL); 2641 2642 /* name string */ 2643 if ((buf = NVP_NAME(nvp)) >= buf_end) 2644 return (EFAULT); 2645 buflen = buf_end - buf; 2646 2647 if (!xdr_string(xdr, &buf, buflen - 1)) 2648 return (EFAULT); 2649 nvp->nvp_name_sz = strlen(buf) + 1; 2650 2651 /* type and nelem */ 2652 if (!xdr_int(xdr, (int *)&nvp->nvp_type) || 2653 !xdr_int(xdr, &nvp->nvp_value_elem)) 2654 return (EFAULT); 2655 2656 type = NVP_TYPE(nvp); 2657 nelem = nvp->nvp_value_elem; 2658 2659 /* 2660 * Verify type and nelem and get the value size. 2661 * In case of data types DATA_TYPE_STRING and DATA_TYPE_STRING_ARRAY 2662 * is the size of the string(s) excluded. 2663 */ 2664 if ((value_sz = i_get_value_size(type, NULL, nelem)) < 0) 2665 return (EFAULT); 2666 2667 /* if there is no data to extract then return */ 2668 if (nelem == 0) 2669 return (0); 2670 2671 /* value */ 2672 if ((buf = NVP_VALUE(nvp)) >= buf_end) 2673 return (EFAULT); 2674 buflen = buf_end - buf; 2675 2676 if (buflen < value_sz) 2677 return (EFAULT); 2678 2679 switch (type) { 2680 case DATA_TYPE_NVLIST: 2681 if (nvs_embedded(nvs, (void *)buf) == 0) 2682 return (0); 2683 break; 2684 2685 case DATA_TYPE_NVLIST_ARRAY: 2686 if (nvs_embedded_nvl_array(nvs, nvp, NULL) == 0) 2687 return (0); 2688 break; 2689 2690 case DATA_TYPE_BOOLEAN: 2691 ret = TRUE; 2692 break; 2693 2694 case DATA_TYPE_BYTE: 2695 case DATA_TYPE_INT8: 2696 case DATA_TYPE_UINT8: 2697 ret = xdr_char(xdr, buf); 2698 break; 2699 2700 case DATA_TYPE_INT16: 2701 ret = xdr_short(xdr, (void *)buf); 2702 break; 2703 2704 case DATA_TYPE_UINT16: 2705 ret = xdr_u_short(xdr, (void *)buf); 2706 break; 2707 2708 case DATA_TYPE_BOOLEAN_VALUE: 2709 case DATA_TYPE_INT32: 2710 ret = xdr_int(xdr, (void *)buf); 2711 break; 2712 2713 case DATA_TYPE_UINT32: 2714 ret = xdr_u_int(xdr, (void *)buf); 2715 break; 2716 2717 case DATA_TYPE_INT64: 2718 ret = xdr_longlong_t(xdr, (void *)buf); 2719 break; 2720 2721 case DATA_TYPE_UINT64: 2722 ret = xdr_u_longlong_t(xdr, (void *)buf); 2723 break; 2724 2725 case DATA_TYPE_HRTIME: 2726 /* 2727 * NOTE: must expose the definition of hrtime_t here 2728 */ 2729 ret = xdr_longlong_t(xdr, (void *)buf); 2730 break; 2731 2732 case DATA_TYPE_STRING: 2733 ret = xdr_string(xdr, &buf, buflen - 1); 2734 break; 2735 2736 case DATA_TYPE_BYTE_ARRAY: 2737 ret = xdr_opaque(xdr, buf, nelem); 2738 break; 2739 2740 case DATA_TYPE_INT8_ARRAY: 2741 case DATA_TYPE_UINT8_ARRAY: 2742 ret = xdr_array(xdr, &buf, &nelem, buflen, sizeof (int8_t), 2743 (xdrproc_t)xdr_char); 2744 break; 2745 2746 case DATA_TYPE_INT16_ARRAY: 2747 ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (int16_t), 2748 sizeof (int16_t), (xdrproc_t)xdr_short); 2749 break; 2750 2751 case DATA_TYPE_UINT16_ARRAY: 2752 ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (uint16_t), 2753 sizeof (uint16_t), (xdrproc_t)xdr_u_short); 2754 break; 2755 2756 case DATA_TYPE_BOOLEAN_ARRAY: 2757 case DATA_TYPE_INT32_ARRAY: 2758 ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (int32_t), 2759 sizeof (int32_t), (xdrproc_t)xdr_int); 2760 break; 2761 2762 case DATA_TYPE_UINT32_ARRAY: 2763 ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (uint32_t), 2764 sizeof (uint32_t), (xdrproc_t)xdr_u_int); 2765 break; 2766 2767 case DATA_TYPE_INT64_ARRAY: 2768 ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (int64_t), 2769 sizeof (int64_t), (xdrproc_t)xdr_longlong_t); 2770 break; 2771 2772 case DATA_TYPE_UINT64_ARRAY: 2773 ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (uint64_t), 2774 sizeof (uint64_t), (xdrproc_t)xdr_u_longlong_t); 2775 break; 2776 2777 case DATA_TYPE_STRING_ARRAY: { 2778 size_t len = nelem * sizeof (uint64_t); 2779 char **strp = (void *)buf; 2780 int i; 2781 2782 if (nvs->nvs_op == NVS_OP_DECODE) 2783 bzero(buf, len); /* don't trust packed data */ 2784 2785 for (i = 0; i < nelem; i++) { 2786 if (buflen <= len) 2787 return (EFAULT); 2788 2789 buf += len; 2790 buflen -= len; 2791 2792 if (xdr_string(xdr, &buf, buflen - 1) != TRUE) 2793 return (EFAULT); 2794 2795 if (nvs->nvs_op == NVS_OP_DECODE) 2796 strp[i] = buf; 2797 len = strlen(buf) + 1; 2798 } 2799 ret = TRUE; 2800 break; 2801 } 2802 default: 2803 break; 2804 } 2805 2806 return (ret == TRUE ? 0 : EFAULT); 2807 } 2808 2809 static int 2810 nvs_xdr_nvp_size(nvstream_t *nvs, nvpair_t *nvp, size_t *size) 2811 { 2812 data_type_t type = NVP_TYPE(nvp); 2813 /* 2814 * encode_size + decode_size + name string size + data type + nelem 2815 * where name string size = 4 + NV_ALIGN4(strlen(NVP_NAME(nvp))) 2816 */ 2817 uint64_t nvp_sz = 4 + 4 + 4 + NV_ALIGN4(strlen(NVP_NAME(nvp))) + 4 + 4; 2818 2819 switch (type) { 2820 case DATA_TYPE_BOOLEAN: 2821 break; 2822 2823 case DATA_TYPE_BOOLEAN_VALUE: 2824 case DATA_TYPE_BYTE: 2825 case DATA_TYPE_INT8: 2826 case DATA_TYPE_UINT8: 2827 case DATA_TYPE_INT16: 2828 case DATA_TYPE_UINT16: 2829 case DATA_TYPE_INT32: 2830 case DATA_TYPE_UINT32: 2831 nvp_sz += 4; /* 4 is the minimum xdr unit */ 2832 break; 2833 2834 case DATA_TYPE_INT64: 2835 case DATA_TYPE_UINT64: 2836 case DATA_TYPE_HRTIME: 2837 nvp_sz += 8; 2838 break; 2839 2840 case DATA_TYPE_STRING: 2841 nvp_sz += 4 + NV_ALIGN4(strlen((char *)NVP_VALUE(nvp))); 2842 break; 2843 2844 case DATA_TYPE_BYTE_ARRAY: 2845 nvp_sz += NV_ALIGN4(NVP_NELEM(nvp)); 2846 break; 2847 2848 case DATA_TYPE_BOOLEAN_ARRAY: 2849 case DATA_TYPE_INT8_ARRAY: 2850 case DATA_TYPE_UINT8_ARRAY: 2851 case DATA_TYPE_INT16_ARRAY: 2852 case DATA_TYPE_UINT16_ARRAY: 2853 case DATA_TYPE_INT32_ARRAY: 2854 case DATA_TYPE_UINT32_ARRAY: 2855 nvp_sz += 4 + 4 * (uint64_t)NVP_NELEM(nvp); 2856 break; 2857 2858 case DATA_TYPE_INT64_ARRAY: 2859 case DATA_TYPE_UINT64_ARRAY: 2860 nvp_sz += 4 + 8 * (uint64_t)NVP_NELEM(nvp); 2861 break; 2862 2863 case DATA_TYPE_STRING_ARRAY: { 2864 int i; 2865 char **strs = (void *)NVP_VALUE(nvp); 2866 2867 for (i = 0; i < NVP_NELEM(nvp); i++) 2868 nvp_sz += 4 + NV_ALIGN4(strlen(strs[i])); 2869 2870 break; 2871 } 2872 2873 case DATA_TYPE_NVLIST: 2874 case DATA_TYPE_NVLIST_ARRAY: { 2875 size_t nvsize = 0; 2876 int old_nvs_op = nvs->nvs_op; 2877 int err; 2878 2879 nvs->nvs_op = NVS_OP_GETSIZE; 2880 if (type == DATA_TYPE_NVLIST) 2881 err = nvs_operation(nvs, EMBEDDED_NVL(nvp), &nvsize); 2882 else 2883 err = nvs_embedded_nvl_array(nvs, nvp, &nvsize); 2884 nvs->nvs_op = old_nvs_op; 2885 2886 if (err != 0) 2887 return (EINVAL); 2888 2889 nvp_sz += nvsize; 2890 break; 2891 } 2892 2893 default: 2894 return (EINVAL); 2895 } 2896 2897 if (nvp_sz > INT32_MAX) 2898 return (EINVAL); 2899 2900 *size = nvp_sz; 2901 2902 return (0); 2903 } 2904 2905 2906 /* 2907 * The NVS_XDR_MAX_LEN macro takes a packed xdr buffer of size x and estimates 2908 * the largest nvpair that could be encoded in the buffer. 2909 * 2910 * See comments above nvpair_xdr_op() for the format of xdr encoding. 2911 * The size of a xdr packed nvpair without any data is 5 words. 2912 * 2913 * Using the size of the data directly as an estimate would be ok 2914 * in all cases except one. If the data type is of DATA_TYPE_STRING_ARRAY 2915 * then the actual nvpair has space for an array of pointers to index 2916 * the strings. These pointers are not encoded into the packed xdr buffer. 2917 * 2918 * If the data is of type DATA_TYPE_STRING_ARRAY and all the strings are 2919 * of length 0, then each string is endcoded in xdr format as a single word. 2920 * Therefore when expanded to an nvpair there will be 2.25 word used for 2921 * each string. (a int64_t allocated for pointer usage, and a single char 2922 * for the null termination.) 2923 * 2924 * This is the calculation performed by the NVS_XDR_MAX_LEN macro. 2925 */ 2926 #define NVS_XDR_HDR_LEN ((size_t)(5 * 4)) 2927 #define NVS_XDR_DATA_LEN(y) (((size_t)(y) <= NVS_XDR_HDR_LEN) ? \ 2928 0 : ((size_t)(y) - NVS_XDR_HDR_LEN)) 2929 #define NVS_XDR_MAX_LEN(x) (NVP_SIZE_CALC(1, 0) + \ 2930 (NVS_XDR_DATA_LEN(x) * 2) + \ 2931 NV_ALIGN4((NVS_XDR_DATA_LEN(x) / 4))) 2932 2933 static int 2934 nvs_xdr_nvpair(nvstream_t *nvs, nvpair_t *nvp, size_t *size) 2935 { 2936 XDR *xdr = nvs->nvs_private; 2937 int32_t encode_len, decode_len; 2938 2939 switch (nvs->nvs_op) { 2940 case NVS_OP_ENCODE: { 2941 size_t nvsize; 2942 2943 if (nvs_xdr_nvp_size(nvs, nvp, &nvsize) != 0) 2944 return (EFAULT); 2945 2946 decode_len = nvp->nvp_size; 2947 encode_len = nvsize; 2948 if (!xdr_int(xdr, &encode_len) || !xdr_int(xdr, &decode_len)) 2949 return (EFAULT); 2950 2951 return (nvs_xdr_nvp_op(nvs, nvp)); 2952 } 2953 case NVS_OP_DECODE: { 2954 struct xdr_bytesrec bytesrec; 2955 2956 /* get the encode and decode size */ 2957 if (!xdr_int(xdr, &encode_len) || !xdr_int(xdr, &decode_len)) 2958 return (EFAULT); 2959 *size = decode_len; 2960 2961 /* are we at the end of the stream? */ 2962 if (*size == 0) 2963 return (0); 2964 2965 /* sanity check the size parameter */ 2966 if (!xdr_control(xdr, XDR_GET_BYTES_AVAIL, &bytesrec)) 2967 return (EFAULT); 2968 2969 if (*size > NVS_XDR_MAX_LEN(bytesrec.xc_num_avail)) 2970 return (EFAULT); 2971 break; 2972 } 2973 2974 default: 2975 return (EINVAL); 2976 } 2977 return (0); 2978 } 2979 2980 static const struct nvs_ops nvs_xdr_ops = { 2981 nvs_xdr_nvlist, 2982 nvs_xdr_nvpair, 2983 nvs_xdr_nvp_op, 2984 nvs_xdr_nvp_size, 2985 nvs_xdr_nvl_fini 2986 }; 2987 2988 static int 2989 nvs_xdr(nvstream_t *nvs, nvlist_t *nvl, char *buf, size_t *buflen) 2990 { 2991 XDR xdr; 2992 int err; 2993 2994 nvs->nvs_ops = &nvs_xdr_ops; 2995 2996 if ((err = nvs_xdr_create(nvs, &xdr, buf + sizeof (nvs_header_t), 2997 *buflen - sizeof (nvs_header_t))) != 0) 2998 return (err); 2999 3000 err = nvs_operation(nvs, nvl, buflen); 3001 3002 nvs_xdr_destroy(nvs); 3003 3004 return (err); 3005 } 3006