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