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