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