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