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