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