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