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 137 static int i_get_value_size(data_type_t type, const void *data, uint_t nelem); 138 static 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 150 static const int nvpair_max_recursion = 20; 151 #else 152 static const int nvpair_max_recursion = 100; 153 #endif 154 155 static const uint64_t nvlist_hashtable_init_size = (1 << 4); 156 157 int 158 nv_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 174 void 175 nv_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 181 void 182 nv_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 188 nv_alloc_t * 189 nvlist_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 200 static void * 201 nv_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 212 static void 213 nv_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 220 static void 221 nv_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 229 static nvpriv_t * 230 nv_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 */ 251 static nvpriv_t * 252 nv_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 264 static int 265 nvt_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 280 static void 281 nvt_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 297 static uint32_t 298 nvt_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 311 static boolean_t 312 nvt_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 327 static nvpair_t * 328 nvt_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 359 static nvpair_t * 360 nvt_lookup_name(const nvlist_t *nvl, const char *name) 361 { 362 return (nvt_lookup_name_type(nvl, name, DATA_TYPE_DONTCARE)); 363 } 364 365 static int 366 nvt_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 412 static boolean_t 413 nvt_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 */ 428 static int 429 nvt_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 437 static boolean_t 438 nvt_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 */ 456 static int 457 nvt_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 465 static int 466 nvt_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 503 static int 504 nvt_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 551 static void 552 nvlist_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 561 uint_t 562 nvlist_nvflag(nvlist_t *nvl) 563 { 564 return (nvl->nvl_nvflag); 565 } 566 567 static nv_alloc_t * 568 nvlist_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 */ 588 int 589 nvlist_alloc(nvlist_t **nvlp, uint_t nvflag, int kmflag) 590 { 591 return (nvlist_xalloc(nvlp, nvflag, nvlist_nv_alloc(kmflag))); 592 } 593 594 int 595 nvlist_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 */ 619 static nvpair_t * 620 nvp_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 */ 644 static void 645 nvp_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 */ 656 static void 657 nvp_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 */ 675 static void 676 nvp_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 */ 701 static int 702 i_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 */ 751 static int 752 i_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 765 static int 766 i_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 */ 795 static int 796 i_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 820 static int 821 nvlist_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 */ 845 static void 846 nvpair_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 */ 869 void 870 nvlist_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 900 static int 901 nvlist_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 */ 919 int 920 nvlist_dup(const nvlist_t *nvl, nvlist_t **nvlp, int kmflag) 921 { 922 return (nvlist_xdup(nvl, nvlp, nvlist_nv_alloc(kmflag))); 923 } 924 925 int 926 nvlist_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 */ 948 int 949 nvlist_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 */ 968 int 969 nvlist_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 981 int 982 nvlist_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 */ 1005 static int 1006 i_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 1121 static int 1122 nvlist_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 */ 1144 static int 1145 nvlist_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 1279 int 1280 nvlist_add_boolean(nvlist_t *nvl, const char *name) 1281 { 1282 return (nvlist_add_common(nvl, name, DATA_TYPE_BOOLEAN, 0, NULL)); 1283 } 1284 1285 int 1286 nvlist_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 1291 int 1292 nvlist_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 1297 int 1298 nvlist_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 1303 int 1304 nvlist_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 1309 int 1310 nvlist_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 1315 int 1316 nvlist_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 1321 int 1322 nvlist_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 1327 int 1328 nvlist_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 1333 int 1334 nvlist_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 1339 int 1340 nvlist_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) 1346 int 1347 nvlist_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 1353 int 1354 nvlist_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 1359 int 1360 nvlist_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 1366 int 1367 nvlist_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 1373 int 1374 nvlist_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 1380 int 1381 nvlist_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 1387 int 1388 nvlist_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 1394 int 1395 nvlist_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 1401 int 1402 nvlist_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 1408 int 1409 nvlist_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 1415 int 1416 nvlist_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 1422 int 1423 nvlist_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 1429 int 1430 nvlist_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 1436 int 1437 nvlist_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 1442 int 1443 nvlist_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 1448 int 1449 nvlist_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 */ 1456 nvpair_t * 1457 nvlist_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 1485 nvpair_t * 1486 nvlist_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 1509 boolean_t 1510 nvlist_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 1521 const char * 1522 nvpair_name(const nvpair_t *nvp) 1523 { 1524 return (NVP_NAME(nvp)); 1525 } 1526 1527 data_type_t 1528 nvpair_type(const nvpair_t *nvp) 1529 { 1530 return (NVP_TYPE(nvp)); 1531 } 1532 1533 int 1534 nvpair_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 1555 static int 1556 nvpair_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 1641 static int 1642 nvlist_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 1658 int 1659 nvlist_lookup_boolean(const nvlist_t *nvl, const char *name) 1660 { 1661 return (nvlist_lookup_common(nvl, name, DATA_TYPE_BOOLEAN, NULL, NULL)); 1662 } 1663 1664 int 1665 nvlist_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 1672 int 1673 nvlist_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 1678 int 1679 nvlist_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 1684 int 1685 nvlist_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 1690 int 1691 nvlist_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 1696 int 1697 nvlist_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 1702 int 1703 nvlist_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 1708 int 1709 nvlist_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 1714 int 1715 nvlist_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 1720 int 1721 nvlist_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) 1727 int 1728 nvlist_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 1734 int 1735 nvlist_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 1740 int 1741 nvlist_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 1746 int 1747 nvlist_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 1754 int 1755 nvlist_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 1761 int 1762 nvlist_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 1767 int 1768 nvlist_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 1774 int 1775 nvlist_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 1781 int 1782 nvlist_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 1788 int 1789 nvlist_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 1795 int 1796 nvlist_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 1802 int 1803 nvlist_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 1809 int 1810 nvlist_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 1816 int 1817 nvlist_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 1823 int 1824 nvlist_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 1830 int 1831 nvlist_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 1836 int 1837 nvlist_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 */ 1919 static int 1920 nvlist_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 2081 fail: if (ep && sepp) 2082 *ep = sepp; 2083 return (EINVAL); 2084 } 2085 2086 /* 2087 * Return pointer to nvpair with specified 'name'. 2088 */ 2089 int 2090 nvlist_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 */ 2100 int 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 2106 boolean_t 2107 nvlist_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 2127 int 2128 nvpair_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 2133 int 2134 nvpair_value_byte(const nvpair_t *nvp, uchar_t *val) 2135 { 2136 return (nvpair_value_common(nvp, DATA_TYPE_BYTE, NULL, val)); 2137 } 2138 2139 int 2140 nvpair_value_int8(const nvpair_t *nvp, int8_t *val) 2141 { 2142 return (nvpair_value_common(nvp, DATA_TYPE_INT8, NULL, val)); 2143 } 2144 2145 int 2146 nvpair_value_uint8(const nvpair_t *nvp, uint8_t *val) 2147 { 2148 return (nvpair_value_common(nvp, DATA_TYPE_UINT8, NULL, val)); 2149 } 2150 2151 int 2152 nvpair_value_int16(const nvpair_t *nvp, int16_t *val) 2153 { 2154 return (nvpair_value_common(nvp, DATA_TYPE_INT16, NULL, val)); 2155 } 2156 2157 int 2158 nvpair_value_uint16(const nvpair_t *nvp, uint16_t *val) 2159 { 2160 return (nvpair_value_common(nvp, DATA_TYPE_UINT16, NULL, val)); 2161 } 2162 2163 int 2164 nvpair_value_int32(const nvpair_t *nvp, int32_t *val) 2165 { 2166 return (nvpair_value_common(nvp, DATA_TYPE_INT32, NULL, val)); 2167 } 2168 2169 int 2170 nvpair_value_uint32(const nvpair_t *nvp, uint32_t *val) 2171 { 2172 return (nvpair_value_common(nvp, DATA_TYPE_UINT32, NULL, val)); 2173 } 2174 2175 int 2176 nvpair_value_int64(const nvpair_t *nvp, int64_t *val) 2177 { 2178 return (nvpair_value_common(nvp, DATA_TYPE_INT64, NULL, val)); 2179 } 2180 2181 int 2182 nvpair_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) 2188 int 2189 nvpair_value_double(const nvpair_t *nvp, double *val) 2190 { 2191 return (nvpair_value_common(nvp, DATA_TYPE_DOUBLE, NULL, val)); 2192 } 2193 #endif 2194 2195 int 2196 nvpair_value_string(const nvpair_t *nvp, const char **val) 2197 { 2198 return (nvpair_value_common(nvp, DATA_TYPE_STRING, NULL, val)); 2199 } 2200 2201 int 2202 nvpair_value_nvlist(nvpair_t *nvp, nvlist_t **val) 2203 { 2204 return (nvpair_value_common(nvp, DATA_TYPE_NVLIST, NULL, val)); 2205 } 2206 2207 int 2208 nvpair_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 2213 int 2214 nvpair_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 2219 int 2220 nvpair_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 2225 int 2226 nvpair_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 2231 int 2232 nvpair_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 2237 int 2238 nvpair_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 2243 int 2244 nvpair_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 2249 int 2250 nvpair_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 2255 int 2256 nvpair_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 2261 int 2262 nvpair_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 2267 int 2268 nvpair_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 2273 int 2274 nvpair_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 2279 int 2280 nvpair_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 */ 2288 int 2289 nvlist_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 */ 2304 int 2305 nvlist_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 2325 typedef struct nvs_ops nvs_ops_t; 2326 2327 typedef 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 */ 2354 struct 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 2362 typedef 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 2369 static int 2370 nvs_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 2385 static int 2386 nvs_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 2429 static int 2430 nvs_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 2452 static int 2453 nvs_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 2486 static int 2487 nvs_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 2529 static int 2530 nvs_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 2581 static int nvs_native(nvstream_t *, nvlist_t *, char *, size_t *); 2582 static 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 */ 2588 static int 2589 nvlist_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 2675 int 2676 nvlist_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 */ 2684 int 2685 nvlist_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 2692 int 2693 nvlist_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 */ 2742 int 2743 nvlist_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 2748 int 2749 nvlist_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 */ 2772 typedef 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 2789 static int 2790 nvs_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 2812 static void 2813 nvs_native_destroy(nvstream_t *nvs) 2814 { 2815 nvs->nvs_private = NULL; 2816 } 2817 2818 static int 2819 native_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 */ 2848 static int 2849 nvs_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 2890 static int 2891 nvs_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 2909 static int 2910 nvpair_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 2928 static int 2929 nvpair_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 2957 static void 2958 nvpair_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 2987 static int 2988 nvs_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 3043 static int 3044 nvs_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 3079 static int 3080 nvs_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 3119 static 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 3127 static int 3128 nvs_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 */ 3166 static int 3167 nvs_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 3190 static void 3191 nvs_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 3203 static int 3204 nvs_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 3230 static int 3231 nvs_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) \ 3251 static bool_t \ 3252 nvs_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) \ 3260 static bool_t \ 3261 nvs_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) \ 3276 static bool_t \ 3277 nvs_xdr_nvp_##type(XDR *xdrs, void *ptr, ...) \ 3278 { \ 3279 return (xdr_##type(xdrs, ptr)); \ 3280 } 3281 3282 #endif 3283 3284 /* BEGIN CSTYLED */ 3285 NVS_BUILD_XDRPROC_T(char); 3286 NVS_BUILD_XDRPROC_T(short); 3287 NVS_BUILD_XDRPROC_T(u_short); 3288 NVS_BUILD_XDRPROC_T(int); 3289 NVS_BUILD_XDRPROC_T(u_int); 3290 NVS_BUILD_XDRPROC_T(longlong_t); 3291 NVS_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 */ 3298 static int 3299 nvs_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 3484 static int 3485 nvs_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 3611 static int 3612 nvs_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 3658 static 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 3666 static int 3667 nvs_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 3685 EXPORT_SYMBOL(nv_alloc_init); 3686 EXPORT_SYMBOL(nv_alloc_reset); 3687 EXPORT_SYMBOL(nv_alloc_fini); 3688 3689 /* list management */ 3690 EXPORT_SYMBOL(nvlist_alloc); 3691 EXPORT_SYMBOL(nvlist_free); 3692 EXPORT_SYMBOL(nvlist_size); 3693 EXPORT_SYMBOL(nvlist_pack); 3694 EXPORT_SYMBOL(nvlist_unpack); 3695 EXPORT_SYMBOL(nvlist_dup); 3696 EXPORT_SYMBOL(nvlist_merge); 3697 3698 EXPORT_SYMBOL(nvlist_xalloc); 3699 EXPORT_SYMBOL(nvlist_xpack); 3700 EXPORT_SYMBOL(nvlist_xunpack); 3701 EXPORT_SYMBOL(nvlist_xdup); 3702 EXPORT_SYMBOL(nvlist_lookup_nv_alloc); 3703 3704 EXPORT_SYMBOL(nvlist_add_nvpair); 3705 EXPORT_SYMBOL(nvlist_add_boolean); 3706 EXPORT_SYMBOL(nvlist_add_boolean_value); 3707 EXPORT_SYMBOL(nvlist_add_byte); 3708 EXPORT_SYMBOL(nvlist_add_int8); 3709 EXPORT_SYMBOL(nvlist_add_uint8); 3710 EXPORT_SYMBOL(nvlist_add_int16); 3711 EXPORT_SYMBOL(nvlist_add_uint16); 3712 EXPORT_SYMBOL(nvlist_add_int32); 3713 EXPORT_SYMBOL(nvlist_add_uint32); 3714 EXPORT_SYMBOL(nvlist_add_int64); 3715 EXPORT_SYMBOL(nvlist_add_uint64); 3716 EXPORT_SYMBOL(nvlist_add_string); 3717 EXPORT_SYMBOL(nvlist_add_nvlist); 3718 EXPORT_SYMBOL(nvlist_add_boolean_array); 3719 EXPORT_SYMBOL(nvlist_add_byte_array); 3720 EXPORT_SYMBOL(nvlist_add_int8_array); 3721 EXPORT_SYMBOL(nvlist_add_uint8_array); 3722 EXPORT_SYMBOL(nvlist_add_int16_array); 3723 EXPORT_SYMBOL(nvlist_add_uint16_array); 3724 EXPORT_SYMBOL(nvlist_add_int32_array); 3725 EXPORT_SYMBOL(nvlist_add_uint32_array); 3726 EXPORT_SYMBOL(nvlist_add_int64_array); 3727 EXPORT_SYMBOL(nvlist_add_uint64_array); 3728 EXPORT_SYMBOL(nvlist_add_string_array); 3729 EXPORT_SYMBOL(nvlist_add_nvlist_array); 3730 EXPORT_SYMBOL(nvlist_next_nvpair); 3731 EXPORT_SYMBOL(nvlist_prev_nvpair); 3732 EXPORT_SYMBOL(nvlist_empty); 3733 EXPORT_SYMBOL(nvlist_add_hrtime); 3734 3735 EXPORT_SYMBOL(nvlist_remove); 3736 EXPORT_SYMBOL(nvlist_remove_nvpair); 3737 EXPORT_SYMBOL(nvlist_remove_all); 3738 3739 EXPORT_SYMBOL(nvlist_lookup_boolean); 3740 EXPORT_SYMBOL(nvlist_lookup_boolean_value); 3741 EXPORT_SYMBOL(nvlist_lookup_byte); 3742 EXPORT_SYMBOL(nvlist_lookup_int8); 3743 EXPORT_SYMBOL(nvlist_lookup_uint8); 3744 EXPORT_SYMBOL(nvlist_lookup_int16); 3745 EXPORT_SYMBOL(nvlist_lookup_uint16); 3746 EXPORT_SYMBOL(nvlist_lookup_int32); 3747 EXPORT_SYMBOL(nvlist_lookup_uint32); 3748 EXPORT_SYMBOL(nvlist_lookup_int64); 3749 EXPORT_SYMBOL(nvlist_lookup_uint64); 3750 EXPORT_SYMBOL(nvlist_lookup_string); 3751 EXPORT_SYMBOL(nvlist_lookup_nvlist); 3752 EXPORT_SYMBOL(nvlist_lookup_boolean_array); 3753 EXPORT_SYMBOL(nvlist_lookup_byte_array); 3754 EXPORT_SYMBOL(nvlist_lookup_int8_array); 3755 EXPORT_SYMBOL(nvlist_lookup_uint8_array); 3756 EXPORT_SYMBOL(nvlist_lookup_int16_array); 3757 EXPORT_SYMBOL(nvlist_lookup_uint16_array); 3758 EXPORT_SYMBOL(nvlist_lookup_int32_array); 3759 EXPORT_SYMBOL(nvlist_lookup_uint32_array); 3760 EXPORT_SYMBOL(nvlist_lookup_int64_array); 3761 EXPORT_SYMBOL(nvlist_lookup_uint64_array); 3762 EXPORT_SYMBOL(nvlist_lookup_string_array); 3763 EXPORT_SYMBOL(nvlist_lookup_nvlist_array); 3764 EXPORT_SYMBOL(nvlist_lookup_hrtime); 3765 EXPORT_SYMBOL(nvlist_lookup_pairs); 3766 3767 EXPORT_SYMBOL(nvlist_lookup_nvpair); 3768 EXPORT_SYMBOL(nvlist_exists); 3769 3770 /* processing nvpair */ 3771 EXPORT_SYMBOL(nvpair_name); 3772 EXPORT_SYMBOL(nvpair_type); 3773 EXPORT_SYMBOL(nvpair_value_boolean_value); 3774 EXPORT_SYMBOL(nvpair_value_byte); 3775 EXPORT_SYMBOL(nvpair_value_int8); 3776 EXPORT_SYMBOL(nvpair_value_uint8); 3777 EXPORT_SYMBOL(nvpair_value_int16); 3778 EXPORT_SYMBOL(nvpair_value_uint16); 3779 EXPORT_SYMBOL(nvpair_value_int32); 3780 EXPORT_SYMBOL(nvpair_value_uint32); 3781 EXPORT_SYMBOL(nvpair_value_int64); 3782 EXPORT_SYMBOL(nvpair_value_uint64); 3783 EXPORT_SYMBOL(nvpair_value_string); 3784 EXPORT_SYMBOL(nvpair_value_nvlist); 3785 EXPORT_SYMBOL(nvpair_value_boolean_array); 3786 EXPORT_SYMBOL(nvpair_value_byte_array); 3787 EXPORT_SYMBOL(nvpair_value_int8_array); 3788 EXPORT_SYMBOL(nvpair_value_uint8_array); 3789 EXPORT_SYMBOL(nvpair_value_int16_array); 3790 EXPORT_SYMBOL(nvpair_value_uint16_array); 3791 EXPORT_SYMBOL(nvpair_value_int32_array); 3792 EXPORT_SYMBOL(nvpair_value_uint32_array); 3793 EXPORT_SYMBOL(nvpair_value_int64_array); 3794 EXPORT_SYMBOL(nvpair_value_uint64_array); 3795 EXPORT_SYMBOL(nvpair_value_string_array); 3796 EXPORT_SYMBOL(nvpair_value_nvlist_array); 3797 EXPORT_SYMBOL(nvpair_value_hrtime); 3798