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 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <sys/stropts.h> 30 #include <sys/debug.h> 31 #include <sys/isa_defs.h> 32 #include <sys/int_limits.h> 33 #include <sys/nvpair.h> 34 #include <sys/nvpair_impl.h> 35 #include <rpc/types.h> 36 #include <rpc/xdr.h> 37 38 #if defined(_KERNEL) && !defined(_BOOT) 39 #include <sys/varargs.h> 40 #include <sys/ddi.h> 41 #include <sys/sunddi.h> 42 #else 43 #include <stdarg.h> 44 #include <stdlib.h> 45 #include <string.h> 46 #include <strings.h> 47 #endif 48 49 #ifndef offsetof 50 #define offsetof(s, m) ((size_t)(&(((s *)0)->m))) 51 #endif 52 #define skip_whitespace(p) while ((*(p) == ' ') || (*(p) == '\t')) p++ 53 54 /* 55 * nvpair.c - Provides kernel & userland interfaces for manipulating 56 * name-value pairs. 57 * 58 * Overview Diagram 59 * 60 * +--------------+ 61 * | nvlist_t | 62 * |--------------| 63 * | nvl_version | 64 * | nvl_nvflag | 65 * | nvl_priv -+-+ 66 * | nvl_flag | | 67 * | nvl_pad | | 68 * +--------------+ | 69 * V 70 * +--------------+ last i_nvp in list 71 * | nvpriv_t | +---------------------> 72 * |--------------| | 73 * +--+- nvp_list | | +------------+ 74 * | | nvp_last -+--+ + nv_alloc_t | 75 * | | nvp_curr | |------------| 76 * | | nvp_nva -+----> | nva_ops | 77 * | | nvp_stat | | nva_arg | 78 * | +--------------+ +------------+ 79 * | 80 * +-------+ 81 * V 82 * +---------------------+ +-------------------+ 83 * | i_nvp_t | +-->| i_nvp_t | +--> 84 * |---------------------| | |-------------------| | 85 * | nvi_next -+--+ | nvi_next -+--+ 86 * | nvi_prev (NULL) | <----+ nvi_prev | 87 * | . . . . . . . . . . | | . . . . . . . . . | 88 * | nvp (nvpair_t) | | nvp (nvpair_t) | 89 * | - nvp_size | | - nvp_size | 90 * | - nvp_name_sz | | - nvp_name_sz | 91 * | - nvp_value_elem | | - nvp_value_elem | 92 * | - nvp_type | | - nvp_type | 93 * | - data ... | | - data ... | 94 * +---------------------+ +-------------------+ 95 * 96 * 97 * 98 * +---------------------+ +---------------------+ 99 * | i_nvp_t | +--> +-->| i_nvp_t (last) | 100 * |---------------------| | | |---------------------| 101 * | nvi_next -+--+ ... --+ | nvi_next (NULL) | 102 * <-+- nvi_prev |<-- ... <----+ nvi_prev | 103 * | . . . . . . . . . | | . . . . . . . . . | 104 * | nvp (nvpair_t) | | nvp (nvpair_t) | 105 * | - nvp_size | | - nvp_size | 106 * | - nvp_name_sz | | - nvp_name_sz | 107 * | - nvp_value_elem | | - nvp_value_elem | 108 * | - DATA_TYPE_NVLIST | | - nvp_type | 109 * | - data (embedded) | | - data ... | 110 * | nvlist name | +---------------------+ 111 * | +--------------+ | 112 * | | nvlist_t | | 113 * | |--------------| | 114 * | | nvl_version | | 115 * | | nvl_nvflag | | 116 * | | nvl_priv --+---+----> 117 * | | nvl_flag | | 118 * | | nvl_pad | | 119 * | +--------------+ | 120 * +---------------------+ 121 * 122 * 123 * N.B. nvpair_t may be aligned on 4 byte boundary, so +4 will 124 * allow value to be aligned on 8 byte boundary 125 * 126 * name_len is the length of the name string including the null terminator 127 * so it must be >= 1 128 */ 129 #define NVP_SIZE_CALC(name_len, data_len) \ 130 (NV_ALIGN((sizeof (nvpair_t)) + name_len) + NV_ALIGN(data_len)) 131 132 static int i_get_value_size(data_type_t type, const void *data, uint_t nelem); 133 static int nvlist_add_common(nvlist_t *nvl, const char *name, data_type_t type, 134 uint_t nelem, const void *data); 135 136 #define NV_STAT_EMBEDDED 0x1 137 #define EMBEDDED_NVL(nvp) ((nvlist_t *)(void *)NVP_VALUE(nvp)) 138 #define EMBEDDED_NVL_ARRAY(nvp) ((nvlist_t **)(void *)NVP_VALUE(nvp)) 139 140 #define NVP_VALOFF(nvp) (NV_ALIGN(sizeof (nvpair_t) + (nvp)->nvp_name_sz)) 141 #define NVPAIR2I_NVP(nvp) \ 142 ((i_nvp_t *)((size_t)(nvp) - offsetof(i_nvp_t, nvi_nvp))) 143 144 145 int 146 nv_alloc_init(nv_alloc_t *nva, const nv_alloc_ops_t *nvo, /* args */ ...) 147 { 148 va_list valist; 149 int err = 0; 150 151 nva->nva_ops = nvo; 152 nva->nva_arg = NULL; 153 154 va_start(valist, nvo); 155 if (nva->nva_ops->nv_ao_init != NULL) 156 err = nva->nva_ops->nv_ao_init(nva, valist); 157 va_end(valist); 158 159 return (err); 160 } 161 162 void 163 nv_alloc_reset(nv_alloc_t *nva) 164 { 165 if (nva->nva_ops->nv_ao_reset != NULL) 166 nva->nva_ops->nv_ao_reset(nva); 167 } 168 169 void 170 nv_alloc_fini(nv_alloc_t *nva) 171 { 172 if (nva->nva_ops->nv_ao_fini != NULL) 173 nva->nva_ops->nv_ao_fini(nva); 174 } 175 176 nv_alloc_t * 177 nvlist_lookup_nv_alloc(nvlist_t *nvl) 178 { 179 nvpriv_t *priv; 180 181 if (nvl == NULL || 182 (priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL) 183 return (NULL); 184 185 return (priv->nvp_nva); 186 } 187 188 static void * 189 nv_mem_zalloc(nvpriv_t *nvp, size_t size) 190 { 191 nv_alloc_t *nva = nvp->nvp_nva; 192 void *buf; 193 194 if ((buf = nva->nva_ops->nv_ao_alloc(nva, size)) != NULL) 195 bzero(buf, size); 196 197 return (buf); 198 } 199 200 static void 201 nv_mem_free(nvpriv_t *nvp, void *buf, size_t size) 202 { 203 nv_alloc_t *nva = nvp->nvp_nva; 204 205 nva->nva_ops->nv_ao_free(nva, buf, size); 206 } 207 208 static void 209 nv_priv_init(nvpriv_t *priv, nv_alloc_t *nva, uint32_t stat) 210 { 211 bzero(priv, sizeof (nvpriv_t)); 212 213 priv->nvp_nva = nva; 214 priv->nvp_stat = stat; 215 } 216 217 static nvpriv_t * 218 nv_priv_alloc(nv_alloc_t *nva) 219 { 220 nvpriv_t *priv; 221 222 /* 223 * nv_mem_alloc() cannot called here because it needs the priv 224 * argument. 225 */ 226 if ((priv = nva->nva_ops->nv_ao_alloc(nva, sizeof (nvpriv_t))) == NULL) 227 return (NULL); 228 229 nv_priv_init(priv, nva, 0); 230 231 return (priv); 232 } 233 234 /* 235 * Embedded lists need their own nvpriv_t's. We create a new 236 * nvpriv_t using the parameters and allocator from the parent 237 * list's nvpriv_t. 238 */ 239 static nvpriv_t * 240 nv_priv_alloc_embedded(nvpriv_t *priv) 241 { 242 nvpriv_t *emb_priv; 243 244 if ((emb_priv = nv_mem_zalloc(priv, sizeof (nvpriv_t))) == NULL) 245 return (NULL); 246 247 nv_priv_init(emb_priv, priv->nvp_nva, NV_STAT_EMBEDDED); 248 249 return (emb_priv); 250 } 251 252 static void 253 nvlist_init(nvlist_t *nvl, uint32_t nvflag, nvpriv_t *priv) 254 { 255 nvl->nvl_version = NV_VERSION; 256 nvl->nvl_nvflag = nvflag & (NV_UNIQUE_NAME|NV_UNIQUE_NAME_TYPE); 257 nvl->nvl_priv = (uint64_t)(uintptr_t)priv; 258 nvl->nvl_flag = 0; 259 nvl->nvl_pad = 0; 260 } 261 262 /* 263 * nvlist_alloc - Allocate nvlist. 264 */ 265 /*ARGSUSED1*/ 266 int 267 nvlist_alloc(nvlist_t **nvlp, uint_t nvflag, int kmflag) 268 { 269 #if defined(_KERNEL) && !defined(_BOOT) 270 return (nvlist_xalloc(nvlp, nvflag, 271 (kmflag == KM_SLEEP ? nv_alloc_sleep : nv_alloc_nosleep))); 272 #else 273 return (nvlist_xalloc(nvlp, nvflag, nv_alloc_nosleep)); 274 #endif 275 } 276 277 int 278 nvlist_xalloc(nvlist_t **nvlp, uint_t nvflag, nv_alloc_t *nva) 279 { 280 nvpriv_t *priv; 281 282 if (nvlp == NULL || nva == NULL) 283 return (EINVAL); 284 285 if ((priv = nv_priv_alloc(nva)) == NULL) 286 return (ENOMEM); 287 288 if ((*nvlp = nv_mem_zalloc(priv, 289 NV_ALIGN(sizeof (nvlist_t)))) == NULL) { 290 nv_mem_free(priv, priv, sizeof (nvpriv_t)); 291 return (ENOMEM); 292 } 293 294 nvlist_init(*nvlp, nvflag, priv); 295 296 return (0); 297 } 298 299 /* 300 * nvp_buf_alloc - Allocate i_nvp_t for storing a new nv pair. 301 */ 302 static nvpair_t * 303 nvp_buf_alloc(nvlist_t *nvl, size_t len) 304 { 305 nvpriv_t *priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv; 306 i_nvp_t *buf; 307 nvpair_t *nvp; 308 size_t nvsize; 309 310 /* 311 * Allocate the buffer 312 */ 313 nvsize = len + offsetof(i_nvp_t, nvi_nvp); 314 315 if ((buf = nv_mem_zalloc(priv, nvsize)) == NULL) 316 return (NULL); 317 318 nvp = &buf->nvi_nvp; 319 nvp->nvp_size = len; 320 321 return (nvp); 322 } 323 324 /* 325 * nvp_buf_free - de-Allocate an i_nvp_t. 326 */ 327 static void 328 nvp_buf_free(nvlist_t *nvl, nvpair_t *nvp) 329 { 330 nvpriv_t *priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv; 331 size_t nvsize = nvp->nvp_size + offsetof(i_nvp_t, nvi_nvp); 332 333 nv_mem_free(priv, NVPAIR2I_NVP(nvp), nvsize); 334 } 335 336 /* 337 * nvp_buf_link - link a new nv pair into the nvlist. 338 */ 339 static void 340 nvp_buf_link(nvlist_t *nvl, nvpair_t *nvp) 341 { 342 nvpriv_t *priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv; 343 i_nvp_t *curr = NVPAIR2I_NVP(nvp); 344 345 /* Put element at end of nvlist */ 346 if (priv->nvp_list == NULL) { 347 priv->nvp_list = priv->nvp_last = curr; 348 } else { 349 curr->nvi_prev = priv->nvp_last; 350 priv->nvp_last->nvi_next = curr; 351 priv->nvp_last = curr; 352 } 353 } 354 355 /* 356 * nvp_buf_unlink - unlink an removed nvpair out of the nvlist. 357 */ 358 static void 359 nvp_buf_unlink(nvlist_t *nvl, nvpair_t *nvp) 360 { 361 nvpriv_t *priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv; 362 i_nvp_t *curr = NVPAIR2I_NVP(nvp); 363 364 /* 365 * protect nvlist_next_nvpair() against walking on freed memory. 366 */ 367 if (priv->nvp_curr == curr) 368 priv->nvp_curr = curr->nvi_next; 369 370 if (curr == priv->nvp_list) 371 priv->nvp_list = curr->nvi_next; 372 else 373 curr->nvi_prev->nvi_next = curr->nvi_next; 374 375 if (curr == priv->nvp_last) 376 priv->nvp_last = curr->nvi_prev; 377 else 378 curr->nvi_next->nvi_prev = curr->nvi_prev; 379 } 380 381 /* 382 * take a nvpair type and number of elements and make sure the are valid 383 */ 384 static int 385 i_validate_type_nelem(data_type_t type, uint_t nelem) 386 { 387 switch (type) { 388 case DATA_TYPE_BOOLEAN: 389 if (nelem != 0) 390 return (EINVAL); 391 break; 392 case DATA_TYPE_BOOLEAN_VALUE: 393 case DATA_TYPE_BYTE: 394 case DATA_TYPE_INT8: 395 case DATA_TYPE_UINT8: 396 case DATA_TYPE_INT16: 397 case DATA_TYPE_UINT16: 398 case DATA_TYPE_INT32: 399 case DATA_TYPE_UINT32: 400 case DATA_TYPE_INT64: 401 case DATA_TYPE_UINT64: 402 case DATA_TYPE_STRING: 403 case DATA_TYPE_HRTIME: 404 case DATA_TYPE_NVLIST: 405 #if !defined(_KERNEL) 406 case DATA_TYPE_DOUBLE: 407 #endif 408 if (nelem != 1) 409 return (EINVAL); 410 break; 411 case DATA_TYPE_BOOLEAN_ARRAY: 412 case DATA_TYPE_BYTE_ARRAY: 413 case DATA_TYPE_INT8_ARRAY: 414 case DATA_TYPE_UINT8_ARRAY: 415 case DATA_TYPE_INT16_ARRAY: 416 case DATA_TYPE_UINT16_ARRAY: 417 case DATA_TYPE_INT32_ARRAY: 418 case DATA_TYPE_UINT32_ARRAY: 419 case DATA_TYPE_INT64_ARRAY: 420 case DATA_TYPE_UINT64_ARRAY: 421 case DATA_TYPE_STRING_ARRAY: 422 case DATA_TYPE_NVLIST_ARRAY: 423 /* we allow arrays with 0 elements */ 424 break; 425 default: 426 return (EINVAL); 427 } 428 return (0); 429 } 430 431 /* 432 * Verify nvp_name_sz and check the name string length. 433 */ 434 static int 435 i_validate_nvpair_name(nvpair_t *nvp) 436 { 437 if ((nvp->nvp_name_sz <= 0) || 438 (nvp->nvp_size < NVP_SIZE_CALC(nvp->nvp_name_sz, 0))) 439 return (EFAULT); 440 441 /* verify the name string, make sure its terminated */ 442 if (NVP_NAME(nvp)[nvp->nvp_name_sz - 1] != '\0') 443 return (EFAULT); 444 445 return (strlen(NVP_NAME(nvp)) == nvp->nvp_name_sz - 1 ? 0 : EFAULT); 446 } 447 448 static int 449 i_validate_nvpair_value(data_type_t type, uint_t nelem, const void *data) 450 { 451 switch (type) { 452 case DATA_TYPE_BOOLEAN_VALUE: 453 if (*(boolean_t *)data != B_TRUE && 454 *(boolean_t *)data != B_FALSE) 455 return (EINVAL); 456 break; 457 case DATA_TYPE_BOOLEAN_ARRAY: { 458 int i; 459 460 for (i = 0; i < nelem; i++) 461 if (((boolean_t *)data)[i] != B_TRUE && 462 ((boolean_t *)data)[i] != B_FALSE) 463 return (EINVAL); 464 break; 465 } 466 default: 467 break; 468 } 469 470 return (0); 471 } 472 473 /* 474 * This function takes a pointer to what should be a nvpair and it's size 475 * and then verifies that all the nvpair fields make sense and can be 476 * trusted. This function is used when decoding packed nvpairs. 477 */ 478 static int 479 i_validate_nvpair(nvpair_t *nvp) 480 { 481 data_type_t type = NVP_TYPE(nvp); 482 int size1, size2; 483 484 /* verify nvp_name_sz, check the name string length */ 485 if (i_validate_nvpair_name(nvp) != 0) 486 return (EFAULT); 487 488 if (i_validate_nvpair_value(type, NVP_NELEM(nvp), NVP_VALUE(nvp)) != 0) 489 return (EFAULT); 490 491 /* 492 * verify nvp_type, nvp_value_elem, and also possibly 493 * verify string values and get the value size. 494 */ 495 size2 = i_get_value_size(type, NVP_VALUE(nvp), NVP_NELEM(nvp)); 496 size1 = nvp->nvp_size - NVP_VALOFF(nvp); 497 if (size2 < 0 || size1 != NV_ALIGN(size2)) 498 return (EFAULT); 499 500 return (0); 501 } 502 503 static int 504 nvlist_copy_pairs(nvlist_t *snvl, nvlist_t *dnvl) 505 { 506 nvpriv_t *priv; 507 i_nvp_t *curr; 508 509 if ((priv = (nvpriv_t *)(uintptr_t)snvl->nvl_priv) == NULL) 510 return (EINVAL); 511 512 for (curr = priv->nvp_list; curr != NULL; curr = curr->nvi_next) { 513 nvpair_t *nvp = &curr->nvi_nvp; 514 int err; 515 516 if ((err = nvlist_add_common(dnvl, NVP_NAME(nvp), NVP_TYPE(nvp), 517 NVP_NELEM(nvp), NVP_VALUE(nvp))) != 0) 518 return (err); 519 } 520 521 return (0); 522 } 523 524 /* 525 * Frees all memory allocated for an nvpair (like embedded lists) with 526 * the exception of the nvpair buffer itself. 527 */ 528 static void 529 nvpair_free(nvpair_t *nvp) 530 { 531 switch (NVP_TYPE(nvp)) { 532 case DATA_TYPE_NVLIST: 533 nvlist_free(EMBEDDED_NVL(nvp)); 534 break; 535 case DATA_TYPE_NVLIST_ARRAY: { 536 nvlist_t **nvlp = EMBEDDED_NVL_ARRAY(nvp); 537 int i; 538 539 for (i = 0; i < NVP_NELEM(nvp); i++) 540 if (nvlp[i] != NULL) 541 nvlist_free(nvlp[i]); 542 break; 543 } 544 default: 545 break; 546 } 547 } 548 549 /* 550 * nvlist_free - free an unpacked nvlist 551 */ 552 void 553 nvlist_free(nvlist_t *nvl) 554 { 555 nvpriv_t *priv; 556 i_nvp_t *curr; 557 558 if (nvl == NULL || 559 (priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL) 560 return; 561 562 /* 563 * Unpacked nvlist are linked through i_nvp_t 564 */ 565 curr = priv->nvp_list; 566 while (curr != NULL) { 567 nvpair_t *nvp = &curr->nvi_nvp; 568 curr = curr->nvi_next; 569 570 nvpair_free(nvp); 571 nvp_buf_free(nvl, nvp); 572 } 573 574 if (!(priv->nvp_stat & NV_STAT_EMBEDDED)) 575 nv_mem_free(priv, nvl, NV_ALIGN(sizeof (nvlist_t))); 576 else 577 nvl->nvl_priv = 0; 578 579 nv_mem_free(priv, priv, sizeof (nvpriv_t)); 580 } 581 582 static int 583 nvlist_contains_nvp(nvlist_t *nvl, nvpair_t *nvp) 584 { 585 nvpriv_t *priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv; 586 i_nvp_t *curr; 587 588 if (nvp == NULL) 589 return (0); 590 591 for (curr = priv->nvp_list; curr != NULL; curr = curr->nvi_next) 592 if (&curr->nvi_nvp == nvp) 593 return (1); 594 595 return (0); 596 } 597 598 /* 599 * Make a copy of nvlist 600 */ 601 /*ARGSUSED1*/ 602 int 603 nvlist_dup(nvlist_t *nvl, nvlist_t **nvlp, int kmflag) 604 { 605 #if defined(_KERNEL) && !defined(_BOOT) 606 return (nvlist_xdup(nvl, nvlp, 607 (kmflag == KM_SLEEP ? nv_alloc_sleep : nv_alloc_nosleep))); 608 #else 609 return (nvlist_xdup(nvl, nvlp, nv_alloc_nosleep)); 610 #endif 611 } 612 613 int 614 nvlist_xdup(nvlist_t *nvl, nvlist_t **nvlp, nv_alloc_t *nva) 615 { 616 int err; 617 nvlist_t *ret; 618 619 if (nvl == NULL || nvlp == NULL) 620 return (EINVAL); 621 622 if ((err = nvlist_xalloc(&ret, nvl->nvl_nvflag, nva)) != 0) 623 return (err); 624 625 if ((err = nvlist_copy_pairs(nvl, ret)) != 0) 626 nvlist_free(ret); 627 else 628 *nvlp = ret; 629 630 return (err); 631 } 632 633 /* 634 * Remove all with matching name 635 */ 636 int 637 nvlist_remove_all(nvlist_t *nvl, const char *name) 638 { 639 nvpriv_t *priv; 640 i_nvp_t *curr; 641 int error = ENOENT; 642 643 if (nvl == NULL || name == NULL || 644 (priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL) 645 return (EINVAL); 646 647 curr = priv->nvp_list; 648 while (curr != NULL) { 649 nvpair_t *nvp = &curr->nvi_nvp; 650 651 curr = curr->nvi_next; 652 if (strcmp(name, NVP_NAME(nvp)) != 0) 653 continue; 654 655 nvp_buf_unlink(nvl, nvp); 656 nvpair_free(nvp); 657 nvp_buf_free(nvl, nvp); 658 659 error = 0; 660 } 661 662 return (error); 663 } 664 665 /* 666 * Remove first one with matching name and type 667 */ 668 int 669 nvlist_remove(nvlist_t *nvl, const char *name, data_type_t type) 670 { 671 nvpriv_t *priv; 672 i_nvp_t *curr; 673 674 if (nvl == NULL || name == NULL || 675 (priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL) 676 return (EINVAL); 677 678 curr = priv->nvp_list; 679 while (curr != NULL) { 680 nvpair_t *nvp = &curr->nvi_nvp; 681 682 if (strcmp(name, NVP_NAME(nvp)) == 0 && NVP_TYPE(nvp) == type) { 683 nvp_buf_unlink(nvl, nvp); 684 nvpair_free(nvp); 685 nvp_buf_free(nvl, nvp); 686 687 return (0); 688 } 689 curr = curr->nvi_next; 690 } 691 692 return (ENOENT); 693 } 694 695 /* 696 * This function calculates the size of an nvpair value. 697 * 698 * The data argument controls the behavior in case of the data types 699 * DATA_TYPE_STRING and 700 * DATA_TYPE_STRING_ARRAY 701 * Is data == NULL then the size of the string(s) is excluded. 702 */ 703 static int 704 i_get_value_size(data_type_t type, const void *data, uint_t nelem) 705 { 706 uint64_t value_sz; 707 708 if (i_validate_type_nelem(type, nelem) != 0) 709 return (-1); 710 711 /* Calculate required size for holding value */ 712 switch (type) { 713 case DATA_TYPE_BOOLEAN: 714 value_sz = 0; 715 break; 716 case DATA_TYPE_BOOLEAN_VALUE: 717 value_sz = sizeof (boolean_t); 718 break; 719 case DATA_TYPE_BYTE: 720 value_sz = sizeof (uchar_t); 721 break; 722 case DATA_TYPE_INT8: 723 value_sz = sizeof (int8_t); 724 break; 725 case DATA_TYPE_UINT8: 726 value_sz = sizeof (uint8_t); 727 break; 728 case DATA_TYPE_INT16: 729 value_sz = sizeof (int16_t); 730 break; 731 case DATA_TYPE_UINT16: 732 value_sz = sizeof (uint16_t); 733 break; 734 case DATA_TYPE_INT32: 735 value_sz = sizeof (int32_t); 736 break; 737 case DATA_TYPE_UINT32: 738 value_sz = sizeof (uint32_t); 739 break; 740 case DATA_TYPE_INT64: 741 value_sz = sizeof (int64_t); 742 break; 743 case DATA_TYPE_UINT64: 744 value_sz = sizeof (uint64_t); 745 break; 746 #if !defined(_KERNEL) 747 case DATA_TYPE_DOUBLE: 748 value_sz = sizeof (double); 749 break; 750 #endif 751 case DATA_TYPE_STRING: 752 if (data == NULL) 753 value_sz = 0; 754 else 755 value_sz = strlen(data) + 1; 756 break; 757 case DATA_TYPE_BOOLEAN_ARRAY: 758 value_sz = (uint64_t)nelem * sizeof (boolean_t); 759 break; 760 case DATA_TYPE_BYTE_ARRAY: 761 value_sz = (uint64_t)nelem * sizeof (uchar_t); 762 break; 763 case DATA_TYPE_INT8_ARRAY: 764 value_sz = (uint64_t)nelem * sizeof (int8_t); 765 break; 766 case DATA_TYPE_UINT8_ARRAY: 767 value_sz = (uint64_t)nelem * sizeof (uint8_t); 768 break; 769 case DATA_TYPE_INT16_ARRAY: 770 value_sz = (uint64_t)nelem * sizeof (int16_t); 771 break; 772 case DATA_TYPE_UINT16_ARRAY: 773 value_sz = (uint64_t)nelem * sizeof (uint16_t); 774 break; 775 case DATA_TYPE_INT32_ARRAY: 776 value_sz = (uint64_t)nelem * sizeof (int32_t); 777 break; 778 case DATA_TYPE_UINT32_ARRAY: 779 value_sz = (uint64_t)nelem * sizeof (uint32_t); 780 break; 781 case DATA_TYPE_INT64_ARRAY: 782 value_sz = (uint64_t)nelem * sizeof (int64_t); 783 break; 784 case DATA_TYPE_UINT64_ARRAY: 785 value_sz = (uint64_t)nelem * sizeof (uint64_t); 786 break; 787 case DATA_TYPE_STRING_ARRAY: 788 value_sz = (uint64_t)nelem * sizeof (uint64_t); 789 790 if (data != NULL) { 791 char *const *strs = data; 792 uint_t i; 793 794 /* no alignment requirement for strings */ 795 for (i = 0; i < nelem; i++) { 796 if (strs[i] == NULL) 797 return (-1); 798 value_sz += strlen(strs[i]) + 1; 799 } 800 } 801 break; 802 case DATA_TYPE_HRTIME: 803 value_sz = sizeof (hrtime_t); 804 break; 805 case DATA_TYPE_NVLIST: 806 value_sz = NV_ALIGN(sizeof (nvlist_t)); 807 break; 808 case DATA_TYPE_NVLIST_ARRAY: 809 value_sz = (uint64_t)nelem * sizeof (uint64_t) + 810 (uint64_t)nelem * NV_ALIGN(sizeof (nvlist_t)); 811 break; 812 default: 813 return (-1); 814 } 815 816 return (value_sz > INT32_MAX ? -1 : (int)value_sz); 817 } 818 819 static int 820 nvlist_copy_embedded(nvlist_t *nvl, nvlist_t *onvl, nvlist_t *emb_nvl) 821 { 822 nvpriv_t *priv; 823 int err; 824 825 if ((priv = nv_priv_alloc_embedded((nvpriv_t *)(uintptr_t) 826 nvl->nvl_priv)) == NULL) 827 return (ENOMEM); 828 829 nvlist_init(emb_nvl, onvl->nvl_nvflag, priv); 830 831 if ((err = nvlist_copy_pairs(onvl, emb_nvl)) != 0) { 832 nvlist_free(emb_nvl); 833 emb_nvl->nvl_priv = 0; 834 } 835 836 return (err); 837 } 838 839 /* 840 * nvlist_add_common - Add new <name,value> pair to nvlist 841 */ 842 static int 843 nvlist_add_common(nvlist_t *nvl, const char *name, 844 data_type_t type, uint_t nelem, const void *data) 845 { 846 nvpair_t *nvp; 847 uint_t i; 848 849 int nvp_sz, name_sz, value_sz; 850 int err = 0; 851 852 if (name == NULL || nvl == NULL || nvl->nvl_priv == 0) 853 return (EINVAL); 854 855 if (nelem != 0 && data == NULL) 856 return (EINVAL); 857 858 /* 859 * Verify type and nelem and get the value size. 860 * In case of data types DATA_TYPE_STRING and DATA_TYPE_STRING_ARRAY 861 * is the size of the string(s) included. 862 */ 863 if ((value_sz = i_get_value_size(type, data, nelem)) < 0) 864 return (EINVAL); 865 866 if (i_validate_nvpair_value(type, nelem, data) != 0) 867 return (EINVAL); 868 869 /* 870 * If we're adding an nvlist or nvlist array, ensure that we are not 871 * adding the input nvlist to itself, which would cause recursion, 872 * and ensure that no NULL nvlist pointers are present. 873 */ 874 switch (type) { 875 case DATA_TYPE_NVLIST: 876 if (data == nvl || data == NULL) 877 return (EINVAL); 878 break; 879 case DATA_TYPE_NVLIST_ARRAY: { 880 nvlist_t **onvlp = (nvlist_t **)data; 881 for (i = 0; i < nelem; i++) { 882 if (onvlp[i] == nvl || onvlp[i] == NULL) 883 return (EINVAL); 884 } 885 break; 886 } 887 default: 888 break; 889 } 890 891 /* calculate sizes of the nvpair elements and the nvpair itself */ 892 name_sz = strlen(name) + 1; 893 894 nvp_sz = NVP_SIZE_CALC(name_sz, value_sz); 895 896 if ((nvp = nvp_buf_alloc(nvl, nvp_sz)) == NULL) 897 return (ENOMEM); 898 899 ASSERT(nvp->nvp_size == nvp_sz); 900 nvp->nvp_name_sz = name_sz; 901 nvp->nvp_value_elem = nelem; 902 nvp->nvp_type = type; 903 bcopy(name, NVP_NAME(nvp), name_sz); 904 905 switch (type) { 906 case DATA_TYPE_BOOLEAN: 907 break; 908 case DATA_TYPE_STRING_ARRAY: { 909 char *const *strs = data; 910 char *buf = NVP_VALUE(nvp); 911 char **cstrs = (void *)buf; 912 913 /* skip pre-allocated space for pointer array */ 914 buf += nelem * sizeof (uint64_t); 915 for (i = 0; i < nelem; i++) { 916 int slen = strlen(strs[i]) + 1; 917 bcopy(strs[i], buf, slen); 918 cstrs[i] = buf; 919 buf += slen; 920 } 921 break; 922 } 923 case DATA_TYPE_NVLIST: { 924 nvlist_t *nnvl = EMBEDDED_NVL(nvp); 925 nvlist_t *onvl = (nvlist_t *)data; 926 927 if ((err = nvlist_copy_embedded(nvl, onvl, nnvl)) != 0) { 928 nvp_buf_free(nvl, nvp); 929 return (err); 930 } 931 break; 932 } 933 case DATA_TYPE_NVLIST_ARRAY: { 934 nvlist_t **onvlp = (nvlist_t **)data; 935 nvlist_t **nvlp = EMBEDDED_NVL_ARRAY(nvp); 936 nvlist_t *embedded = (nvlist_t *) 937 ((uintptr_t)nvlp + nelem * sizeof (uint64_t)); 938 939 for (i = 0; i < nelem; i++) { 940 if ((err = nvlist_copy_embedded(nvl, 941 onvlp[i], embedded)) != 0) { 942 /* 943 * Free any successfully created lists 944 */ 945 nvpair_free(nvp); 946 nvp_buf_free(nvl, nvp); 947 return (err); 948 } 949 950 nvlp[i] = embedded++; 951 } 952 break; 953 } 954 default: 955 bcopy(data, NVP_VALUE(nvp), value_sz); 956 } 957 958 /* if unique name, remove before add */ 959 if (nvl->nvl_nvflag & NV_UNIQUE_NAME) 960 (void) nvlist_remove_all(nvl, name); 961 else if (nvl->nvl_nvflag & NV_UNIQUE_NAME_TYPE) 962 (void) nvlist_remove(nvl, name, type); 963 964 nvp_buf_link(nvl, nvp); 965 966 return (0); 967 } 968 969 int 970 nvlist_add_boolean(nvlist_t *nvl, const char *name) 971 { 972 return (nvlist_add_common(nvl, name, DATA_TYPE_BOOLEAN, 0, NULL)); 973 } 974 975 int 976 nvlist_add_boolean_value(nvlist_t *nvl, const char *name, boolean_t val) 977 { 978 return (nvlist_add_common(nvl, name, DATA_TYPE_BOOLEAN_VALUE, 1, &val)); 979 } 980 981 int 982 nvlist_add_byte(nvlist_t *nvl, const char *name, uchar_t val) 983 { 984 return (nvlist_add_common(nvl, name, DATA_TYPE_BYTE, 1, &val)); 985 } 986 987 int 988 nvlist_add_int8(nvlist_t *nvl, const char *name, int8_t val) 989 { 990 return (nvlist_add_common(nvl, name, DATA_TYPE_INT8, 1, &val)); 991 } 992 993 int 994 nvlist_add_uint8(nvlist_t *nvl, const char *name, uint8_t val) 995 { 996 return (nvlist_add_common(nvl, name, DATA_TYPE_UINT8, 1, &val)); 997 } 998 999 int 1000 nvlist_add_int16(nvlist_t *nvl, const char *name, int16_t val) 1001 { 1002 return (nvlist_add_common(nvl, name, DATA_TYPE_INT16, 1, &val)); 1003 } 1004 1005 int 1006 nvlist_add_uint16(nvlist_t *nvl, const char *name, uint16_t val) 1007 { 1008 return (nvlist_add_common(nvl, name, DATA_TYPE_UINT16, 1, &val)); 1009 } 1010 1011 int 1012 nvlist_add_int32(nvlist_t *nvl, const char *name, int32_t val) 1013 { 1014 return (nvlist_add_common(nvl, name, DATA_TYPE_INT32, 1, &val)); 1015 } 1016 1017 int 1018 nvlist_add_uint32(nvlist_t *nvl, const char *name, uint32_t val) 1019 { 1020 return (nvlist_add_common(nvl, name, DATA_TYPE_UINT32, 1, &val)); 1021 } 1022 1023 int 1024 nvlist_add_int64(nvlist_t *nvl, const char *name, int64_t val) 1025 { 1026 return (nvlist_add_common(nvl, name, DATA_TYPE_INT64, 1, &val)); 1027 } 1028 1029 int 1030 nvlist_add_uint64(nvlist_t *nvl, const char *name, uint64_t val) 1031 { 1032 return (nvlist_add_common(nvl, name, DATA_TYPE_UINT64, 1, &val)); 1033 } 1034 1035 #if !defined(_KERNEL) 1036 int 1037 nvlist_add_double(nvlist_t *nvl, const char *name, double val) 1038 { 1039 return (nvlist_add_common(nvl, name, DATA_TYPE_DOUBLE, 1, &val)); 1040 } 1041 #endif 1042 1043 int 1044 nvlist_add_string(nvlist_t *nvl, const char *name, const char *val) 1045 { 1046 return (nvlist_add_common(nvl, name, DATA_TYPE_STRING, 1, (void *)val)); 1047 } 1048 1049 int 1050 nvlist_add_boolean_array(nvlist_t *nvl, const char *name, 1051 boolean_t *a, uint_t n) 1052 { 1053 return (nvlist_add_common(nvl, name, DATA_TYPE_BOOLEAN_ARRAY, n, a)); 1054 } 1055 1056 int 1057 nvlist_add_byte_array(nvlist_t *nvl, const char *name, uchar_t *a, uint_t n) 1058 { 1059 return (nvlist_add_common(nvl, name, DATA_TYPE_BYTE_ARRAY, n, a)); 1060 } 1061 1062 int 1063 nvlist_add_int8_array(nvlist_t *nvl, const char *name, int8_t *a, uint_t n) 1064 { 1065 return (nvlist_add_common(nvl, name, DATA_TYPE_INT8_ARRAY, n, a)); 1066 } 1067 1068 int 1069 nvlist_add_uint8_array(nvlist_t *nvl, const char *name, uint8_t *a, uint_t n) 1070 { 1071 return (nvlist_add_common(nvl, name, DATA_TYPE_UINT8_ARRAY, n, a)); 1072 } 1073 1074 int 1075 nvlist_add_int16_array(nvlist_t *nvl, const char *name, int16_t *a, uint_t n) 1076 { 1077 return (nvlist_add_common(nvl, name, DATA_TYPE_INT16_ARRAY, n, a)); 1078 } 1079 1080 int 1081 nvlist_add_uint16_array(nvlist_t *nvl, const char *name, uint16_t *a, uint_t n) 1082 { 1083 return (nvlist_add_common(nvl, name, DATA_TYPE_UINT16_ARRAY, n, a)); 1084 } 1085 1086 int 1087 nvlist_add_int32_array(nvlist_t *nvl, const char *name, int32_t *a, uint_t n) 1088 { 1089 return (nvlist_add_common(nvl, name, DATA_TYPE_INT32_ARRAY, n, a)); 1090 } 1091 1092 int 1093 nvlist_add_uint32_array(nvlist_t *nvl, const char *name, uint32_t *a, uint_t n) 1094 { 1095 return (nvlist_add_common(nvl, name, DATA_TYPE_UINT32_ARRAY, n, a)); 1096 } 1097 1098 int 1099 nvlist_add_int64_array(nvlist_t *nvl, const char *name, int64_t *a, uint_t n) 1100 { 1101 return (nvlist_add_common(nvl, name, DATA_TYPE_INT64_ARRAY, n, a)); 1102 } 1103 1104 int 1105 nvlist_add_uint64_array(nvlist_t *nvl, const char *name, uint64_t *a, uint_t n) 1106 { 1107 return (nvlist_add_common(nvl, name, DATA_TYPE_UINT64_ARRAY, n, a)); 1108 } 1109 1110 in