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