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