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