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