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