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 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <libscf.h> 27 #include <stdio.h> 28 #include <stdlib.h> 29 #include <errno.h> 30 #include <assert.h> 31 #include <strings.h> 32 #include <libstmf.h> 33 #include <store.h> 34 #include <syslog.h> 35 #include <signal.h> 36 #include <pthread.h> 37 #include <libnvpair.h> 38 #include <limits.h> 39 #include <unistd.h> 40 41 /* 42 * This file's functions are responsible for all store and retrieve operations 43 * against the STMF smf(5) database. The following shows the currently defined 44 * schema for the STMF database: 45 * 46 * Description of property groups for service: svc:/system/stmf 47 * 48 * Stability: Volatile 49 * 50 * 1. Property Group: host_groups 51 * Properties: group_name-<N> where <N> is an unsigned integer 52 * type: ustring 53 * contains: group name 54 * group_name-<N>-member_list where <N> is an unsigned 55 * integer matching a group_name-<N> property. 56 * type: ustring 57 * contains: list of members 58 * 59 * Description: 60 * Contains the host group names as well as the host group members 61 * for each host group. 62 * 63 * 2. Property Group: target_groups 64 * Properties: group_name-<N> where <N> is an unsigned integer 65 * type: ustring 66 * contains: group name 67 * group_name-<N>-member_list where <N> is an unsigned 68 * integer matching a group_name-<N> property. 69 * type: ustring 70 * contains: list of members 71 * 72 * Description: 73 * Contains the target group names as well as the target group 74 * members for each target group. 75 * 76 * 3. Property Group: lu-<GUID> 77 * where <GUID> is a 32 character hexadecimal string. 78 * Properties: ve_cnt 79 * type: count 80 * contains: the number of current view entries 81 * view-entry-<N>-<GUID> where <N> is an unsigned integer 82 * type: ustring 83 * contains: nothing. Used as reference to the view 84 * entry property group 85 * 86 * Description: 87 * Contains the references to each view entry. One lu-<GUID> 88 * property group will exist for each logical unit with 1 or more 89 * view entries. 90 * Potentially can hold any other data that can be managed on a per 91 * logical unit basis. 92 * 93 * 4. Property Group: view_entry-<N>-<GUID> (matches property in lu-<GUID> 94 * property group) 95 * Properties: all_hosts 96 * type: boolean 97 * contains: when true, the value of host_group is 98 * ignored 99 * all_targets 100 * type: boolean 101 * contains: when true, the value of target_group is 102 * ignored 103 * host_group 104 * type: ustring 105 * contains: host group for logical unit mapping and 106 * masking purposes 107 * target_group 108 * type: ustring 109 * contains: target group for logical unit mapping and 110 * masking purposes 111 * lu_nbr 112 * type: opaque 113 * contains: the 8-byte SCSI logical unit number for 114 * mapping and masking purposes 115 * Description: 116 * One "view_entry-<N>-<GUID>" property group will exist for each 117 * view entry in the system. This property group name maps 118 * directly to the "lu-<GUID>" property group with a matching 119 * <GUID>. 120 * 121 * 5. Property Group: provider_data_pg_<provider-name> 122 * where <provider-name> is the name of the provider 123 * registered with stmf. 124 * Properties: provider_data_prop-<N> 125 * where <N> is a sequential identifier for the data 126 * chunk. 127 * type: opaque 128 * contains: up to STMF_PROVIDER_DATA_PROP_SIZE bytes 129 * of nvlist packed data. 130 * provider_data_count 131 * type: count 132 * contains: the number of provider data chunks 133 * provider_data_type 134 * type: integer 135 * contains: STMF_PORT_PROVIDER_TYPE or 136 * STMF_LU_PROVIDER_TYPE 137 * 138 * Description: 139 * Holds the nvlist packed provider data set via 140 * stmfSetProviderData and retrieved via stmfGetProviderData. Data 141 * is stored in STMF_PROVIDER_DATA_PROP_SIZE chunks. On retrieve, 142 * these chunks are reassembled and unpacked. 143 * 144 */ 145 146 static int iPsInit(scf_handle_t **, scf_service_t **); 147 static int iPsCreateDeleteGroup(char *, char *, int); 148 static int iPsAddRemoveGroupMember(char *, char *, char *, int); 149 static int iPsGetGroupList(char *, stmfGroupList **); 150 static int iPsGetGroupMemberList(char *, char *, stmfGroupProperties **); 151 static int iPsAddViewEntry(char *, char *, stmfViewEntry *); 152 static int iPsAddRemoveLuViewEntry(char *, char *, int); 153 static int iPsGetViewEntry(char *, stmfViewEntry *); 154 static int iPsGetActualGroupName(char *, char *, char *); 155 static int iPsGetServiceVersion(uint64_t *, scf_handle_t *, scf_service_t *); 156 static int viewEntryCompare(const void *, const void *); 157 static int holdSignal(sigset_t *); 158 static int releaseSignal(sigset_t *); 159 static void sigHandler(); 160 161 static pthread_mutex_t sigSetLock = PTHREAD_MUTEX_INITIALIZER; 162 163 sigset_t sigSet; 164 sigset_t signalsCaught; 165 166 struct sigaction currentActionQuit; 167 struct sigaction currentActionTerm; 168 struct sigaction currentActionInt; 169 170 boolean_t actionSet = B_FALSE; 171 172 /* 173 * Version info for the SMF schema 174 */ 175 #define STMF_SMF_VERSION 1 176 177 /* 178 * Property Group Names and prefixes 179 */ 180 #define STMF_HOST_GROUPS "host_groups" 181 #define STMF_TARGET_GROUPS "target_groups" 182 #define STMF_VE_PREFIX "view_entry" 183 #define STMF_LU_PREFIX "lu" 184 #define STMF_DATA_GROUP "stmf_data" 185 186 /* 187 * Property names and prefix for logical unit property group 188 */ 189 #define STMF_VE_CNT "ve_cnt" 190 #define STMF_GROUP_PREFIX "group_name" 191 #define STMF_MEMBER_LIST_SUFFIX "member_list" 192 #define STMF_VERSION_NAME "version_name" 193 194 /* 195 * Property names for view entry 196 */ 197 #define STMF_VE_ALLHOSTS "all_hosts" 198 #define STMF_VE_HOSTGROUP "host_group" 199 #define STMF_VE_ALLTARGETS "all_targets" 200 #define STMF_VE_TARGETGROUP "target_group" 201 #define STMF_VE_LUNBR "lu_nbr" 202 203 /* Property group suffix for provider data */ 204 #define STMF_PROVIDER_DATA_PREFIX "provider_data_pg_" 205 #define STMF_PROVIDER_DATA_PROP_PREFIX "provider_data_prop" 206 #define STMF_PROVIDER_DATA_PROP_NAME_SIZE 256 207 #define STMF_PROVIDER_DATA_PROP_TYPE "provider_type" 208 #define STMF_PROVIDER_DATA_PROP_SET_COUNT "provider_data_set_cnt" 209 #define STMF_PROVIDER_DATA_PROP_COUNT "provider_data_cnt" 210 /* 211 * This is the data chunk size. The current value limit for scf is 4096. 212 * This is defined by REP_PROTOCOL_VALUE_LEN in 213 * OS/Net: usr/src/common/svc/repcache_protocol.h 214 * 215 * Larger data property size = better performance 216 */ 217 #define STMF_PROVIDER_DATA_PROP_SIZE 4000 218 219 #define STMF_SMF_READ_ATTR "solaris.smf.read.stmf" 220 221 222 /* service name */ 223 #define STMF_SERVICE "system/stmf" 224 225 /* limits and flag values */ 226 #define GROUP_MEMBER_ALLOC 100 227 #define VIEW_ENTRY_STRUCT_CNT 6 228 #define VIEW_ENTRY_PG_SIZE 256 229 #define LOGICAL_UNIT_PG_SIZE 256 230 #define VIEW_ENTRY_MAX UINT32_MAX 231 #define GROUP_MAX UINT64_MAX 232 #define ADD 0 233 #define REMOVE 1 234 235 /* 236 * sigHandler 237 * 238 * Catch the signal and set the global signalsCaught to the signal received 239 * 240 * signalsCaught will be used by releaseSignal to raise this signal when 241 * we're done processing our critical code. 242 * 243 */ 244 static void 245 sigHandler(int sig) 246 { 247 (void) sigaddset(&signalsCaught, sig); 248 } 249 250 /* 251 * iPsAddRemoveGroupMember 252 * 253 * Add or remove a member for a given group 254 * 255 * pgName - Property group name 256 * groupName - group name to which the member is added/removed 257 * memberName - member to be added/removed 258 * addRemoveFlag - ADD/REMOVE 259 * 260 * returns: 261 * STMF_PS_SUCCESS on success 262 * STMF_PS_ERROR_* on failure 263 */ 264 static int 265 iPsAddRemoveGroupMember(char *pgName, char *groupName, char *memberName, 266 int addRemoveFlag) 267 { 268 scf_handle_t *handle = NULL; 269 scf_service_t *svc = NULL; 270 scf_propertygroup_t *pg = NULL; 271 scf_property_t *prop = NULL; 272 scf_value_t *valueLookup = NULL; 273 scf_value_t **valueSet = NULL; 274 scf_iter_t *valueIter = NULL; 275 scf_transaction_t *tran = NULL; 276 scf_transaction_entry_t *entry = NULL; 277 int i = 0; 278 int lastAlloc; 279 int valueArraySize = 0; 280 int ret = STMF_PS_SUCCESS; 281 char buf[STMF_IDENT_LENGTH]; 282 int commitRet; 283 boolean_t found = B_FALSE; 284 285 assert(pgName != NULL && groupName != NULL && memberName != NULL); 286 287 /* 288 * Init the service handle 289 */ 290 ret = iPsInit(&handle, &svc); 291 if (ret != STMF_PS_SUCCESS) { 292 goto out; 293 } 294 295 /* 296 * Allocate scf resources 297 */ 298 if (((pg = scf_pg_create(handle)) == NULL) || 299 ((tran = scf_transaction_create(handle)) == NULL) || 300 ((entry = scf_entry_create(handle)) == NULL) || 301 ((prop = scf_property_create(handle)) == NULL) || 302 ((valueIter = scf_iter_create(handle)) == NULL)) { 303 syslog(LOG_ERR, "scf alloc resource failed - %s", 304 scf_strerror(scf_error())); 305 ret = STMF_PS_ERROR; 306 goto out; 307 } 308 309 /* 310 * Get the service property group handle 311 */ 312 if (scf_service_get_pg(svc, pgName, pg) == -1) { 313 if (scf_error() == SCF_ERROR_NOT_FOUND) { 314 ret = STMF_PS_ERROR_NOT_FOUND; 315 } else { 316 syslog(LOG_ERR, "get pg failed - %s", 317 scf_strerror(scf_error())); 318 ret = STMF_PS_ERROR; 319 } 320 goto out; 321 } 322 323 /* 324 * Begin the transaction 325 */ 326 if (scf_transaction_start(tran, pg) == -1) { 327 syslog(LOG_ERR, "start transaction failed - %s", 328 scf_strerror(scf_error())); 329 ret = STMF_PS_ERROR; 330 goto out; 331 } 332 333 /* 334 * We're changing an existing property by adding a propval 335 * There are no add semantics in libscf for a property value. We'll 336 * need to read in the current properties and apply them all to the 337 * set and then add the one we were asked to add or omit the one 338 * we were asked to remove. 339 */ 340 if (scf_transaction_property_change(tran, entry, groupName, 341 SCF_TYPE_USTRING) == -1) { 342 if (scf_error() == SCF_ERROR_NOT_FOUND) { 343 ret = STMF_PS_ERROR_GROUP_NOT_FOUND; 344 } else { 345 ret = STMF_PS_ERROR; 346 syslog(LOG_ERR, "tran property change failed - %s", 347 scf_strerror(scf_error())); 348 } 349 goto out; 350 } 351 352 /* 353 * Get the property handle 354 */ 355 if (scf_pg_get_property(pg, groupName, prop) == -1) { 356 syslog(LOG_ERR, "get property failed - %s", 357 scf_strerror(scf_error())); 358 ret = STMF_PS_ERROR; 359 goto out; 360 } 361 362 /* 363 * Value lookup is used to lookup the existing values 364 */ 365 valueLookup = scf_value_create(handle); 366 if (valueLookup == NULL) { 367 syslog(LOG_ERR, "scf value alloc failed - %s", 368 scf_strerror(scf_error())); 369 ret = STMF_PS_ERROR; 370 goto out; 371 } 372 373 /* 374 * valueIter is the iterator handle, create the resource 375 */ 376 if (scf_iter_property_values(valueIter, prop) == -1) { 377 syslog(LOG_ERR, "iter value failed - %s", 378 scf_strerror(scf_error())); 379 ret = STMF_PS_ERROR; 380 goto out; 381 } 382 383 /* 384 * Allocate value resource pointers. 385 * We need a value resource for each value as value pointers passed 386 * to libscf cannot be destroyed until the commit or destroy on the 387 * transaction is done. 388 * 389 * We're using GROUP_MEMBER_ALLOC initially. If it's not large 390 * enough, we'll realloc on the fly 391 */ 392 valueSet = (scf_value_t **)calloc(1, sizeof (*valueSet) 393 * (lastAlloc = GROUP_MEMBER_ALLOC)); 394 if (valueSet == NULL) { 395 ret = STMF_PS_ERROR_NOMEM; 396 goto out; 397 } 398 399 /* 400 * Iterate through the existing values 401 */ 402 while (scf_iter_next_value(valueIter, valueLookup) == 1) { 403 bzero(buf, sizeof (buf)); 404 if (scf_value_get_ustring(valueLookup, buf, MAXNAMELEN) == -1) { 405 syslog(LOG_ERR, "iter value failed - %s", 406 scf_strerror(scf_error())); 407 ret = STMF_PS_ERROR; 408 break; 409 } 410 411 /* 412 * Check for existing 413 * If we're adding, it's an error 414 * If we're removing, we skip it and simply not 415 * add it to the set. Subtraction by omission. 416 */ 417 if ((strlen(buf) == strlen(memberName)) && 418 bcmp(buf, memberName, strlen(buf)) == 0) { 419 if (addRemoveFlag == ADD) { 420 ret = STMF_PS_ERROR_EXISTS; 421 break; 422 } else { 423 found = B_TRUE; 424 continue; 425 } 426 } 427 428 /* 429 * Create the value resource for this iteration 430 */ 431 valueSet[i] = scf_value_create(handle); 432 if (valueSet[i] == NULL) { 433 syslog(LOG_ERR, "scf value alloc failed - %s", 434 scf_strerror(scf_error())); 435 ret = STMF_PS_ERROR; 436 break; 437 } 438 439 /* 440 * Set the value 441 */ 442 if (scf_value_set_ustring(valueSet[i], buf) == -1) { 443 syslog(LOG_ERR, "set value failed - %s", 444 scf_strerror(scf_error())); 445 ret = STMF_PS_ERROR; 446 break; 447 } 448 449 /* 450 * Now add the value 451 */ 452 if (scf_entry_add_value(entry, valueSet[i]) == -1) { 453 syslog(LOG_ERR, "add value failed - %s", 454 scf_strerror(scf_error())); 455 ret = STMF_PS_ERROR; 456 break; 457 } 458 459 i++; 460 461 /* 462 * realloc if we've hit the previous alloc size 463 */ 464 if (i >= lastAlloc) { 465 lastAlloc += GROUP_MEMBER_ALLOC; 466 valueSet = realloc(valueSet, 467 sizeof (*valueSet) * lastAlloc); 468 if (valueSet == NULL) { 469 ret = STMF_PS_ERROR; 470 break; 471 } 472 } 473 } 474 475 /* 476 * set valueArraySize to final allocated length 477 * so we can use it to destroy the resources correctly 478 */ 479 valueArraySize = i; 480 481 if (!found && (addRemoveFlag == REMOVE)) { 482 ret = STMF_PS_ERROR_MEMBER_NOT_FOUND; 483 } 484 485 if (ret != STMF_PS_SUCCESS) { 486 goto out; 487 } 488 489 /* 490 * If we're adding, we have one more step. Add the member to the 491 * propval list 492 */ 493 if (addRemoveFlag == ADD) { 494 /* 495 * Now create the new entry 496 */ 497 valueSet[i] = scf_value_create(handle); 498 if (valueSet[i] == NULL) { 499 syslog(LOG_ERR, "scf value alloc failed - %s", 500 scf_strerror(scf_error())); 501 ret = STMF_PS_ERROR; 502 goto out; 503 } else { 504 valueArraySize++; 505 } 506 507 /* 508 * Set the new member name 509 */ 510 if (scf_value_set_ustring(valueSet[i], memberName) == -1) { 511 syslog(LOG_ERR, "set value failed - %s", 512 scf_strerror(scf_error())); 513 ret = STMF_PS_ERROR; 514 goto out; 515 } 516 517 /* 518 * Add the new member 519 */ 520 if (scf_entry_add_value(entry, valueSet[i]) == -1) { 521 syslog(LOG_ERR, "add value failed - %s", 522 scf_strerror(scf_error())); 523 ret = STMF_PS_ERROR; 524 goto out; 525 } 526 } 527 528 /* 529 * Yes, we're finally done. We actually added or removed one entry 530 * from the list. 531 * Woohoo! 532 */ 533 if ((commitRet = scf_transaction_commit(tran)) != 1) { 534 syslog(LOG_ERR, "transaction commit failed - %s", 535 scf_strerror(scf_error())); 536 if (commitRet == 0) { 537 ret = STMF_PS_ERROR_BUSY; 538 } else { 539 ret = STMF_PS_ERROR; 540 } 541 goto out; 542 } 543 544 out: 545 /* 546 * Free resources 547 */ 548 if (handle != NULL) { 549 scf_handle_destroy(handle); 550 } 551 if (svc != NULL) { 552 scf_service_destroy(svc); 553 } 554 if (pg != NULL) { 555 scf_pg_destroy(pg); 556 } 557 if (tran != NULL) { 558 scf_transaction_destroy(tran); 559 } 560 if (entry != NULL) { 561 scf_entry_destroy(entry); 562 } 563 if (prop != NULL) { 564 scf_property_destroy(prop); 565 } 566 if (valueLookup != NULL) { 567 scf_value_destroy(valueLookup); 568 } 569 if (valueIter != NULL) { 570 scf_iter_destroy(valueIter); 571 } 572 573 /* 574 * Free valueSet scf resources 575 */ 576 if (valueArraySize > 0) { 577 for (i = 0; i < valueArraySize; i++) { 578 scf_value_destroy(valueSet[i]); 579 } 580 } 581 /* 582 * Now free the pointer array to the resources 583 */ 584 if (valueSet != NULL) { 585 free(valueSet); 586 } 587 588 return (ret); 589 } 590 591 /* 592 * iPsAddRemoveLuViewEntry 593 * 594 * Adds or removes a view entry name property for a given logical unit 595 * property group. There is one logical unit property group for every logical 596 * unit that has one or more associated view entries. 597 * 598 * luPgName - Property group name of logical unit 599 * viewEntryPgName - Property group name of view entry 600 * addRemoveFlag - ADD_VE/REMOVE_VE 601 * 602 * returns: 603 * STMF_PS_SUCCESS on success 604 * STMF_PS_ERROR_* on failure 605 */ 606 static int 607 iPsAddRemoveLuViewEntry(char *luPgName, char *viewEntryPgName, 608 int addRemoveFlag) 609 { 610 scf_handle_t *handle = NULL; 611 scf_service_t *svc = NULL; 612 scf_propertygroup_t *pg = NULL; 613 scf_property_t *prop = NULL; 614 scf_value_t *value = NULL; 615 scf_transaction_t *tran = NULL; 616 scf_transaction_entry_t *entry = NULL; 617 scf_transaction_entry_t *entryVeName = NULL; 618 boolean_t createVeCnt = B_FALSE; 619 uint64_t veCnt = 0; 620 int ret = STMF_PS_SUCCESS; 621 int commitRet; 622 623 assert(luPgName != NULL || viewEntryPgName != NULL); 624 assert(!(addRemoveFlag != ADD && addRemoveFlag != REMOVE)); 625 626 /* 627 * Init the service handle 628 */ 629 ret = iPsInit(&handle, &svc); 630 if (ret != STMF_PS_SUCCESS) { 631 goto out; 632 } 633 634 /* 635 * Allocate scf resources 636 */ 637 if (((pg = scf_pg_create(handle)) == NULL) || 638 ((tran = scf_transaction_create(handle)) == NULL) || 639 ((entry = scf_entry_create(handle)) == NULL) || 640 ((prop = scf_property_create(handle)) == NULL) || 641 ((value = scf_value_create(handle)) == NULL)) { 642 syslog(LOG_ERR, "scf alloc resource failed - %s", 643 scf_strerror(scf_error())); 644 ret = STMF_PS_ERROR; 645 goto out; 646 } 647 648 /* get the LU property group */ 649 if (scf_service_get_pg(svc, luPgName, pg) == -1) { 650 if (scf_error() == SCF_ERROR_NOT_FOUND && 651 addRemoveFlag == ADD) { 652 /* if it doesn't exist, create it */ 653 if (scf_service_add_pg(svc, luPgName, 654 SCF_GROUP_APPLICATION, 0, pg) == -1) { 655 syslog(LOG_ERR, "add pg failed - %s", 656 scf_strerror(scf_error())); 657 ret = STMF_PS_ERROR; 658 } else { 659 /* we need to create the VE_CNT property */ 660 createVeCnt = B_TRUE; 661 ret = STMF_PS_SUCCESS; 662 } 663 } else if (scf_error() == SCF_ERROR_NOT_FOUND) { 664 ret = STMF_PS_ERROR_NOT_FOUND; 665 } else { 666 syslog(LOG_ERR, "get pg failed - %s", 667 scf_strerror(scf_error())); 668 ret = STMF_PS_ERROR; 669 } 670 if (ret != STMF_PS_SUCCESS) { 671 goto out; 672 } 673 } 674 675 676 /* 677 * Begin the transaction 678 */ 679 if (scf_transaction_start(tran, pg) == -1) { 680 syslog(LOG_ERR, "start transaction failed - %s", 681 scf_strerror(scf_error())); 682 ret = STMF_PS_ERROR; 683 goto out; 684 } 685 686 687 if (createVeCnt) { 688 /* 689 * Create the STMF_VE_CNT property. This will keep the current 690 * total view entries for this logical unit. 691 */ 692 if (scf_transaction_property_new(tran, entry, STMF_VE_CNT, 693 SCF_TYPE_COUNT) == -1) { 694 if (scf_error() == SCF_ERROR_EXISTS) { 695 ret = STMF_PS_ERROR_EXISTS; 696 } else { 697 syslog(LOG_ERR, 698 "transaction property new failed - %s", 699 scf_strerror(scf_error())); 700 ret = STMF_PS_ERROR; 701 } 702 goto out; 703 } 704 } else { 705 /* 706 * The STMF_VE_CNT property already exists. Just update 707 * it. 708 */ 709 if (scf_transaction_property_change(tran, entry, 710 STMF_VE_CNT, SCF_TYPE_COUNT) == -1) { 711 syslog(LOG_ERR, "transaction property new failed - %s", 712 scf_strerror(scf_error())); 713 ret = STMF_PS_ERROR; 714 goto out; 715 } 716 717 /* 718 * Get the STMF_VE_CNT property 719 */ 720 if (scf_pg_get_property(pg, STMF_VE_CNT, prop) == -1) { 721 syslog(LOG_ERR, "get property failed - %s", 722 scf_strerror(scf_error())); 723 ret = STMF_PS_ERROR; 724 goto out; 725 } 726 727 /* 728 * Get the STMF_VE_CNT value 729 */ 730 if (scf_property_get_value(prop, value) == -1) { 731 syslog(LOG_ERR, "get property value failed - %s", 732 scf_strerror(scf_error())); 733 ret = STMF_PS_ERROR; 734 goto out; 735 } 736 737 /* 738 * Now get the actual value from the value handle 739 */ 740 if (scf_value_get_count(value, &veCnt) == -1) { 741 syslog(LOG_ERR, "get integer value failed - %s", 742 scf_strerror(scf_error())); 743 ret = STMF_PS_ERROR; 744 goto out; 745 } 746 747 /* 748 * Reset the value resource as it is used below 749 */ 750 scf_value_reset(value); 751 } 752 753 if (addRemoveFlag == ADD) { 754 veCnt++; 755 } else { 756 /* Check if this is the last one being removed */ 757 if (veCnt == 1) { 758 /* 759 * Delete the pg and get out if this is the last 760 * view entry 761 */ 762 if (scf_pg_delete(pg) == -1) { 763 syslog(LOG_ERR, "delete pg failed - %s", 764 scf_strerror(scf_error())); 765 ret = STMF_PS_ERROR; 766 } 767 goto out; 768 } else { 769 veCnt--; 770 } 771 } 772 773 774 /* 775 * Set the view entry count 776 */ 777 scf_value_set_count(value, veCnt); 778 779 /* 780 * Add the value to the transaction entry 781 */ 782 if (scf_entry_add_value(entry, value) == -1) { 783 syslog(LOG_ERR, "add value failed - %s", 784 scf_strerror(scf_error())); 785 ret = STMF_PS_ERROR; 786 goto out; 787 } 788 789 /* 790 * Create a transaction entry resource for the view entry name 791 */ 792 entryVeName = scf_entry_create(handle); 793 if (entryVeName == NULL) { 794 syslog(LOG_ERR, "scf transaction entry alloc failed - %s", 795 scf_strerror(scf_error())); 796 ret = STMF_PS_ERROR; 797 goto out; 798 } 799 800 if (addRemoveFlag == ADD) { 801 /* 802 * If adding, create a property with the view entry name 803 */ 804 if (scf_transaction_property_new(tran, entryVeName, 805 viewEntryPgName, SCF_TYPE_USTRING) == -1) { 806 if (scf_error() == SCF_ERROR_EXISTS) { 807 ret = STMF_PS_ERROR_EXISTS; 808 } else { 809 syslog(LOG_ERR, 810 "transaction property new failed - %s", 811 scf_strerror(scf_error())); 812 ret = STMF_PS_ERROR; 813 } 814 goto out; 815 } 816 } else { 817 /* 818 * If removing, delete the existing property with the view 819 * entry name 820 */ 821 if (scf_transaction_property_delete(tran, entryVeName, 822 viewEntryPgName) == -1) { 823 if (scf_error() == SCF_ERROR_NOT_FOUND) { 824 ret = STMF_PS_ERROR_NOT_FOUND; 825 } else { 826 syslog(LOG_ERR, 827 "transaction property delete failed - %s", 828 scf_strerror(scf_error())); 829 ret = STMF_PS_ERROR; 830 } 831 goto out; 832 } 833 } 834 835 /* 836 * Commit property transaction 837 */ 838 if ((commitRet = scf_transaction_commit(tran)) != 1) { 839 syslog(LOG_ERR, "transaction commit failed - %s", 840 scf_strerror(scf_error())); 841 if (commitRet == 0) { 842 ret = STMF_PS_ERROR_BUSY; 843 } else { 844 ret = STMF_PS_ERROR; 845 } 846 goto out; 847 } 848 849 out: 850 /* 851 * Free resources 852 */ 853 if (handle != NULL) { 854 scf_handle_destroy(handle); 855 } 856 if (svc != NULL) { 857 scf_service_destroy(svc); 858 } 859 if (pg != NULL) { 860 scf_pg_destroy(pg); 861 } 862 if (tran != NULL) { 863 scf_transaction_destroy(tran); 864 } 865 if (entry != NULL) { 866 scf_entry_destroy(entry); 867 } 868 if (entryVeName != NULL) { 869 scf_entry_destroy(entryVeName); 870 } 871 if (prop != NULL) { 872 scf_property_destroy(prop); 873 } 874 if (value != NULL) { 875 scf_value_destroy(value); 876 } 877 878 return (ret); 879 } 880 881 /* 882 * iPsAddViewEntry 883 * 884 * Add a view entry property group and optionally, a logical unit property 885 * group if it does not exist. 886 * 887 * luName - ascii hexadecimal logical unit identifier 888 * viewEntryName - name of view entry (VIEW_ENTRY_nn) 889 * viewEntry - pointer to stmfViewEntry structure 890 */ 891 static int 892 iPsAddViewEntry(char *luPgName, char *viewEntryPgName, stmfViewEntry *viewEntry) 893 { 894 scf_handle_t *handle = NULL; 895 scf_service_t *svc = NULL; 896 scf_propertygroup_t *pg = NULL; 897 scf_value_t *value[VIEW_ENTRY_STRUCT_CNT]; 898 scf_transaction_t *tran = NULL; 899 scf_transaction_entry_t *entry[VIEW_ENTRY_STRUCT_CNT]; 900 int i = 0; 901 int j = 0; 902 int ret; 903 uint8_t scfBool; 904 boolean_t createdVePg = B_FALSE; 905 int backoutRet; 906 int commitRet; 907 908 assert(luPgName != NULL || viewEntryPgName != NULL || 909 viewEntry == NULL); 910 911 bzero(value, sizeof (value)); 912 bzero(entry, sizeof (entry)); 913 914 /* 915 * Init the service handle 916 */ 917 ret = iPsInit(&handle, &svc); 918 if (ret != STMF_PS_SUCCESS) { 919 goto out; 920 } 921 922 /* 923 * Allocate scf resources 924 */ 925 if (((pg = scf_pg_create(handle)) == NULL) || 926 ((tran = scf_transaction_create(handle)) == NULL)) { 927 syslog(LOG_ERR, "scf alloc resource failed - %s", 928 scf_strerror(scf_error())); 929 ret = STMF_PS_ERROR; 930 goto out; 931 } 932 933 /* 934 * allocate value and entry resources for scf 935 */ 936 for (i = 0; i < VIEW_ENTRY_STRUCT_CNT; i++) { 937 if (((value[i] = scf_value_create(handle)) == NULL) || 938 ((entry[i] = scf_entry_create(handle)) == NULL)) { 939 syslog(LOG_ERR, "scf alloc resource failed - %s", 940 scf_strerror(scf_error())); 941 ret = STMF_PS_ERROR; 942 goto out; 943 } 944 } 945 946 i = 0; 947 948 /* 949 * Create the View Entry property group 950 */ 951 if (scf_service_add_pg(svc, viewEntryPgName, SCF_GROUP_APPLICATION, 952 0, pg) == -1) { 953 if (scf_error() == SCF_ERROR_EXISTS) { 954 ret = STMF_PS_ERROR_EXISTS; 955 } else { 956 syslog(LOG_ERR, "add pg failed - %s", 957 scf_strerror(scf_error())); 958 ret = STMF_PS_ERROR; 959 } 960 goto out; 961 } 962 963 createdVePg = B_TRUE; 964 965 /* 966 * Add the view entry as properties on the view entry group 967 */ 968 969 /* 970 * Begin property update transaction 971 */ 972 if (scf_transaction_start(tran, pg) == -1) { 973 syslog(LOG_ERR, "start transaction failed - %s", 974 scf_strerror(scf_error())); 975 ret = STMF_PS_ERROR; 976 goto out; 977 } 978 979 /* 980 * Add allHosts property 981 */ 982 if (scf_transaction_property_new(tran, entry[i], 983 STMF_VE_ALLHOSTS, SCF_TYPE_BOOLEAN) == -1) { 984 if (scf_error() == SCF_ERROR_EXISTS) { 985 ret = STMF_PS_ERROR_EXISTS; 986 } else { 987 syslog(LOG_ERR, "transaction property new failed - %s", 988 scf_strerror(scf_error())); 989 ret = STMF_PS_ERROR; 990 } 991 goto out; 992 } 993 994 /* Set the allHosts value */ 995 scfBool = viewEntry->allHosts; 996 scf_value_set_boolean(value[i], scfBool); 997 998 /* 999 * Add the allHosts value to the transaction 1000 */ 1001 if (scf_entry_add_value(entry[i], value[i]) == -1) { 1002 syslog(LOG_ERR, "add value failed - %s", 1003 scf_strerror(scf_error())); 1004 ret = STMF_PS_ERROR; 1005 goto out; 1006 } 1007 1008 i++; 1009 1010 /* 1011 * Create hostGroup property 1012 */ 1013 if (scf_transaction_property_new(tran, entry[i], 1014 STMF_VE_HOSTGROUP, SCF_TYPE_USTRING) == -1) { 1015 if (scf_error() == SCF_ERROR_EXISTS) { 1016 ret = STMF_PS_ERROR_EXISTS; 1017 } else { 1018 syslog(LOG_ERR, "transaction property new failed - %s", 1019 scf_strerror(scf_error())); 1020 ret = STMF_PS_ERROR; 1021 } 1022 goto out; 1023 } 1024 1025 /* 1026 * Set the value for hostGroup 1027 */ 1028 if (scf_value_set_ustring(value[i], viewEntry->hostGroup) == -1) { 1029 syslog(LOG_ERR, "set value failed - %s", 1030 scf_strerror(scf_error())); 1031 ret = STMF_PS_ERROR; 1032 goto out; 1033 } 1034 1035 /* 1036 * Add the hostGroup value to the transaction entry 1037 */ 1038 if (scf_entry_add_value(entry[i], value[i]) == -1) { 1039 syslog(LOG_ERR, "add value failed - %s", 1040 scf_strerror(scf_error())); 1041 ret = STMF_PS_ERROR; 1042 goto out; 1043 } 1044 1045 i++; 1046 1047 /* 1048 * Create the allTargets property 1049 */ 1050 if (scf_transaction_property_new(tran, entry[i], 1051 STMF_VE_ALLTARGETS, SCF_TYPE_BOOLEAN) == -1) { 1052 if (scf_error() == SCF_ERROR_EXISTS) { 1053 ret = STMF_PS_ERROR_EXISTS; 1054 } else { 1055 syslog(LOG_ERR, "transaction property new failed - %s", 1056 scf_strerror(scf_error())); 1057 ret = STMF_PS_ERROR; 1058 } 1059 goto out; 1060 } 1061 1062 /* 1063 * Set the allTargets value 1064 */ 1065 scfBool = viewEntry->allTargets; 1066 scf_value_set_boolean(value[i], scfBool); 1067 1068 /* 1069 * Add the allTargets value to the transaction 1070 */ 1071 if (scf_entry_add_value(entry[i], value[i]) == -1) { 1072 syslog(LOG_ERR, "add value failed - %s", 1073 scf_strerror(scf_error())); 1074 ret = STMF_PS_ERROR; 1075 goto out; 1076 } 1077 1078 i++; 1079 1080 /* 1081 * Create targetGroup property 1082 */ 1083 if (scf_transaction_property_new(tran, entry[i], 1084 STMF_VE_TARGETGROUP, SCF_TYPE_USTRING) == -1) { 1085 if (scf_error() == SCF_ERROR_EXISTS) { 1086 ret = STMF_PS_ERROR_EXISTS; 1087 } else { 1088 syslog(LOG_ERR, "transaction property new failed - %s", 1089 scf_strerror(scf_error())); 1090 ret = STMF_PS_ERROR; 1091 } 1092 goto out; 1093 } 1094 1095 /* 1096 * Set the value for targetGroup 1097 */ 1098 if (scf_value_set_ustring(value[i], viewEntry->targetGroup) == -1) { 1099 syslog(LOG_ERR, "set value failed - %s", 1100 scf_strerror(scf_error())); 1101 ret = STMF_PS_ERROR; 1102 goto out; 1103 } 1104 1105 /* 1106 * Add targetGroup value to the transaction 1107 */ 1108 if (scf_entry_add_value(entry[i], value[i]) == -1) { 1109 syslog(LOG_ERR, "add value failed - %s", 1110 scf_strerror(scf_error())); 1111 ret = STMF_PS_ERROR; 1112 goto out; 1113 } 1114 1115 i++; 1116 1117 /* 1118 * Create the luNbr property 1119 */ 1120 if (scf_transaction_property_new(tran, entry[i], STMF_VE_LUNBR, 1121 SCF_TYPE_OPAQUE) == -1) { 1122 if (scf_error() == SCF_ERROR_EXISTS) { 1123 ret = STMF_PS_ERROR_EXISTS; 1124 } else { 1125 syslog(LOG_ERR, "transaction property new failed - %s", 1126 scf_strerror(scf_error())); 1127 ret = STMF_PS_ERROR; 1128 } 1129 goto out; 1130 } 1131 1132 /* 1133 * Set the luNbr 1134 */ 1135 if (scf_value_set_opaque(value[i], (char *)viewEntry->luNbr, 1136 sizeof (viewEntry->luNbr)) == -1) { 1137 syslog(LOG_ERR, "set value failed - %s", 1138 scf_strerror(scf_error())); 1139 ret = STMF_PS_ERROR; 1140 goto out; 1141 } 1142 1143 /* 1144 * Add luNbr to the transaction entry 1145 */ 1146 if (scf_entry_add_value(entry[i], value[i]) == -1) { 1147 syslog(LOG_ERR, "add value failed - %s", 1148 scf_strerror(scf_error())); 1149 ret = STMF_PS_ERROR; 1150 goto out; 1151 } 1152 1153 /* 1154 * Now that we've successfully added the view entry, 1155 * update the logical unit property group or create 1156 * it if it does not exist 1157 */ 1158 ret = iPsAddRemoveLuViewEntry(luPgName, viewEntryPgName, ADD); 1159 1160 /* 1161 * If we did not add the view entry name to the logical unit, 1162 * make sure we do not commit the transaction 1163 */ 1164 if (ret != STMF_PS_SUCCESS) { 1165 goto out; 1166 } 1167 1168 /* 1169 * Commit property transaction 1170 */ 1171 if ((commitRet = scf_transaction_commit(tran)) != 1) { 1172 syslog(LOG_ERR, "transaction commit failed - %s", 1173 scf_strerror(scf_error())); 1174 if (commitRet == 0) { 1175 ret = STMF_PS_ERROR_BUSY; 1176 } else { 1177 ret = STMF_PS_ERROR; 1178 } 1179 } 1180 1181 if (ret != STMF_PS_SUCCESS) { 1182 /* 1183 * If we did not commit, try to remove the view entry name 1184 * from the logical unit. 1185 * If that fails, we're now inconsistent. 1186 */ 1187 backoutRet = iPsAddRemoveLuViewEntry(luPgName, viewEntryPgName, 1188 REMOVE); 1189 1190 if (backoutRet != STMF_PS_SUCCESS) { 1191 syslog(LOG_ERR, "remove lu view entry failed" 1192 "possible inconsistency - %s", 1193 scf_strerror(scf_error())); 1194 } 1195 /* 1196 * We are still in an error scenario even though the remove 1197 * lu view entry succeeded. 1198 */ 1199 goto out; 1200 } 1201 1202 out: 1203 /* 1204 * Free resources 1205 */ 1206 if (handle != NULL) { 1207 scf_handle_destroy(handle); 1208 } 1209 if (svc != NULL) { 1210 scf_service_destroy(svc); 1211 } 1212 /* if there was an error, delete the created pg if one was created */ 1213 if ((ret != STMF_PS_SUCCESS) && createdVePg) { 1214 if (scf_pg_delete(pg) == -1) { 1215 syslog(LOG_ERR, "delete VE pg failed - %s", 1216 scf_strerror(scf_error())); 1217 } 1218 } 1219 if (pg != NULL) { 1220 scf_pg_destroy(pg); 1221 } 1222 if (tran != NULL) { 1223 scf_transaction_destroy(tran); 1224 } 1225 /* 1226 * Free value and entry scf resources 1227 */ 1228 if (i > 0) { 1229 for (j = 0; j < VIEW_ENTRY_STRUCT_CNT; j++) { 1230 if (value[j] != NULL) 1231 scf_value_destroy(value[j]); 1232 if (entry[j] != NULL) 1233 scf_entry_destroy(entry[j]); 1234 } 1235 } 1236 1237 return (ret); 1238 } 1239 /* 1240 * psClearProviderData 1241 * 1242 * providerName - name of provider data to clear 1243 */ 1244 int 1245 psClearProviderData(char *providerName, int providerType) 1246 { 1247 scf_handle_t *handle = NULL; 1248 scf_service_t *svc = NULL; 1249 scf_propertygroup_t *pg = NULL; 1250 char pgName[MAXPATHLEN]; 1251 int ret = STMF_PS_SUCCESS; 1252 boolean_t pgNotFound = B_FALSE; 1253 1254 if (providerName == NULL || (providerType != STMF_LU_PROVIDER_TYPE && 1255 providerType != STMF_PORT_PROVIDER_TYPE)) { 1256 ret = STMF_PS_ERROR_INVALID_ARG; 1257 goto out; 1258 } 1259 1260 ret = iPsInit(&handle, &svc); 1261 if (ret != STMF_PS_SUCCESS) { 1262 goto out; 1263 } 1264 1265 /* 1266 * Allocate scf resources 1267 */ 1268 if ((pg = scf_pg_create(handle)) == NULL) { 1269 syslog(LOG_ERR, "scf alloc resource failed - %s", 1270 scf_strerror(scf_error())); 1271 ret = STMF_PS_ERROR; 1272 goto out; 1273 } 1274 1275 /* 1276 * create the property group name 1277 */ 1278 (void) snprintf(pgName, sizeof (pgName), "%s%s", 1279 STMF_PROVIDER_DATA_PREFIX, providerName); 1280 1281 /* 1282 * delete provider property group 1283 */ 1284 if (scf_service_get_pg(svc, pgName, pg) == -1) { 1285 if (scf_error() != SCF_ERROR_NOT_FOUND) { 1286 syslog(LOG_ERR, "get pg failed - %s", 1287 scf_strerror(scf_error())); 1288 ret = STMF_PS_ERROR; 1289 goto out; 1290 } else { 1291 pgNotFound = B_TRUE; 1292 } 1293 } 1294 1295 if (!pgNotFound && (scf_pg_delete(pg) == -1)) { 1296 syslog(LOG_ERR, "delete pg failed - %s", 1297 scf_strerror(scf_error())); 1298 ret = STMF_PS_ERROR; 1299 goto out; 1300 } 1301 1302 if (pgNotFound) { 1303 ret = STMF_PS_ERROR_NOT_FOUND; 1304 } 1305 1306 out: 1307 /* 1308 * Free resources 1309 */ 1310 if (handle != NULL) { 1311 scf_handle_destroy(handle); 1312 } 1313 if (svc != NULL) { 1314 scf_service_destroy(svc); 1315 } 1316 if (pg != NULL) { 1317 scf_pg_destroy(pg); 1318 } 1319 1320 return (ret); 1321 } 1322 1323 /* 1324 * iPsCreateDeleteGroup 1325 * 1326 * Creates or deletes a group (target or host) 1327 * 1328 * When creating a group, two properties are created. One to hold the group 1329 * name and the other to hold the group members. 1330 * 1331 * pgName - Property group name 1332 * groupName - group name to create 1333 * addRemoveFlag - ADD_GROUP/REMOVE_GROUP 1334 * 1335 * returns: 1336 * STMF_PS_SUCCESS on success 1337 * STMF_PS_ERROR_* on failure 1338 */ 1339 static int 1340 iPsCreateDeleteGroup(char *pgRefName, char *groupName, int addRemoveFlag) 1341 { 1342 scf_handle_t *handle = NULL; 1343 scf_service_t *svc = NULL; 1344 scf_propertygroup_t *pg = NULL; 1345 scf_property_t *prop = NULL; 1346 scf_iter_t *propIter = NULL; 1347 scf_transaction_t *tran = NULL; 1348 scf_transaction_entry_t *entry1 = NULL; 1349 scf_transaction_entry_t *entry2 = NULL; 1350 scf_value_t *value = NULL; 1351 uint64_t groupIdx; 1352 char buf1[MAXNAMELEN]; 1353 char buf2[MAXNAMELEN]; 1354 char tmpbuf[MAXNAMELEN]; 1355 boolean_t found = B_FALSE; 1356 int ret = STMF_PS_SUCCESS; 1357 int commitRet; 1358 1359 assert(groupName != NULL); 1360 1361 ret = iPsInit(&handle, &svc); 1362 if (ret != STMF_PS_SUCCESS) { 1363 goto out; 1364 } 1365 1366 /* 1367 * Allocate scf resources 1368 */ 1369 if (((pg = scf_pg_create(handle)) == NULL) || 1370 ((tran = scf_transaction_create(handle)) == NULL) || 1371 ((entry1 = scf_entry_create(handle)) == NULL) || 1372 ((entry2 = scf_entry_create(handle)) == NULL) || 1373 ((prop = scf_property_create(handle)) == NULL) || 1374 ((propIter = scf_iter_create(handle)) == NULL) || 1375 ((value = scf_value_create(handle)) == NULL)) { 1376 syslog(LOG_ERR, "scf alloc resource failed - %s", 1377 scf_strerror(scf_error())); 1378 ret = STMF_PS_ERROR; 1379 goto out; 1380 } 1381 1382 /* 1383 * Get the property group being modified 1384 */ 1385 if (scf_service_get_pg(svc, pgRefName, pg) == -1) { 1386 if (scf_error() == SCF_ERROR_NOT_FOUND && 1387 addRemoveFlag == ADD) { 1388 if (scf_service_add_pg(svc, pgRefName, 1389 SCF_GROUP_APPLICATION, 0, pg) == -1) { 1390 syslog(LOG_ERR, "add pg failed - %s", 1391 scf_strerror(scf_error())); 1392 ret = STMF_PS_ERROR; 1393 } 1394 } else if (scf_error() == SCF_ERROR_NOT_FOUND) { 1395 ret = STMF_PS_ERROR_NOT_FOUND; 1396 } else { 1397 syslog(LOG_ERR, "get pg failed - %s", 1398 scf_strerror(scf_error())); 1399 ret = STMF_PS_ERROR; 1400 } 1401 if (ret != STMF_PS_SUCCESS) { 1402 goto out; 1403 } 1404 } 1405 1406 /* 1407 * propIter is the iterator handle 1408 */ 1409 if (scf_iter_pg_properties(propIter, pg) == -1) { 1410 syslog(LOG_ERR, "iter properties failed - %s", 1411 scf_strerror(scf_error())); 1412 ret = STMF_PS_ERROR; 1413 goto out; 1414 } 1415 1416 /* 1417 * Iterate through the group names. 1418 * If we find it in the list, it's an error when addRemoveFlag == ADD. 1419 */ 1420 while (scf_iter_next_property(propIter, prop) == 1) { 1421 if (scf_property_get_name(prop, buf1, sizeof (buf1)) == -1) { 1422 syslog(LOG_ERR, "get name failed - %s", 1423 scf_strerror(scf_error())); 1424 ret = STMF_PS_ERROR; 1425 break; 1426 } 1427 /* 1428 * Skip over member list properties 1429 */ 1430 if (strstr(buf1, STMF_MEMBER_LIST_SUFFIX)) { 1431 continue; 1432 } 1433 if (scf_property_get_value(prop, value) == -1) { 1434 syslog(LOG_ERR, "get property value failed - %s", 1435 scf_strerror(scf_error())); 1436 ret = STMF_PS_ERROR; 1437 break; 1438 } 1439 if (scf_value_get_ustring(value, tmpbuf, 1440 sizeof (tmpbuf)) == -1) { 1441 syslog(LOG_ERR, "get ustring failed - %s", 1442 scf_strerror(scf_error())); 1443 ret = STMF_PS_ERROR; 1444 break; 1445 } 1446 1447 if ((strlen(tmpbuf) == strlen(groupName)) && 1448 bcmp(tmpbuf, groupName, strlen(tmpbuf)) == 0) { 1449 if (addRemoveFlag == ADD) { 1450 ret = STMF_PS_ERROR_EXISTS; 1451 } 1452 found = B_TRUE; 1453 /* 1454 * buf1 contains the name for REMOVE 1455 */ 1456 break; 1457 } 1458 } 1459 1460 if (ret != STMF_PS_SUCCESS) { 1461 goto out; 1462 } 1463 1464 scf_value_reset(value); 1465 1466 if (!found && addRemoveFlag == REMOVE) { 1467 ret = STMF_PS_ERROR_NOT_FOUND; 1468 goto out; 1469 } 1470 1471 /* 1472 * If we're adding, we need to create a new property name for the 1473 * new group 1474 */ 1475 if (addRemoveFlag == ADD) { 1476 for (groupIdx = 0; groupIdx < GROUP_MAX; groupIdx++) { 1477 if (snprintf(buf1, sizeof (buf1), "%s-%lld", 1478 STMF_GROUP_PREFIX, groupIdx) > sizeof (buf1)) { 1479 syslog(LOG_ERR, 1480 "buffer overflow on property name %s", 1481 buf1); 1482 ret = STMF_PS_ERROR; 1483 break; 1484 } 1485 if (scf_pg_get_property(pg, buf1, prop) == -1) { 1486 if (scf_error() != SCF_ERROR_NOT_FOUND) { 1487 syslog(LOG_ERR, "get pg failed - %s", 1488 scf_strerror(scf_error())); 1489 ret = STMF_PS_ERROR; 1490 } 1491 break; 1492 } 1493 } 1494 } 1495 1496 /* 1497 * Now create the new member list property for the new group 1498 */ 1499 if (snprintf(buf2, sizeof (buf2), "%s-%s", buf1, 1500 STMF_MEMBER_LIST_SUFFIX) > sizeof (buf2)) { 1501 syslog(LOG_ERR, "buffer overflow on property name %s", 1502 buf1); 1503 ret = STMF_PS_ERROR; 1504 goto out; 1505 } 1506 1507 /* 1508 * buf1 now contains the name of the property if it was found in the 1509 * list in the case of delete or the next available property name 1510 * in the case of create 1511 * 1512 * buf2 now contains the member list property name 1513 */ 1514 if (scf_transaction_start(tran, pg) == -1) { 1515 syslog(LOG_ERR, "start transaction failed - %s", 1516 scf_strerror(scf_error())); 1517 ret = STMF_PS_ERROR; 1518 goto out; 1519 } 1520 1521 if (addRemoveFlag == ADD) { 1522 /* 1523 * Create the property 'group name' 1524 * This is the container for the group name 1525 */ 1526 if (scf_transaction_property_new(tran, entry1, buf1, 1527 SCF_TYPE_USTRING) == -1) { 1528 syslog(LOG_ERR, "transaction property new failed - %s", 1529 scf_strerror(scf_error())); 1530 ret = STMF_PS_ERROR; 1531 goto out; 1532 } 1533 if (scf_value_set_ustring(value, groupName) == -1) { 1534 syslog(LOG_ERR, "set ustring failed - %s", 1535 scf_strerror(scf_error())); 1536 ret = STMF_PS_ERROR; 1537 goto out; 1538 } 1539 if (scf_entry_add_value(entry1, value) == -1) { 1540 syslog(LOG_ERR, "add value failed - %s", 1541 scf_strerror(scf_error())); 1542 ret = STMF_PS_ERROR; 1543 goto out; 1544 } 1545 /* 1546 * Create the property 'group list' 1547 * This is the container for the group members 1548 */ 1549 if (scf_transaction_property_new(tran, entry2, buf2, 1550 SCF_TYPE_USTRING) == -1) { 1551 syslog(LOG_ERR, "transaction property new failed - %s", 1552 scf_strerror(scf_error())); 1553 ret = STMF_PS_ERROR; 1554 goto out; 1555 } 1556 } else { 1557 /* 1558 * Delete the property 'group name' 1559 */ 1560 if (scf_transaction_property_delete(tran, entry1, buf1) 1561 == -1) { 1562 syslog(LOG_ERR, 1563 "transaction property delete failed - %s", 1564 scf_strerror(scf_error())); 1565 ret = STMF_PS_ERROR; 1566 goto out; 1567 } 1568 /* 1569 * Delete the property 'group list' 1570 */ 1571 if (scf_transaction_property_delete(tran, entry2, buf2) 1572 == -1) { 1573 syslog(LOG_ERR, 1574 "transaction property delete failed - %s", 1575 scf_strerror(scf_error())); 1576 ret = STMF_PS_ERROR; 1577 goto out; 1578 } 1579 } 1580 1581 if (ret != STMF_PS_SUCCESS) { 1582 goto out; 1583 } 1584 1585 if ((commitRet = scf_transaction_commit(tran)) != 1) { 1586 syslog(LOG_ERR, "transaction commit failed - %s", 1587 scf_strerror(scf_error())); 1588 if (commitRet == 0) { 1589 ret = STMF_PS_ERROR_BUSY; 1590 } else { 1591 ret = STMF_PS_ERROR; 1592 } 1593 } 1594 1595 out: 1596 /* 1597 * Free resources 1598 */ 1599 if (handle != NULL) { 1600 scf_handle_destroy(handle); 1601 } 1602 if (svc != NULL) { 1603 scf_service_destroy(svc); 1604 } 1605 if (pg != NULL) { 1606 scf_pg_destroy(pg); 1607 } 1608 if (tran != NULL) { 1609 scf_transaction_destroy(tran); 1610 } 1611 if (entry1 != NULL) { 1612 scf_entry_destroy(entry1); 1613 } 1614 if (entry2 != NULL) { 1615 scf_entry_destroy(entry2); 1616 } 1617 if (prop != NULL) { 1618 scf_property_destroy(prop); 1619 } 1620 if (propIter != NULL) { 1621 scf_iter_destroy(propIter); 1622 } 1623 if (value != NULL) { 1624 scf_value_destroy(value); 1625 } 1626 1627 return (ret); 1628 } 1629 1630 /* 1631 * iPsGetGroupList 1632 * 1633 * pgName - Property group name 1634 * groupList - pointer to pointer to stmfGroupList structure. On success, 1635 * contains the list of groups 1636 * 1637 * returns: 1638 * STMF_PS_SUCCESS on success 1639 * STMF_PS_ERROR_* on failure 1640 */ 1641 static int 1642 iPsGetGroupList(char *pgName, stmfGroupList **groupList) 1643 { 1644 scf_handle_t *handle = NULL; 1645 scf_service_t *svc = NULL; 1646 scf_propertygroup_t *pg = NULL; 1647 scf_property_t *prop = NULL; 1648 scf_iter_t *propIter = NULL; 1649 scf_value_t *value = NULL; 1650 char buf[MAXNAMELEN]; 1651 int memberCnt = 0; 1652 int i = 0; 1653 int ret = STMF_PS_SUCCESS; 1654 1655 assert(groupList != NULL); 1656 1657 ret = iPsInit(&handle, &svc); 1658 if (ret != STMF_PS_SUCCESS) { 1659 goto out; 1660 } 1661 1662 /* 1663 * Allocate scf resources 1664 */ 1665 if (((pg = scf_pg_create(handle)) == NULL) || 1666 ((prop = scf_property_create(handle)) == NULL) || 1667 ((propIter = scf_iter_create(handle)) == NULL) || 1668 ((value = scf_value_create(handle)) == NULL)) { 1669 syslog(LOG_ERR, "scf alloc resource failed - %s", 1670 scf_strerror(scf_error())); 1671 ret = STMF_PS_ERROR; 1672 goto out; 1673 } 1674 1675 if (scf_service_get_pg(svc, pgName, pg) == -1) { 1676 if (scf_error() == SCF_ERROR_NOT_FOUND) { 1677 ret = STMF_PS_ERROR_NOT_FOUND; 1678 } else { 1679 syslog(LOG_ERR, "get pg failed - %s", 1680 scf_strerror(scf_error())); 1681 ret = STMF_PS_ERROR; 1682 } 1683 goto out; 1684 } 1685 1686 /* 1687 * propIter is the iterator handle 1688 */ 1689 if (scf_iter_pg_properties(propIter, pg) == -1) { 1690 syslog(LOG_ERR, "iter properties failed - %s", 1691 scf_strerror(scf_error())); 1692 ret = STMF_PS_ERROR; 1693 goto out; 1694 } 1695 1696 while (scf_iter_next_property(propIter, prop) == 1) { 1697 if (scf_property_get_name(prop, buf, sizeof (buf)) == -1) { 1698 syslog(LOG_ERR, "get name failed - %s", 1699 scf_strerror(scf_error())); 1700 ret = STMF_PS_ERROR; 1701 break; 1702 } 1703 /* 1704 * Skip over member list properties 1705 */ 1706 if (strstr(buf, STMF_MEMBER_LIST_SUFFIX)) { 1707 continue; 1708 } 1709 memberCnt++; 1710 } 1711 1712 /* 1713 * propIter is the iterator handle 1714 */ 1715 if (scf_iter_pg_properties(propIter, pg) == -1) { 1716 syslog(LOG_ERR, "iter properties failed - %s", 1717 scf_strerror(scf_error())); 1718 ret = STMF_PS_ERROR; 1719 goto out; 1720 } 1721 1722 *groupList = (stmfGroupList *)calloc(1, sizeof (stmfGroupList) + 1723 memberCnt * sizeof (stmfGroupName)); 1724 1725 if (*groupList == NULL) { 1726 ret = STMF_PS_ERROR_NOMEM; 1727 goto out; 1728 } 1729 1730 /* 1731 * In order to get a list of groups, simply get all of the 1732 * properties that are not member list properties, i.e. the group 1733 * name properties. 1734 * It's possible for this list to grow beyond what was originally 1735 * read so just ensure we're not writing beyond our allocated buffer 1736 * by ensuring i < memberCnt 1737 */ 1738 while ((scf_iter_next_property(propIter, prop) == 1) && 1739 (i < memberCnt)) { 1740 if (scf_property_get_name(prop, buf, sizeof (buf)) == -1) { 1741 syslog(LOG_ERR, "get name failed - %s", 1742 scf_strerror(scf_error())); 1743 ret = STMF_PS_ERROR; 1744 break; 1745 } 1746 /* 1747 * Skip over member list properties 1748 */ 1749 if (strstr(buf, STMF_MEMBER_LIST_SUFFIX)) { 1750 continue; 1751 } 1752 if (scf_property_get_value(prop, value) == -1) { 1753 syslog(LOG_ERR, "get property value failed - %s", 1754 scf_strerror(scf_error())); 1755 ret = STMF_PS_ERROR; 1756 break; 1757 } 1758 if (scf_value_get_ustring(value, buf, sizeof (buf)) == -1) { 1759 syslog(LOG_ERR, "get ustring failed - %s", 1760 scf_strerror(scf_error())); 1761 ret = STMF_PS_ERROR; 1762 break; 1763 } 1764 bcopy(buf, (*groupList)->name[i++], strlen(buf)); 1765 (*groupList)->cnt++; 1766 } 1767 1768 if (ret != STMF_PS_SUCCESS) { 1769 free(*groupList); 1770 goto out; 1771 } 1772 1773 out: 1774 /* 1775 * Free resources 1776 */ 1777 if (handle != NULL) { 1778 scf_handle_destroy(handle); 1779 } 1780 if (svc != NULL) { 1781 scf_service_destroy(svc); 1782 } 1783 if (pg != NULL) { 1784 scf_pg_destroy(pg); 1785 } 1786 if (propIter != NULL) { 1787 scf_iter_destroy(propIter); 1788 } 1789 if (prop != NULL) { 1790 scf_property_destroy(prop); 1791 } 1792 if (value != NULL) { 1793 scf_value_destroy(value); 1794 } 1795 1796 return (ret); 1797 } 1798 1799 /* 1800 * iPsGetGroupMemberList 1801 * 1802 * pgName - Property group name 1803 * groupName - group name (host group or target group) 1804 * groupMemberList - pointer to pointer to stmfGroupProperties structure. On 1805 * success, contains the list of group members 1806 * 1807 * returns: 1808 * STMF_PS_SUCCESS on success 1809 * STMF_PS_ERROR_* on failure 1810 */ 1811 static int 1812 iPsGetGroupMemberList(char *pgName, char *groupName, 1813 stmfGroupProperties **groupMemberList) 1814 { 1815 scf_handle_t *handle = NULL; 1816 scf_service_t *svc = NULL; 1817 scf_propertygroup_t *pg = NULL; 1818 scf_property_t *prop = NULL; 1819 scf_value_t *valueLookup = NULL; 1820 scf_iter_t *valueIter = NULL; 1821 int i = 0; 1822 int memberCnt; 1823 int len; 1824 int ret = STMF_PS_SUCCESS; 1825 char buf[MAXNAMELEN]; 1826 1827 assert(pgName != NULL && groupName != NULL); 1828 1829 /* 1830 * init the service handle 1831 */ 1832 ret = iPsInit(&handle, &svc); 1833 if (ret != STMF_PS_SUCCESS) { 1834 goto out; 1835 } 1836 1837 /* 1838 * Allocate scf resources 1839 */ 1840 if (((pg = scf_pg_create(handle)) == NULL) || 1841 ((prop = scf_property_create(handle)) == NULL) || 1842 ((valueIter = scf_iter_create(handle)) == NULL) || 1843 ((valueLookup = scf_value_create(handle)) == NULL)) { 1844 syslog(LOG_ERR, "scf alloc resource failed - %s", 1845 scf_strerror(scf_error())); 1846 ret = STMF_PS_ERROR; 1847 goto out; 1848 } 1849 1850 /* 1851 * get the service property group handle 1852 */ 1853 if (scf_service_get_pg(svc, pgName, pg) == -1) { 1854 if (scf_error() == SCF_ERROR_NOT_FOUND) { 1855 ret = STMF_PS_ERROR_NOT_FOUND; 1856 } else { 1857 syslog(LOG_ERR, "get pg failed - %s", 1858 scf_strerror(scf_error())); 1859 ret = STMF_PS_ERROR; 1860 } 1861 goto out; 1862 } 1863 1864 /* 1865 * Get the property handle 1866 * based on the target or host group name 1867 */ 1868 if (scf_pg_get_property(pg, groupName, prop) == -1) { 1869 syslog(LOG_ERR, "get property failed - %s", 1870 scf_strerror(scf_error())); 1871 ret = STMF_PS_ERROR; 1872 goto out; 1873 } 1874 1875 /* 1876 * valueIter is the iterator handle 1877 */ 1878 if (scf_iter_property_values(valueIter, prop) == -1) { 1879 syslog(LOG_ERR, "iter value failed - %s", 1880 scf_strerror(scf_error())); 1881 ret = STMF_PS_ERROR; 1882 goto out; 1883 } 1884 1885 while (scf_iter_next_value(valueIter, valueLookup) == 1) { 1886 if (scf_value_get_ustring(valueLookup, buf, MAXNAMELEN) == -1) { 1887 syslog(LOG_ERR, "iter value failed - %s", 1888 scf_strerror(scf_error())); 1889 ret = STMF_PS_ERROR; 1890 break; 1891 } 1892 i++; 1893 } 1894 1895 /* 1896 * valueIter is the iterator handle 1897 */ 1898 if (scf_iter_property_values(valueIter, prop) == -1) { 1899 syslog(LOG_ERR, "iter value failed - %s", 1900 scf_strerror(scf_error())); 1901 ret = STMF_PS_ERROR; 1902 goto out; 1903 } 1904 1905 memberCnt = i; 1906 1907 *groupMemberList = (stmfGroupProperties *)calloc(1, 1908 sizeof (stmfGroupProperties) + memberCnt * sizeof (stmfDevid)); 1909 if (*groupMemberList == NULL) { 1910 ret = STMF_PS_ERROR_NOMEM; 1911 goto out; 1912 } 1913 1914 i = 0; 1915 while ((scf_iter_next_value(valueIter, valueLookup) == 1) && 1916 (i < memberCnt)) { 1917 if ((len = scf_value_get_ustring(valueLookup, buf, MAXNAMELEN)) 1918 == -1) { 1919 syslog(LOG_ERR, "iter value failed - %s", 1920 scf_strerror(scf_error())); 1921 ret = STMF_PS_ERROR; 1922 break; 1923 } 1924 if (len < sizeof (stmfDevid) - 1) { 1925 (*groupMemberList)->name[i].identLength = len; 1926 bcopy(buf, 1927 (*groupMemberList)->name[i++].ident, len); 1928 (*groupMemberList)->cnt++; 1929 } else { 1930 ret = STMF_PS_ERROR; 1931 break; 1932 } 1933 } 1934 1935 if (ret != STMF_PS_SUCCESS) { 1936 free(*groupMemberList); 1937 goto out; 1938 } 1939 1940 out: 1941 /* 1942 * Free resources 1943 */ 1944 if (handle != NULL) { 1945 scf_handle_destroy(handle); 1946 } 1947 if (svc != NULL) { 1948 scf_service_destroy(svc); 1949 } 1950 if (pg != NULL) { 1951 scf_pg_destroy(pg); 1952 } 1953 if (prop != NULL) { 1954 scf_property_destroy(prop); 1955 } 1956 if (valueLookup != NULL) { 1957 scf_value_destroy(valueLookup); 1958 } 1959 if (valueIter != NULL) { 1960 scf_iter_destroy(valueIter); 1961 } 1962 1963 return (ret); 1964 } 1965 1966 /* 1967 * Initialize scf stmf service access 1968 * handle - returned handle 1969 * service - returned service handle 1970 * 1971 * Both handle and service must be destroyed by the caller 1972 */ 1973 static int 1974 iPsInit(scf_handle_t **handle, scf_service_t **service) 1975 { 1976 scf_scope_t *scope = NULL; 1977 uint64_t version; 1978 int ret; 1979 1980 assert(handle != NULL && service != NULL); 1981 1982 if ((*handle = scf_handle_create(SCF_VERSION)) == NULL) { 1983 syslog(LOG_ERR, "scf_handle_create failed - %s", 1984 scf_strerror(scf_error())); 1985 ret = STMF_PS_ERROR; 1986 goto err; 1987 } 1988 1989 if (scf_handle_bind(*handle) == -1) { 1990 syslog(LOG_ERR, "scf_handle_bind failed - %s", 1991 scf_strerror(scf_error())); 1992 ret = STMF_PS_ERROR; 1993 goto err; 1994 } 1995 1996 if ((*service = scf_service_create(*handle)) == NULL) { 1997 syslog(LOG_ERR, "scf_service_create failed - %s", 1998 scf_strerror(scf_error())); 1999 ret = STMF_PS_ERROR; 2000 goto err; 2001 } 2002 2003 if ((scope = scf_scope_create(*handle)) == NULL) { 2004 syslog(LOG_ERR, "scf_scope_create failed - %s", 2005 scf_strerror(scf_error())); 2006 ret = STMF_PS_ERROR; 2007 goto err; 2008 } 2009 2010 if (scf_handle_get_scope(*handle, SCF_SCOPE_LOCAL, scope) == -1) { 2011 syslog(LOG_ERR, "scf_handle_get_scope failed - %s", 2012 scf_strerror(scf_error())); 2013 ret = STMF_PS_ERROR; 2014 goto err; 2015 } 2016 2017 if (scf_scope_get_service(scope, STMF_SERVICE, *service) == -1) { 2018 syslog(LOG_ERR, "scf_scope_get_service failed - %s", 2019 scf_strerror(scf_error())); 2020 ret = STMF_PS_ERROR_SERVICE_NOT_FOUND; 2021 goto err; 2022 } 2023 2024 2025 /* 2026 * Get and check the version number 2027 */ 2028 ret = iPsGetServiceVersion(&version, *handle, *service); 2029 if (ret != STMF_PS_SUCCESS) { 2030 goto err; 2031 } 2032 2033 if (version != STMF_SMF_VERSION) { 2034 ret = STMF_PS_ERROR_VERSION_MISMATCH; 2035 goto err; 2036 } 2037 2038 /* we only need destroy the scope here */ 2039 scf_scope_destroy(scope); 2040 2041 return (STMF_PS_SUCCESS); 2042 2043 err: 2044 if (*handle != NULL) { 2045 scf_handle_destroy(*handle); 2046 } 2047 if (*service != NULL) { 2048 scf_service_destroy(*service); 2049 *service = NULL; 2050 } 2051 if (scope != NULL) { 2052 scf_scope_destroy(scope); 2053 } 2054 return (ret); 2055 } 2056 2057 /* 2058 * called by iPsInit only 2059 * iPsGetServiceVersion 2060 */ 2061 static int 2062 iPsGetServiceVersion(uint64_t *version, scf_handle_t *handle, 2063 scf_service_t *svc) 2064 { 2065 scf_propertygroup_t *pg = NULL; 2066 scf_property_t *prop = NULL; 2067 scf_value_t *value = NULL; 2068 scf_transaction_t *tran = NULL; 2069 scf_transaction_entry_t *entry = NULL; 2070 int ret = STMF_PS_SUCCESS; 2071 int commitRet; 2072 2073 if (((pg = scf_pg_create(handle)) == NULL) || 2074 ((prop = scf_property_create(handle)) == NULL) || 2075 ((entry = scf_entry_create(handle)) == NULL) || 2076 ((tran = scf_transaction_create(handle)) == NULL) || 2077 ((value = scf_value_create(handle)) == NULL)) { 2078 syslog(LOG_ERR, "scf alloc resource failed - %s", 2079 scf_strerror(scf_error())); 2080 ret = STMF_PS_ERROR; 2081 goto out; 2082 } 2083 2084 *version = STMF_SMF_VERSION; 2085 2086 /* 2087 * get stmf data property group 2088 */ 2089 if (scf_service_get_pg(svc, STMF_DATA_GROUP, pg) == -1) { 2090 if (scf_error() == SCF_ERROR_NOT_FOUND) { 2091 ret = STMF_PS_ERROR_NOT_FOUND; 2092 } else { 2093 syslog(LOG_ERR, "get pg failed - %s", 2094 scf_strerror(scf_error())); 2095 ret = STMF_PS_ERROR; 2096 goto out; 2097 } 2098 } 2099 2100 /* create the group */ 2101 if (ret == STMF_PS_ERROR_NOT_FOUND) { 2102 /* 2103 * create the property group. 2104 */ 2105 if (scf_service_add_pg(svc, STMF_DATA_GROUP, 2106 SCF_GROUP_APPLICATION, 0, pg) == -1) { 2107 syslog(LOG_ERR, "add pg failed - %s", 2108 scf_strerror(scf_error())); 2109 ret = STMF_PS_ERROR; 2110 goto out; 2111 } 2112 /* reset return value */ 2113 ret = STMF_PS_SUCCESS; 2114 } 2115 2116 /* find version property */ 2117 /* 2118 * Get the version property 2119 */ 2120 if (scf_pg_get_property(pg, STMF_VERSION_NAME, prop) == -1) { 2121 if (scf_error() == SCF_ERROR_NOT_FOUND) { 2122 ret = STMF_PS_ERROR_NOT_FOUND; 2123 } else { 2124 syslog(LOG_ERR, "get property failed - %s", 2125 scf_strerror(scf_error())); 2126 ret = STMF_PS_ERROR; 2127 goto out; 2128 } 2129 } 2130 2131 /* no version property found */ 2132 if (ret == STMF_PS_ERROR_NOT_FOUND) { 2133 /* 2134 * If we have no version property, go ahead 2135 * and create it. We're obviously making an assumption 2136 * here that someone did not delete the existing property 2137 * and that this is the initial set and the initial call 2138 * to iPsInit. 2139 * If they did delete it, this will simply plant this 2140 * library's version on this service. That may or may not be 2141 * correct and we have no way of determining that. 2142 */ 2143 /* 2144 * Begin the transaction 2145 */ 2146 if (scf_transaction_start(tran, pg) == -1) { 2147 syslog(LOG_ERR, "start transaction failed - %s", 2148 scf_strerror(scf_error())); 2149 ret = STMF_PS_ERROR; 2150 goto out; 2151 } 2152 2153 if (scf_transaction_property_new(tran, entry, 2154 STMF_VERSION_NAME, SCF_TYPE_COUNT) == -1) { 2155 syslog(LOG_ERR, 2156 "transaction property new failed - %s", 2157 scf_strerror(scf_error())); 2158 ret = STMF_PS_ERROR; 2159 goto out; 2160 } 2161 2162 /* 2163 * set the version number 2164 */ 2165 scf_value_set_count(value, *version); 2166 2167 /* 2168 * add the value to the transaction 2169 */ 2170 if (scf_entry_add_value(entry, value) == -1) { 2171 syslog(LOG_ERR, "add value failed - %s", 2172 scf_strerror(scf_error())); 2173 ret = STMF_PS_ERROR; 2174 goto out; 2175 } 2176 if ((commitRet = scf_transaction_commit(tran)) != 1) { 2177 syslog(LOG_ERR, "transaction commit failed - %s", 2178 scf_strerror(scf_error())); 2179 if (commitRet == 0) { 2180 ret = STMF_PS_ERROR_BUSY; 2181 } else { 2182 ret = STMF_PS_ERROR; 2183 } 2184 goto out; 2185 } 2186 /* reset return value */ 2187 ret = STMF_PS_SUCCESS; 2188 } else { 2189 /* get the version property */ 2190 if (scf_pg_get_property(pg, STMF_VERSION_NAME, prop) == -1) { 2191 syslog(LOG_ERR, "get property failed - %s", 2192 scf_strerror(scf_error())); 2193 ret = STMF_PS_ERROR; 2194 goto out; 2195 } 2196 2197 if (scf_property_get_value(prop, value) == -1) { 2198 syslog(LOG_ERR, "get property value failed - %s", 2199 scf_strerror(scf_error())); 2200 ret = STMF_PS_ERROR; 2201 goto out; 2202 } 2203 2204 /* 2205 * Get the actual value of the view entry count property 2206 */ 2207 if (scf_value_get_count(value, version) == -1) { 2208 syslog(LOG_ERR, "get count value failed - %s", 2209 scf_strerror(scf_error())); 2210 ret = STMF_PS_ERROR; 2211 goto out; 2212 } 2213 } 2214 2215 out: 2216 /* 2217 * Free resources. 2218 * handle and svc should not be free'd here. They're 2219 * free'd elsewhere 2220 */ 2221 if (pg != NULL) { 2222 scf_pg_destroy(pg); 2223 } 2224 if (prop != NULL) { 2225 scf_property_destroy(prop); 2226 } 2227 if (entry != NULL) { 2228 scf_entry_destroy(entry); 2229 } 2230 if (tran != NULL) { 2231 scf_transaction_destroy(tran); 2232 } 2233 if (value != NULL) { 2234 scf_value_destroy(value); 2235 } 2236 return (ret); 2237 } 2238 2239 2240 2241 /* 2242 * iPsGetActualGroupName 2243 * 2244 * pgName - Property group name 2245 * groupName - requested group name 2246 * actualName - actual group name to reference (len must be >= MAXNAMELEN) 2247 * 2248 * returns: 2249 * STMF_PS_SUCCESS on success 2250 * STMF_PS_ERROR_* on failure 2251 */ 2252 static int 2253 iPsGetActualGroupName(char *pgName, char *groupName, char *actualName) 2254 { 2255 scf_handle_t *handle = NULL; 2256 scf_service_t *svc = NULL; 2257 scf_propertygroup_t *pg = NULL; 2258 scf_property_t *prop = NULL; 2259 scf_iter_t *propIter = NULL; 2260 scf_value_t *value = NULL; 2261 char buf[MAXNAMELEN]; 2262 int ret; 2263 2264 ret = iPsInit(&handle, &svc); 2265 if (ret != STMF_PS_SUCCESS) { 2266 goto out; 2267 } 2268 2269 /* 2270 * Allocate scf resources 2271 */ 2272 if (((pg = scf_pg_create(handle)) == NULL) || 2273 ((prop = scf_property_create(handle)) == NULL) || 2274 ((propIter = scf_iter_create(handle)) == NULL) || 2275 ((value = scf_value_create(handle)) == NULL)) { 2276 syslog(LOG_ERR, "scf alloc resource failed - %s", 2277 scf_strerror(scf_error())); 2278 ret = STMF_PS_ERROR; 2279 goto out; 2280 } 2281 2282 /* 2283 * get group list property group 2284 */ 2285 if (scf_service_get_pg(svc, pgName, pg) == -1) { 2286 if (scf_error() == SCF_ERROR_NOT_FOUND) { 2287 ret = STMF_PS_ERROR_GROUP_NOT_FOUND; 2288 } else { 2289 syslog(LOG_ERR, "get pg failed - %s", 2290 scf_strerror(scf_error())); 2291 ret = STMF_PS_ERROR; 2292 } 2293 goto out; 2294 } 2295 2296 /* 2297 * propIter is the iterator handle 2298 */ 2299 if (scf_iter_pg_properties(propIter, pg) == -1) { 2300 syslog(LOG_ERR, "iter properties failed - %s", 2301 scf_strerror(scf_error())); 2302 ret = STMF_PS_ERROR; 2303 goto out; 2304 } 2305 2306 /* 2307 * Iterate through group properties searching for the requested 2308 * group name. When we find it, we need to get the property name 2309 * since it refers to the actual group name. 2310 */ 2311 2312 /* initialize to not found */ 2313 ret = STMF_PS_ERROR_GROUP_NOT_FOUND; 2314 while (scf_iter_next_property(propIter, prop) == 1) { 2315 if (scf_property_get_name(prop, actualName, MAXNAMELEN) == -1) { 2316 syslog(LOG_ERR, "get name failed - %s", 2317 scf_strerror(scf_error())); 2318 ret = STMF_PS_ERROR; 2319 break; 2320 } 2321 /* 2322 * Skip over non-member list properties 2323 */ 2324 if (strstr(actualName, STMF_MEMBER_LIST_SUFFIX)) { 2325 continue; 2326 } 2327 if (scf_property_get_value(prop, value) == -1) { 2328 syslog(LOG_ERR, "get property value failed - %s", 2329 scf_strerror(scf_error())); 2330 ret = STMF_PS_ERROR; 2331 break; 2332 } 2333 if (scf_value_get_ustring(value, buf, sizeof (buf)) == -1) { 2334 syslog(LOG_ERR, "get ustring failed - %s", 2335 scf_strerror(scf_error())); 2336 ret = STMF_PS_ERROR; 2337 break; 2338 } 2339 2340 /* 2341 * When we find a match, set success and break 2342 */ 2343 if ((strlen(buf) == strlen(groupName)) && 2344 bcmp(buf, groupName, strlen(buf)) == 0) { 2345 ret = STMF_PS_SUCCESS; 2346 break; 2347 } 2348 } 2349 2350 /* 2351 * if we didn't find it, ret is set to STMF_PS_ERROR_GROUP_NOT_FOUND 2352 */ 2353 2354 out: 2355 /* 2356 * Free resources 2357 */ 2358 if (handle != NULL) { 2359 scf_handle_destroy(handle); 2360 } 2361 if (svc != NULL) { 2362 scf_service_destroy(svc); 2363 } 2364 if (pg != NULL) { 2365 scf_pg_destroy(pg); 2366 } 2367 if (propIter != NULL) { 2368 scf_iter_destroy(propIter); 2369 } 2370 if (prop != NULL) { 2371 scf_property_destroy(prop); 2372 } 2373 if (value != NULL) { 2374 scf_value_destroy(value); 2375 } 2376 2377 return (ret); 2378 } 2379 2380 /* 2381 * psAddHostGroupMember 2382 * 2383 * Add a host group member to a host group, 2384 * 2385 * Input: groupName - name of group to which the member is added 2386 * memberName - name of group member to add 2387 */ 2388 int 2389 psAddHostGroupMember(char *groupName, char *memberName) 2390 { 2391 int ret; 2392 char groupPropListName[MAXNAMELEN]; 2393 char groupPropName[MAXNAMELEN]; 2394 2395 ret = iPsGetActualGroupName(STMF_HOST_GROUPS, groupName, 2396 groupPropName); 2397 if (ret != STMF_PS_SUCCESS) { 2398 return (ret); 2399 } 2400 2401 if (snprintf(groupPropListName, sizeof (groupPropListName), 2402 "%s-%s", groupPropName, STMF_MEMBER_LIST_SUFFIX) > 2403 sizeof (groupPropListName)) { 2404 syslog(LOG_ERR, "buffer overflow on property name %s", 2405 groupPropName); 2406 return (STMF_PS_ERROR); 2407 } 2408 2409 return (iPsAddRemoveGroupMember(STMF_HOST_GROUPS, groupPropListName, 2410 memberName, ADD)); 2411 } 2412 2413 /* 2414 * psAddTargetGroupMember 2415 * 2416 * Add a target port group member to a target group 2417 * 2418 * Input: groupName - name of group to which the member is added 2419 * memberName - name of group member to add. Must be nul terminated. 2420 */ 2421 int 2422 psAddTargetGroupMember(char *groupName, char *memberName) 2423 { 2424 int ret; 2425 char groupPropListName[MAXNAMELEN]; 2426 char groupPropName[MAXNAMELEN]; 2427 2428 ret = iPsGetActualGroupName(STMF_TARGET_GROUPS, groupName, 2429 groupPropName); 2430 if (ret != STMF_PS_SUCCESS) { 2431 return (ret); 2432 } 2433 2434 if (snprintf(groupPropListName, sizeof (groupPropListName), 2435 "%s-%s", groupPropName, STMF_MEMBER_LIST_SUFFIX) > 2436 sizeof (groupPropListName)) { 2437 syslog(LOG_ERR, "buffer overflow on property name %s", 2438 groupPropName); 2439 return (STMF_PS_ERROR); 2440 } 2441 2442 return (iPsAddRemoveGroupMember(STMF_TARGET_GROUPS, groupPropListName, 2443 memberName, ADD)); 2444 } 2445 2446 2447 /* 2448 * psAddViewEntry 2449 * 2450 * luGuid - logical unit identifier 2451 * viewEntry - pointer to viewEntry allocated by the caller that contains 2452 * the values to set for this view entry 2453 * 2454 * returns: 2455 * STMF_PS_SUCCESS on success 2456 * STMF_PS_ERROR_* on failure 2457 */ 2458 int 2459 psAddViewEntry(stmfGuid *lu, stmfViewEntry *viewEntry) 2460 { 2461 scf_handle_t *handle = NULL; 2462 scf_service_t *svc = NULL; 2463 scf_propertygroup_t *pg = NULL; 2464 char guidAsciiBuf[33]; /* size of ascii hex 16 byte guid with NULL */ 2465 char viewEntryPgName[VIEW_ENTRY_PG_SIZE]; 2466 char scfLuPgName[LOGICAL_UNIT_PG_SIZE]; 2467 int ret = STMF_PS_SUCCESS; 2468 sigset_t sigmaskRestore; 2469 2470 /* grab the signal hold lock */ 2471 (void) pthread_mutex_lock(&sigSetLock); 2472 2473 /* 2474 * hold signals until we're done 2475 */ 2476 if (holdSignal(&sigmaskRestore) != 0) { 2477 (void) pthread_mutex_unlock(&sigSetLock); 2478 return (STMF_PS_ERROR); 2479 } 2480 2481 ret = iPsInit(&handle, &svc); 2482 if (ret != STMF_PS_SUCCESS) { 2483 goto out; 2484 } 2485 2486 pg = scf_pg_create(handle); 2487 if (pg == NULL) { 2488 syslog(LOG_ERR, "scf pg alloc failed - %s", 2489 scf_strerror(scf_error())); 2490 ret = STMF_PS_ERROR; 2491 goto out; 2492 } 2493 2494 /* Convert to ASCII uppercase hexadecimal string */ 2495 (void) snprintf(guidAsciiBuf, sizeof (guidAsciiBuf), 2496 "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", 2497 lu->guid[0], lu->guid[1], lu->guid[2], lu->guid[3], lu->guid[4], 2498 lu->guid[5], lu->guid[6], lu->guid[7], lu->guid[8], lu->guid[9], 2499 lu->guid[10], lu->guid[11], lu->guid[12], lu->guid[13], 2500 lu->guid[14], lu->guid[15]); 2501 2502 (void) snprintf(scfLuPgName, sizeof (scfLuPgName), "%s-%s", 2503 STMF_LU_PREFIX, guidAsciiBuf); 2504 2505 bzero(viewEntryPgName, sizeof (viewEntryPgName)); 2506 /* 2507 * Format of view entry property group name: 2508 * VE-<view_entry_name>-<lu_name> 2509 */ 2510 (void) snprintf(viewEntryPgName, sizeof (viewEntryPgName), 2511 "%s-%d-%s", STMF_VE_PREFIX, viewEntry->veIndex, guidAsciiBuf); 2512 2513 ret = iPsAddViewEntry(scfLuPgName, viewEntryPgName, viewEntry); 2514 2515 out: 2516 /* 2517 * Okay, we're done. Release the signals 2518 */ 2519 if (releaseSignal(&sigmaskRestore) != 0) { 2520 /* 2521 * Don't set this as an STMF_PS_ERROR_*. We succeeded 2522 * the requested operation. But we do need to log it. 2523 */ 2524 syslog(LOG_ERR, "Unable to release one or more signals - %s", 2525 strerror(errno)); 2526 } 2527 2528 /* 2529 * Free resources 2530 */ 2531 if (handle != NULL) { 2532 scf_handle_destroy(handle); 2533 } 2534 if (svc != NULL) { 2535 scf_service_destroy(svc); 2536 } 2537 if (pg != NULL) { 2538 scf_pg_destroy(pg); 2539 } 2540 2541 /* release the signal hold lock */ 2542 (void) pthread_mutex_unlock(&sigSetLock); 2543 2544 return (ret); 2545 } 2546 2547 /* 2548 * psCheckService 2549 * 2550 * Purpose: Checks whether service exists 2551 * 2552 */ 2553 int 2554 psCheckService() 2555 { 2556 int ret; 2557 scf_handle_t *handle = NULL; 2558 scf_service_t *svc = NULL; 2559 2560 ret = iPsInit(&handle, &svc); 2561 2562 /* 2563 * Free resources 2564 */ 2565 if (handle != NULL) { 2566 scf_handle_destroy(handle); 2567 } 2568 if (svc != NULL) { 2569 scf_service_destroy(svc); 2570 } 2571 2572 return (ret); 2573 } 2574 2575 /* 2576 * psCreateHostGroup 2577 * 2578 * groupName - name of group to create 2579 * 2580 * returns: 2581 * STMF_PS_SUCCESS on success 2582 * STMF_PS_ERROR_* on failure 2583 */ 2584 int 2585 psCreateHostGroup(char *groupName) 2586 { 2587 return (iPsCreateDeleteGroup(STMF_HOST_GROUPS, groupName, ADD)); 2588 } 2589 2590 /* 2591 * psCreateTargetGroup 2592 * 2593 * groupName - name of group to create 2594 * 2595 * returns: 2596 * STMF_PS_SUCCESS on success 2597 * STMF_PS_ERROR_* on failure 2598 */ 2599 int 2600 psCreateTargetGroup(char *groupName) 2601 { 2602 return (iPsCreateDeleteGroup(STMF_TARGET_GROUPS, groupName, ADD)); 2603 } 2604 2605 /* 2606 * psDeleteHostGroup 2607 * 2608 * groupName - name of group to delete 2609 * 2610 * returns: 2611 * STMF_PS_SUCCESS on success 2612 * STMF_PS_ERROR_* on failure 2613 */ 2614 int 2615 psDeleteHostGroup(char *groupName) 2616 { 2617 return (iPsCreateDeleteGroup(STMF_HOST_GROUPS, groupName, REMOVE)); 2618 } 2619 2620 /* 2621 * psDeleteTargetGroup 2622 * 2623 * groupName - name of group to delete 2624 * 2625 * returns: 2626 * STMF_PS_SUCCESS on success 2627 * STMF_PS_ERROR_* on failure 2628 */ 2629 int 2630 psDeleteTargetGroup(char *groupName) 2631 { 2632 return (iPsCreateDeleteGroup(STMF_TARGET_GROUPS, groupName, 2633 REMOVE)); 2634 } 2635 2636 /* 2637 * psGetHostGroupList 2638 * 2639 * groupList - pointer to pointer to stmfGroupList. Contains the list 2640 * of host groups on successful return. 2641 * 2642 * returns: 2643 * STMF_PS_SUCCESS on success 2644 * STMF_PS_ERROR_* on failure 2645 */ 2646 int 2647 psGetHostGroupList(stmfGroupList **groupList) 2648 { 2649 return (iPsGetGroupList(STMF_HOST_GROUPS, groupList)); 2650 } 2651 2652 /* 2653 * psGetLogicalUnitList 2654 * 2655 * 2656 */ 2657 int 2658 psGetLogicalUnitList(stmfGuidList **guidList) 2659 { 2660 scf_handle_t *handle = NULL; 2661 scf_service_t *svc = NULL; 2662 scf_propertygroup_t *pg = NULL; 2663 scf_iter_t *pgIter = NULL; 2664 char buf[MAXNAMELEN]; 2665 int guidCnt = 0; 2666 int i = 0, j; 2667 int ret = STMF_PS_SUCCESS; 2668 unsigned int guid[sizeof (stmfGuid)]; 2669 stmfGuid outGuid; 2670 2671 assert(guidList != NULL); 2672 2673 ret = iPsInit(&handle, &svc); 2674 if (ret != STMF_PS_SUCCESS) { 2675 goto out; 2676 } 2677 2678 /* 2679 * Allocate scf resources 2680 */ 2681 if (((pg = scf_pg_create(handle)) == NULL) || 2682 ((pgIter = scf_iter_create(handle)) == NULL)) { 2683 syslog(LOG_ERR, "scf alloc resource failed - %s", 2684 scf_strerror(scf_error())); 2685 ret = STMF_PS_ERROR; 2686 goto out; 2687 } 2688 2689 /* 2690 * pgIter is the iterator handle 2691 */ 2692 if (scf_iter_service_pgs(pgIter, svc) == -1) { 2693 syslog(LOG_ERR, "iter property groups failed - %s", 2694 scf_strerror(scf_error())); 2695 ret = STMF_PS_ERROR; 2696 goto out; 2697 } 2698 2699 while (scf_iter_next_pg(pgIter, pg) == 1) { 2700 if (scf_pg_get_name(pg, buf, sizeof (buf)) == -1) { 2701 syslog(LOG_ERR, "get name failed - %s", 2702 scf_strerror(scf_error())); 2703 ret = STMF_PS_ERROR; 2704 break; 2705 } 2706 /* 2707 * Only count LU property groups 2708 */ 2709 if (strncmp(buf, STMF_LU_PREFIX, strlen(STMF_LU_PREFIX)) == 0) { 2710 guidCnt++; 2711 } 2712 } 2713 2714 /* 2715 * pgIter is the iterator handle 2716 */ 2717 if (scf_iter_service_pgs(pgIter, svc) == -1) { 2718 syslog(LOG_ERR, "iter property groups failed - %s", 2719 scf_strerror(scf_error())); 2720 ret = STMF_PS_ERROR; 2721 goto out; 2722 } 2723 2724 *guidList = (stmfGuidList *)calloc(1, sizeof (stmfGuidList) + 2725 guidCnt * sizeof (stmfGuid)); 2726 if (*guidList == NULL) { 2727 ret = STMF_PS_ERROR_NOMEM; 2728 goto out; 2729 } 2730 2731 /* 2732 * it's possible for entries to be added/removed while we're retrieving 2733 * the property groups. Just make sure we don't write beyond our 2734 * allocated buffer by checking to ensure i < guidCnt. 2735 */ 2736 while ((scf_iter_next_pg(pgIter, pg) == 1) && (i < guidCnt)) { 2737 if (scf_pg_get_name(pg, buf, sizeof (buf)) == -1) { 2738 syslog(LOG_ERR, "get name failed - %s", 2739 scf_strerror(scf_error())); 2740 ret = STMF_PS_ERROR; 2741 break; 2742 } 2743 /* 2744 * Only use LU property groups 2745 */ 2746 if (strncmp(buf, STMF_LU_PREFIX, strlen(STMF_LU_PREFIX)) != 0) { 2747 continue; 2748 } 2749 2750 j = strlen(STMF_LU_PREFIX) + strlen("-"); 2751 2752 (void) sscanf(buf + j, 2753 "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x", 2754 &guid[0], &guid[1], &guid[2], &guid[3], &guid[4], &guid[5], 2755 &guid[6], &guid[7], &guid[8], &guid[9], &guid[10], 2756 &guid[11], &guid[12], &guid[13], &guid[14], &guid[15]); 2757 2758 for (j = 0; j < sizeof (stmfGuid); j++) { 2759 outGuid.guid[j] = guid[j]; 2760 } 2761 2762 bcopy(&outGuid, (*guidList)->guid[i++].guid, sizeof (stmfGuid)); 2763 (*guidList)->cnt++; 2764 } 2765 2766 if (ret != STMF_PS_SUCCESS) { 2767 free(*guidList); 2768 goto out; 2769 } 2770 2771 out: 2772 /* 2773 * Free resources 2774 */ 2775 if (handle != NULL) { 2776 scf_handle_destroy(handle); 2777 } 2778 if (svc != NULL) { 2779 scf_service_destroy(svc); 2780 } 2781 if (pg != NULL) { 2782 scf_pg_destroy(pg); 2783 } 2784 if (pgIter != NULL) { 2785 scf_iter_destroy(pgIter); 2786 } 2787 2788 return (ret); 2789 } 2790 2791 /* 2792 * psGetTargetGroupList 2793 * 2794 * groupList - pointer to pointer to stmfGroupList. Contains the list 2795 * of target groups on successful return. 2796 * 2797 * returns: 2798 * STMF_PS_SUCCESS on success 2799 * STMF_PS_ERROR_* on failure 2800 */ 2801 int 2802 psGetTargetGroupList(stmfGroupList **groupList) 2803 { 2804 return (iPsGetGroupList(STMF_TARGET_GROUPS, groupList)); 2805 } 2806 2807 /* 2808 * psGetHostGroupMemberList 2809 * 2810 * groupName - group name for which to retrieve a member list 2811 * groupMemberList - pointer to pointer to stmfGroupProperties list 2812 * 2813 * returns: 2814 * STMF_PS_SUCCESS on success 2815 * STMF_PS_ERROR_* on failure 2816 */ 2817 int 2818 psGetHostGroupMemberList(char *groupName, stmfGroupProperties **groupMemberList) 2819 { 2820 int ret; 2821 char groupPropListName[MAXNAMELEN]; 2822 char groupPropName[MAXNAMELEN]; 2823 2824 ret = iPsGetActualGroupName(STMF_HOST_GROUPS, groupName, 2825 groupPropName); 2826 if (ret != STMF_PS_SUCCESS) { 2827 return (ret); 2828 } 2829 2830 if (snprintf(groupPropListName, sizeof (groupPropListName), 2831 "%s-%s", groupPropName, STMF_MEMBER_LIST_SUFFIX) > 2832 sizeof (groupPropListName)) { 2833 syslog(LOG_ERR, "buffer overflow on property name %s", 2834 groupPropName); 2835 return (STMF_PS_ERROR); 2836 } 2837 2838 return (iPsGetGroupMemberList(STMF_HOST_GROUPS, groupPropListName, 2839 groupMemberList)); 2840 } 2841 2842 /* 2843 * psGetTargetGroupMemberList 2844 * 2845 * groupName - group name for which to retrieve a member list 2846 * groupMemberList - pointer to pointer to stmfGroupProperties list 2847 * 2848 * returns: 2849 * STMF_PS_SUCCESS on success 2850 * STMF_PS_ERROR_* on failure 2851 */ 2852 int 2853 psGetTargetGroupMemberList(char *groupName, 2854 stmfGroupProperties **groupMemberList) 2855 { 2856 int ret; 2857 char groupPropListName[MAXNAMELEN]; 2858 char groupPropName[MAXNAMELEN]; 2859 2860 ret = iPsGetActualGroupName(STMF_TARGET_GROUPS, groupName, 2861 groupPropName); 2862 if (ret != STMF_PS_SUCCESS) { 2863 return (ret); 2864 } 2865 2866 if (snprintf(groupPropListName, sizeof (groupPropListName), 2867 "%s-%s", groupPropName, STMF_MEMBER_LIST_SUFFIX) > 2868 sizeof (groupPropListName)) { 2869 syslog(LOG_ERR, "buffer overflow on property name %s", 2870 groupPropName); 2871 return (STMF_PS_ERROR); 2872 } 2873 2874 return (iPsGetGroupMemberList(STMF_TARGET_GROUPS, 2875 groupPropListName, groupMemberList)); 2876 } 2877 2878 /* 2879 * qsort function 2880 * sort on veIndex 2881 */ 2882 static int 2883 viewEntryCompare(const void *p1, const void *p2) 2884 { 2885 2886 stmfViewEntry *v1 = (stmfViewEntry *)p1, *v2 = (stmfViewEntry *)p2; 2887 if (v1->veIndex > v2->veIndex) 2888 return (1); 2889 if (v1->veIndex < v2->veIndex) 2890 return (-1); 2891 return (0); 2892 } 2893 2894 /* 2895 * psGetViewEntryList 2896 * 2897 * luGuid - identifier of logical unit for which to retrieve a view entry list 2898 * viewEntryList - pointer to pointer to stmfViewEntryList. It will be allocated 2899 * on successful return. 2900 * 2901 * returns: 2902 * STMF_PS_SUCCESS on success 2903 * STMF_PS_ERROR_* on failure 2904 */ 2905 int 2906 psGetViewEntryList(stmfGuid *lu, stmfViewEntryList **viewEntryList) 2907 { 2908 scf_handle_t *handle = NULL; 2909 scf_service_t *svc = NULL; 2910 scf_propertygroup_t *pg = NULL; 2911 scf_property_t *prop = NULL; 2912 scf_value_t *value = NULL; 2913 scf_iter_t *propIter = NULL; 2914 char guidAsciiBuf[33]; /* size of ascii hex 16 byte guid with NULL */ 2915 char viewEntryPgName[VIEW_ENTRY_PG_SIZE]; 2916 char luPgName[LOGICAL_UNIT_PG_SIZE]; 2917 int ret = STMF_PS_SUCCESS; 2918 uint64_t i = 0; 2919 uint64_t veCnt; 2920 2921 2922 ret = iPsInit(&handle, &svc); 2923 if (ret != STMF_PS_SUCCESS) { 2924 goto out; 2925 } 2926 2927 /* 2928 * Allocate scf resources 2929 */ 2930 if (((pg = scf_pg_create(handle)) == NULL) || 2931 ((prop = scf_property_create(handle)) == NULL) || 2932 ((propIter = scf_iter_create(handle)) == NULL) || 2933 ((value = scf_value_create(handle)) == NULL)) { 2934 syslog(LOG_ERR, "scf alloc resource failed - %s", 2935 scf_strerror(scf_error())); 2936 ret = STMF_PS_ERROR; 2937 goto out; 2938 } 2939 2940 /* Convert to ASCII uppercase hexadecimal string */ 2941 (void) snprintf(guidAsciiBuf, sizeof (guidAsciiBuf), 2942 "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", 2943 lu->guid[0], lu->guid[1], lu->guid[2], lu->guid[3], lu->guid[4], 2944 lu->guid[5], lu->guid[6], lu->guid[7], lu->guid[8], lu->guid[9], 2945 lu->guid[10], lu->guid[11], lu->guid[12], lu->guid[13], 2946 lu->guid[14], lu->guid[15]); 2947 2948 /* form the LU property group name (LU-<guid>) */ 2949 (void) snprintf(luPgName, sizeof (luPgName), "%s-%s", 2950 STMF_LU_PREFIX, guidAsciiBuf); 2951 2952 /* get the property group associated with this LU */ 2953 if (scf_service_get_pg(svc, luPgName, pg) == -1) { 2954 if (scf_error() == SCF_ERROR_NOT_FOUND) { 2955 ret = STMF_PS_ERROR_NOT_FOUND; 2956 } else { 2957 syslog(LOG_ERR, "get pg failed - %s", 2958 scf_strerror(scf_error())); 2959 ret = STMF_PS_ERROR; 2960 } 2961 goto out; 2962 } 2963 2964 /* get the view entry count property */ 2965 if (scf_pg_get_property(pg, STMF_VE_CNT, prop) == -1) { 2966 syslog(LOG_ERR, "get property failed - %s", 2967 scf_strerror(scf_error())); 2968 ret = STMF_PS_ERROR; 2969 goto out; 2970 } 2971 2972 if (scf_property_get_value(prop, value) == -1) { 2973 syslog(LOG_ERR, "get property value failed - %s", 2974 scf_strerror(scf_error())); 2975 ret = STMF_PS_ERROR; 2976 goto out; 2977 } 2978 2979 /* 2980 * Get the actual value of the view entry count property 2981 */ 2982 if (scf_value_get_count(value, &veCnt) == -1) { 2983 syslog(LOG_ERR, "get integer value failed - %s", 2984 scf_strerror(scf_error())); 2985 ret = STMF_PS_ERROR; 2986 goto out; 2987 } 2988 2989 /* 2990 * propIter is the iterator handle 2991 */ 2992 if (scf_iter_pg_properties(propIter, pg) == -1) { 2993 syslog(LOG_ERR, "iter properties failed - %s", 2994 scf_strerror(scf_error())); 2995 ret = STMF_PS_ERROR; 2996 goto out; 2997 } 2998 2999 /* 3000 * alloc the list based on the view entry count 3001 */ 3002 *viewEntryList = (stmfViewEntryList *)calloc(1, 3003 sizeof (stmfViewEntryList) + veCnt * sizeof (stmfViewEntry)); 3004 if (*viewEntryList == NULL) { 3005 ret = STMF_PS_ERROR_NOMEM; 3006 goto out; 3007 } 3008 3009 i = 0; 3010 /* 3011 * iterate through the view entry properties to find the 3012 * view entries 3013 */ 3014 while (scf_iter_next_property(propIter, prop) == 1) { 3015 /* find match for view entry property */ 3016 if (scf_property_get_name(prop, viewEntryPgName, 3017 sizeof (viewEntryPgName)) != -1) { 3018 if (strncmp(viewEntryPgName, STMF_VE_PREFIX, 3019 strlen(STMF_VE_PREFIX)) != 0) { 3020 continue; 3021 } 3022 /* 3023 * We've exceeded our alloc limit 3024 * break with error 3025 */ 3026 if (i == veCnt) { 3027 ret = STMF_PS_ERROR; 3028 break; 3029 } 3030 3031 if ((ret = iPsGetViewEntry(viewEntryPgName, 3032 &((*viewEntryList)->ve[i]))) != STMF_PS_SUCCESS) { 3033 break; 3034 } 3035 3036 i++; 3037 3038 /* set the list count */ 3039 (*viewEntryList)->cnt++; 3040 } else { 3041 syslog(LOG_ERR, "scf pg iter service failed - %s", 3042 scf_strerror(scf_error())); 3043 ret = STMF_PS_ERROR; 3044 break; 3045 } 3046 3047 } 3048 3049 if (ret != STMF_PS_SUCCESS) { 3050 free(*viewEntryList); 3051 goto out; 3052 } 3053 3054 /* 3055 * We're sorting the final list here based on the veIndex 3056 * If we don't, the caller is going to have to do it to reap 3057 * some intelligent output. 3058 */ 3059 qsort((void *)&((*viewEntryList)->ve[0]), (*viewEntryList)->cnt, 3060 sizeof (stmfViewEntry), viewEntryCompare); 3061 3062 out: 3063 /* 3064 * Free resources 3065 */ 3066 if (handle != NULL) { 3067 scf_handle_destroy(handle); 3068 } 3069 if (svc != NULL) { 3070 scf_service_destroy(svc); 3071 } 3072 if (pg != NULL) { 3073 scf_pg_destroy(pg); 3074 } 3075 if (prop != NULL) { 3076 scf_property_destroy(prop); 3077 } 3078 if (value != NULL) { 3079 scf_value_destroy(value); 3080 } 3081 if (propIter != NULL) { 3082 scf_iter_destroy(propIter); 3083 } 3084 3085 return (ret); 3086 } 3087 3088 /* 3089 * iPsGetViewEntry 3090 * 3091 * viewEntryPgName - view entry property group name to retrieve 3092 * viewEntry - pointer to stmfViewEntry structure allocated by the caller 3093 * 3094 * returns: 3095 * STMF_PS_SUCCESS on success 3096 * STMF_PS_ERROR_* on failure 3097 */ 3098 static int 3099 iPsGetViewEntry(char *viewEntryPgName, stmfViewEntry *viewEntry) 3100 { 3101 scf_handle_t *handle = NULL; 3102 scf_service_t *svc = NULL; 3103 scf_propertygroup_t *pg = NULL; 3104 scf_property_t *prop = NULL; 3105 scf_value_t *value = NULL; 3106 uint8_t scfBool; 3107 char *indexPtr; 3108 char groupName[sizeof (stmfGroupName)]; 3109 int ret = STMF_PS_SUCCESS; 3110 3111 3112 ret = iPsInit(&handle, &svc); 3113 if (ret != STMF_PS_SUCCESS) { 3114 goto out; 3115 } 3116 3117 /* 3118 * Allocate scf resources 3119 */ 3120 if (((pg = scf_pg_create(handle)) == NULL) || 3121 ((prop = scf_property_create(handle)) == NULL) || 3122 ((value = scf_value_create(handle)) == NULL)) { 3123 syslog(LOG_ERR, "scf alloc resource failed - %s", 3124 scf_strerror(scf_error())); 3125 ret = STMF_PS_ERROR; 3126 goto out; 3127 } 3128 3129 bzero(viewEntry, sizeof (stmfViewEntry)); 3130 3131 /* 3132 * get the service property group view entry handle 3133 */ 3134 if (scf_service_get_pg(svc, viewEntryPgName, pg) == -1) { 3135 if (scf_error() == SCF_ERROR_NOT_FOUND) { 3136 ret = STMF_PS_ERROR_NOT_FOUND; 3137 } else { 3138 syslog(LOG_ERR, "get pg failed - %s", 3139 scf_strerror(scf_error())); 3140 ret = STMF_PS_ERROR; 3141 } 3142 goto out; 3143 } 3144 3145 3146 /* 3147 * get index 3148 * format is: VE-<veIndex>-GUID 3149 */ 3150 indexPtr = strchr(viewEntryPgName, '-'); 3151 if (!indexPtr) { 3152 ret = STMF_PS_ERROR; 3153 goto out; 3154 } 3155 3156 /* Set the index */ 3157 viewEntry->veIndex = atoi(strtok(++indexPtr, "-")); 3158 3159 viewEntry->veIndexValid = B_TRUE; 3160 3161 /* get allHosts property */ 3162 if (scf_pg_get_property(pg, STMF_VE_ALLHOSTS, 3163 prop) == -1) { 3164 syslog(LOG_ERR, "get property failed - %s", 3165 scf_strerror(scf_error())); 3166 ret = STMF_PS_ERROR; 3167 goto out; 3168 } 3169 3170 if (scf_property_get_value(prop, value) == -1) { 3171 syslog(LOG_ERR, "get property failed - %s", 3172 scf_strerror(scf_error())); 3173 ret = STMF_PS_ERROR; 3174 goto out; 3175 } 3176 3177 /* set allHosts */ 3178 if (scf_value_get_boolean(value, (uint8_t *)&scfBool) == -1) { 3179 syslog(LOG_ERR, "get property failed - %s", 3180 scf_strerror(scf_error())); 3181 ret = STMF_PS_ERROR; 3182 goto out; 3183 } 3184 viewEntry->allHosts = scfBool; 3185 3186 /* get hostGroup property */ 3187 if (scf_pg_get_property(pg, STMF_VE_HOSTGROUP, 3188 prop) == -1) { 3189 syslog(LOG_ERR, "get property failed - %s", 3190 scf_strerror(scf_error())); 3191 ret = STMF_PS_ERROR; 3192 goto out; 3193 } 3194 3195 if (scf_property_get_value(prop, value) == -1) { 3196 syslog(LOG_ERR, "get property failed - %s", 3197 scf_strerror(scf_error())); 3198 ret = STMF_PS_ERROR; 3199 goto out; 3200 } 3201 3202 if (scf_value_get_ustring(value, groupName, 3203 sizeof (groupName)) == -1) { 3204 syslog(LOG_ERR, "set value failed - %s", 3205 scf_strerror(scf_error())); 3206 ret = STMF_PS_ERROR; 3207 goto out; 3208 } 3209 /* set hostGroup */ 3210 bcopy(groupName, viewEntry->hostGroup, strlen(groupName)); 3211 3212 /* get allTargets property */ 3213 if (scf_pg_get_property(pg, STMF_VE_ALLTARGETS, 3214 prop) == -1) { 3215 syslog(LOG_ERR, "get property failed - %s", 3216 scf_strerror(scf_error())); 3217 ret = STMF_PS_ERROR; 3218 goto out; 3219 } 3220 3221 if (scf_property_get_value(prop, value) == -1) { 3222 syslog(LOG_ERR, "get property failed - %s", 3223 scf_strerror(scf_error())); 3224 ret = STMF_PS_ERROR; 3225 goto out; 3226 } 3227 3228 /* set allTargets */ 3229 if (scf_value_get_boolean(value, (uint8_t *)&scfBool) == -1) { 3230 syslog(LOG_ERR, "get property failed - %s", 3231 scf_strerror(scf_error())); 3232 ret = STMF_PS_ERROR; 3233 goto out; 3234 } 3235 viewEntry->allTargets = scfBool; 3236 3237 /* get targetGroup property */ 3238 if (scf_pg_get_property(pg, STMF_VE_TARGETGROUP, prop) == -1) { 3239 syslog(LOG_ERR, "get property failed - %s", 3240 scf_strerror(scf_error())); 3241 ret = STMF_PS_ERROR; 3242 goto out; 3243 } 3244 3245 if (scf_property_get_value(prop, value) == -1) { 3246 syslog(LOG_ERR, "get property failed - %s", 3247 scf_strerror(scf_error())); 3248 ret = STMF_PS_ERROR; 3249 goto out; 3250 } 3251 3252 if (scf_value_get_ustring(value, groupName, 3253 sizeof (groupName)) == -1) { 3254 syslog(LOG_ERR, "set value failed - %s", 3255 scf_strerror(scf_error())); 3256 ret = STMF_PS_ERROR; 3257 goto out; 3258 } 3259 /* set targetGroup */ 3260 bcopy(groupName, viewEntry->targetGroup, strlen(groupName)); 3261 3262 /* get luNbr property */ 3263 if (scf_pg_get_property(pg, STMF_VE_LUNBR, 3264 prop) == -1) { 3265 syslog(LOG_ERR, "get property failed - %s", 3266 scf_strerror(scf_error())); 3267 ret = STMF_PS_ERROR; 3268 goto out; 3269 } 3270 3271 if (scf_property_get_value(prop, value) == -1) { 3272 syslog(LOG_ERR, "get property value failed - %s", 3273 scf_strerror(scf_error())); 3274 ret = STMF_PS_ERROR; 3275 goto out; 3276 } 3277 3278 /* set luNbr */ 3279 if (scf_value_get_opaque(value, (char *)viewEntry->luNbr, 3280 sizeof (viewEntry->luNbr)) == -1) { 3281 syslog(LOG_ERR, "get opaque value failed - %s", 3282 scf_strerror(scf_error())); 3283 ret = STMF_PS_ERROR; 3284 goto out; 3285 } 3286 /* set luNbrValid to true since we just got it */ 3287 viewEntry->luNbrValid = B_TRUE; 3288 3289 out: 3290 /* 3291 * Free resources 3292 */ 3293 if (handle != NULL) { 3294 scf_handle_destroy(handle); 3295 } 3296 if (svc != NULL) { 3297 scf_service_destroy(svc); 3298 } 3299 if (pg != NULL) { 3300 scf_pg_destroy(pg); 3301 } 3302 if (value != NULL) { 3303 scf_value_destroy(value); 3304 } 3305 if (prop != NULL) { 3306 scf_property_destroy(prop); 3307 } 3308 3309 return (ret); 3310 } 3311 3312 3313 /* 3314 * psRemoveHostGroupMember 3315 * 3316 * Remove a host group member from a host group, 3317 * 3318 * groupName - name of group from which the member is removed 3319 * memberName - name of group member to remove 3320 * 3321 * returns: 3322 * STMF_PS_SUCCESS on success 3323 * STMF_PS_ERROR_* on failure 3324 */ 3325 int 3326 psRemoveHostGroupMember(char *groupName, char *memberName) 3327 { 3328 int ret; 3329 char groupPropListName[MAXNAMELEN]; 3330 char groupPropName[MAXNAMELEN]; 3331 3332 ret = iPsGetActualGroupName(STMF_HOST_GROUPS, groupName, 3333 groupPropName); 3334 if (ret != STMF_PS_SUCCESS) { 3335 return (ret); 3336 } 3337 3338 if (snprintf(groupPropListName, sizeof (groupPropListName), 3339 "%s-%s", groupPropName, STMF_MEMBER_LIST_SUFFIX) > 3340 sizeof (groupPropListName)) { 3341 syslog(LOG_ERR, "buffer overflow on property name %s", 3342 groupPropName); 3343 return (STMF_PS_ERROR); 3344 } 3345 3346 return (iPsAddRemoveGroupMember(STMF_HOST_GROUPS, groupPropListName, 3347 memberName, REMOVE)); 3348 } 3349 3350 /* 3351 * psRemoveTargetGroupMember 3352 * 3353 * Remove a target port group member from an target port group, 3354 * 3355 * groupName - name of group from which the member is removed 3356 * memberName - name of group member to remove 3357 * 3358 * returns: 3359 * STMF_PS_SUCCESS on success 3360 * STMF_PS_ERROR_* on failure 3361 */ 3362 int 3363 psRemoveTargetGroupMember(char *groupName, char *memberName) 3364 { 3365 int ret; 3366 char groupPropListName[MAXNAMELEN]; 3367 char groupPropName[MAXNAMELEN]; 3368 3369 ret = iPsGetActualGroupName(STMF_TARGET_GROUPS, groupName, 3370 groupPropName); 3371 if (ret != STMF_PS_SUCCESS) { 3372 return (ret); 3373 } 3374 3375 if (snprintf(groupPropListName, sizeof (groupPropListName), 3376 "%s-%s", groupPropName, STMF_MEMBER_LIST_SUFFIX) > 3377 sizeof (groupPropListName)) { 3378 syslog(LOG_ERR, "buffer overflow on property name %s", 3379 groupPropName); 3380 return (STMF_PS_ERROR); 3381 } 3382 3383 return (iPsAddRemoveGroupMember(STMF_TARGET_GROUPS, groupPropListName, 3384 memberName, REMOVE)); 3385 } 3386 3387 /* 3388 * psGetProviderData 3389 * 3390 * Retrieves an nvlist on a per provider basis 3391 * 3392 * providerName - property group name to use 3393 * nvl - nvlist to retrieve 3394 * 3395 */ 3396 int 3397 psGetProviderData(char *providerName, nvlist_t **nvl, int providerType, 3398 uint64_t *setToken) 3399 { 3400 scf_handle_t *handle = NULL; 3401 scf_service_t *svc = NULL; 3402 scf_propertygroup_t *pg = NULL; 3403 scf_property_t *prop = NULL; 3404 scf_value_t *value = NULL; 3405 uint64_t blockCnt = 0; 3406 ssize_t blockOffset = 0; 3407 ssize_t actualBlockSize = 0; 3408 char pgName[MAXPATHLEN]; 3409 char dataPropertyName[STMF_PROVIDER_DATA_PROP_NAME_SIZE]; 3410 char *nvlistEncoded = NULL; 3411 ssize_t nvlistEncodedSize = 0; 3412 boolean_t foundSetCnt = B_TRUE; 3413 int i; 3414 int ret = STMF_PS_SUCCESS; 3415 3416 if (providerName == NULL || (providerType != STMF_LU_PROVIDER_TYPE && 3417 providerType != STMF_PORT_PROVIDER_TYPE)) { 3418 ret = STMF_PS_ERROR_INVALID_ARG; 3419 goto out; 3420 } 3421 3422 ret = iPsInit(&handle, &svc); 3423 if (ret != STMF_PS_SUCCESS) { 3424 goto out; 3425 } 3426 3427 /* 3428 * create the property group name 3429 */ 3430 (void) snprintf(pgName, sizeof (pgName), "%s%s", 3431 STMF_PROVIDER_DATA_PREFIX, providerName); 3432 3433 /* 3434 * Allocate scf resources 3435 */ 3436 if (((pg = scf_pg_create(handle)) == NULL) || 3437 ((value = scf_value_create(handle)) == NULL) || 3438 ((prop = scf_property_create(handle)) == NULL)) { 3439 syslog(LOG_ERR, "scf alloc resource failed - %s", 3440 scf_strerror(scf_error())); 3441 ret = STMF_PS_ERROR; 3442 goto out; 3443 } 3444 3445 /* 3446 * Retrieve the existing property group. 3447 */ 3448 if (scf_service_get_pg(svc, pgName, pg) == -1) { 3449 if (scf_error() != SCF_ERROR_NOT_FOUND) { 3450 syslog(LOG_ERR, "get pg failed - %s", 3451 scf_strerror(scf_error())); 3452 ret = STMF_PS_ERROR; 3453 goto out; 3454 } else { 3455 ret = STMF_PS_ERROR_NOT_FOUND; 3456 goto out; 3457 } 3458 } 3459 3460 /* 3461 * Get the STMF_PROVIDER_DATA_PROP_COUNT property 3462 */ 3463 if (scf_pg_get_property(pg, STMF_PROVIDER_DATA_PROP_COUNT, 3464 prop) == -1) { 3465 syslog(LOG_ERR, "get property failed - %s", 3466 scf_strerror(scf_error())); 3467 ret = STMF_PS_ERROR; 3468 goto out; 3469 } 3470 3471 /* 3472 * Get the STMF_PROVIDER_DATA_PROP_COUNT value 3473 */ 3474 if (scf_property_get_value(prop, value) == -1) { 3475 syslog(LOG_ERR, "get property value failed - %s", 3476 scf_strerror(scf_error())); 3477 ret = STMF_PS_ERROR; 3478 goto out; 3479 } 3480 3481 /* 3482 * Now get the actual value from the value handle 3483 */ 3484 if (scf_value_get_count(value, &blockCnt) == -1) { 3485 syslog(LOG_ERR, "get integer value failed - %s", 3486 scf_strerror(scf_error())); 3487 ret = STMF_PS_ERROR; 3488 goto out; 3489 } 3490 3491 /* Has the caller requested the token to be set? */ 3492 if (setToken) { 3493 /* 3494 * Get the STMF_PROVIDER_DATA_PROP_SET_COUNT property 3495 * If it doesn't exist, we assume it to be zero. 3496 */ 3497 *setToken = 0; 3498 if (scf_pg_get_property(pg, STMF_PROVIDER_DATA_PROP_SET_COUNT, 3499 prop) == -1) { 3500 if (scf_error() == SCF_ERROR_NOT_FOUND) { 3501 foundSetCnt = B_FALSE; 3502 } else { 3503 syslog(LOG_ERR, "get property failed - %s", 3504 scf_strerror(scf_error())); 3505 ret = STMF_PS_ERROR; 3506 goto out; 3507 } 3508 } 3509 3510 if (foundSetCnt) { 3511 /* 3512 * Get the STMF_PROVIDER_DATA_PROP_SET_COUNT value 3513 */ 3514 if (scf_property_get_value(prop, value) == -1) { 3515 syslog(LOG_ERR, 3516 "get property value failed - %s", 3517 scf_strerror(scf_error())); 3518 ret = STMF_PS_ERROR; 3519 goto out; 3520 } 3521 3522 /* 3523 * Now get the actual value from the value handle 3524 * and set the caller's token 3525 */ 3526 if (scf_value_get_count(value, setToken) == -1) { 3527 syslog(LOG_ERR, 3528 "get integer value failed - %s", 3529 scf_strerror(scf_error())); 3530 ret = STMF_PS_ERROR; 3531 goto out; 3532 } 3533 } 3534 } 3535 3536 nvlistEncoded = (char *)calloc(1, 3537 blockCnt * STMF_PROVIDER_DATA_PROP_SIZE); 3538 if (nvlistEncoded == NULL) { 3539 syslog(LOG_ERR, "nvlistEncoded alloc failed"); 3540 ret = STMF_PS_ERROR_NOMEM; 3541 goto out; 3542 } 3543 3544 for (i = 0; i < blockCnt; i++) { 3545 bzero(dataPropertyName, sizeof (dataPropertyName)); 3546 /* 3547 * create the name to use for the property 3548 */ 3549 (void) snprintf(dataPropertyName, sizeof (dataPropertyName), 3550 "%s-%d", STMF_PROVIDER_DATA_PROP_PREFIX, i); 3551 3552 if (scf_pg_get_property(pg, dataPropertyName, prop) == -1) { 3553 syslog(LOG_ERR, "get property failed - %s", 3554 scf_strerror(scf_error())); 3555 ret = STMF_PS_ERROR; 3556 goto out; 3557 } 3558 3559 if (scf_property_get_value(prop, value) == -1) { 3560 syslog(LOG_ERR, "get property value failed - %s", 3561 scf_strerror(scf_error())); 3562 ret = STMF_PS_ERROR; 3563 goto out; 3564 } 3565 3566 /* 3567 * Set the data block offset 3568 */ 3569 blockOffset = STMF_PROVIDER_DATA_PROP_SIZE * i; 3570 actualBlockSize = scf_value_get_opaque(value, 3571 &nvlistEncoded[blockOffset], STMF_PROVIDER_DATA_PROP_SIZE); 3572 if (actualBlockSize == -1) { 3573 syslog(LOG_ERR, "get opaque property value failed - %s", 3574 scf_strerror(scf_error())); 3575 ret = STMF_PS_ERROR; 3576 goto out; 3577 } 3578 nvlistEncodedSize += actualBlockSize; 3579 } 3580 3581 if (nvlist_unpack(nvlistEncoded, nvlistEncodedSize, nvl, 0) != 0) { 3582 syslog(LOG_ERR, "unable to unpack nvlist"); 3583 ret = STMF_PS_ERROR; 3584 goto out; 3585 } 3586 3587 3588 out: 3589 /* 3590 * Free resources 3591 */ 3592 if (handle != NULL) { 3593 scf_handle_destroy(handle); 3594 } 3595 if (svc != NULL) { 3596 scf_service_destroy(svc); 3597 } 3598 if (pg != NULL) { 3599 scf_pg_destroy(pg); 3600 } 3601 if (prop != NULL) { 3602 scf_property_destroy(prop); 3603 } 3604 if (value != NULL) { 3605 scf_value_destroy(value); 3606 } 3607 if (nvlistEncoded != NULL) { 3608 free(nvlistEncoded); 3609 } 3610 3611 return (ret); 3612 3613 } 3614 /* 3615 * psGetProviderDataList 3616 * 3617 * Retrieves the list of providers that currently store persistent data 3618 * 3619 * providerList - pointer to a pointer to an stmfProviderList structure 3620 * On success, this will contain the list of providers 3621 * currently storing persistent data. 3622 */ 3623 int 3624 psGetProviderDataList(stmfProviderList **providerList) 3625 { 3626 scf_handle_t *handle = NULL; 3627 scf_service_t *svc = NULL; 3628 scf_propertygroup_t *pg = NULL; 3629 scf_property_t *prop = NULL; 3630 scf_value_t *value = NULL; 3631 scf_iter_t *pgIter = NULL; 3632 char buf[MAXNAMELEN]; 3633 int providerCnt = 0; 3634 int64_t providerType; 3635 int i = 0, j; 3636 int ret = STMF_PS_SUCCESS; 3637 3638 ret = iPsInit(&handle, &svc); 3639 if (ret != STMF_PS_SUCCESS) { 3640 goto out; 3641 } 3642 3643 *providerList = NULL; 3644 3645 /* 3646 * Allocate scf resources 3647 */ 3648 if (((pg = scf_pg_create(handle)) == NULL) || 3649 ((value = scf_value_create(handle)) == NULL) || 3650 ((prop = scf_property_create(handle)) == NULL) || 3651 ((pgIter = scf_iter_create(handle)) == NULL)) { 3652 syslog(LOG_ERR, "scf alloc resource failed - %s", 3653 scf_strerror(scf_error())); 3654 ret = STMF_PS_ERROR; 3655 goto out; 3656 } 3657 3658 /* 3659 * pgIter is the iterator handle 3660 */ 3661 if (scf_iter_service_pgs(pgIter, svc) == -1) { 3662 syslog(LOG_ERR, "iter property groups failed - %s", 3663 scf_strerror(scf_error())); 3664 ret = STMF_PS_ERROR; 3665 goto out; 3666 } 3667 3668 while (scf_iter_next_pg(pgIter, pg) == 1) { 3669 if (scf_pg_get_name(pg, buf, sizeof (buf)) == -1) { 3670 syslog(LOG_ERR, "get name failed - %s", 3671 scf_strerror(scf_error())); 3672 ret = STMF_PS_ERROR; 3673 break; 3674 } 3675 /* 3676 * Only count LU property groups 3677 */ 3678 if (strncmp(buf, STMF_PROVIDER_DATA_PREFIX, 3679 strlen(STMF_PROVIDER_DATA_PREFIX)) == 0) { 3680 providerCnt++; 3681 } 3682 } 3683 3684 /* 3685 * pgIter is the iterator handle 3686 */ 3687 if (scf_iter_service_pgs(pgIter, svc) == -1) { 3688 syslog(LOG_ERR, "iter property groups failed - %s", 3689 scf_strerror(scf_error())); 3690 ret = STMF_PS_ERROR; 3691 goto out; 3692 } 3693 3694 *providerList = (stmfProviderList *)calloc(1, 3695 sizeof (stmfProviderList) + providerCnt * sizeof (stmfProvider)); 3696 if (*providerList == NULL) { 3697 ret = STMF_PS_ERROR_NOMEM; 3698 goto out; 3699 } 3700 3701 /* 3702 * it's possible for entries to be added/removed while we're retrieving 3703 * the property groups. Just make sure we don't write beyond our 3704 * allocated buffer by checking to ensure i < providerCnt. 3705 */ 3706 while ((scf_iter_next_pg(pgIter, pg) == 1) && (i < providerCnt)) { 3707 if (scf_pg_get_name(pg, buf, sizeof (buf)) == -1) { 3708 syslog(LOG_ERR, "get name failed - %s", 3709 scf_strerror(scf_error())); 3710 ret = STMF_PS_ERROR; 3711 break; 3712 } 3713 /* 3714 * Only use provider data property groups 3715 */ 3716 if (strncmp(buf, STMF_PROVIDER_DATA_PREFIX, 3717 strlen(STMF_PROVIDER_DATA_PREFIX)) != 0) { 3718 continue; 3719 } 3720 3721 /* 3722 * Get the STMF_PROVIDER_DATA_PROP_TYPE property 3723 */ 3724 if (scf_pg_get_property(pg, STMF_PROVIDER_DATA_PROP_TYPE, 3725 prop) == -1) { 3726 syslog(LOG_ERR, "get property failed - %s", 3727 scf_strerror(scf_error())); 3728 ret = STMF_PS_ERROR; 3729 break; 3730 } 3731 3732 /* 3733 * Get the STMF_PROVIDER_DATA_PROP_TYPE value 3734 */ 3735 if (scf_property_get_value(prop, value) == -1) { 3736 syslog(LOG_ERR, "get property value failed - %s", 3737 scf_strerror(scf_error())); 3738 ret = STMF_PS_ERROR; 3739 break; 3740 } 3741 3742 /* 3743 * Now get the actual value from the value handle 3744 */ 3745 if (scf_value_get_integer(value, &providerType) == -1) { 3746 syslog(LOG_ERR, "get integer value failed - %s", 3747 scf_strerror(scf_error())); 3748 ret = STMF_PS_ERROR; 3749 break; 3750 } 3751 3752 (*providerList)->provider[i].providerType = providerType; 3753 3754 /* determine offset for copy of provider name */ 3755 j = strlen(STMF_PROVIDER_DATA_PREFIX); 3756 3757 /* copy provider name to caller's list */ 3758 (void) strncpy((*providerList)->provider[i].name, buf + j, 3759 sizeof ((*providerList)->provider[i].name)); 3760 i++; 3761 (*providerList)->cnt++; 3762 } 3763 3764 if (ret != STMF_PS_SUCCESS) { 3765 free(*providerList); 3766 goto out; 3767 } 3768 3769 out: 3770 /* 3771 * Free resources 3772 */ 3773 if (handle != NULL) { 3774 scf_handle_destroy(handle); 3775 } 3776 if (svc != NULL) { 3777 scf_service_destroy(svc); 3778 } 3779 if (pg != NULL) { 3780 scf_pg_destroy(pg); 3781 } 3782 if (value != NULL) { 3783 scf_value_destroy(value); 3784 } 3785 if (prop != NULL) { 3786 scf_property_destroy(prop); 3787 } 3788 if (pgIter != NULL) { 3789 scf_iter_destroy(pgIter); 3790 } 3791 3792 return (ret); 3793 } 3794 3795 3796 /* 3797 * psSetProviderData 3798 * 3799 * Stores a packed nvlist on a per provider basis 3800 * 3801 * providerName - property group name to use 3802 * nvl - nvlist to store 3803 * providerType - type of provider (logical unit or port) 3804 * 3805 */ 3806 int 3807 psSetProviderData(char *providerName, nvlist_t *nvl, int providerType, 3808 uint64_t *setToken) 3809 { 3810 scf_handle_t *handle = NULL; 3811 scf_service_t *svc = NULL; 3812 scf_propertygroup_t *pg = NULL; 3813 scf_property_t *prop = NULL; 3814 scf_transaction_t *tran = NULL; 3815 /* represents arrays of entry and value pointers for scf */ 3816 scf_transaction_entry_t **addEntry = NULL; 3817 scf_transaction_entry_t **deleteEntry = NULL; 3818 scf_value_t **addValue = NULL; 3819 3820 /* 3821 * These declarations are for known entry and value set/get 3822 * operations 3823 */ 3824 scf_transaction_entry_t *entry1 = NULL; 3825 scf_transaction_entry_t *entry2 = NULL; 3826 scf_transaction_entry_t *entry3 = NULL; 3827 scf_transaction_entry_t *entry5 = NULL; 3828 scf_value_t *value1 = NULL; 3829 scf_value_t *value2 = NULL; 3830 scf_value_t *value3 = NULL; 3831 scf_value_t *value4 = NULL; 3832 scf_value_t *value5 = NULL; 3833 3834 boolean_t newPg = B_FALSE; 3835 char pgName[MAXPATHLEN]; 3836 char dataPropertyName[STMF_PROVIDER_DATA_PROP_NAME_SIZE]; 3837 char *nvlistEncoded = NULL; 3838 size_t nvlistEncodedSize; 3839 size_t blockSize; 3840 int i, j = 0; 3841 int addEntryAlloc = 0, deleteEntryAlloc = 0, addValueAlloc = 0; 3842 int blockOffset; 3843 uint64_t oldBlockCnt = 0; 3844 uint64_t blockCnt = 0; 3845 uint64_t setCnt = 0; 3846 boolean_t foundSetCnt = B_TRUE; 3847 int ret = STMF_PS_SUCCESS; 3848 int commitRet; 3849 3850 if (providerName == NULL || (providerType != STMF_LU_PROVIDER_TYPE && 3851 providerType != STMF_PORT_PROVIDER_TYPE)) { 3852 ret = STMF_PS_ERROR_INVALID_ARG; 3853 goto out; 3854 } 3855 3856 ret = iPsInit(&handle, &svc); 3857 if (ret != STMF_PS_SUCCESS) { 3858 goto out; 3859 } 3860 3861 bzero(pgName, sizeof (pgName)); 3862 /* 3863 * create the property group name 3864 */ 3865 (void) snprintf(pgName, sizeof (pgName), "%s%s", 3866 STMF_PROVIDER_DATA_PREFIX, providerName); 3867 3868 /* 3869 * Allocate scf resources 3870 */ 3871 if (((pg = scf_pg_create(handle)) == NULL) || 3872 ((entry1 = scf_entry_create(handle)) == NULL) || 3873 ((entry2 = scf_entry_create(handle)) == NULL) || 3874 ((entry3 = scf_entry_create(handle)) == NULL) || 3875 ((entry5 = scf_entry_create(handle)) == NULL) || 3876 ((value1 = scf_value_create(handle)) == NULL) || 3877 ((value2 = scf_value_create(handle)) == NULL) || 3878 ((value3 = scf_value_create(handle)) == NULL) || 3879 ((value4 = scf_value_create(handle)) == NULL) || 3880 ((value5 = scf_value_create(handle)) == NULL) || 3881 ((prop = scf_property_create(handle)) == NULL) || 3882 ((tran = scf_transaction_create(handle)) == NULL)) { 3883 syslog(LOG_ERR, "scf alloc resource failed - %s", 3884 scf_strerror(scf_error())); 3885 ret = STMF_PS_ERROR; 3886 goto out; 3887 } 3888 3889 /* 3890 * Get the existing property group 3891 */ 3892 if (scf_service_get_pg(svc, pgName, pg) == -1) { 3893 if (scf_error() != SCF_ERROR_NOT_FOUND) { 3894 syslog(LOG_ERR, "get pg failed - %s", 3895 scf_strerror(scf_error())); 3896 ret = STMF_PS_ERROR; 3897 goto out; 3898 } else { 3899 /* 3900 * create the property group. 3901 */ 3902 if (scf_service_add_pg(svc, pgName, 3903 SCF_GROUP_APPLICATION, 0, pg) == -1) { 3904 syslog(LOG_ERR, "add pg failed - %s", 3905 scf_strerror(scf_error())); 3906 ret = STMF_PS_ERROR; 3907 goto out; 3908 } 3909 newPg = B_TRUE; 3910 } 3911 } 3912 3913 /* 3914 * Begin the transaction 3915 */ 3916 if (scf_transaction_start(tran, pg) == -1) { 3917 syslog(LOG_ERR, "start transaction failed - %s", 3918 scf_strerror(scf_error())); 3919 ret = STMF_PS_ERROR; 3920 goto out; 3921 } 3922 3923 if (!newPg) { 3924 /* 3925 * Get the STMF_PROVIDER_DATA_PROP_COUNT property 3926 */ 3927 if (scf_pg_get_property(pg, STMF_PROVIDER_DATA_PROP_COUNT, 3928 prop) == -1) { 3929 syslog(LOG_ERR, "get property failed - %s", 3930 scf_strerror(scf_error())); 3931 ret = STMF_PS_ERROR; 3932 goto out; 3933 } 3934 3935 /* 3936 * Get the STMF_PROVIDER_DATA_PROP_COUNT value 3937 */ 3938 if (scf_property_get_value(prop, value4) == -1) { 3939 syslog(LOG_ERR, "get property value failed - %s", 3940 scf_strerror(scf_error())); 3941 ret = STMF_PS_ERROR; 3942 goto out; 3943 } 3944 3945 /* 3946 * Now get the actual value from the value handle 3947 */ 3948 if (scf_value_get_count(value4, &oldBlockCnt) == -1) { 3949 syslog(LOG_ERR, "get integer value failed - %s", 3950 scf_strerror(scf_error())); 3951 ret = STMF_PS_ERROR; 3952 goto out; 3953 } 3954 } 3955 3956 /* 3957 * Get the STMF_PROVIDER_DATA_PROP_SET_COUNT property 3958 * If it doesn't exist, we'll create it later after successfully 3959 * setting the data. 3960 */ 3961 if (scf_pg_get_property(pg, STMF_PROVIDER_DATA_PROP_SET_COUNT, 3962 prop) == -1) { 3963 if (scf_error() == SCF_ERROR_NOT_FOUND) { 3964 foundSetCnt = B_FALSE; 3965 } else { 3966 syslog(LOG_ERR, "get property failed - %s", 3967 scf_strerror(scf_error())); 3968 ret = STMF_PS_ERROR; 3969 goto out; 3970 } 3971 } 3972 3973 if (foundSetCnt) { 3974 /* 3975 * Get the STMF_PROVIDER_DATA_PROP_SET_COUNT value 3976 */ 3977 if (scf_property_get_value(prop, value5) == -1) { 3978 syslog(LOG_ERR, 3979 "get property value failed - %s", 3980 scf_strerror(scf_error())); 3981 ret = STMF_PS_ERROR; 3982 goto out; 3983 } 3984 3985 /* 3986 * Now get the actual value from the value handle 3987 */ 3988 if (scf_value_get_count(value5, &setCnt) == -1) { 3989 syslog(LOG_ERR, 3990 "get integer value failed - %s", 3991 scf_strerror(scf_error())); 3992 ret = STMF_PS_ERROR; 3993 goto out; 3994 } 3995 3996 /* 3997 * Compare the setCnt prop to the caller's. 3998 */ 3999 if (setToken && (*setToken != setCnt)) { 4000 ret = STMF_PS_ERROR_PROV_DATA_STALE; 4001 goto out; 4002 } 4003 } 4004 4005 setCnt++; 4006 4007 /* 4008 * prepare the list for writing 4009 */ 4010 if (nvlist_pack(nvl, &nvlistEncoded, &nvlistEncodedSize, 4011 NV_ENCODE_XDR, 0) != 0) { 4012 syslog(LOG_ERR, "nvlist_pack failed"); 4013 ret = STMF_PS_ERROR_NOMEM; 4014 goto out; 4015 } 4016 4017 /* Determine how many chunks we need to write */ 4018 blockCnt = nvlistEncodedSize/STMF_PROVIDER_DATA_PROP_SIZE; 4019 if (nvlistEncodedSize % STMF_PROVIDER_DATA_PROP_SIZE) 4020 blockCnt++; 4021 4022 /* allocate entry and value resources for writing those chunks */ 4023 addEntry = (scf_transaction_entry_t **)calloc(1, sizeof (*addEntry) 4024 * blockCnt); 4025 if (addEntry == NULL) { 4026 syslog(LOG_ERR, "addEntry alloc failed"); 4027 ret = STMF_PS_ERROR_NOMEM; 4028 goto out; 4029 } 4030 4031 addValue = (scf_value_t **)calloc(1, sizeof (*addValue) 4032 * blockCnt); 4033 if (addValue == NULL) { 4034 syslog(LOG_ERR, "value alloc failed"); 4035 ret = STMF_PS_ERROR_NOMEM; 4036 goto out; 4037 } 4038 4039 /* 4040 * allocate entry delete resources for deleting anything existing 4041 * that is more than the new block count. We could leave them around 4042 * without suffering any ill effects but it will be cleaner to look at 4043 * in smf tools if they are deleted. 4044 */ 4045 if (oldBlockCnt > blockCnt) { 4046 deleteEntry = (scf_transaction_entry_t **)calloc(1, 4047 sizeof (*deleteEntry) * (oldBlockCnt - blockCnt)); 4048 if (deleteEntry == NULL) { 4049 syslog(LOG_ERR, "deleteEntry alloc failed"); 4050 ret = STMF_PS_ERROR_NOMEM; 4051 goto out; 4052 } 4053 deleteEntryAlloc = oldBlockCnt - blockCnt; 4054 } 4055 4056 4057 for (i = 0; i < blockCnt; i++) { 4058 /* 4059 * Create the entry resource for the prop 4060 */ 4061 addEntry[i] = scf_entry_create(handle); 4062 if (addEntry[i] == NULL) { 4063 syslog(LOG_ERR, "scf value alloc failed - %s", 4064 scf_strerror(scf_error())); 4065 ret = STMF_PS_ERROR; 4066 goto out; 4067 } 4068 4069 /* bump alloc count for addEntry allocation */ 4070 addEntryAlloc++; 4071 4072 /* 4073 * create the name to use for the property 4074 */ 4075 (void) snprintf(dataPropertyName, sizeof (dataPropertyName), 4076 "%s-%d", STMF_PROVIDER_DATA_PROP_PREFIX, i); 4077 4078 /* 4079 * Create the new property 4080 */ 4081 if (scf_transaction_property_new(tran, addEntry[i], 4082 dataPropertyName, SCF_TYPE_OPAQUE) == -1) { 4083 if (scf_error() == SCF_ERROR_EXISTS) { 4084 if (scf_transaction_property_change(tran, 4085 addEntry[i], dataPropertyName, 4086 SCF_TYPE_OPAQUE) == -1) { 4087 syslog(LOG_ERR, "transaction property" 4088 "change failed - %s", 4089 scf_strerror(scf_error())); 4090 ret = STMF_PS_ERROR; 4091 goto out; 4092 } 4093 } else { 4094 syslog(LOG_ERR, 4095 "transaction property new failed - %s", 4096 scf_strerror(scf_error())); 4097 ret = STMF_PS_ERROR; 4098 goto out; 4099 } 4100 } 4101 /* 4102 * Create the value resource for the prop 4103 */ 4104 addValue[i] = scf_value_create(handle); 4105 if (addValue[i] == NULL) { 4106 syslog(LOG_ERR, "scf value alloc failed - %s", 4107 scf_strerror(scf_error())); 4108 ret = STMF_PS_ERROR; 4109 goto out; 4110 } 4111 4112 /* bump alloc count for addValue allocation */ 4113 addValueAlloc++; 4114 4115 /* 4116 * Set the data block offset and size 4117 */ 4118 if ((STMF_PROVIDER_DATA_PROP_SIZE * (i + 1)) 4119 > nvlistEncodedSize) { 4120 blockSize = nvlistEncodedSize 4121 - STMF_PROVIDER_DATA_PROP_SIZE * i; 4122 } else { 4123 blockSize = STMF_PROVIDER_DATA_PROP_SIZE; 4124 } 4125 4126 blockOffset = STMF_PROVIDER_DATA_PROP_SIZE * i; 4127 if (scf_value_set_opaque(addValue[i], 4128 &nvlistEncoded[blockOffset], blockSize) == -1) { 4129 syslog(LOG_ERR, "set value failed - %s", 4130 scf_strerror(scf_error())); 4131 ret = STMF_PS_ERROR; 4132 goto out; 4133 } 4134 4135 /* 4136 * Add the data block to the transaction entry 4137 */ 4138 if (scf_entry_add_value(addEntry[i], addValue[i]) == -1) { 4139 syslog(LOG_ERR, "add value failed - %s", 4140 scf_strerror(scf_error())); 4141 ret = STMF_PS_ERROR; 4142 goto out; 4143 } 4144 } 4145 4146 /* 4147 * Now we need to delete any chunks (properties) that are no longer 4148 * needed. Iterate through the rest of the chunks deleting each. 4149 */ 4150 for (i = blockCnt; i < oldBlockCnt; i++) { 4151 /* 4152 * Create the entry resource for the prop 4153 */ 4154 deleteEntry[j] = scf_entry_create(handle); 4155 if (deleteEntry[j] == NULL) { 4156 syslog(LOG_ERR, "scf value alloc failed - %s", 4157 scf_strerror(scf_error())); 4158 ret = STMF_PS_ERROR; 4159 goto out; 4160 } 4161 4162 /* 4163 * create the name to use for the property 4164 */ 4165 (void) snprintf(dataPropertyName, sizeof (dataPropertyName), 4166 "%s-%d", STMF_PROVIDER_DATA_PROP_PREFIX, i); 4167 4168 /* 4169 * Delete the existing property 4170 */ 4171 if (scf_transaction_property_delete(tran, deleteEntry[j++], 4172 dataPropertyName) == -1) { 4173 syslog(LOG_ERR, "get property failed - %s", 4174 scf_strerror(scf_error())); 4175 ret = STMF_PS_ERROR; 4176 goto out; 4177 } 4178 } 4179 4180 if (newPg) { 4181 /* 4182 * Ensure the read_authorization property is set 4183 * for the group 4184 */ 4185 if (scf_transaction_property_new(tran, entry1, 4186 "read_authorization", SCF_TYPE_ASTRING) == -1) { 4187 syslog(LOG_ERR, "transaction property new failed - %s", 4188 scf_strerror(scf_error())); 4189 ret = STMF_PS_ERROR; 4190 goto out; 4191 } 4192 4193 if (scf_value_set_astring(value1, STMF_SMF_READ_ATTR) == -1) { 4194 syslog(LOG_ERR, "set value failed - %s", 4195 scf_strerror(scf_error())); 4196 ret = STMF_PS_ERROR; 4197 goto out; 4198 } 4199 4200 if (scf_entry_add_value(entry1, value1) == -1) { 4201 syslog(LOG_ERR, "add value failed - %s", 4202 scf_strerror(scf_error())); 4203 ret = STMF_PS_ERROR; 4204 goto out; 4205 } 4206 } 4207 4208 /* create or change the count property */ 4209 if (scf_transaction_property_new(tran, entry2, 4210 STMF_PROVIDER_DATA_PROP_COUNT, SCF_TYPE_COUNT) == -1) { 4211 if (scf_error() == SCF_ERROR_EXISTS) { 4212 if (scf_transaction_property_change(tran, entry2, 4213 STMF_PROVIDER_DATA_PROP_COUNT, 4214 SCF_TYPE_COUNT) == -1) { 4215 syslog(LOG_ERR, 4216 "transaction property change failed - %s", 4217 scf_strerror(scf_error())); 4218 ret = STMF_PS_ERROR; 4219 goto out; 4220 } 4221 } else { 4222 syslog(LOG_ERR, "transaction property new failed - %s", 4223 scf_strerror(scf_error())); 4224 ret = STMF_PS_ERROR; 4225 goto out; 4226 } 4227 } 4228 4229 scf_value_set_count(value2, blockCnt); 4230 4231 if (scf_entry_add_value(entry2, value2) == -1) { 4232 syslog(LOG_ERR, "add value failed - %s", 4233 scf_strerror(scf_error())); 4234 ret = STMF_PS_ERROR; 4235 goto out; 4236 } 4237 4238 /* create or change the set count property */ 4239 if (scf_transaction_property_new(tran, entry5, 4240 STMF_PROVIDER_DATA_PROP_SET_COUNT, SCF_TYPE_COUNT) == -1) { 4241 if (scf_error() == SCF_ERROR_EXISTS) { 4242 if (scf_transaction_property_change(tran, entry5, 4243 STMF_PROVIDER_DATA_PROP_SET_COUNT, 4244 SCF_TYPE_COUNT) == -1) { 4245 syslog(LOG_ERR, 4246 "transaction property change failed - %s", 4247 scf_strerror(scf_error())); 4248 ret = STMF_PS_ERROR; 4249 goto out; 4250 } 4251 } else { 4252 syslog(LOG_ERR, "transaction property new failed - %s", 4253 scf_strerror(scf_error())); 4254 ret = STMF_PS_ERROR; 4255 goto out; 4256 } 4257 } 4258 4259 4260 4261 scf_value_set_count(value5, setCnt); 4262 4263 if (scf_entry_add_value(entry5, value5) == -1) { 4264 syslog(LOG_ERR, "add value failed - %s", 4265 scf_strerror(scf_error())); 4266 ret = STMF_PS_ERROR; 4267 goto out; 4268 } 4269 4270 /* create or change the provider type property */ 4271 if (scf_transaction_property_new(tran, entry3, 4272 STMF_PROVIDER_DATA_PROP_TYPE, SCF_TYPE_INTEGER) == -1) { 4273 if (scf_error() == SCF_ERROR_EXISTS) { 4274 if (scf_transaction_property_change(tran, entry3, 4275 STMF_PROVIDER_DATA_PROP_TYPE, 4276 SCF_TYPE_INTEGER) == -1) { 4277 syslog(LOG_ERR, 4278 "transaction property change failed - %s", 4279 scf_strerror(scf_error())); 4280 ret = STMF_PS_ERROR; 4281 goto out; 4282 } 4283 } else { 4284 syslog(LOG_ERR, "transaction property new failed - %s", 4285 scf_strerror(scf_error())); 4286 ret = STMF_PS_ERROR; 4287 goto out; 4288 } 4289 } 4290 4291 switch (providerType) { 4292 case STMF_PORT_PROVIDER_TYPE: 4293 case STMF_LU_PROVIDER_TYPE: 4294 scf_value_set_integer(value3, providerType); 4295 break; 4296 default: 4297 ret = STMF_PS_ERROR; 4298 goto out; 4299 } 4300 4301 if (scf_entry_add_value(entry3, value3) == -1) { 4302 syslog(LOG_ERR, "add value failed - %s", 4303 scf_strerror(scf_error())); 4304 ret = STMF_PS_ERROR; 4305 goto out; 4306 } 4307 4308 4309 if ((commitRet = scf_transaction_commit(tran)) != 1) { 4310 syslog(LOG_ERR, "transaction commit failed - %s", 4311 scf_strerror(scf_error())); 4312 if (commitRet == 0) { 4313 ret = STMF_PS_ERROR_BUSY; 4314 } else { 4315 ret = STMF_PS_ERROR; 4316 } 4317 goto out; 4318 } 4319 4320 /* pass the new token back to the caller if requested */ 4321 if (ret == STMF_PS_SUCCESS && setToken) { 4322 *setToken = setCnt; 4323 } 4324 4325 out: 4326 /* 4327 * Free resources 4328 */ 4329 if (handle != NULL) { 4330 scf_handle_destroy(handle); 4331 } 4332 if (svc != NULL) { 4333 scf_service_destroy(svc); 4334 } 4335 if (pg != NULL) { 4336 scf_pg_destroy(pg); 4337 } 4338 if (prop != NULL) { 4339 scf_property_destroy(prop); 4340 } 4341 if (tran != NULL) { 4342 scf_transaction_destroy(tran); 4343 } 4344 for (i = 0; i < addEntryAlloc; i++) { 4345 scf_entry_destroy(addEntry[i]); 4346 } 4347 for (i = 0; i < addValueAlloc; i++) { 4348 scf_value_destroy(addValue[i]); 4349 } 4350 free(addValue); 4351 free(addEntry); 4352 for (i = 0; i < deleteEntryAlloc; i++) { 4353 scf_entry_destroy(deleteEntry[i]); 4354 } 4355 free(deleteEntry); 4356 if (entry1 != NULL) { 4357 scf_entry_destroy(entry1); 4358 } 4359 if (entry2 != NULL) { 4360 scf_entry_destroy(entry2); 4361 } 4362 if (entry3 != NULL) { 4363 scf_entry_destroy(entry3); 4364 } 4365 if (entry5 != NULL) { 4366 scf_entry_destroy(entry5); 4367 } 4368 if (value1 != NULL) { 4369 scf_value_destroy(value1); 4370 } 4371 if (value2 != NULL) { 4372 scf_value_destroy(value2); 4373 } 4374 if (value3 != NULL) { 4375 scf_value_destroy(value3); 4376 } 4377 if (value4 != NULL) { 4378 scf_value_destroy(value4); 4379 } 4380 if (value5 != NULL) { 4381 scf_value_destroy(value5); 4382 } 4383 if (nvlistEncoded != NULL) { 4384 free(nvlistEncoded); 4385 } 4386 4387 return (ret); 4388 } 4389 4390 /* 4391 * psGetViewEntry 4392 * 4393 * Purpose: Get a single view entry based on the logical unit identifier and 4394 * view entry index 4395 * 4396 * lu - logical unit identifier 4397 * viewEntryIndex - index of view entry 4398 * ve - caller allocated stmfViewEntry structure. On success, this will 4399 * contain the retrieved view entry 4400 */ 4401 int 4402 psGetViewEntry(stmfGuid *lu, uint32_t viewEntryIndex, stmfViewEntry *ve) 4403 { 4404 scf_handle_t *handle = NULL; 4405 scf_service_t *svc = NULL; 4406 scf_propertygroup_t *pg = NULL; 4407 char guidAsciiBuf[33]; /* size of ascii hex 16 byte guid with NULL */ 4408 char viewEntryPgName[VIEW_ENTRY_PG_SIZE]; 4409 char luPgName[LOGICAL_UNIT_PG_SIZE]; 4410 int ret = STMF_PS_SUCCESS; 4411 4412 ret = iPsInit(&handle, &svc); 4413 if (ret != STMF_PS_SUCCESS) { 4414 goto out; 4415 } 4416 4417 pg = scf_pg_create(handle); 4418 if (pg == NULL) { 4419 syslog(LOG_ERR, "scf pg alloc failed - %s", 4420 scf_strerror(scf_error())); 4421 ret = STMF_PS_ERROR; 4422 goto out; 4423 } 4424 4425 /* Convert to ASCII uppercase hexadecimal string */ 4426 (void) snprintf(guidAsciiBuf, sizeof (guidAsciiBuf), 4427 "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", 4428 lu->guid[0], lu->guid[1], lu->guid[2], lu->guid[3], lu->guid[4], 4429 lu->guid[5], lu->guid[6], lu->guid[7], lu->guid[8], lu->guid[9], 4430 lu->guid[10], lu->guid[11], lu->guid[12], lu->guid[13], 4431 lu->guid[14], lu->guid[15]); 4432 4433 (void) snprintf(luPgName, sizeof (luPgName), "%s-%s", 4434 STMF_LU_PREFIX, guidAsciiBuf); 4435 4436 /* 4437 * Format of view entry property group name: 4438 * VE-<view_entry_index>-<lu_name> 4439 */ 4440 (void) snprintf(viewEntryPgName, sizeof (viewEntryPgName), 4441 "%s-%d-%s", STMF_VE_PREFIX, viewEntryIndex, guidAsciiBuf); 4442 4443 if (scf_service_get_pg(svc, viewEntryPgName, pg) == -1) { 4444 if (scf_error() == SCF_ERROR_NOT_FOUND) { 4445 ret = STMF_PS_ERROR_NOT_FOUND; 4446 } else { 4447 syslog(LOG_ERR, "get pg failed - %s", 4448 scf_strerror(scf_error())); 4449 ret = STMF_PS_ERROR; 4450 } 4451 goto out; 4452 } 4453 4454 4455 if ((ret = iPsGetViewEntry(viewEntryPgName, ve)) != STMF_PS_SUCCESS) { 4456 ret = STMF_PS_ERROR; 4457 goto out; 4458 } 4459 4460 out: 4461 /* 4462 * Free resources 4463 */ 4464 if (handle != NULL) { 4465 scf_handle_destroy(handle); 4466 } 4467 if (svc != NULL) { 4468 scf_service_destroy(svc); 4469 } 4470 if (pg != NULL) { 4471 scf_pg_destroy(pg); 4472 } 4473 4474 return (ret); 4475 } 4476 4477 /* 4478 * psRemoveViewEntry 4479 * 4480 * Remove a view entry 4481 * 4482 * luGuid - identifier of logical unit from which to remove view entry 4483 * viewEntryIndex - view entry name to remove 4484 * 4485 * returns: 4486 * STMF_PS_SUCCESS on success 4487 * STMF_PS_ERROR_* on failure 4488 */ 4489 int 4490 psRemoveViewEntry(stmfGuid *lu, uint32_t viewEntryIndex) 4491 { 4492 scf_handle_t *handle = NULL; 4493 scf_service_t *svc = NULL; 4494 scf_propertygroup_t *pg = NULL; 4495 char guidAsciiBuf[33]; /* size of ascii hex 16 byte guid with NULL */ 4496 char viewEntryPgName[VIEW_ENTRY_PG_SIZE]; 4497 char luPgName[LOGICAL_UNIT_PG_SIZE]; 4498 int ret = STMF_PS_SUCCESS; 4499 sigset_t sigmaskRestore; 4500 4501 /* grab the signal hold lock */ 4502 (void) pthread_mutex_lock(&sigSetLock); 4503 4504 /* 4505 * hold signals until we're done 4506 */ 4507 if (holdSignal(&sigmaskRestore) != 0) { 4508 (void) pthread_mutex_unlock(&sigSetLock); 4509 return (STMF_PS_ERROR); 4510 } 4511 4512 ret = iPsInit(&handle, &svc); 4513 if (ret != STMF_PS_SUCCESS) { 4514 goto out; 4515 } 4516 4517 pg = scf_pg_create(handle); 4518 if (pg == NULL) { 4519 syslog(LOG_ERR, "scf pg alloc failed - %s", 4520 scf_strerror(scf_error())); 4521 ret = STMF_PS_ERROR; 4522 goto out; 4523 } 4524 4525 /* Convert to ASCII uppercase hexadecimal string */ 4526 (void) snprintf(guidAsciiBuf, sizeof (guidAsciiBuf), 4527 "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", 4528 lu->guid[0], lu->guid[1], lu->guid[2], lu->guid[3], lu->guid[4], 4529 lu->guid[5], lu->guid[6], lu->guid[7], lu->guid[8], lu->guid[9], 4530 lu->guid[10], lu->guid[11], lu->guid[12], lu->guid[13], 4531 lu->guid[14], lu->guid[15]); 4532 4533 (void) snprintf(luPgName, sizeof (luPgName), "%s-%s", 4534 STMF_LU_PREFIX, guidAsciiBuf); 4535 4536 /* 4537 * Format of view entry property group name: 4538 * VE-<view_entry_index>-<lu_name> 4539 */ 4540 (void) snprintf(viewEntryPgName, sizeof (viewEntryPgName), 4541 "%s-%d-%s", STMF_VE_PREFIX, viewEntryIndex, guidAsciiBuf); 4542 4543 if (scf_service_get_pg(svc, viewEntryPgName, pg) == -1) { 4544 if (scf_error() == SCF_ERROR_NOT_FOUND) { 4545 ret = STMF_PS_ERROR_NOT_FOUND; 4546 } else { 4547 syslog(LOG_ERR, "get pg failed - %s", 4548 scf_strerror(scf_error())); 4549 ret = STMF_PS_ERROR; 4550 } 4551 goto out; 4552 } 4553 4554 /* 4555 * update the logical unit property group to remove 4556 * the view entry and update the view entry count 4557 * If it fails, we won't delete the property group so that 4558 * we maintain consistency. 4559 */ 4560 if ((ret = iPsAddRemoveLuViewEntry(luPgName, viewEntryPgName, 4561 REMOVE)) != STMF_PS_SUCCESS) { 4562 goto out; 4563 } 4564 4565 /* 4566 * Delete the view entry. If this fails, we should try to add 4567 * the logical unit view entry property group back otherwise 4568 * we're inconsistent. 4569 */ 4570 if (scf_pg_delete(pg) == -1) { 4571 syslog(LOG_ERR, "delete pg failed - %s", 4572 scf_strerror(scf_error())); 4573 if ((ret = iPsAddRemoveLuViewEntry(luPgName, viewEntryPgName, 4574 ADD)) != STMF_PS_SUCCESS) { 4575 syslog(LOG_ERR, "add of view entry failed, possible" 4576 "inconsistency - %s", scf_strerror(scf_error())); 4577 } 4578 ret = STMF_PS_ERROR; 4579 goto out; 4580 } 4581 4582 out: 4583 /* 4584 * Okay, we're done. Release the signals 4585 */ 4586 if (releaseSignal(&sigmaskRestore) != 0) { 4587 /* 4588 * Don't set this as an STMF_PS_ERROR_*. We succeeded 4589 * the requested operation. But we do need to log it. 4590 */ 4591 syslog(LOG_ERR, "Unable to release one or more signals - %s", 4592 strerror(errno)); 4593 } 4594 4595 /* 4596 * Free resources 4597 */ 4598 if (handle != NULL) { 4599 scf_handle_destroy(handle); 4600 } 4601 if (svc != NULL) { 4602 scf_service_destroy(svc); 4603 } 4604 if (pg != NULL) { 4605 scf_pg_destroy(pg); 4606 } 4607 4608 /* release the signal hold lock */ 4609 (void) pthread_mutex_unlock(&sigSetLock); 4610 4611 return (ret); 4612 } 4613 4614 4615 4616 /* 4617 * holdSignal 4618 * 4619 * Hold SIGINT, SIGTERM, SIGQUIT until further notice. 4620 * 4621 * Saves old signal mask on a per thread basis 4622 * and saves action for the process. 4623 * 4624 * Installs action for above signals. 4625 * 4626 * locks held: sigSetLock 4627 * 4628 * returns: 4629 * 0 on success 4630 * non-zero otherwise 4631 */ 4632 static int 4633 holdSignal(sigset_t *sigmaskRestore) 4634 { 4635 struct sigaction act; 4636 sigset_t sigmask; 4637 4638 /* 4639 * Return existing signal mask for this thread 4640 */ 4641 if (pthread_sigmask(0, NULL, sigmaskRestore) != 0) { 4642 return (1); 4643 } 4644 4645 (void) sigemptyset(&act.sa_mask); 4646 act.sa_handler = sigHandler; 4647 act.sa_flags = 0; 4648 4649 /* 4650 * Have we set the actions for the signals we want to catch? 4651 */ 4652 if (!actionSet) { 4653 if (sigaction(SIGQUIT, &act, ¤tActionQuit) != 0) { 4654 return (1); 4655 } 4656 4657 if (sigaction(SIGINT, &act, ¤tActionInt) != 0) { 4658 return (1); 4659 } 4660 4661 if (sigaction(SIGTERM, &act, ¤tActionTerm) != 0) { 4662 return (1); 4663 } 4664 4665 actionSet = B_TRUE; 4666 } 4667 4668 /* 4669 * We still need to change the mask for the current thread 4670 */ 4671 if (sigfillset(&sigmask) != 0) { 4672 return (1); 4673 } 4674 4675 (void) sigdelset(&sigmask, SIGQUIT); 4676 4677 (void) sigdelset(&sigmask, SIGINT); 4678 4679 (void) sigdelset(&sigmask, SIGTERM); 4680 4681 if (pthread_sigmask(SIG_SETMASK, &sigmask, NULL) != 0) { 4682 return (1); 4683 } 4684 4685 return (0); 4686 } 4687 4688 /* 4689 * releaseSignal 4690 * 4691 * Re-install the original signal mask and signal actions 4692 * 4693 * Also, raise any signals that were caught during the hold period and clear 4694 * the signal from the caught set (signalsCaught). 4695 * 4696 * locks held: sigSetLock 4697 * 4698 * Returns 4699 * 0 on success 4700 * non-zero otherwise 4701 */ 4702 static int 4703 releaseSignal(sigset_t *sigmaskRestore) 4704 { 4705 int ret = 0; 4706 4707 if (sigaction(SIGQUIT, ¤tActionQuit, NULL) != 0) { 4708 ret = 1; 4709 } 4710 4711 if (sigaction(SIGINT, ¤tActionInt, NULL) != 0) { 4712 ret = 1; 4713 } 4714 4715 if (sigaction(SIGTERM, ¤tActionTerm, NULL) != 0) { 4716 ret = 1; 4717 } 4718 4719 actionSet = B_FALSE; 4720 4721 /* 4722 * Restore previous signal mask for this thread 4723 */ 4724 if (pthread_sigmask(SIG_SETMASK, sigmaskRestore, NULL) != 0) { 4725 syslog(LOG_ERR, "Unable to restore sigmask"); 4726 } 4727 4728 /* 4729 * Now raise signals that were raised while we were held 4730 */ 4731 if (sigismember(&signalsCaught, SIGTERM)) { 4732 (void) sigdelset(&signalsCaught, SIGTERM); 4733 (void) raise(SIGTERM); 4734 } 4735 4736 if (sigismember(&signalsCaught, SIGINT)) { 4737 (void) sigdelset(&signalsCaught, SIGINT); 4738 (void) raise(SIGINT); 4739 } 4740 4741 if (sigismember(&signalsCaught, SIGQUIT)) { 4742 (void) sigdelset(&signalsCaught, SIGQUIT); 4743 (void) raise(SIGQUIT); 4744 } 4745 4746 return (ret); 4747 } 4748