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