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