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