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