xref: /onnv-gate/usr/src/lib/smbsrv/libsmb/common/smb_scfutil.c (revision 5331:3047ad28a67b)
1*5331Samw /*
2*5331Samw  * CDDL HEADER START
3*5331Samw  *
4*5331Samw  * The contents of this file are subject to the terms of the
5*5331Samw  * Common Development and Distribution License (the "License").
6*5331Samw  * You may not use this file except in compliance with the License.
7*5331Samw  *
8*5331Samw  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*5331Samw  * or http://www.opensolaris.org/os/licensing.
10*5331Samw  * See the License for the specific language governing permissions
11*5331Samw  * and limitations under the License.
12*5331Samw  *
13*5331Samw  * When distributing Covered Code, include this CDDL HEADER in each
14*5331Samw  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*5331Samw  * If applicable, add the following below this CDDL HEADER, with the
16*5331Samw  * fields enclosed by brackets "[]" replaced with your own identifying
17*5331Samw  * information: Portions Copyright [yyyy] [name of copyright owner]
18*5331Samw  *
19*5331Samw  * CDDL HEADER END
20*5331Samw  */
21*5331Samw /*
22*5331Samw  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23*5331Samw  * Use is subject to license terms.
24*5331Samw  */
25*5331Samw 
26*5331Samw #pragma ident	"%Z%%M%	%I%	%E% SMI"
27*5331Samw 
28*5331Samw /* helper functions for using libscf with CIFS */
29*5331Samw 
30*5331Samw #include <libscf.h>
31*5331Samw #include <string.h>
32*5331Samw #include <stdio.h>
33*5331Samw #include <stdlib.h>
34*5331Samw #include <syslog.h>
35*5331Samw #include <errno.h>
36*5331Samw #include <libintl.h>
37*5331Samw #include <assert.h>
38*5331Samw #include <strings.h>
39*5331Samw 
40*5331Samw #include <uuid/uuid.h>
41*5331Samw #include <sys/param.h>
42*5331Samw 
43*5331Samw #include <smbsrv/alloc.h>
44*5331Samw 
45*5331Samw #include <smbsrv/libsmb.h>
46*5331Samw 
47*5331Samw /*
48*5331Samw  * smb_smf_scf_log_error(msg)
49*5331Samw  * Logs error messages from scf API's
50*5331Samw  */
51*5331Samw static void
52*5331Samw smb_smf_scf_log_error(char *msg)
53*5331Samw {
54*5331Samw 	if (!msg) {
55*5331Samw 		syslog(LOG_ERR, " SMBD SMF problem: %s\n",
56*5331Samw 		    scf_strerror(scf_error()));
57*5331Samw 	} else { /*LINTED E_SEC_PRINTF_E_VAR_FMT*/
58*5331Samw 		syslog(LOG_ERR, msg, scf_strerror(scf_error()));
59*5331Samw 	}
60*5331Samw }
61*5331Samw 
62*5331Samw /*
63*5331Samw  * Check if instance with given name exists for a service.
64*5331Samw  * Returns 0 is instance exist
65*5331Samw  */
66*5331Samw int
67*5331Samw smb_smf_instance_exists(smb_scfhandle_t *handle, char *inst_name)
68*5331Samw {
69*5331Samw 	int ret = SMBD_SMF_OK;
70*5331Samw 	if (handle == NULL)
71*5331Samw 		return (SMBD_SMF_SYSTEM_ERR);
72*5331Samw 
73*5331Samw 	handle->scf_instance = scf_instance_create(handle->scf_handle);
74*5331Samw 	if (scf_service_get_instance(handle->scf_service, inst_name,
75*5331Samw 	    handle->scf_instance) != SCF_SUCCESS)
76*5331Samw 		ret = SMBD_SMF_SYSTEM_ERR;
77*5331Samw 
78*5331Samw 	scf_instance_destroy(handle->scf_instance);
79*5331Samw 	handle->scf_instance = NULL;
80*5331Samw 	return (ret);
81*5331Samw }
82*5331Samw 
83*5331Samw /*
84*5331Samw  * Create a service instance. returns 0 if successful.
85*5331Samw  * If instance already exists enable it.
86*5331Samw  */
87*5331Samw int
88*5331Samw smb_smf_instance_create(smb_scfhandle_t *handle, char *serv_prefix,
89*5331Samw 	char *inst_name)
90*5331Samw {
91*5331Samw 	char *instance;
92*5331Samw 	int ret = SMBD_SMF_OK;
93*5331Samw 	int sz;
94*5331Samw 
95*5331Samw 	if (handle == NULL)
96*5331Samw 		return (SMBD_SMF_SYSTEM_ERR);
97*5331Samw 
98*5331Samw 	if (!serv_prefix || !inst_name)
99*5331Samw 		return (SMBD_SMF_SYSTEM_ERR);
100*5331Samw 
101*5331Samw 	sz = strlen(serv_prefix) + strlen(inst_name) + 2;
102*5331Samw 	instance = malloc(sz);
103*5331Samw 	if (!instance)
104*5331Samw 		return (SMBD_SMF_NO_MEMORY);
105*5331Samw 
106*5331Samw 	(void) snprintf(instance, sz, "%s:%s", serv_prefix, inst_name);
107*5331Samw 	handle->scf_instance = scf_instance_create(handle->scf_handle);
108*5331Samw 	if (scf_service_get_instance(handle->scf_service, inst_name,
109*5331Samw 	    handle->scf_instance) != SCF_SUCCESS) {
110*5331Samw 		if (scf_service_add_instance(handle->scf_service,
111*5331Samw 		    inst_name, handle->scf_instance) == SCF_SUCCESS) {
112*5331Samw 			if (smf_enable_instance(instance, 0))
113*5331Samw 				ret = SMBD_SMF_SYSTEM_ERR;
114*5331Samw 		} else {
115*5331Samw 			ret = SMBD_SMF_SYSTEM_ERR;
116*5331Samw 		}
117*5331Samw 	} else {
118*5331Samw 		if (smf_enable_instance(instance, 0))
119*5331Samw 			ret = SMBD_SMF_SYSTEM_ERR;
120*5331Samw 	}
121*5331Samw 	free(instance);
122*5331Samw 	return (ret);
123*5331Samw }
124*5331Samw 
125*5331Samw /*
126*5331Samw  * Delete a specified instance. Return SMBD_SMF_OK for success.
127*5331Samw  */
128*5331Samw int
129*5331Samw smb_smf_instance_delete(smb_scfhandle_t *handle, char *inst_name)
130*5331Samw {
131*5331Samw 	int ret = SMBD_SMF_OK;
132*5331Samw 
133*5331Samw 	if (handle == NULL)
134*5331Samw 		return (SMBD_SMF_SYSTEM_ERR);
135*5331Samw 
136*5331Samw 	handle->scf_instance = scf_instance_create(handle->scf_handle);
137*5331Samw 	if (scf_service_get_instance(handle->scf_service, inst_name,
138*5331Samw 	    handle->scf_instance) == SCF_SUCCESS) {
139*5331Samw 		if (scf_instance_delete(handle->scf_instance) == SCF_SUCCESS) {
140*5331Samw 			return (ret);
141*5331Samw 		} else {
142*5331Samw 			ret = SMBD_SMF_SYSTEM_ERR;
143*5331Samw 		}
144*5331Samw 	} else {
145*5331Samw 		smb_smf_scf_log_error(NULL);
146*5331Samw 		ret = SMBD_SMF_SYSTEM_ERR;
147*5331Samw 	}
148*5331Samw 	return (ret);
149*5331Samw }
150*5331Samw 
151*5331Samw /*
152*5331Samw  * smb_smf_create_service_pgroup(handle, pgroup)
153*5331Samw  *
154*5331Samw  * create a new property group at service level.
155*5331Samw  */
156*5331Samw int
157*5331Samw smb_smf_create_service_pgroup(smb_scfhandle_t *handle, char *pgroup)
158*5331Samw {
159*5331Samw 	int ret = SMBD_SMF_OK;
160*5331Samw 	int err;
161*5331Samw 
162*5331Samw 	if (handle == NULL) {
163*5331Samw 		return (SMBD_SMF_SYSTEM_ERR);
164*5331Samw 	}
165*5331Samw 
166*5331Samw 	/*
167*5331Samw 	 * only create a handle if it doesn't exist. It is ok to exist
168*5331Samw 	 * since the pg handle will be set as a side effect.
169*5331Samw 	 */
170*5331Samw 	if (handle->scf_pg == NULL)
171*5331Samw 		handle->scf_pg = scf_pg_create(handle->scf_handle);
172*5331Samw 
173*5331Samw 	/*
174*5331Samw 	 * if the pgroup exists, we are done. If it doesn't, then we
175*5331Samw 	 * need to actually add one to the service instance.
176*5331Samw 	 */
177*5331Samw 	if (scf_service_get_pg(handle->scf_service,
178*5331Samw 	    pgroup, handle->scf_pg) != 0) {
179*5331Samw 		/* doesn't exist so create one */
180*5331Samw 		if (scf_service_add_pg(handle->scf_service, pgroup,
181*5331Samw 		    SCF_GROUP_APPLICATION, 0, handle->scf_pg) != 0) {
182*5331Samw 			err = scf_error();
183*5331Samw 			if (err != SCF_ERROR_NONE)
184*5331Samw 				smb_smf_scf_log_error(NULL);
185*5331Samw 			switch (err) {
186*5331Samw 			case SCF_ERROR_PERMISSION_DENIED:
187*5331Samw 				ret = SMBD_SMF_NO_PERMISSION;
188*5331Samw 				break;
189*5331Samw 			default:
190*5331Samw 				ret = SMBD_SMF_SYSTEM_ERR;
191*5331Samw 				break;
192*5331Samw 			}
193*5331Samw 		}
194*5331Samw 	}
195*5331Samw 	return (ret);
196*5331Samw }
197*5331Samw 
198*5331Samw /*
199*5331Samw  * smb_smf_create_instance_pgroup(handle, pgroup)
200*5331Samw  *
201*5331Samw  * create a new property group at instance level.
202*5331Samw  */
203*5331Samw int
204*5331Samw smb_smf_create_instance_pgroup(smb_scfhandle_t *handle, char *pgroup)
205*5331Samw {
206*5331Samw 	int ret = SMBD_SMF_OK;
207*5331Samw 	int err;
208*5331Samw 
209*5331Samw 	if (handle == NULL) {
210*5331Samw 		return (SMBD_SMF_SYSTEM_ERR);
211*5331Samw 	}
212*5331Samw 
213*5331Samw 	/*
214*5331Samw 	 * only create a handle if it doesn't exist. It is ok to exist
215*5331Samw 	 * since the pg handle will be set as a side effect.
216*5331Samw 	 */
217*5331Samw 	if (handle->scf_pg == NULL)
218*5331Samw 		handle->scf_pg = scf_pg_create(handle->scf_handle);
219*5331Samw 
220*5331Samw 	/*
221*5331Samw 	 * if the pgroup exists, we are done. If it doesn't, then we
222*5331Samw 	 * need to actually add one to the service instance.
223*5331Samw 	 */
224*5331Samw 	if (scf_instance_get_pg(handle->scf_instance,
225*5331Samw 	    pgroup, handle->scf_pg) != 0) {
226*5331Samw 		/* doesn't exist so create one */
227*5331Samw 		if (scf_instance_add_pg(handle->scf_instance, pgroup,
228*5331Samw 		    SCF_GROUP_FRAMEWORK, 0, handle->scf_pg) != 0) {
229*5331Samw 			err = scf_error();
230*5331Samw 			if (err != SCF_ERROR_NONE)
231*5331Samw 				smb_smf_scf_log_error(NULL);
232*5331Samw 			switch (err) {
233*5331Samw 			case SCF_ERROR_PERMISSION_DENIED:
234*5331Samw 				ret = SMBD_SMF_NO_PERMISSION;
235*5331Samw 				break;
236*5331Samw 			default:
237*5331Samw 				ret = SMBD_SMF_SYSTEM_ERR;
238*5331Samw 				break;
239*5331Samw 			}
240*5331Samw 		}
241*5331Samw 	}
242*5331Samw 	return (ret);
243*5331Samw }
244*5331Samw 
245*5331Samw /*
246*5331Samw  * smb_smf_delete_service_pgroup(handle, pgroup)
247*5331Samw  *
248*5331Samw  * remove the property group from the current service.
249*5331Samw  * but only if it actually exists.
250*5331Samw  */
251*5331Samw int
252*5331Samw smb_smf_delete_service_pgroup(smb_scfhandle_t *handle, char *pgroup)
253*5331Samw {
254*5331Samw 	int ret = SMBD_SMF_OK;
255*5331Samw 	int err;
256*5331Samw 
257*5331Samw 	if (handle == NULL) {
258*5331Samw 		return (SMBD_SMF_SYSTEM_ERR);
259*5331Samw 	}
260*5331Samw 
261*5331Samw 	/*
262*5331Samw 	 * only create a handle if it doesn't exist. It is ok to exist
263*5331Samw 	 * since the pg handle will be set as a side effect.
264*5331Samw 	 */
265*5331Samw 	if (handle->scf_pg == NULL)
266*5331Samw 		handle->scf_pg = scf_pg_create(handle->scf_handle);
267*5331Samw 
268*5331Samw 	/*
269*5331Samw 	 * only delete if it does exist.
270*5331Samw 	 */
271*5331Samw 	if (scf_service_get_pg(handle->scf_service,
272*5331Samw 	    pgroup, handle->scf_pg) == 0) {
273*5331Samw 		/* does exist so delete it */
274*5331Samw 		if (scf_pg_delete(handle->scf_pg) != 0) {
275*5331Samw 			ret = SMBD_SMF_SYSTEM_ERR;
276*5331Samw 			err = scf_error();
277*5331Samw 			if (err != SCF_ERROR_NONE) {
278*5331Samw 				smb_smf_scf_log_error("SMF delpg "
279*5331Samw 				    "problem: %s\n");
280*5331Samw 			}
281*5331Samw 		}
282*5331Samw 	} else {
283*5331Samw 		err = scf_error();
284*5331Samw 		if (err != SCF_ERROR_NONE)
285*5331Samw 			smb_smf_scf_log_error("SMF getpg problem: %s\n");
286*5331Samw 		ret = SMBD_SMF_SYSTEM_ERR;
287*5331Samw 	}
288*5331Samw 	if (ret == SMBD_SMF_SYSTEM_ERR &&
289*5331Samw 	    scf_error() == SCF_ERROR_PERMISSION_DENIED) {
290*5331Samw 		ret = SMBD_SMF_NO_PERMISSION;
291*5331Samw 	}
292*5331Samw 	return (ret);
293*5331Samw }
294*5331Samw 
295*5331Samw /*
296*5331Samw  * smb_smf_delete_instance_pgroup(handle, pgroup)
297*5331Samw  *
298*5331Samw  * remove the property group from the current instance.
299*5331Samw  * but only if it actually exists.
300*5331Samw  */
301*5331Samw int
302*5331Samw smb_smf_delete_instance_pgroup(smb_scfhandle_t *handle, char *pgroup)
303*5331Samw {
304*5331Samw 	int ret = SMBD_SMF_OK;
305*5331Samw 	int err;
306*5331Samw 
307*5331Samw 	if (handle == NULL)
308*5331Samw 		return (SMBD_SMF_SYSTEM_ERR);
309*5331Samw 
310*5331Samw 	/*
311*5331Samw 	 * only create a handle if it doesn't exist. It is ok to exist
312*5331Samw 	 * since the pg handle will be set as a side effect.
313*5331Samw 	 */
314*5331Samw 	if (handle->scf_pg == NULL)
315*5331Samw 		handle->scf_pg = scf_pg_create(handle->scf_handle);
316*5331Samw 
317*5331Samw 	/*
318*5331Samw 	 * only delete if it does exist.
319*5331Samw 	 */
320*5331Samw 	if (scf_instance_get_pg(handle->scf_instance,
321*5331Samw 	    pgroup, handle->scf_pg) == 0) {
322*5331Samw 		/* does exist so delete it */
323*5331Samw 		if (scf_pg_delete(handle->scf_pg) != 0) {
324*5331Samw 			ret = SMBD_SMF_SYSTEM_ERR;
325*5331Samw 			err = scf_error();
326*5331Samw 			if (err != SCF_ERROR_NONE) {
327*5331Samw 				smb_smf_scf_log_error("SMF delpg "
328*5331Samw 				    "problem: %s\n");
329*5331Samw 			}
330*5331Samw 		}
331*5331Samw 	} else {
332*5331Samw 		err = scf_error();
333*5331Samw 		if (err != SCF_ERROR_NONE)
334*5331Samw 			smb_smf_scf_log_error("SMF getpg problem: %s\n");
335*5331Samw 		ret = SMBD_SMF_SYSTEM_ERR;
336*5331Samw 	}
337*5331Samw 	if (ret == SMBD_SMF_SYSTEM_ERR &&
338*5331Samw 	    scf_error() == SCF_ERROR_PERMISSION_DENIED)
339*5331Samw 		ret = SMBD_SMF_NO_PERMISSION;
340*5331Samw 
341*5331Samw 	return (ret);
342*5331Samw }
343*5331Samw 
344*5331Samw /*
345*5331Samw  * Start transaction on current pg in handle.
346*5331Samw  * The pg could be service or instance level.
347*5331Samw  * Must be called after pg handle is obtained
348*5331Samw  * from create or get.
349*5331Samw  */
350*5331Samw int
351*5331Samw smb_smf_start_transaction(smb_scfhandle_t *handle)
352*5331Samw {
353*5331Samw 	int ret = SMBD_SMF_OK;
354*5331Samw 
355*5331Samw 	if (!handle || (!handle->scf_pg))
356*5331Samw 		return (SMBD_SMF_SYSTEM_ERR);
357*5331Samw 
358*5331Samw 	/*
359*5331Samw 	 * lookup the property group and create it if it doesn't already
360*5331Samw 	 * exist.
361*5331Samw 	 */
362*5331Samw 	if (handle->scf_state == SCH_STATE_INIT) {
363*5331Samw 		if (ret == SMBD_SMF_OK) {
364*5331Samw 			handle->scf_trans =
365*5331Samw 			    scf_transaction_create(handle->scf_handle);
366*5331Samw 			if (handle->scf_trans != NULL) {
367*5331Samw 				if (scf_transaction_start(handle->scf_trans,
368*5331Samw 				    handle->scf_pg) != 0) {
369*5331Samw 					ret = SMBD_SMF_SYSTEM_ERR;
370*5331Samw 					scf_transaction_destroy(
371*5331Samw 					    handle->scf_trans);
372*5331Samw 					handle->scf_trans = NULL;
373*5331Samw 				}
374*5331Samw 			} else {
375*5331Samw 				ret = SMBD_SMF_SYSTEM_ERR;
376*5331Samw 			}
377*5331Samw 		}
378*5331Samw 	}
379*5331Samw 	if (ret == SMBD_SMF_SYSTEM_ERR &&
380*5331Samw 	    scf_error() == SCF_ERROR_PERMISSION_DENIED)
381*5331Samw 		ret = SMBD_SMF_NO_PERMISSION;
382*5331Samw 
383*5331Samw 	return (ret);
384*5331Samw }
385*5331Samw 
386*5331Samw /*
387*5331Samw  * smb_smf_end_transaction(handle)
388*5331Samw  *
389*5331Samw  * Commit the changes that were added to the transaction in the
390*5331Samw  * handle. Do all necessary cleanup.
391*5331Samw  */
392*5331Samw int
393*5331Samw smb_smf_end_transaction(smb_scfhandle_t *handle)
394*5331Samw {
395*5331Samw 	int ret = SMBD_SMF_OK;
396*5331Samw 
397*5331Samw 	if (handle == NULL)
398*5331Samw 		return (SMBD_SMF_SYSTEM_ERR);
399*5331Samw 
400*5331Samw 	if (handle->scf_trans == NULL) {
401*5331Samw 		ret = SMBD_SMF_SYSTEM_ERR;
402*5331Samw 	} else {
403*5331Samw 		if (scf_transaction_commit(handle->scf_trans) < 0) {
404*5331Samw 			ret = SMBD_SMF_SYSTEM_ERR;
405*5331Samw 			smb_smf_scf_log_error("Failed to commit "
406*5331Samw 			    "transaction: %s");
407*5331Samw 		}
408*5331Samw 		scf_transaction_destroy_children(handle->scf_trans);
409*5331Samw 		scf_transaction_destroy(handle->scf_trans);
410*5331Samw 		handle->scf_trans = NULL;
411*5331Samw 	}
412*5331Samw 	return (ret);
413*5331Samw }
414*5331Samw 
415*5331Samw /*
416*5331Samw  * Deletes property in current pg
417*5331Samw  */
418*5331Samw int
419*5331Samw smb_smf_delete_property(smb_scfhandle_t *handle, char *propname)
420*5331Samw {
421*5331Samw 	int ret = SMBD_SMF_OK;
422*5331Samw 	scf_transaction_entry_t *entry = NULL;
423*5331Samw 
424*5331Samw 	if (handle == NULL)
425*5331Samw 		return (SMBD_SMF_SYSTEM_ERR);
426*5331Samw 
427*5331Samw 	/*
428*5331Samw 	 * properties must be set in transactions and don't take
429*5331Samw 	 * effect until the transaction has been ended/committed.
430*5331Samw 	 */
431*5331Samw 	entry = scf_entry_create(handle->scf_handle);
432*5331Samw 	if (entry != NULL) {
433*5331Samw 		if (scf_transaction_property_delete(handle->scf_trans, entry,
434*5331Samw 		    propname) != 0) {
435*5331Samw 			ret = SMBD_SMF_SYSTEM_ERR;
436*5331Samw 		}
437*5331Samw 	} else {
438*5331Samw 		ret = SMBD_SMF_SYSTEM_ERR;
439*5331Samw 	}
440*5331Samw 	if (ret == SMBD_SMF_SYSTEM_ERR) {
441*5331Samw 		switch (scf_error()) {
442*5331Samw 		case SCF_ERROR_PERMISSION_DENIED:
443*5331Samw 			ret = SMBD_SMF_NO_PERMISSION;
444*5331Samw 			break;
445*5331Samw 		}
446*5331Samw 	}
447*5331Samw 
448*5331Samw 	/*
449*5331Samw 	 * cleanup if there were any errors that didn't leave these
450*5331Samw 	 * values where they would be cleaned up later.
451*5331Samw 	 */
452*5331Samw 	if ((ret != SMBD_SMF_OK) && (entry != NULL))
453*5331Samw 		scf_entry_destroy(entry);
454*5331Samw 
455*5331Samw 	return (ret);
456*5331Samw }
457*5331Samw 
458*5331Samw /*
459*5331Samw  * Sets string property in current pg
460*5331Samw  */
461*5331Samw int
462*5331Samw smb_smf_set_string_property(smb_scfhandle_t *handle,
463*5331Samw     char *propname, char *valstr)
464*5331Samw {
465*5331Samw 	int ret = SMBD_SMF_OK;
466*5331Samw 	scf_value_t *value = NULL;
467*5331Samw 	scf_transaction_entry_t *entry = NULL;
468*5331Samw 
469*5331Samw 	if (handle == NULL)
470*5331Samw 		return (SMBD_SMF_SYSTEM_ERR);
471*5331Samw 
472*5331Samw 	/*
473*5331Samw 	 * properties must be set in transactions and don't take
474*5331Samw 	 * effect until the transaction has been ended/committed.
475*5331Samw 	 */
476*5331Samw 	value = scf_value_create(handle->scf_handle);
477*5331Samw 	entry = scf_entry_create(handle->scf_handle);
478*5331Samw 	if (value != NULL && entry != NULL) {
479*5331Samw 		if (scf_transaction_property_change(handle->scf_trans, entry,
480*5331Samw 		    propname, SCF_TYPE_ASTRING) == 0 ||
481*5331Samw 		    scf_transaction_property_new(handle->scf_trans, entry,
482*5331Samw 		    propname, SCF_TYPE_ASTRING) == 0) {
483*5331Samw 			if (scf_value_set_astring(value, valstr) == 0) {
484*5331Samw 				if (scf_entry_add_value(entry, value) != 0) {
485*5331Samw 					ret = SMBD_SMF_SYSTEM_ERR;
486*5331Samw 					scf_value_destroy(value);
487*5331Samw 				}
488*5331Samw 				/* the value is in the transaction */
489*5331Samw 				value = NULL;
490*5331Samw 			} else {
491*5331Samw 				/* value couldn't be constructed */
492*5331Samw 				ret = SMBD_SMF_SYSTEM_ERR;
493*5331Samw 			}
494*5331Samw 			/* the entry is in the transaction */
495*5331Samw 			entry = NULL;
496*5331Samw 		} else {
497*5331Samw 			ret = SMBD_SMF_SYSTEM_ERR;
498*5331Samw 		}
499*5331Samw 	} else {
500*5331Samw 		ret = SMBD_SMF_SYSTEM_ERR;
501*5331Samw 	}
502*5331Samw 	if (ret == SMBD_SMF_SYSTEM_ERR) {
503*5331Samw 		switch (scf_error()) {
504*5331Samw 		case SCF_ERROR_PERMISSION_DENIED:
505*5331Samw 			ret = SMBD_SMF_NO_PERMISSION;
506*5331Samw 			break;
507*5331Samw 		}
508*5331Samw 	}
509*5331Samw 
510*5331Samw 	/*
511*5331Samw 	 * cleanup if there were any errors that didn't leave these
512*5331Samw 	 * values where they would be cleaned up later.
513*5331Samw 	 */
514*5331Samw 	if (value != NULL)
515*5331Samw 		scf_value_destroy(value);
516*5331Samw 	if (entry != NULL)
517*5331Samw 		scf_entry_destroy(entry);
518*5331Samw 	return (ret);
519*5331Samw }
520*5331Samw 
521*5331Samw /*
522*5331Samw  * Gets string property value.upto sz size.
523*5331Samw  * Caller is responsible to have enough memory allocated.
524*5331Samw  */
525*5331Samw int
526*5331Samw smb_smf_get_string_property(smb_scfhandle_t *handle, char *propname,
527*5331Samw     char *valstr, size_t sz)
528*5331Samw {
529*5331Samw 	int ret = SMBD_SMF_OK;
530*5331Samw 	scf_value_t *value;
531*5331Samw 	scf_property_t *prop;
532*5331Samw 
533*5331Samw 	if (handle == NULL)
534*5331Samw 		return (SMBD_SMF_SYSTEM_ERR);
535*5331Samw 
536*5331Samw 	value = scf_value_create(handle->scf_handle);
537*5331Samw 	prop = scf_property_create(handle->scf_handle);
538*5331Samw 	if (value && prop &&
539*5331Samw 	    (scf_pg_get_property(handle->scf_pg, propname, prop) == 0)) {
540*5331Samw 		if (scf_property_get_value(prop, value) == 0) {
541*5331Samw 			if (scf_value_get_astring(value, valstr, sz) < 0) {
542*5331Samw 				ret = SMBD_SMF_SYSTEM_ERR;
543*5331Samw 			}
544*5331Samw 		} else {
545*5331Samw 			ret = SMBD_SMF_SYSTEM_ERR;
546*5331Samw 		}
547*5331Samw 	} else {
548*5331Samw 		ret = SMBD_SMF_SYSTEM_ERR;
549*5331Samw 	}
550*5331Samw 	if (value != NULL)
551*5331Samw 		scf_value_destroy(value);
552*5331Samw 	if (prop != NULL)
553*5331Samw 		scf_property_destroy(prop);
554*5331Samw 	return (ret);
555*5331Samw }
556*5331Samw 
557*5331Samw /*
558*5331Samw  * Set integer value of property.
559*5331Samw  * The value is returned as int64_t value
560*5331Samw  * Caller ensures appropriate translation.
561*5331Samw  */
562*5331Samw int
563*5331Samw smb_smf_set_integer_property(smb_scfhandle_t *handle, char *propname,
564*5331Samw     int64_t valint)
565*5331Samw {
566*5331Samw 	int ret = SMBD_SMF_OK;
567*5331Samw 	scf_value_t *value = NULL;
568*5331Samw 	scf_transaction_entry_t *entry = NULL;
569*5331Samw 
570*5331Samw 	if (handle == NULL)
571*5331Samw 		return (SMBD_SMF_SYSTEM_ERR);
572*5331Samw 
573*5331Samw 	/*
574*5331Samw 	 * properties must be set in transactions and don't take
575*5331Samw 	 * effect until the transaction has been ended/committed.
576*5331Samw 	 */
577*5331Samw 	value = scf_value_create(handle->scf_handle);
578*5331Samw 	entry = scf_entry_create(handle->scf_handle);
579*5331Samw 	if (value != NULL && entry != NULL) {
580*5331Samw 		if (scf_transaction_property_change(handle->scf_trans, entry,
581*5331Samw 		    propname, SCF_TYPE_INTEGER) == 0 ||
582*5331Samw 		    scf_transaction_property_new(handle->scf_trans, entry,
583*5331Samw 		    propname, SCF_TYPE_INTEGER) == 0) {
584*5331Samw 			scf_value_set_integer(value, valint);
585*5331Samw 			if (scf_entry_add_value(entry, value) != 0) {
586*5331Samw 				ret = SMBD_SMF_SYSTEM_ERR;
587*5331Samw 				scf_value_destroy(value);
588*5331Samw 			}
589*5331Samw 			/* the value is in the transaction */
590*5331Samw 			value = NULL;
591*5331Samw 		}
592*5331Samw 		/* the entry is in the transaction */
593*5331Samw 		entry = NULL;
594*5331Samw 	} else {
595*5331Samw 		ret = SMBD_SMF_SYSTEM_ERR;
596*5331Samw 	}
597*5331Samw 	if (ret == SMBD_SMF_SYSTEM_ERR) {
598*5331Samw 		switch (scf_error()) {
599*5331Samw 		case SCF_ERROR_PERMISSION_DENIED:
600*5331Samw 			ret = SMBD_SMF_NO_PERMISSION;
601*5331Samw 			break;
602*5331Samw 		}
603*5331Samw 	}
604*5331Samw 	/*
605*5331Samw 	 * cleanup if there were any errors that didn't leave these
606*5331Samw 	 * values where they would be cleaned up later.
607*5331Samw 	 */
608*5331Samw 	if (value != NULL)
609*5331Samw 		scf_value_destroy(value);
610*5331Samw 	if (entry != NULL)
611*5331Samw 		scf_entry_destroy(entry);
612*5331Samw 	return (ret);
613*5331Samw }
614*5331Samw 
615*5331Samw /*
616*5331Samw  * Gets integer property value.
617*5331Samw  * Caller is responsible to have enough memory allocated.
618*5331Samw  */
619*5331Samw int
620*5331Samw smb_smf_get_integer_property(smb_scfhandle_t *handle, char *propname,
621*5331Samw     int64_t *valint)
622*5331Samw {
623*5331Samw 	int ret = SMBD_SMF_OK;
624*5331Samw 	scf_value_t *value = NULL;
625*5331Samw 	scf_property_t *prop = NULL;
626*5331Samw 
627*5331Samw 	if (handle == NULL)
628*5331Samw 		return (SMBD_SMF_SYSTEM_ERR);
629*5331Samw 
630*5331Samw 	value = scf_value_create(handle->scf_handle);
631*5331Samw 	prop = scf_property_create(handle->scf_handle);
632*5331Samw 	if ((prop) && (value) &&
633*5331Samw 	    (scf_pg_get_property(handle->scf_pg, propname, prop) == 0)) {
634*5331Samw 		if (scf_property_get_value(prop, value) == 0) {
635*5331Samw 			if (scf_value_get_integer(value,
636*5331Samw 			    valint) != 0) {
637*5331Samw 				ret = SMBD_SMF_SYSTEM_ERR;
638*5331Samw 			}
639*5331Samw 		} else {
640*5331Samw 			ret = SMBD_SMF_SYSTEM_ERR;
641*5331Samw 		}
642*5331Samw 	} else {
643*5331Samw 		ret = SMBD_SMF_SYSTEM_ERR;
644*5331Samw 	}
645*5331Samw 	if (value != NULL)
646*5331Samw 		scf_value_destroy(value);
647*5331Samw 	if (prop != NULL)
648*5331Samw 		scf_property_destroy(prop);
649*5331Samw 	return (ret);
650*5331Samw }
651*5331Samw 
652*5331Samw /*
653*5331Samw  * Set boolean value of property.
654*5331Samw  * The value is returned as int64_t value
655*5331Samw  * Caller ensures appropriate translation.
656*5331Samw  */
657*5331Samw int
658*5331Samw smb_smf_set_boolean_property(smb_scfhandle_t *handle, char *propname,
659*5331Samw     uint8_t valbool)
660*5331Samw {
661*5331Samw 	int ret = SMBD_SMF_OK;
662*5331Samw 	scf_value_t *value = NULL;
663*5331Samw 	scf_transaction_entry_t *entry = NULL;
664*5331Samw 
665*5331Samw 	if (handle == NULL)
666*5331Samw 		return (SMBD_SMF_SYSTEM_ERR);
667*5331Samw 
668*5331Samw 	/*
669*5331Samw 	 * properties must be set in transactions and don't take
670*5331Samw 	 * effect until the transaction has been ended/committed.
671*5331Samw 	 */
672*5331Samw 	value = scf_value_create(handle->scf_handle);
673*5331Samw 	entry = scf_entry_create(handle->scf_handle);
674*5331Samw 	if (value != NULL && entry != NULL) {
675*5331Samw 		if (scf_transaction_property_change(handle->scf_trans, entry,
676*5331Samw 		    propname, SCF_TYPE_BOOLEAN) == 0 ||
677*5331Samw 		    scf_transaction_property_new(handle->scf_trans, entry,
678*5331Samw 		    propname, SCF_TYPE_BOOLEAN) == 0) {
679*5331Samw 			scf_value_set_boolean(value, valbool);
680*5331Samw 			if (scf_entry_add_value(entry, value) != 0) {
681*5331Samw 				ret = SMBD_SMF_SYSTEM_ERR;
682*5331Samw 				scf_value_destroy(value);
683*5331Samw 			}
684*5331Samw 			/* the value is in the transaction */
685*5331Samw 			value = NULL;
686*5331Samw 		}
687*5331Samw 		/* the entry is in the transaction */
688*5331Samw 		entry = NULL;
689*5331Samw 	} else {
690*5331Samw 		ret = SMBD_SMF_SYSTEM_ERR;
691*5331Samw 	}
692*5331Samw 	if (ret == SMBD_SMF_SYSTEM_ERR) {
693*5331Samw 		switch (scf_error()) {
694*5331Samw 		case SCF_ERROR_PERMISSION_DENIED:
695*5331Samw 			ret = SMBD_SMF_NO_PERMISSION;
696*5331Samw 			break;
697*5331Samw 		}
698*5331Samw 	}
699*5331Samw 	/*
700*5331Samw 	 * cleanup if there were any errors that didn't leave these
701*5331Samw 	 * values where they would be cleaned up later.
702*5331Samw 	 */
703*5331Samw 	if (value != NULL)
704*5331Samw 		scf_value_destroy(value);
705*5331Samw 	if (entry != NULL)
706*5331Samw 		scf_entry_destroy(entry);
707*5331Samw 	return (ret);
708*5331Samw }
709*5331Samw 
710*5331Samw /*
711*5331Samw  * Gets boolean property value.
712*5331Samw  * Caller is responsible to have enough memory allocated.
713*5331Samw  */
714*5331Samw int
715*5331Samw smb_smf_get_boolean_property(smb_scfhandle_t *handle, char *propname,
716*5331Samw     uint8_t *valbool)
717*5331Samw {
718*5331Samw 	int ret = SMBD_SMF_OK;
719*5331Samw 	scf_value_t *value = NULL;
720*5331Samw 	scf_property_t *prop = NULL;
721*5331Samw 
722*5331Samw 	if (handle == NULL)
723*5331Samw 		return (SMBD_SMF_SYSTEM_ERR);
724*5331Samw 
725*5331Samw 	value = scf_value_create(handle->scf_handle);
726*5331Samw 	prop = scf_property_create(handle->scf_handle);
727*5331Samw 	if ((prop) && (value) &&
728*5331Samw 	    (scf_pg_get_property(handle->scf_pg, propname, prop) == 0)) {
729*5331Samw 		if (scf_property_get_value(prop, value) == 0) {
730*5331Samw 			if (scf_value_get_boolean(value,
731*5331Samw 			    valbool) != 0) {
732*5331Samw 				ret = SMBD_SMF_SYSTEM_ERR;
733*5331Samw 			}
734*5331Samw 		} else {
735*5331Samw 			ret = SMBD_SMF_SYSTEM_ERR;
736*5331Samw 		}
737*5331Samw 	} else {
738*5331Samw 		ret = SMBD_SMF_SYSTEM_ERR;
739*5331Samw 	}
740*5331Samw 	if (value != NULL)
741*5331Samw 		scf_value_destroy(value);
742*5331Samw 	if (prop != NULL)
743*5331Samw 		scf_property_destroy(prop);
744*5331Samw 	return (ret);
745*5331Samw }
746*5331Samw 
747*5331Samw /*
748*5331Samw  * Sets a blob property value.
749*5331Samw  */
750*5331Samw int
751*5331Samw smb_smf_set_opaque_property(smb_scfhandle_t *handle, char *propname,
752*5331Samw     void *voidval, size_t sz)
753*5331Samw {
754*5331Samw 	int ret = SMBD_SMF_OK;
755*5331Samw 	scf_value_t *value;
756*5331Samw 	scf_transaction_entry_t *entry;
757*5331Samw 
758*5331Samw 	if (handle == NULL)
759*5331Samw 		return (SMBD_SMF_SYSTEM_ERR);
760*5331Samw 
761*5331Samw 	/*
762*5331Samw 	 * properties must be set in transactions and don't take
763*5331Samw 	 * effect until the transaction has been ended/committed.
764*5331Samw 	 */
765*5331Samw 	value = scf_value_create(handle->scf_handle);
766*5331Samw 	entry = scf_entry_create(handle->scf_handle);
767*5331Samw 	if (value != NULL && entry != NULL) {
768*5331Samw 		if (scf_transaction_property_change(handle->scf_trans, entry,
769*5331Samw 		    propname, SCF_TYPE_OPAQUE) == 0 ||
770*5331Samw 		    scf_transaction_property_new(handle->scf_trans, entry,
771*5331Samw 		    propname, SCF_TYPE_OPAQUE) == 0) {
772*5331Samw 			if (scf_value_set_opaque(value, voidval, sz) == 0) {
773*5331Samw 				if (scf_entry_add_value(entry, value) != 0) {
774*5331Samw 					ret = SMBD_SMF_SYSTEM_ERR;
775*5331Samw 					scf_value_destroy(value);
776*5331Samw 				}
777*5331Samw 				/* the value is in the transaction */
778*5331Samw 				value = NULL;
779*5331Samw 			} else {
780*5331Samw 				/* value couldn't be constructed */
781*5331Samw 				ret = SMBD_SMF_SYSTEM_ERR;
782*5331Samw 			}
783*5331Samw 			/* the entry is in the transaction */
784*5331Samw 			entry = NULL;
785*5331Samw 		} else {
786*5331Samw 			ret = SMBD_SMF_SYSTEM_ERR;
787*5331Samw 		}
788*5331Samw 	} else {
789*5331Samw 		ret = SMBD_SMF_SYSTEM_ERR;
790*5331Samw 	}
791*5331Samw 	if (ret == SMBD_SMF_SYSTEM_ERR) {
792*5331Samw 		switch (scf_error()) {
793*5331Samw 		case SCF_ERROR_PERMISSION_DENIED:
794*5331Samw 			ret = SMBD_SMF_NO_PERMISSION;
795*5331Samw 			break;
796*5331Samw 		}
797*5331Samw 	}
798*5331Samw 	/*
799*5331Samw 	 * cleanup if there were any errors that didn't leave these
800*5331Samw 	 * values where they would be cleaned up later.
801*5331Samw 	 */
802*5331Samw 	if (value != NULL)
803*5331Samw 		scf_value_destroy(value);
804*5331Samw 	if (entry != NULL)
805*5331Samw 		scf_entry_destroy(entry);
806*5331Samw 	return (ret);
807*5331Samw }
808*5331Samw 
809*5331Samw /*
810*5331Samw  * Gets a blob property value.
811*5331Samw  * Caller is responsible to have enough memory allocated.
812*5331Samw  */
813*5331Samw int
814*5331Samw smb_smf_get_opaque_property(smb_scfhandle_t *handle, char *propname,
815*5331Samw     void *v, size_t sz)
816*5331Samw {
817*5331Samw 	int ret = SMBD_SMF_OK;
818*5331Samw 	scf_value_t *value = NULL;
819*5331Samw 	scf_property_t *prop = NULL;
820*5331Samw 
821*5331Samw 	if (handle == NULL)
822*5331Samw 		return (SMBD_SMF_SYSTEM_ERR);
823*5331Samw 
824*5331Samw 	value = scf_value_create(handle->scf_handle);
825*5331Samw 	prop = scf_property_create(handle->scf_handle);
826*5331Samw 	if ((prop) && (value) &&
827*5331Samw 	    (scf_pg_get_property(handle->scf_pg, propname, prop) == 0)) {
828*5331Samw 		if (scf_property_get_value(prop, value) == 0) {
829*5331Samw 			if (scf_value_get_opaque(value, (char *)v, sz) != sz) {
830*5331Samw 				ret = SMBD_SMF_SYSTEM_ERR;
831*5331Samw 			}
832*5331Samw 		} else {
833*5331Samw 			ret = SMBD_SMF_SYSTEM_ERR;
834*5331Samw 		}
835*5331Samw 	} else {
836*5331Samw 		ret = SMBD_SMF_SYSTEM_ERR;
837*5331Samw 	}
838*5331Samw 	if (value != NULL)
839*5331Samw 		scf_value_destroy(value);
840*5331Samw 	if (prop != NULL)
841*5331Samw 		scf_property_destroy(prop);
842*5331Samw 	return (ret);
843*5331Samw }
844*5331Samw 
845*5331Samw /*
846*5331Samw  * Get property based on property type. Returns string value of that
847*5331Samw  * property. Only SCF_TYPE_ASTRING, SCF_TYPE_INTEGER, SCF_TYPE_BOOLEAN
848*5331Samw  * supported.
849*5331Samw  */
850*5331Samw int
851*5331Samw smb_smf_get_property(smb_scfhandle_t *handle, int proptype, char *propname,
852*5331Samw     char *valstr, size_t sz)
853*5331Samw {
854*5331Samw 	int64_t valint = 0;
855*5331Samw 	uint8_t valbool = 0;
856*5331Samw 	int ret = SMBD_SMF_OK;
857*5331Samw 
858*5331Samw 	switch (proptype) {
859*5331Samw 	case SCF_TYPE_ASTRING:
860*5331Samw 		ret = smb_smf_get_string_property(handle, propname,
861*5331Samw 		    valstr, sz);
862*5331Samw 		break;
863*5331Samw 	case SCF_TYPE_INTEGER:
864*5331Samw 		if ((ret = smb_smf_get_integer_property(handle, propname,
865*5331Samw 		    &valint)) != 0)
866*5331Samw 			return (ret);
867*5331Samw 		(void) snprintf(valstr, sz, "%lld", valint);
868*5331Samw 		break;
869*5331Samw 	case SCF_TYPE_BOOLEAN:
870*5331Samw 		if ((ret = smb_smf_get_boolean_property(handle, propname,
871*5331Samw 		    &valbool)) != 0)
872*5331Samw 			return (ret);
873*5331Samw 		(void) strlcpy(valstr, (valbool ? "true" : "false"), sz);
874*5331Samw 		break;
875*5331Samw 	default:
876*5331Samw 		return (SMBD_SMF_SYSTEM_ERR);
877*5331Samw 	}
878*5331Samw 	return (ret);
879*5331Samw }
880*5331Samw 
881*5331Samw /*
882*5331Samw  * Set property based on property type.
883*5331Samw  * Only SCF_TYPE_ASTRING, SCF_TYPE_INTEGER, SCF_TYPE_BOOLEAN supported.
884*5331Samw  */
885*5331Samw int
886*5331Samw smb_smf_set_property(smb_scfhandle_t *handle, int proptype,
887*5331Samw     char *propname, char *valstr)
888*5331Samw {
889*5331Samw 	int64_t valint = 0;
890*5331Samw 	uint8_t valbool = 0;
891*5331Samw 	int ret = SMBD_SMF_OK;
892*5331Samw 
893*5331Samw 	switch (proptype) {
894*5331Samw 	case SCF_TYPE_ASTRING:
895*5331Samw 		ret = smb_smf_set_string_property(handle, propname,
896*5331Samw 		    valstr);
897*5331Samw 		break;
898*5331Samw 	case SCF_TYPE_INTEGER:
899*5331Samw 		valint = strtol(valstr, 0, 10);
900*5331Samw 		ret = smb_smf_set_integer_property(handle, propname,
901*5331Samw 		    valint);
902*5331Samw 		break;
903*5331Samw 	case SCF_TYPE_BOOLEAN:
904*5331Samw 		if (strcasecmp(valstr, "true") == 0)
905*5331Samw 			valbool = 1;
906*5331Samw 		ret = smb_smf_set_boolean_property(handle, propname, valbool);
907*5331Samw 		break;
908*5331Samw 	default:
909*5331Samw 		return (SMBD_SMF_SYSTEM_ERR);
910*5331Samw 	}
911*5331Samw 	return (ret);
912*5331Samw }
913*5331Samw 
914*5331Samw /*
915*5331Samw  * Gets an instance iterator for the service specified.
916*5331Samw  */
917*5331Samw smb_scfhandle_t *
918*5331Samw smb_smf_get_iterator(char *svc_name)
919*5331Samw {
920*5331Samw 	smb_scfhandle_t *handle = NULL;
921*5331Samw 
922*5331Samw 	handle = smb_smf_scf_init(svc_name);
923*5331Samw 	if (!handle)
924*5331Samw 		return (NULL);
925*5331Samw 
926*5331Samw 	handle->scf_inst_iter = scf_iter_create(handle->scf_handle);
927*5331Samw 	if (handle->scf_inst_iter) {
928*5331Samw 		if (scf_iter_service_instances(handle->scf_inst_iter,
929*5331Samw 		    handle->scf_service) != 0) {
930*5331Samw 			smb_smf_scf_fini(handle);
931*5331Samw 			handle = NULL;
932*5331Samw 		} else {
933*5331Samw 			handle->scf_instance = NULL;
934*5331Samw 		}
935*5331Samw 	} else {
936*5331Samw 		smb_smf_scf_fini(handle);
937*5331Samw 		handle = NULL;
938*5331Samw 	}
939*5331Samw 	return (handle);
940*5331Samw }
941*5331Samw 
942*5331Samw /*
943*5331Samw  * smb_smf_scf_init()
944*5331Samw  *
945*5331Samw  * must be called before using any of the SCF functions.
946*5331Samw  * Returns smb_scfhandle_t pointer if success.
947*5331Samw  */
948*5331Samw smb_scfhandle_t *
949*5331Samw smb_smf_scf_init(char *svc_name)
950*5331Samw {
951*5331Samw 	smb_scfhandle_t *handle;
952*5331Samw 
953*5331Samw 	handle = malloc(sizeof (smb_scfhandle_t));
954*5331Samw 	if (handle != NULL) {
955*5331Samw 		bzero((char *)handle, sizeof (smb_scfhandle_t));
956*5331Samw 		handle->scf_state = SCH_STATE_INITIALIZING;
957*5331Samw 		handle->scf_handle = scf_handle_create(SCF_VERSION);
958*5331Samw 		if (handle->scf_handle != NULL) {
959*5331Samw 			if (scf_handle_bind(handle->scf_handle) == 0) {
960*5331Samw 				handle->scf_scope =
961*5331Samw 				    scf_scope_create(handle->scf_handle);
962*5331Samw 				if (scf_handle_get_local_scope(
963*5331Samw 				    handle->scf_handle, handle->scf_scope) != 0)
964*5331Samw 					goto err;
965*5331Samw 
966*5331Samw 				handle->scf_service =
967*5331Samw 				    scf_service_create(handle->scf_handle);
968*5331Samw 
969*5331Samw 				if (scf_scope_get_service(handle->scf_scope,
970*5331Samw 				    svc_name, handle->scf_service)
971*5331Samw 				    != SCF_SUCCESS) {
972*5331Samw 					goto err;
973*5331Samw 				}
974*5331Samw 				handle->scf_pg =
975*5331Samw 				    scf_pg_create(handle->scf_handle);
976*5331Samw 				handle->scf_state = SCH_STATE_INIT;
977*5331Samw 			} else {
978*5331Samw 				goto err;
979*5331Samw 			}
980*5331Samw 		} else {
981*5331Samw 			free(handle);
982*5331Samw 			handle = NULL;
983*5331Samw 			smb_smf_scf_log_error("Could not access SMF "
984*5331Samw 			    "repository: %s\n");
985*5331Samw 		}
986*5331Samw 	}
987*5331Samw 	return (handle);
988*5331Samw 
989*5331Samw 	/* error handling/unwinding */
990*5331Samw err:
991*5331Samw 	(void) smb_smf_scf_fini(handle);
992*5331Samw 	(void) smb_smf_scf_log_error("SMF initialization problem: %s\n");
993*5331Samw 	return (NULL);
994*5331Samw }
995*5331Samw 
996*5331Samw /*
997*5331Samw  * smb_smf_scf_fini(handle)
998*5331Samw  *
999*5331Samw  * must be called when done. Called with the handle allocated in
1000*5331Samw  * smb_smf_scf_init(), it cleans up the state and frees any SCF resources
1001*5331Samw  * still in use.
1002*5331Samw  */
1003*5331Samw void
1004*5331Samw smb_smf_scf_fini(smb_scfhandle_t *handle)
1005*5331Samw {
1006*5331Samw 	if (handle != NULL) {
1007*5331Samw 		int unbind = 0;
1008*5331Samw 		scf_iter_destroy(handle->scf_pg_iter);
1009*5331Samw 		handle->scf_pg_iter = NULL;
1010*5331Samw 
1011*5331Samw 		scf_iter_destroy(handle->scf_inst_iter);
1012*5331Samw 		handle->scf_inst_iter = NULL;
1013*5331Samw 
1014*5331Samw 		unbind = 1;
1015*5331Samw 		scf_scope_destroy(handle->scf_scope);
1016*5331Samw 		handle->scf_scope = NULL;
1017*5331Samw 
1018*5331Samw 		scf_instance_destroy(handle->scf_instance);
1019*5331Samw 		handle->scf_instance = NULL;
1020*5331Samw 
1021*5331Samw 		scf_service_destroy(handle->scf_service);
1022*5331Samw 		handle->scf_service = NULL;
1023*5331Samw 
1024*5331Samw 		scf_pg_destroy(handle->scf_pg);
1025*5331Samw 		handle->scf_pg = NULL;
1026*5331Samw 
1027*5331Samw 		handle->scf_state = SCH_STATE_UNINIT;
1028*5331Samw 		if (unbind)
1029*5331Samw 			(void) scf_handle_unbind(handle->scf_handle);
1030*5331Samw 		scf_handle_destroy(handle->scf_handle);
1031*5331Samw 		handle->scf_handle = NULL;
1032*5331Samw 
1033*5331Samw 		free(handle);
1034*5331Samw 	}
1035*5331Samw }
1036