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