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