PageRenderTime 274ms CodeModel.GetById 24ms RepoModel.GetById 2ms app.codeStats 0ms

/usr/src/lib/libstmf/common/store.c

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