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