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