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 2006 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 = NULL; 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 } 876 877 /* calculate sizes of the nvpair elements and the nvpair itself */ 878 name_sz = strlen(name) + 1; 879 880 nvp_sz = NVP_SIZE_CALC(name_sz, value_sz); 881 882 if ((nvp = nvp_buf_alloc(nvl, nvp_sz)) == NULL) 883 return (ENOMEM); 884 885 ASSERT(nvp->nvp_size == nvp_sz); 886 nvp->nvp_name_sz = name_sz; 887 nvp->nvp_value_elem = nelem; 888 nvp->nvp_type = type; 889 bcopy(name, NVP_NAME(nvp), name_sz); 890 891 switch (type) { 892 case DATA_TYPE_BOOLEAN: 893 break; 894 case DATA_TYPE_STRING_ARRAY: { 895 char *const *strs = data; 896 char *buf = NVP_VALUE(nvp); 897 char **cstrs = (void *)buf; 898 899 /* skip pre-allocated space for pointer array */ 900 buf += nelem * sizeof (uint64_t); 901 for (i = 0; i < nelem; i++) { 902 int slen = strlen(strs[i]) + 1; 903 bcopy(strs[i], buf, slen); 904 cstrs[i] = buf; 905 buf += slen; 906 } 907 break; 908 } 909 case DATA_TYPE_NVLIST: { 910 nvlist_t *nnvl = EMBEDDED_NVL(nvp); 911 nvlist_t *onvl = (nvlist_t *)data; 912 913 if ((err = nvlist_copy_embedded(nvl, onvl, nnvl)) != 0) { 914 nvp_buf_free(nvl, nvp); 915 return (err); 916 } 917 break; 918 } 919 case DATA_TYPE_NVLIST_ARRAY: { 920 nvlist_t **onvlp = (nvlist_t **)data; 921 nvlist_t **nvlp = EMBEDDED_NVL_ARRAY(nvp); 922 nvlist_t *embedded = (nvlist_t *) 923 ((uintptr_t)nvlp + nelem * sizeof (uint64_t)); 924 925 for (i = 0; i < nelem; i++) { 926 if ((err = nvlist_copy_embedded(nvl, 927 onvlp[i], embedded)) != 0) { 928 /* 929 * Free any successfully created lists 930 */ 931 nvpair_free(nvp); 932 nvp_buf_free(nvl, nvp); 933 return (err); 934 } 935 936 nvlp[i] = embedded++; 937 } 938 break; 939 } 940 default: 941 bcopy(data, NVP_VALUE(nvp), value_sz); 942 } 943 944 /* if unique name, remove before add */ 945 if (nvl->nvl_nvflag & NV_UNIQUE_NAME) 946 (void) nvlist_remove_all(nvl, name); 947 else if (nvl->nvl_nvflag & NV_UNIQUE_NAME_TYPE) 948 (void) nvlist_remove(nvl, name, type); 949 950 nvp_buf_link(nvl, nvp); 951 952 return (0); 953 } 954 955 int 956 nvlist_add_boolean(nvlist_t *nvl, const char *name) 957 { 958 return (nvlist_add_common(nvl, name, DATA_TYPE_BOOLEAN, 0, NULL)); 959 } 960 961 int 962 nvlist_add_boolean_value(nvlist_t *nvl, const char *name, boolean_t val) 963 { 964 return (nvlist_add_common(nvl, name, DATA_TYPE_BOOLEAN_VALUE, 1, &val)); 965 } 966 967 int 968 nvlist_add_byte(nvlist_t *nvl, const char *name, uchar_t val) 969 { 970 return (nvlist_add_common(nvl, name, DATA_TYPE_BYTE, 1, &val)); 971 } 972 973 int 974 nvlist_add_int8(nvlist_t *nvl, const char *name, int8_t val) 975 { 976 return (nvlist_add_common(nvl, name, DATA_TYPE_INT8, 1, &val)); 977 } 978 979 int 980 nvlist_add_uint8(nvlist_t *nvl, const char *name, uint8_t val) 981 { 982 return (nvlist_add_common(nvl, name, DATA_TYPE_UINT8, 1, &val)); 983 } 984 985 int 986 nvlist_add_int16(nvlist_t *nvl, const char *name, int16_t val) 987 { 988 return (nvlist_add_common(nvl, name, DATA_TYPE_INT16, 1, &val)); 989 } 990 991 int 992 nvlist_add_uint16(nvlist_t *nvl, const char *name, uint16_t val) 993 { 994 return (nvlist_add_common(nvl, name, DATA_TYPE_UINT16, 1, &val)); 995 } 996 997 int 998 nvlist_add_int32(nvlist_t *nvl, const char *name, int32_t val) 999 { 1000 return (nvlist_add_common(nvl, name, DATA_TYPE_INT32, 1, &val)); 1001 } 1002 1003 int 1004 nvlist_add_uint32(nvlist_t *nvl, const char *name, uint32_t val) 1005 { 1006 return (nvlist_add_common(nvl, name, DATA_TYPE_UINT32, 1, &val)); 1007 } 1008 1009 int 1010 nvlist_add_int64(nvlist_t *nvl, const char *name, int64_t val) 1011 { 1012 return (nvlist_add_common(nvl, name, DATA_TYPE_INT64, 1, &val)); 1013 } 1014 1015 int 1016 nvlist_add_uint64(nvlist_t *nvl, const char *name, uint64_t val) 1017 { 1018 return (nvlist_add_common(nvl, name, DATA_TYPE_UINT64, 1, &val)); 1019 } 1020 1021 int 1022 nvlist_add_string(nvlist_t *nvl, const char *name, const char *val) 1023 { 1024 return (nvlist_add_common(nvl, name, DATA_TYPE_STRING, 1, (void *)val)); 1025 } 1026 1027 int 1028 nvlist_add_boolean_array(nvlist_t *nvl, const char *name, 1029 boolean_t *a, uint_t n) 1030 { 1031 return (nvlist_add_common(nvl, name, DATA_TYPE_BOOLEAN_ARRAY, n, a)); 1032 } 1033 1034 int 1035 nvlist_add_byte_array(nvlist_t *nvl, const char *name, uchar_t *a, uint_t n) 1036 { 1037 return (nvlist_add_common(nvl, name, DATA_TYPE_BYTE_ARRAY, n, a)); 1038 } 1039 1040 int 1041 nvlist_add_int8_array(nvlist_t *nvl, const char *name, int8_t *a, uint_t n) 1042 { 1043 return (nvlist_add_common(nvl, name, DATA_TYPE_INT8_ARRAY, n, a)); 1044 } 1045 1046 int 1047 nvlist_add_uint8_array(nvlist_t *nvl, const char *name, uint8_t *a, uint_t n) 1048 { 1049 return (nvlist_add_common(nvl, name, DATA_TYPE_UINT8_ARRAY, n, a)); 1050 } 1051 1052 int 1053 nvlist_add_int16_array(nvlist_t *nvl, const char *name, int16_t *a, uint_t n) 1054 { 1055 return (nvlist_add_common(nvl, name, DATA_TYPE_INT16_ARRAY, n, a)); 1056 } 1057 1058 int 1059 nvlist_add_uint16_array(nvlist_t *nvl, const char *name, uint16_t *a, uint_t n) 1060 { 1061 return (nvlist_add_common(nvl, name, DATA_TYPE_UINT16_ARRAY, n, a)); 1062 } 1063 1064 int 1065 nvlist_add_int32_array(nvlist_t *nvl, const char *name, int32_t *a, uint_t n) 1066 { 1067 return (nvlist_add_common(nvl, name, DATA_TYPE_INT32_ARRAY, n, a)); 1068 } 1069 1070 int 1071 nvlist_add_uint32_array(nvlist_t *nvl, const char *name, uint32_t *a, uint_t n) 1072 { 1073 return (nvlist_add_common(nvl, name, DATA_TYPE_UINT32_ARRAY, n, a)); 1074 } 1075 1076 int 1077 nvlist_add_int64_array(nvlist_t *nvl, const char *name, int64_t *a, uint_t n) 1078 { 1079 return (nvlist_add_common(nvl, name, DATA_TYPE_INT64_ARRAY, n, a)); 1080 } 1081 1082 int 1083 nvlist_add_uint64_array(nvlist_t *nvl, const char *name, uint64_t *a, uint_t n) 1084 { 1085 return (nvlist_add_common(nvl, name, DATA_TYPE_UINT64_ARRAY, n, a)); 1086 } 1087 1088 int 1089 nvlist_add_string_array(nvlist_t *nvl, const char *name, 1090 char *const *a, uint_t n) 1091 { 1092 return (nvlist_add_common(nvl, name, DATA_TYPE_STRING_ARRAY, n, a)); 1093 } 1094 1095 int 1096 nvlist_add_hrtime(nvlist_t *nvl, const char *name, hrtime_t val) 1097 { 1098 return (nvlist_add_common(nvl, name, DATA_TYPE_HRTIME, 1, &val)); 1099 } 1100 1101 int 1102 nvlist_add_nvlist(nvlist_t *nvl, const char *name, nvlist_t *val) 1103 { 1104 return (nvlist_add_common(nvl, name, DATA_TYPE_NVLIST, 1, val)); 1105 } 1106 1107 int 1108 nvlist_add_nvlist_array(nvlist_t *nvl, const char *name, nvlist_t **a, uint_t n) 1109 { 1110 return (nvlist_add_common(nvl, name, DATA_TYPE_NVLIST_ARRAY, n, a)); 1111 } 1112 1113 /* reading name-value pairs */ 1114 nvpair_t * 1115 nvlist_next_nvpair(nvlist_t *nvl, nvpair_t *nvp) 1116 { 1117 nvpriv_t *priv; 1118 i_nvp_t *curr; 1119 1120 if (nvl == NULL || 1121 (priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL) 1122 return (NULL); 1123 1124 curr = NVPAIR2I_NVP(nvp); 1125 1126 /* 1127 * Ensure that nvp is an valid pointer. 1128 */ 1129 if (nvp == NULL) 1130 curr = priv->nvp_list; 1131 else if (priv->nvp_curr == curr) 1132 curr = curr->nvi_next; 1133 else if (nvlist_contains_nvp(nvl, nvp) == 0) 1134 curr = NULL; 1135 1136 priv->nvp_curr = curr; 1137 1138 return (curr != NULL ? &curr->nvi_nvp : NULL); 1139 } 1140 1141 char * 1142 nvpair_name(nvpair_t *nvp) 1143 { 1144 return (NVP_NAME(nvp)); 1145 } 1146 1147 data_type_t 1148 nvpair_type(nvpair_t *nvp) 1149 { 1150 return (NVP_TYPE(nvp)); 1151 } 1152 1153 static int 1154 nvpair_value_common(nvpair_t *nvp, data_type_t type, uint_t *nelem, void *data) 1155 { 1156 if (nvp == NULL || nvpair_type(nvp) != type) 1157 return (EINVAL); 1158 1159 /* 1160 * For non-array types, we copy the data. 1161 * For array types (including string), we set a pointer. 1162 */ 1163 switch (type) { 1164 case DATA_TYPE_BOOLEAN: 1165 if (nelem != NULL) 1166 *nelem = 0; 1167 break; 1168 1169 case DATA_TYPE_BOOLEAN_VALUE: 1170 case DATA_TYPE_BYTE: 1171 case DATA_TYPE_INT8: 1172 case DATA_TYPE_UINT8: 1173 case DATA_TYPE_INT16: 1174 case DATA_TYPE_UINT16: 1175 case DATA_TYPE_INT32: 1176 case DATA_TYPE_UINT32: 1177 case DATA_TYPE_INT64: 1178 case DATA_TYPE_UINT64: 1179 case DATA_TYPE_HRTIME: 1180 if (data == NULL) 1181 return (EINVAL); 1182 bcopy(NVP_VALUE(nvp), data, 1183 (size_t)i_get_value_size(type, NULL, 1)); 1184 if (nelem != NULL) 1185 *nelem = 1; 1186 break; 1187 1188 case DATA_TYPE_NVLIST: 1189 case DATA_TYPE_STRING: 1190 if (data == NULL) 1191 return (EINVAL); 1192 *(void **)data = (void *)NVP_VALUE(nvp); 1193 if (nelem != NULL) 1194 *nelem = 1; 1195 break; 1196 1197 case DATA_TYPE_BOOLEAN_ARRAY: 1198 case DATA_TYPE_BYTE_ARRAY: 1199 case DATA_TYPE_INT8_ARRAY: 1200 case DATA_TYPE_UINT8_ARRAY: 1201 case DATA_TYPE_INT16_ARRAY: 1202 case DATA_TYPE_UINT16_ARRAY: 1203 case DATA_TYPE_INT32_ARRAY: 1204 case DATA_TYPE_UINT32_ARRAY: 1205 case DATA_TYPE_INT64_ARRAY: 1206 case DATA_TYPE_UINT64_ARRAY: 1207 case DATA_TYPE_STRING_ARRAY: 1208 case DATA_TYPE_NVLIST_ARRAY: 1209 if (nelem == NULL || data == NULL) 1210 return (EINVAL); 1211 if ((*nelem = NVP_NELEM(nvp)) != 0) 1212 *(void **)data = (void *)NVP_VALUE(nvp); 1213 else 1214 *(void **)data = NULL; 1215 break; 1216 1217 default: 1218 return (ENOTSUP); 1219 } 1220 1221 return (0); 1222 } 1223 1224 static int 1225 nvlist_lookup_common(nvlist_t *nvl, const char *name, data_type_t type, 1226 uint_t *nelem, void *data) 1227 { 1228 nvpriv_t *priv; 1229 nvpair_t *nvp; 1230 i_nvp_t *curr; 1231 1232 if (name == NULL || nvl == NULL || 1233 (priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL) 1234 return (EINVAL); 1235 1236 if (!(nvl->nvl_nvflag & (NV_UNIQUE_NAME | NV_UNIQUE_NAME_TYPE))) 1237 return (ENOTSUP); 1238 1239 for (curr = priv->nvp_list; curr != NULL; curr = curr->nvi_next) { 1240 nvp = &curr->nvi_nvp; 1241 1242 if (strcmp(name, NVP_NAME(nvp)) == 0 && NVP_TYPE(nvp) == type) 1243 return (nvpair_value_common(nvp, type, nelem, data)); 1244 } 1245 1246 return (ENOENT); 1247 } 1248 1249 int 1250 nvlist_lookup_boolean(nvlist_t *nvl, const char *name) 1251 { 1252 return (nvlist_lookup_common(nvl, name, DATA_TYPE_BOOLEAN, NULL, NULL)); 1253 } 1254 1255 int 1256 nvlist_lookup_boolean_value(nvlist_t *nvl, const char *name, boolean_t *val) 1257 { 1258 return (nvlist_lookup_common(nvl, name, 1259 DATA_TYPE_BOOLEAN_VALUE, NULL, val)); 1260 } 1261 1262 int 1263 nvlist_lookup_byte(nvlist_t *nvl, const char *name, uchar_t *val) 1264 { 1265 return (nvlist_lookup_common(nvl, name, DATA_TYPE_BYTE, NULL, val)); 1266 } 1267 1268 int 1269 nvlist_lookup_int8(nvlist_t *nvl, const char *name, int8_t *val) 1270 { 1271 return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT8, NULL, val)); 1272 } 1273 1274 int 1275 nvlist_lookup_uint8(nvlist_t *nvl, const char *name, uint8_t *val) 1276 { 1277 return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT8, NULL, val)); 1278 } 1279 1280 int 1281 nvlist_lookup_int16(nvlist_t *nvl, const char *name, int16_t *val) 1282 { 1283 return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT16, NULL, val)); 1284 } 1285 1286 int 1287 nvlist_lookup_uint16(nvlist_t *nvl, const char *name, uint16_t *val) 1288 { 1289 return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT16, NULL, val)); 1290 } 1291 1292 int 1293 nvlist_lookup_int32(nvlist_t *nvl, const char *name, int32_t *val) 1294 { 1295 return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT32, NULL, val)); 1296 } 1297 1298 int 1299 nvlist_lookup_uint32(nvlist_t *nvl, const char *name, uint32_t *val) 1300 { 1301 return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT32, NULL, val)); 1302 } 1303 1304 int 1305 nvlist_lookup_int64(nvlist_t *nvl, const char *name, int64_t *val) 1306 { 1307 return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT64, NULL, val)); 1308 } 1309 1310 int 1311 nvlist_lookup_uint64(nvlist_t *nvl, const char *name, uint64_t *val) 1312 { 1313 return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT64, NULL, val)); 1314 } 1315 1316 int 1317 nvlist_lookup_string(nvlist_t *nvl, const char *name, char **val) 1318 { 1319 return (nvlist_lookup_common(nvl, name, DATA_TYPE_STRING, NULL, val)); 1320 } 1321 1322 int 1323 nvlist_lookup_nvlist(nvlist_t *nvl, const char *name, nvlist_t **val) 1324 { 1325 return (nvlist_lookup_common(nvl, name, DATA_TYPE_NVLIST, NULL, val)); 1326 } 1327 1328 int 1329 nvlist_lookup_boolean_array(nvlist_t *nvl, const char *name, 1330 boolean_t **a, uint_t *n) 1331 { 1332 return (nvlist_lookup_common(nvl, name, 1333 DATA_TYPE_BOOLEAN_ARRAY, n, a)); 1334 } 1335 1336 int 1337 nvlist_lookup_byte_array(nvlist_t *nvl, const char *name, 1338 uchar_t **a, uint_t *n) 1339 { 1340 return (nvlist_lookup_common(nvl, name, DATA_TYPE_BYTE_ARRAY, n, a)); 1341 } 1342 1343 int 1344 nvlist_lookup_int8_array(nvlist_t *nvl, const char *name, int8_t **a, uint_t *n) 1345 { 1346 return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT8_ARRAY, n, a)); 1347 } 1348 1349 int 1350 nvlist_lookup_uint8_array(nvlist_t *nvl, const char *name, 1351 uint8_t **a, uint_t *n) 1352 { 1353 return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT8_ARRAY, n, a)); 1354 } 1355 1356 int 1357 nvlist_lookup_int16_array(nvlist_t *nvl, const char *name, 1358 int16_t **a, uint_t *n) 1359 { 1360 return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT16_ARRAY, n, a)); 1361 } 1362 1363 int 1364 nvlist_lookup_uint16_array(nvlist_t *nvl, const char *name, 1365 uint16_t **a, uint_t *n) 1366 { 1367 return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT16_ARRAY, n, a)); 1368 } 1369 1370 int 1371 nvlist_lookup_int32_array(nvlist_t *nvl, const char *name, 1372 int32_t **a, uint_t *n) 1373 { 1374 return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT32_ARRAY, n, a)); 1375 } 1376 1377 int 1378 nvlist_lookup_uint32_array(nvlist_t *nvl, const char *name, 1379 uint32_t **a, uint_t *n) 1380 { 1381 return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT32_ARRAY, n, a)); 1382 } 1383 1384 int 1385 nvlist_lookup_int64_array(nvlist_t *nvl, const char *name, 1386 int64_t **a, uint_t *n) 1387 { 1388 return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT64_ARRAY, n, a)); 1389 } 1390 1391 int 1392 nvlist_lookup_uint64_array(nvlist_t *nvl, const char *name, 1393 uint64_t **a, uint_t *n) 1394 { 1395 return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT64_ARRAY, n, a)); 1396 } 1397 1398 int 1399 nvlist_lookup_string_array(nvlist_t *nvl, const char *name, 1400 char ***a, uint_t *n) 1401 { 1402 return (nvlist_lookup_common(nvl, name, DATA_TYPE_STRING_ARRAY, n, a)); 1403 } 1404 1405 int 1406 nvlist_lookup_nvlist_array(nvlist_t *nvl, const char *name, 1407 nvlist_t ***a, uint_t *n) 1408 { 1409 return (nvlist_lookup_common(nvl, name, DATA_TYPE_NVLIST_ARRAY, n, a)); 1410 } 1411 1412 int 1413 nvlist_lookup_hrtime(nvlist_t *nvl, const char *name, hrtime_t *val) 1414 { 1415 return (nvlist_lookup_common(nvl, name, DATA_TYPE_HRTIME, NULL, val)); 1416 } 1417 1418 int 1419 nvlist_lookup_pairs(nvlist_t *nvl, int flag, ...) 1420 { 1421 va_list ap; 1422 char *name; 1423 int noentok = (flag & NV_FLAG_NOENTOK ? 1 : 0); 1424 int ret = 0; 1425 1426 va_start(ap, flag); 1427 while (ret == 0 && (name = va_arg(ap, char *)) != NULL) { 1428 data_type_t type; 1429 void *val; 1430 uint_t *nelem; 1431 1432 switch (type = va_arg(ap, data_type_t)) { 1433 case DATA_TYPE_BOOLEAN: 1434 ret = nvlist_lookup_common(nvl, name, type, NULL, NULL); 1435 break; 1436 1437 case DATA_TYPE_BOOLEAN_VALUE: 1438 case DATA_TYPE_BYTE: 1439 case DATA_TYPE_INT8: 1440 case DATA_TYPE_UINT8: 1441 case DATA_TYPE_INT16: 1442 case DATA_TYPE_UINT16: 1443 case DATA_TYPE_INT32: 1444 case DATA_TYPE_UINT32: 1445 case DATA_TYPE_INT64: 1446 case DATA_TYPE_UINT64: 1447 case DATA_TYPE_HRTIME: 1448 case DATA_TYPE_STRING: 1449 case DATA_TYPE_NVLIST: 1450 val = va_arg(ap, void *); 1451 ret = nvlist_lookup_common(nvl, name, type, NULL, val); 1452 break; 1453 1454 case DATA_TYPE_BYTE_ARRAY: 1455 case DATA_TYPE_BOOLEAN_ARRAY: 1456 case DATA_TYPE_INT8_ARRAY: 1457 case DATA_TYPE_UINT8_ARRAY: 1458 case DATA_TYPE_INT16_ARRAY: 1459 case DATA_TYPE_UINT16_ARRAY: 1460 case DATA_TYPE_INT32_ARRAY: 1461 case DATA_TYPE_UINT32_ARRAY: 1462 case DATA_TYPE_INT64_ARRAY: 1463 case DATA_TYPE_UINT64_ARRAY: 1464 case DATA_TYPE_STRING_ARRAY: 1465 case DATA_TYPE_NVLIST_ARRAY: 1466 val = va_arg(ap, void *); 1467 nelem = va_arg(ap, uint_t *); 1468 ret = nvlist_lookup_common(nvl, name, type, nelem, val); 1469 break; 1470 1471 default: 1472 ret = EINVAL; 1473 } 1474 1475 if (ret == ENOENT && noentok) 1476 ret = 0; 1477 } 1478 va_end(ap); 1479 1480 return (ret); 1481 } 1482 1483 int 1484 nvpair_value_boolean_value(nvpair_t *nvp, boolean_t *val) 1485 { 1486 return (nvpair_value_common(nvp, DATA_TYPE_BOOLEAN_VALUE, NULL, val)); 1487 } 1488 1489 int 1490 nvpair_value_byte(nvpair_t *nvp, uchar_t *val) 1491 { 1492 return (nvpair_value_common(nvp, DATA_TYPE_BYTE, NULL, val)); 1493 } 1494 1495 int 1496 nvpair_value_int8(nvpair_t *nvp, int8_t *val) 1497 { 1498 return (nvpair_value_common(nvp, DATA_TYPE_INT8, NULL, val)); 1499 } 1500 1501 int 1502 nvpair_value_uint8(nvpair_t *nvp, uint8_t *val) 1503 { 1504 return (nvpair_value_common(nvp, DATA_TYPE_UINT8, NULL, val)); 1505 } 1506 1507 int 1508 nvpair_value_int16(nvpair_t *nvp, int16_t *val) 1509 { 1510 return (nvpair_value_common(nvp, DATA_TYPE_INT16, NULL, val)); 1511 } 1512 1513 int 1514 nvpair_value_uint16(nvpair_t *nvp, uint16_t *val) 1515 { 1516 return (nvpair_value_common(nvp, DATA_TYPE_UINT16, NULL, val)); 1517 } 1518 1519 int 1520 nvpair_value_int32(nvpair_t *nvp, int32_t *val) 1521 { 1522 return (nvpair_value_common(nvp, DATA_TYPE_INT32, NULL, val)); 1523 } 1524 1525 int 1526 nvpair_value_uint32(nvpair_t *nvp, uint32_t *val) 1527 { 1528 return (nvpair_value_common(nvp, DATA_TYPE_UINT32, NULL, val)); 1529 } 1530 1531 int 1532 nvpair_value_int64(nvpair_t *nvp, int64_t *val) 1533 { 1534 return (nvpair_value_common(nvp, DATA_TYPE_INT64, NULL, val)); 1535 } 1536 1537 int 1538 nvpair_value_uint64(nvpair_t *nvp, uint64_t *val) 1539 { 1540 return (nvpair_value_common(nvp, DATA_TYPE_UINT64, NULL, val)); 1541 } 1542 1543 int 1544 nvpair_value_string(nvpair_t *nvp, char **val) 1545 { 1546 return (nvpair_value_common(nvp, DATA_TYPE_STRING, NULL, val)); 1547 } 1548 1549 int 1550 nvpair_value_nvlist(nvpair_t *nvp, nvlist_t **val) 1551 { 1552 return (nvpair_value_common(nvp, DATA_TYPE_NVLIST, NULL, val)); 1553 } 1554 1555 int 1556 nvpair_value_boolean_array(nvpair_t *nvp, boolean_t **val, uint_t *nelem) 1557 { 1558 return (nvpair_value_common(nvp, DATA_TYPE_BOOLEAN_ARRAY, nelem, val)); 1559 } 1560 1561 int 1562 nvpair_value_byte_array(nvpair_t *nvp, uchar_t **val, uint_t *nelem) 1563 { 1564 return (nvpair_value_common(nvp, DATA_TYPE_BYTE_ARRAY, nelem, val)); 1565 } 1566 1567 int 1568 nvpair_value_int8_array(nvpair_t *nvp, int8_t **val, uint_t *nelem) 1569 { 1570 return (nvpair_value_common(nvp, DATA_TYPE_INT8_ARRAY, nelem, val)); 1571 } 1572 1573 int 1574 nvpair_value_uint8_array(nvpair_t *nvp, uint8_t **val, uint_t *nelem) 1575 { 1576 return (nvpair_value_common(nvp, DATA_TYPE_UINT8_ARRAY, nelem, val)); 1577 } 1578 1579 int 1580 nvpair_value_int16_array(nvpair_t *nvp, int16_t **val, uint_t *nelem) 1581 { 1582 return (nvpair_value_common(nvp, DATA_TYPE_INT16_ARRAY, nelem, val)); 1583 } 1584 1585 int 1586 nvpair_value_uint16_array(nvpair_t *nvp, uint16_t **val, uint_t *nelem) 1587 { 1588 return (nvpair_value_common(nvp, DATA_TYPE_UINT16_ARRAY, nelem, val)); 1589 } 1590 1591 int 1592 nvpair_value_int32_array(nvpair_t *nvp, int32_t **val, uint_t *nelem) 1593 { 1594 return (nvpair_value_common(nvp, DATA_TYPE_INT32_ARRAY, nelem, val)); 1595 } 1596 1597 int 1598 nvpair_value_uint32_array(nvpair_t *nvp, uint32_t **val, uint_t *nelem) 1599 { 1600 return (nvpair_value_common(nvp, DATA_TYPE_UINT32_ARRAY, nelem, val)); 1601 } 1602 1603 int 1604 nvpair_value_int64_array(nvpair_t *nvp, int64_t **val, uint_t *nelem) 1605 { 1606 return (nvpair_value_common(nvp, DATA_TYPE_INT64_ARRAY, nelem, val)); 1607 } 1608 1609 int 1610 nvpair_value_uint64_array(nvpair_t *nvp, uint64_t **val, uint_t *nelem) 1611 { 1612 return (nvpair_value_common(nvp, DATA_TYPE_UINT64_ARRAY, nelem, val)); 1613 } 1614 1615 int 1616 nvpair_value_string_array(nvpair_t *nvp, char ***val, uint_t *nelem) 1617 { 1618 return (nvpair_value_common(nvp, DATA_TYPE_STRING_ARRAY, nelem, val)); 1619 } 1620 1621 int 1622 nvpair_value_nvlist_array(nvpair_t *nvp, nvlist_t ***val, uint_t *nelem) 1623 { 1624 return (nvpair_value_common(nvp, DATA_TYPE_NVLIST_ARRAY, nelem, val)); 1625 } 1626 1627 int 1628 nvpair_value_hrtime(nvpair_t *nvp, hrtime_t *val) 1629 { 1630 return (nvpair_value_common(nvp, DATA_TYPE_HRTIME, NULL, val)); 1631 } 1632 1633 /* 1634 * Add specified pair to the list. 1635 */ 1636 int 1637 nvlist_add_nvpair(nvlist_t *nvl, nvpair_t *nvp) 1638 { 1639 if (nvl == NULL || nvp == NULL) 1640 return (EINVAL); 1641 1642 return (nvlist_add_common(nvl, NVP_NAME(nvp), NVP_TYPE(nvp), 1643 NVP_NELEM(nvp), NVP_VALUE(nvp))); 1644 } 1645 1646 /* 1647 * Merge the supplied nvlists and put the result in dst. 1648 * The merged list will contain all names specified in both lists, 1649 * the values are taken from nvl in the case of duplicates. 1650 * Return 0 on success. 1651 */ 1652 /*ARGSUSED*/ 1653 int 1654 nvlist_merge(nvlist_t *dst, nvlist_t *nvl, int flag) 1655 { 1656 if (nvl == NULL || dst == NULL) 1657 return (EINVAL); 1658 1659 if (dst != nvl) 1660 return (nvlist_copy_pairs(nvl, dst)); 1661 1662 return (0); 1663 } 1664 1665 /* 1666 * Encoding related routines 1667 */ 1668 #define NVS_OP_ENCODE 0 1669 #define NVS_OP_DECODE 1 1670 #define NVS_OP_GETSIZE 2 1671 1672 typedef struct nvs_ops nvs_ops_t; 1673 1674 typedef struct { 1675 int nvs_op; 1676 const nvs_ops_t *nvs_ops; 1677 void *nvs_private; 1678 nvpriv_t *nvs_priv; 1679 } nvstream_t; 1680 1681 /* 1682 * nvs operations are: 1683 * - nvs_nvlist 1684 * encoding / decoding of a nvlist header (nvlist_t) 1685 * calculates the size used for header and end detection 1686 * 1687 * - nvs_nvpair 1688 * responsible for the first part of encoding / decoding of an nvpair 1689 * calculates the decoded size of an nvpair 1690 * 1691 * - nvs_nvp_op 1692 * second part of encoding / decoding of an nvpair 1693 * 1694 * - nvs_nvp_size 1695 * calculates the encoding size of an nvpair 1696 * 1697 * - nvs_nvl_fini 1698 * encodes the end detection mark (zeros). 1699 */ 1700 struct nvs_ops { 1701 int (*nvs_nvlist)(nvstream_t *, nvlist_t *, size_t *); 1702 int (*nvs_nvpair)(nvstream_t *, nvpair_t *, size_t *); 1703 int (*nvs_nvp_op)(nvstream_t *, nvpair_t *); 1704 int (*nvs_nvp_size)(nvstream_t *, nvpair_t *, size_t *); 1705 int (*nvs_nvl_fini)(nvstream_t *); 1706 }; 1707 1708 typedef struct { 1709 char nvh_encoding; /* nvs encoding method */ 1710 char nvh_endian; /* nvs endian */ 1711 char nvh_reserved1; /* reserved for future use */ 1712 char nvh_reserved2; /* reserved for future use */ 1713 } nvs_header_t; 1714 1715 static int 1716 nvs_encode_pairs(nvstream_t *nvs, nvlist_t *nvl) 1717 { 1718 nvpriv_t *priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv; 1719 i_nvp_t *curr; 1720 1721 /* 1722 * Walk nvpair in list and encode each nvpair 1723 */ 1724 for (curr = priv->nvp_list; curr != NULL; curr = curr->nvi_next) 1725 if (nvs->nvs_ops->nvs_nvpair(nvs, &curr->nvi_nvp, NULL) != 0) 1726 return (EFAULT); 1727 1728 return (nvs->nvs_ops->nvs_nvl_fini(nvs)); 1729 } 1730 1731 static int 1732 nvs_decode_pairs(nvstream_t *nvs, nvlist_t *nvl) 1733 { 1734 nvpair_t *nvp; 1735 size_t nvsize; 1736 int err; 1737 1738 /* 1739 * Get decoded size of next pair in stream, alloc 1740 * memory for nvpair_t, then decode the nvpair 1741 */ 1742 while ((err = nvs->nvs_ops->nvs_nvpair(nvs, NULL, &nvsize)) == 0) { 1743 if (nvsize == 0) /* end of list */ 1744 break; 1745 1746 /* make sure len makes sense */ 1747 if (nvsize < NVP_SIZE_CALC(1, 0)) 1748 return (EFAULT); 1749 1750 if ((nvp = nvp_buf_alloc(nvl, nvsize)) == NULL) 1751 return (ENOMEM); 1752 1753 if ((err = nvs->nvs_ops->nvs_nvp_op(nvs, nvp)) != 0) { 1754 nvp_buf_free(nvl, nvp); 1755 return (err); 1756 } 1757 1758 if (i_validate_nvpair(nvp) != 0) { 1759 nvpair_free(nvp); 1760 nvp_buf_free(nvl, nvp); 1761 return (EFAULT); 1762 } 1763 1764 nvp_buf_link(nvl, nvp); 1765 } 1766 return (err); 1767 } 1768 1769 static int 1770 nvs_getsize_pairs(nvstream_t *nvs, nvlist_t *nvl, size_t *buflen) 1771 { 1772 nvpriv_t *priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv; 1773 i_nvp_t *curr; 1774 uint64_t nvsize = *buflen; 1775 size_t size; 1776 1777 /* 1778 * Get encoded size of nvpairs in nvlist 1779 */ 1780 for (curr = priv->nvp_list; curr != NULL; curr = curr->nvi_next) { 1781 if (nvs->nvs_ops->nvs_nvp_size(nvs, &curr->nvi_nvp, &size) != 0) 1782 return (EINVAL); 1783 1784 if ((nvsize += size) > INT32_MAX) 1785 return (EINVAL); 1786 } 1787 1788 *buflen = nvsize; 1789 return (0); 1790 } 1791 1792 static int 1793 nvs_operation(nvstream_t *nvs, nvlist_t *nvl, size_t *buflen) 1794 { 1795 int err; 1796 1797 if (nvl->nvl_priv == NULL) 1798 return (EFAULT); 1799 1800 /* 1801 * Perform the operation, starting with header, then each nvpair 1802 */ 1803 if ((err = nvs->nvs_ops->nvs_nvlist(nvs, nvl, buflen)) != 0) 1804 return (err); 1805 1806 switch (nvs->nvs_op) { 1807 case NVS_OP_ENCODE: 1808 err = nvs_encode_pairs(nvs, nvl); 1809 break; 1810 1811 case NVS_OP_DECODE: 1812 err = nvs_decode_pairs(nvs, nvl); 1813 break; 1814 1815 case NVS_OP_GETSIZE: 1816 err = nvs_getsize_pairs(nvs, nvl, buflen); 1817 break; 1818 1819 default: 1820 err = EINVAL; 1821 } 1822 1823 return (err); 1824 } 1825 1826 static int 1827 nvs_embedded(nvstream_t *nvs, nvlist_t *embedded) 1828 { 1829 switch (nvs->nvs_op) { 1830 case NVS_OP_ENCODE: 1831 return (nvs_operation(nvs, embedded, NULL)); 1832 1833 case NVS_OP_DECODE: { 1834 nvpriv_t *priv; 1835 int err; 1836 1837 if (embedded->nvl_version != NV_VERSION) 1838 return (ENOTSUP); 1839 1840 if ((priv = nv_priv_alloc_embedded(nvs->nvs_priv)) == NULL) 1841 return (ENOMEM); 1842 1843 nvlist_init(embedded, embedded->nvl_nvflag, priv); 1844 1845 if ((err = nvs_operation(nvs, embedded, NULL)) != 0) 1846 nvlist_free(embedded); 1847 return (err); 1848 } 1849 default: 1850 break; 1851 } 1852 1853 return (EINVAL); 1854 } 1855 1856 static int 1857 nvs_embedded_nvl_array(nvstream_t *nvs, nvpair_t *nvp, size_t *size) 1858 { 1859 size_t nelem = NVP_NELEM(nvp); 1860 nvlist_t **nvlp = EMBEDDED_NVL_ARRAY(nvp); 1861 int i; 1862 1863 switch (nvs->nvs_op) { 1864 case NVS_OP_ENCODE: 1865 for (i = 0; i < nelem; i++) 1866 if (nvs_embedded(nvs, nvlp[i]) != 0) 1867 return (EFAULT); 1868 break; 1869 1870 case NVS_OP_DECODE: { 1871 size_t len = nelem * sizeof (uint64_t); 1872 nvlist_t *embedded = (nvlist_t *)((uintptr_t)nvlp + len); 1873 1874 bzero(nvlp, len); /* don't trust packed data */ 1875 for (i = 0; i < nelem; i++) { 1876 if (nvs_embedded(nvs, embedded) != 0) { 1877 nvpair_free(nvp); 1878 return (EFAULT); 1879 } 1880 1881 nvlp[i] = embedded++; 1882 } 1883 break; 1884 } 1885 case NVS_OP_GETSIZE: { 1886 uint64_t nvsize = 0; 1887 1888 for (i = 0; i < nelem; i++) { 1889 size_t nvp_sz = 0; 1890 1891 if (nvs_operation(nvs, nvlp[i], &nvp_sz) != 0) 1892 return (EINVAL); 1893 1894 if ((nvsize += nvp_sz) > INT32_MAX) 1895 return (EINVAL); 1896 } 1897 1898 *size = nvsize; 1899 break; 1900 } 1901 default: 1902 return (EINVAL); 1903 } 1904 1905 return (0); 1906 } 1907 1908 static int nvs_native(nvstream_t *, nvlist_t *, char *, size_t *); 1909 static int nvs_xdr(nvstream_t *, nvlist_t *, char *, size_t *); 1910 1911 /* 1912 * Common routine for nvlist operations: 1913 * encode, decode, getsize (encoded size). 1914 */ 1915 static int 1916 nvlist_common(nvlist_t *nvl, char *buf, size_t *buflen, int encoding, 1917 int nvs_op) 1918 { 1919 int err = 0; 1920 nvstream_t nvs; 1921 int nvl_endian; 1922 #ifdef _LITTLE_ENDIAN 1923 int host_endian = 1; 1924 #else 1925 int host_endian = 0; 1926 #endif /* _LITTLE_ENDIAN */ 1927 nvs_header_t *nvh = (void *)buf; 1928 1929 if (buflen == NULL || nvl == NULL || 1930 (nvs.nvs_priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL) 1931 return (EINVAL); 1932 1933 nvs.nvs_op = nvs_op; 1934 1935 /* 1936 * For NVS_OP_ENCODE and NVS_OP_DECODE make sure an nvlist and 1937 * a buffer is allocated. The first 4 bytes in the buffer are 1938 * used for encoding method and host endian. 1939 */ 1940 switch (nvs_op) { 1941 case NVS_OP_ENCODE: 1942 if (buf == NULL || *buflen < sizeof (nvs_header_t)) 1943 return (EINVAL); 1944 1945 nvh->nvh_encoding = encoding; 1946 nvh->nvh_endian = nvl_endian = host_endian; 1947 nvh->nvh_reserved1 = 0; 1948 nvh->nvh_reserved2 = 0; 1949 break; 1950 1951 case NVS_OP_DECODE: 1952 if (buf == NULL || *buflen < sizeof (nvs_header_t)) 1953 return (EINVAL); 1954 1955 /* get method of encoding from first byte */ 1956 encoding = nvh->nvh_encoding; 1957 nvl_endian = nvh->nvh_endian; 1958 break; 1959 1960 case NVS_OP_GETSIZE: 1961 nvl_endian = host_endian; 1962 1963 /* 1964 * add the size for encoding 1965 */ 1966 *buflen = sizeof (nvs_header_t); 1967 break; 1968 1969 default: 1970 return (ENOTSUP); 1971 } 1972 1973 /* 1974 * Create an nvstream with proper encoding method 1975 */ 1976 switch (encoding) { 1977 case NV_ENCODE_NATIVE: 1978 /* 1979 * check endianness, in case we are unpacking 1980 * from a file 1981 */ 1982 if (nvl_endian != host_endian) 1983 return (ENOTSUP); 1984 err = nvs_native(&nvs, nvl, buf, buflen); 1985 break; 1986 case NV_ENCODE_XDR: 1987 err = nvs_xdr(&nvs, nvl, buf, buflen); 1988 break; 1989 default: 1990 err = ENOTSUP; 1991 break; 1992 } 1993 1994 return (err); 1995 } 1996 1997 int 1998 nvlist_size(nvlist_t *nvl, size_t *size, int encoding) 1999 { 2000 return (nvlist_common(nvl, NULL, size, encoding, NVS_OP_GETSIZE)); 2001 } 2002 2003 /* 2004 * Pack nvlist into contiguous memory 2005 */ 2006 /*ARGSUSED1*/ 2007 int 2008 nvlist_pack(nvlist_t *nvl, char **bufp, size_t *buflen, int encoding, 2009 int kmflag) 2010 { 2011 #if defined(_KERNEL) && !defined(_BOOT) 2012 return (nvlist_xpack(nvl, bufp, buflen, encoding, 2013 (kmflag == KM_SLEEP ? nv_alloc_sleep : nv_alloc_nosleep))); 2014 #else 2015 return (nvlist_xpack(nvl, bufp, buflen, encoding, nv_alloc_nosleep)); 2016 #endif 2017 } 2018 2019 int 2020 nvlist_xpack(nvlist_t *nvl, char **bufp, size_t *buflen, int encoding, 2021 nv_alloc_t *nva) 2022 { 2023 nvpriv_t nvpriv; 2024 size_t alloc_size; 2025 char *buf; 2026 int err; 2027 2028 if (nva == NULL || nvl == NULL || bufp == NULL || buflen == NULL) 2029 return (EINVAL); 2030 2031 if (*bufp != NULL) 2032 return (nvlist_common(nvl, *bufp, buflen, encoding, 2033 NVS_OP_ENCODE)); 2034 2035 /* 2036 * Here is a difficult situation: 2037 * 1. The nvlist has fixed allocator properties. 2038 * All other nvlist routines (like nvlist_add_*, ...) use 2039 * these properties. 2040 * 2. When using nvlist_pack() the user can specify his own 2041 * allocator properties (e.g. by using KM_NOSLEEP). 2042 * 2043 * We use the user specified properties (2). A clearer solution 2044 * will be to remove the kmflag from nvlist_pack(), but we will 2045 * not change the interface. 2046 */ 2047 nv_priv_init(&nvpriv, nva, 0); 2048 2049 if (err = nvlist_size(nvl, &alloc_size, encoding)) 2050 return (err); 2051 2052 if ((buf = nv_mem_zalloc(&nvpriv, alloc_size)) == NULL) 2053 return (ENOMEM); 2054 2055 if ((err = nvlist_common(nvl, buf, &alloc_size, encoding, 2056 NVS_OP_ENCODE)) != 0) { 2057 nv_mem_free(&nvpriv, buf, alloc_size); 2058 } else { 2059 *buflen = alloc_size; 2060 *bufp = buf; 2061 } 2062 2063 return (err); 2064 } 2065 2066 /* 2067 * Unpack buf into an nvlist_t 2068 */ 2069 /*ARGSUSED1*/ 2070 int 2071 nvlist_unpack(char *buf, size_t buflen, nvlist_t **nvlp, int kmflag) 2072 { 2073 #if defined(_KERNEL) && !defined(_BOOT) 2074 return (nvlist_xunpack(buf, buflen, nvlp, 2075 (kmflag == KM_SLEEP ? nv_alloc_sleep : nv_alloc_nosleep))); 2076 #else 2077 return (nvlist_xunpack(buf, buflen, nvlp, nv_alloc_nosleep)); 2078 #endif 2079 } 2080 2081 int 2082 nvlist_xunpack(char *buf, size_t buflen, nvlist_t **nvlp, nv_alloc_t *nva) 2083 { 2084 nvlist_t *nvl; 2085 int err; 2086 2087 if (nvlp == NULL) 2088 return (EINVAL); 2089 2090 if ((err = nvlist_xalloc(&nvl, 0, nva)) != 0) 2091 return (err); 2092 2093 if ((err = nvlist_common(nvl, buf, &buflen, 0, NVS_OP_DECODE)) != 0) 2094 nvlist_free(nvl); 2095 else 2096 *nvlp = nvl; 2097 2098 return (err); 2099 } 2100 2101 /* 2102 * Native encoding functions 2103 */ 2104 typedef struct { 2105 /* 2106 * This structure is used when decoding a packed nvpair in 2107 * the native format. n_base points to a buffer containing the 2108 * packed nvpair. n_end is a pointer to the end of the buffer. 2109 * (n_end actually points to the first byte past the end of the 2110 * buffer.) n_curr is a pointer that lies between n_base and n_end. 2111 * It points to the current data that we are decoding. 2112 * The amount of data left in the buffer is equal to n_end - n_curr. 2113 * n_flag is used to recognize a packed embedded list. 2114 */ 2115 caddr_t n_base; 2116 caddr_t n_end; 2117 caddr_t n_curr; 2118 uint_t n_flag; 2119 } nvs_native_t; 2120 2121 static int 2122 nvs_native_create(nvstream_t *nvs, nvs_native_t *native, char *buf, 2123 size_t buflen) 2124 { 2125 switch (nvs->nvs_op) { 2126 case NVS_OP_ENCODE: 2127 case NVS_OP_DECODE: 2128 nvs->nvs_private = native; 2129 native->n_curr = native->n_base = buf; 2130 native->n_end = buf + buflen; 2131 native->n_flag = 0; 2132 return (0); 2133 2134 case NVS_OP_GETSIZE: 2135 nvs->nvs_private = native; 2136 native->n_curr = native->n_base = native->n_end = NULL; 2137 native->n_flag = 0; 2138 return (0); 2139 default: 2140 return (EINVAL); 2141 } 2142 } 2143 2144 /*ARGSUSED*/ 2145 static void 2146 nvs_native_destroy(nvstream_t *nvs) 2147 { 2148 } 2149 2150 static int 2151 native_cp(nvstream_t *nvs, void *buf, size_t size) 2152 { 2153 nvs_native_t *native = (nvs_native_t *)nvs->nvs_private; 2154 2155 if (native->n_curr + size > native->n_end) 2156 return (EFAULT); 2157 2158 /* 2159 * The bcopy() below eliminates alignment requirement 2160 * on the buffer (stream) and is preferred over direct access. 2161 */ 2162 switch (nvs->nvs_op) { 2163 case NVS_OP_ENCODE: 2164 bcopy(buf, native->n_curr, size); 2165 break; 2166 case NVS_OP_DECODE: 2167 bcopy(native->n_curr, buf, size); 2168 break; 2169 default: 2170 return (EINVAL); 2171 } 2172 2173 native->n_curr += size; 2174 return (0); 2175 } 2176 2177 /* 2178 * operate on nvlist_t header 2179 */ 2180 static int 2181 nvs_native_nvlist(nvstream_t *nvs, nvlist_t *nvl, size_t *size) 2182 { 2183 nvs_native_t *native = nvs->nvs_private; 2184 2185 switch (nvs->nvs_op) { 2186 case NVS_OP_ENCODE: 2187 case NVS_OP_DECODE: 2188 if (native->n_flag) 2189 return (0); /* packed embedded list */ 2190 2191 native->n_flag = 1; 2192 2193 /* copy version and nvflag of the nvlist_t */ 2194 if (native_cp(nvs, &nvl->nvl_version, sizeof (int32_t)) != 0 || 2195 native_cp(nvs, &nvl->nvl_nvflag, sizeof (int32_t)) != 0) 2196 return (EFAULT); 2197 2198 return (0); 2199 2200 case NVS_OP_GETSIZE: 2201 /* 2202 * if calculate for packed embedded list 2203 * 4 for end of the embedded list 2204 * else 2205 * 2 * sizeof (int32_t) for nvl_version and nvl_nvflag 2206 * and 4 for end of the entire list 2207 */ 2208 if (native->n_flag) { 2209 *size += 4; 2210 } else { 2211 native->n_flag = 1; 2212 *size += 2 * sizeof (int32_t) + 4; 2213 } 2214 2215 return (0); 2216 2217 default: 2218 return (EINVAL); 2219 } 2220 } 2221 2222 static int 2223 nvs_native_nvl_fini(nvstream_t *nvs) 2224 { 2225 if (nvs->nvs_op == NVS_OP_ENCODE) { 2226 nvs_native_t *native = (nvs_native_t *)nvs->nvs_private; 2227 /* 2228 * Add 4 zero bytes at end of nvlist. They are used 2229 * for end detection by the decode routine. 2230 */ 2231 if (native->n_curr + sizeof (int) > native->n_end) 2232 return (EFAULT); 2233 2234 bzero(native->n_curr, sizeof (int)); 2235 native->n_curr += sizeof (int); 2236 } 2237 2238 return (0); 2239 } 2240 2241 static int 2242 nvpair_native_embedded(nvstream_t *nvs, nvpair_t *nvp) 2243 { 2244 if (nvs->nvs_op == NVS_OP_ENCODE) { 2245 nvs_native_t *native = (nvs_native_t *)nvs->nvs_private; 2246 nvlist_t *packed = (void *) 2247 (native->n_curr - nvp->nvp_size + NVP_VALOFF(nvp)); 2248 /* 2249 * Null out the pointer that is meaningless in the packed 2250 * structure. The address may not be aligned, so we have 2251 * to use bzero. 2252 */ 2253 bzero(&packed->nvl_priv, sizeof (packed->nvl_priv)); 2254 } 2255 2256 return (nvs_embedded(nvs, EMBEDDED_NVL(nvp))); 2257 } 2258 2259 static int 2260 nvpair_native_embedded_array(nvstream_t *nvs, nvpair_t *nvp) 2261 { 2262 if (nvs->nvs_op == NVS_OP_ENCODE) { 2263 nvs_native_t *native = (nvs_native_t *)nvs->nvs_private; 2264 char *value = native->n_curr - nvp->nvp_size + NVP_VALOFF(nvp); 2265 size_t len = NVP_NELEM(nvp) * sizeof (uint64_t); 2266 nvlist_t *packed = (nvlist_t *)((uintptr_t)value + len); 2267 int i; 2268 /* 2269 * Null out pointers that are meaningless in the packed 2270 * structure. The addresses may not be aligned, so we have 2271 * to use bzero. 2272 */ 2273 bzero(value, len); 2274 2275 for (i = 0; i < NVP_NELEM(nvp); i++, packed++) 2276 /* 2277 * Null out the pointer that is meaningless in the 2278 * packed structure. The address may not be aligned, 2279 * so we have to use bzero. 2280 */ 2281 bzero(&packed->nvl_priv, sizeof (packed->nvl_priv)); 2282 } 2283 2284 return (nvs_embedded_nvl_array(nvs, nvp, NULL)); 2285 } 2286 2287 static void 2288 nvpair_native_string_array(nvstream_t *nvs, nvpair_t *nvp) 2289 { 2290 switch (nvs->nvs_op) { 2291 case NVS_OP_ENCODE: { 2292 nvs_native_t *native = (nvs_native_t *)nvs->nvs_private; 2293 uint64_t *strp = (void *) 2294 (native->n_curr - nvp->nvp_size + NVP_VALOFF(nvp)); 2295 /* 2296 * Null out pointers that are meaningless in the packed 2297 * structure. The addresses may not be aligned, so we have 2298 * to use bzero. 2299 */ 2300 bzero(strp, NVP_NELEM(nvp) * sizeof (uint64_t)); 2301 break; 2302 } 2303 case NVS_OP_DECODE: { 2304 char **strp = (void *)NVP_VALUE(nvp); 2305 char *buf = ((char *)strp + NVP_NELEM(nvp) * sizeof (uint64_t)); 2306 int i; 2307 2308 for (i = 0; i < NVP_NELEM(nvp); i++) { 2309 strp[i] = buf; 2310 buf += strlen(buf) + 1; 2311 } 2312 break; 2313 } 2314 } 2315 } 2316 2317 static int 2318 nvs_native_nvp_op(nvstream_t *nvs, nvpair_t *nvp) 2319 { 2320 data_type_t type; 2321 int value_sz; 2322 int ret = 0; 2323 2324 /* 2325 * We do the initial bcopy of the data before we look at 2326 * the nvpair type, because when we're decoding, we won't 2327 * have the correct values for the pair until we do the bcopy. 2328 */ 2329 switch (nvs->nvs_op) { 2330 case NVS_OP_ENCODE: 2331 case NVS_OP_DECODE: 2332 if (native_cp(nvs, nvp, nvp->nvp_size) != 0) 2333 return (EFAULT); 2334 break; 2335 default: 2336 return (EINVAL); 2337 } 2338 2339 /* verify nvp_name_sz, check the name string length */ 2340 if (i_validate_nvpair_name(nvp) != 0) 2341 return (EFAULT); 2342 2343 type = NVP_TYPE(nvp); 2344 2345 /* 2346 * Verify type and nelem and get the value size. 2347 * In case of data types DATA_TYPE_STRING and DATA_TYPE_STRING_ARRAY 2348 * is the size of the string(s) excluded. 2349 */ 2350 if ((value_sz = i_get_value_size(type, NULL, NVP_NELEM(nvp))) < 0) 2351 return (EFAULT); 2352 2353 if (NVP_SIZE_CALC(nvp->nvp_name_sz, value_sz) > nvp->nvp_size) 2354 return (EFAULT); 2355 2356 switch (type) { 2357 case DATA_TYPE_NVLIST: 2358 ret = nvpair_native_embedded(nvs, nvp); 2359 break; 2360 case DATA_TYPE_NVLIST_ARRAY: 2361 ret = nvpair_native_embedded_array(nvs, nvp); 2362 break; 2363 case DATA_TYPE_STRING_ARRAY: 2364 nvpair_native_string_array(nvs, nvp); 2365 break; 2366 default: 2367 break; 2368 } 2369 2370 return (ret); 2371 } 2372 2373 static int 2374 nvs_native_nvp_size(nvstream_t *nvs, nvpair_t *nvp, size_t *size) 2375 { 2376 uint64_t nvp_sz = nvp->nvp_size; 2377 2378 switch (NVP_TYPE(nvp)) { 2379 case DATA_TYPE_NVLIST: { 2380 size_t nvsize = 0; 2381 2382 if (nvs_operation(nvs, EMBEDDED_NVL(nvp), &nvsize) != 0) 2383 return (EINVAL); 2384 2385 nvp_sz += nvsize; 2386 break; 2387 } 2388 case DATA_TYPE_NVLIST_ARRAY: { 2389 size_t nvsize; 2390 2391 if (nvs_embedded_nvl_array(nvs, nvp, &nvsize) != 0) 2392 return (EINVAL); 2393 2394 nvp_sz += nvsize; 2395 break; 2396 } 2397 default: 2398 break; 2399 } 2400 2401 if (nvp_sz > INT32_MAX) 2402 return (EINVAL); 2403 2404 *size = nvp_sz; 2405 2406 return (0); 2407 } 2408 2409 static int 2410 nvs_native_nvpair(nvstream_t *nvs, nvpair_t *nvp, size_t *size) 2411 { 2412 switch (nvs->nvs_op) { 2413 case NVS_OP_ENCODE: 2414 return (nvs_native_nvp_op(nvs, nvp)); 2415 2416 case NVS_OP_DECODE: { 2417 nvs_native_t *native = (nvs_native_t *)nvs->nvs_private; 2418 int32_t decode_len; 2419 2420 /* try to read the size value from the stream */ 2421 if (native->n_curr + sizeof (int32_t) > native->n_end) 2422 return (EFAULT); 2423 bcopy(native->n_curr, &decode_len, sizeof (int32_t)); 2424 2425 /* sanity check the size value */ 2426 if (decode_len < 0 || 2427 decode_len > native->n_end - native->n_curr) 2428 return (EFAULT); 2429 2430 *size = decode_len; 2431 2432 /* 2433 * If at the end of the stream then move the cursor 2434 * forward, otherwise nvpair_native_op() will read 2435 * the entire nvpair at the same cursor position. 2436 */ 2437 if (*size == 0) 2438 native->n_curr += sizeof (int32_t); 2439 break; 2440 } 2441 2442 default: 2443 return (EINVAL); 2444 } 2445 2446 return (0); 2447 } 2448 2449 static const nvs_ops_t nvs_native_ops = { 2450 nvs_native_nvlist, 2451 nvs_native_nvpair, 2452 nvs_native_nvp_op, 2453 nvs_native_nvp_size, 2454 nvs_native_nvl_fini 2455 }; 2456 2457 static int 2458 nvs_native(nvstream_t *nvs, nvlist_t *nvl, char *buf, size_t *buflen) 2459 { 2460 nvs_native_t native; 2461 int err; 2462 2463 nvs->nvs_ops = &nvs_native_ops; 2464 2465 if ((err = nvs_native_create(nvs, &native, buf + sizeof (nvs_header_t), 2466 *buflen - sizeof (nvs_header_t))) != 0) 2467 return (err); 2468 2469 err = nvs_operation(nvs, nvl, buflen); 2470 2471 nvs_native_destroy(nvs); 2472 2473 return (err); 2474 } 2475 2476 /* 2477 * XDR encoding functions 2478 * 2479 * An xdr packed nvlist is encoded as: 2480 * 2481 * - encoding methode and host endian (4 bytes) 2482 * - nvl_version (4 bytes) 2483 * - nvl_nvflag (4 bytes) 2484 * 2485 * - encoded nvpairs, the format of one xdr encoded nvpair is: 2486 * - encoded size of the nvpair (4 bytes) 2487 * - decoded size of the nvpair (4 bytes) 2488 * - name string, (4 + sizeof(NV_ALIGN4(string)) 2489 * a string is coded as size (4 bytes) and data 2490 * - data type (4 bytes) 2491 * - number of elements in the nvpair (4 bytes) 2492 * - data 2493 * 2494 * - 2 zero's for end of the entire list (8 bytes) 2495 */ 2496 static int 2497 nvs_xdr_create(nvstream_t *nvs, XDR *xdr, char *buf, size_t buflen) 2498 { 2499 /* xdr data must be 4 byte aligned */ 2500 if ((ulong_t)buf % 4 != 0) 2501 return (EFAULT); 2502 2503 switch (nvs->nvs_op) { 2504 case NVS_OP_ENCODE: 2505 xdrmem_create(xdr, buf, (uint_t)buflen, XDR_ENCODE); 2506 nvs->nvs_private = xdr; 2507 return (0); 2508 case NVS_OP_DECODE: 2509 xdrmem_create(xdr, buf, (uint_t)buflen, XDR_DECODE); 2510 nvs->nvs_private = xdr; 2511 return (0); 2512 case NVS_OP_GETSIZE: 2513 nvs->nvs_private = NULL; 2514 return (0); 2515 default: 2516 return (EINVAL); 2517 } 2518 } 2519 2520 static void 2521 nvs_xdr_destroy(nvstream_t *nvs) 2522 { 2523 switch (nvs->nvs_op) { 2524 case NVS_OP_ENCODE: 2525 case NVS_OP_DECODE: 2526 xdr_destroy((XDR *)nvs->nvs_private); 2527 break; 2528 default: 2529 break; 2530 } 2531 } 2532 2533 static int 2534 nvs_xdr_nvlist(nvstream_t *nvs, nvlist_t *nvl, size_t *size) 2535 { 2536 switch (nvs->nvs_op) { 2537 case NVS_OP_ENCODE: 2538 case NVS_OP_DECODE: { 2539 XDR *xdr = nvs->nvs_private; 2540 2541 if (!xdr_int(xdr, &nvl->nvl_version) || 2542 !xdr_u_int(xdr, &nvl->nvl_nvflag)) 2543 return (EFAULT); 2544 break; 2545 } 2546 case NVS_OP_GETSIZE: { 2547 /* 2548 * 2 * 4 for nvl_version + nvl_nvflag 2549 * and 8 for end of the entire list 2550 */ 2551 *size += 2 * 4 + 8; 2552 break; 2553 } 2554 default: 2555 return (EINVAL); 2556 } 2557 return (0); 2558 } 2559 2560 static int 2561 nvs_xdr_nvl_fini(nvstream_t *nvs) 2562 { 2563 if (nvs->nvs_op == NVS_OP_ENCODE) { 2564 XDR *xdr = nvs->nvs_private; 2565 int zero = 0; 2566 2567 if (!xdr_int(xdr, &zero) || !xdr_int(xdr, &zero)) 2568 return (EFAULT); 2569 } 2570 2571 return (0); 2572 } 2573 2574 /* 2575 * The format of xdr encoded nvpair is: 2576 * encode_size, decode_size, name string, data type, nelem, data 2577 */ 2578 static int 2579 nvs_xdr_nvp_op(nvstream_t *nvs, nvpair_t *nvp) 2580 { 2581 data_type_t type; 2582 char *buf; 2583 char *buf_end = (char *)nvp + nvp->nvp_size; 2584 int value_sz; 2585 uint_t nelem, buflen; 2586 bool_t ret = FALSE; 2587 XDR *xdr = nvs->nvs_private; 2588 2589 ASSERT(xdr != NULL && nvp != NULL); 2590 2591 /* name string */ 2592 if ((buf = NVP_NAME(nvp)) >= buf_end) 2593 return (EFAULT); 2594 buflen = buf_end - buf; 2595 2596 if (!xdr_string(xdr, &buf, buflen - 1)) 2597 return (EFAULT); 2598 nvp->nvp_name_sz = strlen(buf) + 1; 2599 2600 /* type and nelem */ 2601 if (!xdr_int(xdr, (int *)&nvp->nvp_type) || 2602 !xdr_int(xdr, &nvp->nvp_value_elem)) 2603 return (EFAULT); 2604 2605 type = NVP_TYPE(nvp); 2606 nelem = nvp->nvp_value_elem; 2607 2608 /* 2609 * Verify type and nelem and get the value size. 2610 * In case of data types DATA_TYPE_STRING and DATA_TYPE_STRING_ARRAY 2611 * is the size of the string(s) excluded. 2612 */ 2613 if ((value_sz = i_get_value_size(type, NULL, nelem)) < 0) 2614 return (EFAULT); 2615 2616 /* if there is no data to extract then return */ 2617 if (nelem == 0) 2618 return (0); 2619 2620 /* value */ 2621 if ((buf = NVP_VALUE(nvp)) >= buf_end) 2622 return (EFAULT); 2623 buflen = buf_end - buf; 2624 2625 if (buflen < value_sz) 2626 return (EFAULT); 2627 2628 switch (type) { 2629 case DATA_TYPE_NVLIST: 2630 if (nvs_embedded(nvs, (void *)buf) == 0) 2631 return (0); 2632 break; 2633 2634 case DATA_TYPE_NVLIST_ARRAY: 2635 if (nvs_embedded_nvl_array(nvs, nvp, NULL) == 0) 2636 return (0); 2637 break; 2638 2639 case DATA_TYPE_BOOLEAN: 2640 ret = TRUE; 2641 break; 2642 2643 case DATA_TYPE_BYTE: 2644 case DATA_TYPE_INT8: 2645 case DATA_TYPE_UINT8: 2646 ret = xdr_char(xdr, buf); 2647 break; 2648 2649 case DATA_TYPE_INT16: 2650 ret = xdr_short(xdr, (void *)buf); 2651 break; 2652 2653 case DATA_TYPE_UINT16: 2654 ret = xdr_u_short(xdr, (void *)buf); 2655 break; 2656 2657 case DATA_TYPE_BOOLEAN_VALUE: 2658 case DATA_TYPE_INT32: 2659 ret = xdr_int(xdr, (void *)buf); 2660 break; 2661 2662 case DATA_TYPE_UINT32: 2663 ret = xdr_u_int(xdr, (void *)buf); 2664 break; 2665 2666 case DATA_TYPE_INT64: 2667 ret = xdr_longlong_t(xdr, (void *)buf); 2668 break; 2669 2670 case DATA_TYPE_UINT64: 2671 ret = xdr_u_longlong_t(xdr, (void *)buf); 2672 break; 2673 2674 case DATA_TYPE_HRTIME: 2675 /* 2676 * NOTE: must expose the definition of hrtime_t here 2677 */ 2678 ret = xdr_longlong_t(xdr, (void *)buf); 2679 break; 2680 2681 case DATA_TYPE_STRING: 2682 ret = xdr_string(xdr, &buf, buflen - 1); 2683 break; 2684 2685 case DATA_TYPE_BYTE_ARRAY: 2686 ret = xdr_opaque(xdr, buf, nelem); 2687 break; 2688 2689 case DATA_TYPE_INT8_ARRAY: 2690 case DATA_TYPE_UINT8_ARRAY: 2691 ret = xdr_array(xdr, &buf, &nelem, buflen, sizeof (int8_t), 2692 (xdrproc_t)xdr_char); 2693 break; 2694 2695 case DATA_TYPE_INT16_ARRAY: 2696 ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (int16_t), 2697 sizeof (int16_t), (xdrproc_t)xdr_short); 2698 break; 2699 2700 case DATA_TYPE_UINT16_ARRAY: 2701 ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (uint16_t), 2702 sizeof (uint16_t), (xdrproc_t)xdr_u_short); 2703 break; 2704 2705 case DATA_TYPE_BOOLEAN_ARRAY: 2706 case DATA_TYPE_INT32_ARRAY: 2707 ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (int32_t), 2708 sizeof (int32_t), (xdrproc_t)xdr_int); 2709 break; 2710 2711 case DATA_TYPE_UINT32_ARRAY: 2712 ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (uint32_t), 2713 sizeof (uint32_t), (xdrproc_t)xdr_u_int); 2714 break; 2715 2716 case DATA_TYPE_INT64_ARRAY: 2717 ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (int64_t), 2718 sizeof (int64_t), (xdrproc_t)xdr_longlong_t); 2719 break; 2720 2721 case DATA_TYPE_UINT64_ARRAY: 2722 ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (uint64_t), 2723 sizeof (uint64_t), (xdrproc_t)xdr_u_longlong_t); 2724 break; 2725 2726 case DATA_TYPE_STRING_ARRAY: { 2727 size_t len = nelem * sizeof (uint64_t); 2728 char **strp = (void *)buf; 2729 int i; 2730 2731 if (nvs->nvs_op == NVS_OP_DECODE) 2732 bzero(buf, len); /* don't trust packed data */ 2733 2734 for (i = 0; i < nelem; i++) { 2735 if (buflen <= len) 2736 return (EFAULT); 2737 2738 buf += len; 2739 buflen -= len; 2740 2741 if (xdr_string(xdr, &buf, buflen - 1) != TRUE) 2742 return (EFAULT); 2743 2744 if (nvs->nvs_op == NVS_OP_DECODE) 2745 strp[i] = buf; 2746 len = strlen(buf) + 1; 2747 } 2748 ret = TRUE; 2749 break; 2750 } 2751 default: 2752 break; 2753 } 2754 2755 return (ret == TRUE ? 0 : EFAULT); 2756 } 2757 2758 static int 2759 nvs_xdr_nvp_size(nvstream_t *nvs, nvpair_t *nvp, size_t *size) 2760 { 2761 data_type_t type = NVP_TYPE(nvp); 2762 /* 2763 * encode_size + decode_size + name string size + data type + nelem 2764 * where name string size = 4 + NV_ALIGN4(strlen(NVP_NAME(nvp))) 2765 */ 2766 uint64_t nvp_sz = 4 + 4 + 4 + NV_ALIGN4(strlen(NVP_NAME(nvp))) + 4 + 4; 2767 2768 switch (type) { 2769 case DATA_TYPE_BOOLEAN: 2770 break; 2771 2772 case DATA_TYPE_BOOLEAN_VALUE: 2773 case DATA_TYPE_BYTE: 2774 case DATA_TYPE_INT8: 2775 case DATA_TYPE_UINT8: 2776 case DATA_TYPE_INT16: 2777 case DATA_TYPE_UINT16: 2778 case DATA_TYPE_INT32: 2779 case DATA_TYPE_UINT32: 2780 nvp_sz += 4; /* 4 is the minimum xdr unit */ 2781 break; 2782 2783 case DATA_TYPE_INT64: 2784 case DATA_TYPE_UINT64: 2785 case DATA_TYPE_HRTIME: 2786 nvp_sz += 8; 2787 break; 2788 2789 case DATA_TYPE_STRING: 2790 nvp_sz += 4 + NV_ALIGN4(strlen((char *)NVP_VALUE(nvp))); 2791 break; 2792 2793 case DATA_TYPE_BYTE_ARRAY: 2794 nvp_sz += NV_ALIGN4(NVP_NELEM(nvp)); 2795 break; 2796 2797 case DATA_TYPE_BOOLEAN_ARRAY: 2798 case DATA_TYPE_INT8_ARRAY: 2799 case DATA_TYPE_UINT8_ARRAY: 2800 case DATA_TYPE_INT16_ARRAY: 2801 case DATA_TYPE_UINT16_ARRAY: 2802 case DATA_TYPE_INT32_ARRAY: 2803 case DATA_TYPE_UINT32_ARRAY: 2804 nvp_sz += 4 + 4 * (uint64_t)NVP_NELEM(nvp); 2805 break; 2806 2807 case DATA_TYPE_INT64_ARRAY: 2808 case DATA_TYPE_UINT64_ARRAY: 2809 nvp_sz += 4 + 8 * (uint64_t)NVP_NELEM(nvp); 2810 break; 2811 2812 case DATA_TYPE_STRING_ARRAY: { 2813 int i; 2814 char **strs = (void *)NVP_VALUE(nvp); 2815 2816 for (i = 0; i < NVP_NELEM(nvp); i++) 2817 nvp_sz += 4 + NV_ALIGN4(strlen(strs[i])); 2818 2819 break; 2820 } 2821 2822 case DATA_TYPE_NVLIST: 2823 case DATA_TYPE_NVLIST_ARRAY: { 2824 size_t nvsize = 0; 2825 int old_nvs_op = nvs->nvs_op; 2826 int err; 2827 2828 nvs->nvs_op = NVS_OP_GETSIZE; 2829 if (type == DATA_TYPE_NVLIST) 2830 err = nvs_operation(nvs, EMBEDDED_NVL(nvp), &nvsize); 2831 else 2832 err = nvs_embedded_nvl_array(nvs, nvp, &nvsize); 2833 nvs->nvs_op = old_nvs_op; 2834 2835 if (err != 0) 2836 return (EINVAL); 2837 2838 nvp_sz += nvsize; 2839 break; 2840 } 2841 2842 default: 2843 return (EINVAL); 2844 } 2845 2846 if (nvp_sz > INT32_MAX) 2847 return (EINVAL); 2848 2849 *size = nvp_sz; 2850 2851 return (0); 2852 } 2853 2854 2855 /* 2856 * The NVS_XDR_MAX_LEN macro takes a packed xdr buffer of size x and estimates 2857 * the largest nvpair that could be encoded in the buffer. 2858 * 2859 * See comments above nvpair_xdr_op() for the format of xdr encoding. 2860 * The size of a xdr packed nvpair without any data is 5 words. 2861 * 2862 * Using the size of the data directly as an estimate would be ok 2863 * in all cases except one. If the data type is of DATA_TYPE_STRING_ARRAY 2864 * then the actual nvpair has space for an array of pointers to index 2865 * the strings. These pointers are not encoded into the packed xdr buffer. 2866 * 2867 * If the data is of type DATA_TYPE_STRING_ARRAY and all the strings are 2868 * of length 0, then each string is endcoded in xdr format as a single word. 2869 * Therefore when expanded to an nvpair there will be 2.25 word used for 2870 * each string. (a int64_t allocated for pointer usage, and a single char 2871 * for the null termination.) 2872 * 2873 * This is the calculation performed by the NVS_XDR_MAX_LEN macro. 2874 */ 2875 #define NVS_XDR_HDR_LEN ((size_t)(5 * 4)) 2876 #define NVS_XDR_DATA_LEN(y) (((size_t)(y) <= NVS_XDR_HDR_LEN) ? \ 2877 0 : ((size_t)(y) - NVS_XDR_HDR_LEN)) 2878 #define NVS_XDR_MAX_LEN(x) (NVP_SIZE_CALC(1, 0) + \ 2879 (NVS_XDR_DATA_LEN(x) * 2) + \ 2880 NV_ALIGN4((NVS_XDR_DATA_LEN(x) / 4))) 2881 2882 static int 2883 nvs_xdr_nvpair(nvstream_t *nvs, nvpair_t *nvp, size_t *size) 2884 { 2885 XDR *xdr = nvs->nvs_private; 2886 int32_t encode_len, decode_len; 2887 2888 switch (nvs->nvs_op) { 2889 case NVS_OP_ENCODE: { 2890 size_t nvsize; 2891 2892 if (nvs_xdr_nvp_size(nvs, nvp, &nvsize) != 0) 2893 return (EFAULT); 2894 2895 decode_len = nvp->nvp_size; 2896 encode_len = nvsize; 2897 if (!xdr_int(xdr, &encode_len) || !xdr_int(xdr, &decode_len)) 2898 return (EFAULT); 2899 2900 return (nvs_xdr_nvp_op(nvs, nvp)); 2901 } 2902 case NVS_OP_DECODE: { 2903 struct xdr_bytesrec bytesrec; 2904 2905 /* get the encode and decode size */ 2906 if (!xdr_int(xdr, &encode_len) || !xdr_int(xdr, &decode_len)) 2907 return (EFAULT); 2908 *size = decode_len; 2909 2910 /* are we at the end of the stream? */ 2911 if (*size == 0) 2912 return (0); 2913 2914 /* sanity check the size parameter */ 2915 if (!xdr_control(xdr, XDR_GET_BYTES_AVAIL, &bytesrec)) 2916 return (EFAULT); 2917 2918 if (*size > NVS_XDR_MAX_LEN(bytesrec.xc_num_avail)) 2919 return (EFAULT); 2920 break; 2921 } 2922 2923 default: 2924 return (EINVAL); 2925 } 2926 return (0); 2927 } 2928 2929 static const struct nvs_ops nvs_xdr_ops = { 2930 nvs_xdr_nvlist, 2931 nvs_xdr_nvpair, 2932 nvs_xdr_nvp_op, 2933 nvs_xdr_nvp_size, 2934 nvs_xdr_nvl_fini 2935 }; 2936 2937 static int 2938 nvs_xdr(nvstream_t *nvs, nvlist_t *nvl, char *buf, size_t *buflen) 2939 { 2940 XDR xdr; 2941 int err; 2942 2943 nvs->nvs_ops = &nvs_xdr_ops; 2944 2945 if ((err = nvs_xdr_create(nvs, &xdr, buf + sizeof (nvs_header_t), 2946 *buflen - sizeof (nvs_header_t))) != 0) 2947 return (err); 2948 2949 err = nvs_operation(nvs, nvl, buflen); 2950 2951 nvs_xdr_destroy(nvs); 2952 2953 return (err); 2954 } 2955