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