xref: /onnv-gate/usr/src/lib/smbsrv/libsmb/common/smb_scfutil.c (revision 6030:6bebab7d43d5)
15331Samw /*
25331Samw  * CDDL HEADER START
35331Samw  *
45331Samw  * The contents of this file are subject to the terms of the
55331Samw  * Common Development and Distribution License (the "License").
65331Samw  * You may not use this file except in compliance with the License.
75331Samw  *
85331Samw  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95331Samw  * or http://www.opensolaris.org/os/licensing.
105331Samw  * See the License for the specific language governing permissions
115331Samw  * and limitations under the License.
125331Samw  *
135331Samw  * When distributing Covered Code, include this CDDL HEADER in each
145331Samw  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155331Samw  * If applicable, add the following below this CDDL HEADER, with the
165331Samw  * fields enclosed by brackets "[]" replaced with your own identifying
175331Samw  * information: Portions Copyright [yyyy] [name of copyright owner]
185331Samw  *
195331Samw  * CDDL HEADER END
205331Samw  */
215331Samw /*
225772Sas200622  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
235331Samw  * Use is subject to license terms.
245331Samw  */
255331Samw 
265331Samw #pragma ident	"%Z%%M%	%I%	%E% SMI"
275331Samw 
285331Samw /* helper functions for using libscf with CIFS */
295331Samw 
305331Samw #include <libscf.h>
315331Samw #include <string.h>
325331Samw #include <stdio.h>
335331Samw #include <stdlib.h>
345331Samw #include <syslog.h>
355331Samw #include <errno.h>
365331Samw #include <libintl.h>
375331Samw #include <assert.h>
385331Samw #include <strings.h>
395331Samw 
405331Samw #include <uuid/uuid.h>
415331Samw #include <sys/param.h>
425331Samw 
435331Samw #include <smbsrv/alloc.h>
445331Samw 
455331Samw #include <smbsrv/libsmb.h>
465331Samw 
475331Samw /*
485331Samw  * smb_smf_scf_log_error(msg)
495331Samw  * Logs error messages from scf API's
505331Samw  */
515331Samw static void
525331Samw smb_smf_scf_log_error(char *msg)
535331Samw {
545331Samw 	if (!msg) {
555331Samw 		syslog(LOG_ERR, " SMBD SMF problem: %s\n",
565331Samw 		    scf_strerror(scf_error()));
575331Samw 	} else { /*LINTED E_SEC_PRINTF_E_VAR_FMT*/
585331Samw 		syslog(LOG_ERR, msg, scf_strerror(scf_error()));
595331Samw 	}
605331Samw }
615331Samw 
625331Samw /*
635331Samw  * smb_smf_create_service_pgroup(handle, pgroup)
645331Samw  *
655331Samw  * create a new property group at service level.
665331Samw  */
675331Samw int
685331Samw smb_smf_create_service_pgroup(smb_scfhandle_t *handle, char *pgroup)
695331Samw {
705331Samw 	int ret = SMBD_SMF_OK;
715331Samw 	int err;
725331Samw 
73*6030Sjb150015 	if (handle == NULL)
745331Samw 		return (SMBD_SMF_SYSTEM_ERR);
755331Samw 
765331Samw 	/*
775331Samw 	 * only create a handle if it doesn't exist. It is ok to exist
785331Samw 	 * since the pg handle will be set as a side effect.
795331Samw 	 */
805331Samw 	if (handle->scf_pg == NULL)
81*6030Sjb150015 		if ((handle->scf_pg =
82*6030Sjb150015 		    scf_pg_create(handle->scf_handle)) == NULL)
83*6030Sjb150015 			return (SMBD_SMF_SYSTEM_ERR);
845331Samw 
855331Samw 	/*
865331Samw 	 * if the pgroup exists, we are done. If it doesn't, then we
875331Samw 	 * need to actually add one to the service instance.
885331Samw 	 */
895331Samw 	if (scf_service_get_pg(handle->scf_service,
905331Samw 	    pgroup, handle->scf_pg) != 0) {
915331Samw 		/* doesn't exist so create one */
925331Samw 		if (scf_service_add_pg(handle->scf_service, pgroup,
935331Samw 		    SCF_GROUP_APPLICATION, 0, handle->scf_pg) != 0) {
945331Samw 			err = scf_error();
955331Samw 			if (err != SCF_ERROR_NONE)
965331Samw 				smb_smf_scf_log_error(NULL);
975331Samw 			switch (err) {
985331Samw 			case SCF_ERROR_PERMISSION_DENIED:
995331Samw 				ret = SMBD_SMF_NO_PERMISSION;
1005331Samw 				break;
1015331Samw 			default:
1025331Samw 				ret = SMBD_SMF_SYSTEM_ERR;
1035331Samw 				break;
1045331Samw 			}
1055331Samw 		}
1065331Samw 	}
1075331Samw 	return (ret);
1085331Samw }
1095331Samw 
1105331Samw /*
1115331Samw  * Start transaction on current pg in handle.
1125331Samw  * The pg could be service or instance level.
1135331Samw  * Must be called after pg handle is obtained
1145331Samw  * from create or get.
1155331Samw  */
1165331Samw int
1175331Samw smb_smf_start_transaction(smb_scfhandle_t *handle)
1185331Samw {
1195331Samw 	int ret = SMBD_SMF_OK;
1205331Samw 
1215331Samw 	if (!handle || (!handle->scf_pg))
1225331Samw 		return (SMBD_SMF_SYSTEM_ERR);
1235331Samw 
1245331Samw 	/*
1255331Samw 	 * lookup the property group and create it if it doesn't already
1265331Samw 	 * exist.
1275331Samw 	 */
1285331Samw 	if (handle->scf_state == SCH_STATE_INIT) {
1295331Samw 		if (ret == SMBD_SMF_OK) {
1305331Samw 			handle->scf_trans =
1315331Samw 			    scf_transaction_create(handle->scf_handle);
1325331Samw 			if (handle->scf_trans != NULL) {
1335331Samw 				if (scf_transaction_start(handle->scf_trans,
1345331Samw 				    handle->scf_pg) != 0) {
1355331Samw 					ret = SMBD_SMF_SYSTEM_ERR;
1365331Samw 					scf_transaction_destroy(
1375331Samw 					    handle->scf_trans);
1385331Samw 					handle->scf_trans = NULL;
1395331Samw 				}
1405331Samw 			} else {
1415331Samw 				ret = SMBD_SMF_SYSTEM_ERR;
1425331Samw 			}
1435331Samw 		}
1445331Samw 	}
1455331Samw 	if (ret == SMBD_SMF_SYSTEM_ERR &&
1465331Samw 	    scf_error() == SCF_ERROR_PERMISSION_DENIED)
1475331Samw 		ret = SMBD_SMF_NO_PERMISSION;
1485331Samw 
1495331Samw 	return (ret);
1505331Samw }
1515331Samw 
1525331Samw /*
1535331Samw  * smb_smf_end_transaction(handle)
1545331Samw  *
1555331Samw  * Commit the changes that were added to the transaction in the
1565331Samw  * handle. Do all necessary cleanup.
1575331Samw  */
1585331Samw int
1595331Samw smb_smf_end_transaction(smb_scfhandle_t *handle)
1605331Samw {
1615331Samw 	int ret = SMBD_SMF_OK;
1625331Samw 
1635331Samw 	if (handle == NULL)
1645331Samw 		return (SMBD_SMF_SYSTEM_ERR);
1655331Samw 
1665331Samw 	if (handle->scf_trans == NULL) {
1675331Samw 		ret = SMBD_SMF_SYSTEM_ERR;
1685331Samw 	} else {
1695331Samw 		if (scf_transaction_commit(handle->scf_trans) < 0) {
1705331Samw 			ret = SMBD_SMF_SYSTEM_ERR;
1715331Samw 			smb_smf_scf_log_error("Failed to commit "
1725331Samw 			    "transaction: %s");
1735331Samw 		}
1745331Samw 		scf_transaction_destroy_children(handle->scf_trans);
1755331Samw 		scf_transaction_destroy(handle->scf_trans);
1765331Samw 		handle->scf_trans = NULL;
1775331Samw 	}
1785331Samw 	return (ret);
1795331Samw }
1805331Samw 
1815331Samw /*
1825331Samw  * Sets string property in current pg
1835331Samw  */
1845331Samw int
1855331Samw smb_smf_set_string_property(smb_scfhandle_t *handle,
1865331Samw     char *propname, char *valstr)
1875331Samw {
1885331Samw 	int ret = SMBD_SMF_OK;
1895331Samw 	scf_value_t *value = NULL;
1905331Samw 	scf_transaction_entry_t *entry = NULL;
1915331Samw 
1925331Samw 	if (handle == NULL)
1935331Samw 		return (SMBD_SMF_SYSTEM_ERR);
1945331Samw 
1955331Samw 	/*
1965331Samw 	 * properties must be set in transactions and don't take
1975331Samw 	 * effect until the transaction has been ended/committed.
1985331Samw 	 */
1995331Samw 	value = scf_value_create(handle->scf_handle);
2005331Samw 	entry = scf_entry_create(handle->scf_handle);
2015331Samw 	if (value != NULL && entry != NULL) {
2025331Samw 		if (scf_transaction_property_change(handle->scf_trans, entry,
2035331Samw 		    propname, SCF_TYPE_ASTRING) == 0 ||
2045331Samw 		    scf_transaction_property_new(handle->scf_trans, entry,
2055331Samw 		    propname, SCF_TYPE_ASTRING) == 0) {
2065331Samw 			if (scf_value_set_astring(value, valstr) == 0) {
2075331Samw 				if (scf_entry_add_value(entry, value) != 0) {
2085331Samw 					ret = SMBD_SMF_SYSTEM_ERR;
2095331Samw 					scf_value_destroy(value);
2105331Samw 				}
2115331Samw 				/* the value is in the transaction */
2125331Samw 				value = NULL;
2135331Samw 			} else {
2145331Samw 				/* value couldn't be constructed */
2155331Samw 				ret = SMBD_SMF_SYSTEM_ERR;
2165331Samw 			}
2175331Samw 			/* the entry is in the transaction */
2185331Samw 			entry = NULL;
2195331Samw 		} else {
2205331Samw 			ret = SMBD_SMF_SYSTEM_ERR;
2215331Samw 		}
2225331Samw 	} else {
2235331Samw 		ret = SMBD_SMF_SYSTEM_ERR;
2245331Samw 	}
2255331Samw 	if (ret == SMBD_SMF_SYSTEM_ERR) {
2265331Samw 		switch (scf_error()) {
2275331Samw 		case SCF_ERROR_PERMISSION_DENIED:
2285331Samw 			ret = SMBD_SMF_NO_PERMISSION;
2295331Samw 			break;
2305331Samw 		}
2315331Samw 	}
2325331Samw 
2335331Samw 	/*
2345331Samw 	 * cleanup if there were any errors that didn't leave these
2355331Samw 	 * values where they would be cleaned up later.
2365331Samw 	 */
2375331Samw 	if (value != NULL)
2385331Samw 		scf_value_destroy(value);
2395331Samw 	if (entry != NULL)
2405331Samw 		scf_entry_destroy(entry);
2415331Samw 	return (ret);
2425331Samw }
2435331Samw 
2445331Samw /*
2455331Samw  * Gets string property value.upto sz size.
2465331Samw  * Caller is responsible to have enough memory allocated.
2475331Samw  */
2485331Samw int
2495331Samw smb_smf_get_string_property(smb_scfhandle_t *handle, char *propname,
2505331Samw     char *valstr, size_t sz)
2515331Samw {
2525331Samw 	int ret = SMBD_SMF_OK;
2535331Samw 	scf_value_t *value;
2545331Samw 	scf_property_t *prop;
2555331Samw 
2565331Samw 	if (handle == NULL)
2575331Samw 		return (SMBD_SMF_SYSTEM_ERR);
2585331Samw 
2595331Samw 	value = scf_value_create(handle->scf_handle);
2605331Samw 	prop = scf_property_create(handle->scf_handle);
2615331Samw 	if (value && prop &&
2625331Samw 	    (scf_pg_get_property(handle->scf_pg, propname, prop) == 0)) {
2635331Samw 		if (scf_property_get_value(prop, value) == 0) {
2645331Samw 			if (scf_value_get_astring(value, valstr, sz) < 0) {
2655331Samw 				ret = SMBD_SMF_SYSTEM_ERR;
2665331Samw 			}
2675331Samw 		} else {
2685331Samw 			ret = SMBD_SMF_SYSTEM_ERR;
2695331Samw 		}
2705331Samw 	} else {
2715331Samw 		ret = SMBD_SMF_SYSTEM_ERR;
2725331Samw 	}
2735331Samw 	if (value != NULL)
2745331Samw 		scf_value_destroy(value);
2755331Samw 	if (prop != NULL)
2765331Samw 		scf_property_destroy(prop);
2775331Samw 	return (ret);
2785331Samw }
2795331Samw 
2805331Samw /*
2815331Samw  * Set integer value of property.
2825331Samw  * The value is returned as int64_t value
2835331Samw  * Caller ensures appropriate translation.
2845331Samw  */
2855331Samw int
2865331Samw smb_smf_set_integer_property(smb_scfhandle_t *handle, char *propname,
2875331Samw     int64_t valint)
2885331Samw {
2895331Samw 	int ret = SMBD_SMF_OK;
2905331Samw 	scf_value_t *value = NULL;
2915331Samw 	scf_transaction_entry_t *entry = NULL;
2925331Samw 
2935331Samw 	if (handle == NULL)
2945331Samw 		return (SMBD_SMF_SYSTEM_ERR);
2955331Samw 
2965331Samw 	/*
2975331Samw 	 * properties must be set in transactions and don't take
2985331Samw 	 * effect until the transaction has been ended/committed.
2995331Samw 	 */
3005331Samw 	value = scf_value_create(handle->scf_handle);
3015331Samw 	entry = scf_entry_create(handle->scf_handle);
3025331Samw 	if (value != NULL && entry != NULL) {
3035331Samw 		if (scf_transaction_property_change(handle->scf_trans, entry,
3045331Samw 		    propname, SCF_TYPE_INTEGER) == 0 ||
3055331Samw 		    scf_transaction_property_new(handle->scf_trans, entry,
3065331Samw 		    propname, SCF_TYPE_INTEGER) == 0) {
3075331Samw 			scf_value_set_integer(value, valint);
3085331Samw 			if (scf_entry_add_value(entry, value) != 0) {
3095331Samw 				ret = SMBD_SMF_SYSTEM_ERR;
3105331Samw 				scf_value_destroy(value);
3115331Samw 			}
3125331Samw 			/* the value is in the transaction */
3135331Samw 			value = NULL;
3145331Samw 		}
3155331Samw 		/* the entry is in the transaction */
3165331Samw 		entry = NULL;
3175331Samw 	} else {
3185331Samw 		ret = SMBD_SMF_SYSTEM_ERR;
3195331Samw 	}
3205331Samw 	if (ret == SMBD_SMF_SYSTEM_ERR) {
3215331Samw 		switch (scf_error()) {
3225331Samw 		case SCF_ERROR_PERMISSION_DENIED:
3235331Samw 			ret = SMBD_SMF_NO_PERMISSION;
3245331Samw 			break;
3255331Samw 		}
3265331Samw 	}
3275331Samw 	/*
3285331Samw 	 * cleanup if there were any errors that didn't leave these
3295331Samw 	 * values where they would be cleaned up later.
3305331Samw 	 */
3315331Samw 	if (value != NULL)
3325331Samw 		scf_value_destroy(value);
3335331Samw 	if (entry != NULL)
3345331Samw 		scf_entry_destroy(entry);
3355331Samw 	return (ret);
3365331Samw }
3375331Samw 
3385331Samw /*
3395331Samw  * Gets integer property value.
3405331Samw  * Caller is responsible to have enough memory allocated.
3415331Samw  */
3425331Samw int
3435331Samw smb_smf_get_integer_property(smb_scfhandle_t *handle, char *propname,
3445331Samw     int64_t *valint)
3455331Samw {
3465331Samw 	int ret = SMBD_SMF_OK;
3475331Samw 	scf_value_t *value = NULL;
3485331Samw 	scf_property_t *prop = NULL;
3495331Samw 
3505331Samw 	if (handle == NULL)
3515331Samw 		return (SMBD_SMF_SYSTEM_ERR);
3525331Samw 
3535331Samw 	value = scf_value_create(handle->scf_handle);
3545331Samw 	prop = scf_property_create(handle->scf_handle);
3555331Samw 	if ((prop) && (value) &&
3565331Samw 	    (scf_pg_get_property(handle->scf_pg, propname, prop) == 0)) {
3575331Samw 		if (scf_property_get_value(prop, value) == 0) {
3585331Samw 			if (scf_value_get_integer(value,
3595331Samw 			    valint) != 0) {
3605331Samw 				ret = SMBD_SMF_SYSTEM_ERR;
3615331Samw 			}
3625331Samw 		} else {
3635331Samw 			ret = SMBD_SMF_SYSTEM_ERR;
3645331Samw 		}
3655331Samw 	} else {
3665331Samw 		ret = SMBD_SMF_SYSTEM_ERR;
3675331Samw 	}
3685331Samw 	if (value != NULL)
3695331Samw 		scf_value_destroy(value);
3705331Samw 	if (prop != NULL)
3715331Samw 		scf_property_destroy(prop);
3725331Samw 	return (ret);
3735331Samw }
3745331Samw 
3755331Samw /*
3765331Samw  * Set boolean value of property.
3775331Samw  * The value is returned as int64_t value
3785331Samw  * Caller ensures appropriate translation.
3795331Samw  */
3805331Samw int
3815331Samw smb_smf_set_boolean_property(smb_scfhandle_t *handle, char *propname,
3825331Samw     uint8_t valbool)
3835331Samw {
3845331Samw 	int ret = SMBD_SMF_OK;
3855331Samw 	scf_value_t *value = NULL;
3865331Samw 	scf_transaction_entry_t *entry = NULL;
3875331Samw 
3885331Samw 	if (handle == NULL)
3895331Samw 		return (SMBD_SMF_SYSTEM_ERR);
3905331Samw 
3915331Samw 	/*
3925331Samw 	 * properties must be set in transactions and don't take
3935331Samw 	 * effect until the transaction has been ended/committed.
3945331Samw 	 */
3955331Samw 	value = scf_value_create(handle->scf_handle);
3965331Samw 	entry = scf_entry_create(handle->scf_handle);
3975331Samw 	if (value != NULL && entry != NULL) {
3985331Samw 		if (scf_transaction_property_change(handle->scf_trans, entry,
3995331Samw 		    propname, SCF_TYPE_BOOLEAN) == 0 ||
4005331Samw 		    scf_transaction_property_new(handle->scf_trans, entry,
4015331Samw 		    propname, SCF_TYPE_BOOLEAN) == 0) {
4025331Samw 			scf_value_set_boolean(value, valbool);
4035331Samw 			if (scf_entry_add_value(entry, value) != 0) {
4045331Samw 				ret = SMBD_SMF_SYSTEM_ERR;
4055331Samw 				scf_value_destroy(value);
4065331Samw 			}
4075331Samw 			/* the value is in the transaction */
4085331Samw 			value = NULL;
4095331Samw 		}
4105331Samw 		/* the entry is in the transaction */
4115331Samw 		entry = NULL;
4125331Samw 	} else {
4135331Samw 		ret = SMBD_SMF_SYSTEM_ERR;
4145331Samw 	}
4155331Samw 	if (ret == SMBD_SMF_SYSTEM_ERR) {
4165331Samw 		switch (scf_error()) {
4175331Samw 		case SCF_ERROR_PERMISSION_DENIED:
4185331Samw 			ret = SMBD_SMF_NO_PERMISSION;
4195331Samw 			break;
4205331Samw 		}
4215331Samw 	}
4225331Samw 	/*
4235331Samw 	 * cleanup if there were any errors that didn't leave these
4245331Samw 	 * values where they would be cleaned up later.
4255331Samw 	 */
4265331Samw 	if (value != NULL)
4275331Samw 		scf_value_destroy(value);
4285331Samw 	if (entry != NULL)
4295331Samw 		scf_entry_destroy(entry);
4305331Samw 	return (ret);
4315331Samw }
4325331Samw 
4335331Samw /*
4345331Samw  * Gets boolean property value.
4355331Samw  * Caller is responsible to have enough memory allocated.
4365331Samw  */
4375331Samw int
4385331Samw smb_smf_get_boolean_property(smb_scfhandle_t *handle, char *propname,
4395331Samw     uint8_t *valbool)
4405331Samw {
4415331Samw 	int ret = SMBD_SMF_OK;
4425331Samw 	scf_value_t *value = NULL;
4435331Samw 	scf_property_t *prop = NULL;
4445331Samw 
4455331Samw 	if (handle == NULL)
4465331Samw 		return (SMBD_SMF_SYSTEM_ERR);
4475331Samw 
4485331Samw 	value = scf_value_create(handle->scf_handle);
4495331Samw 	prop = scf_property_create(handle->scf_handle);
4505331Samw 	if ((prop) && (value) &&
4515331Samw 	    (scf_pg_get_property(handle->scf_pg, propname, prop) == 0)) {
4525331Samw 		if (scf_property_get_value(prop, value) == 0) {
4535331Samw 			if (scf_value_get_boolean(value,
4545331Samw 			    valbool) != 0) {
4555331Samw 				ret = SMBD_SMF_SYSTEM_ERR;
4565331Samw 			}
4575331Samw 		} else {
4585331Samw 			ret = SMBD_SMF_SYSTEM_ERR;
4595331Samw 		}
4605331Samw 	} else {
4615331Samw 		ret = SMBD_SMF_SYSTEM_ERR;
4625331Samw 	}
4635331Samw 	if (value != NULL)
4645331Samw 		scf_value_destroy(value);
4655331Samw 	if (prop != NULL)
4665331Samw 		scf_property_destroy(prop);
4675331Samw 	return (ret);
4685331Samw }
4695331Samw 
4705331Samw /*
4715331Samw  * Sets a blob property value.
4725331Samw  */
4735331Samw int
4745331Samw smb_smf_set_opaque_property(smb_scfhandle_t *handle, char *propname,
4755331Samw     void *voidval, size_t sz)
4765331Samw {
4775331Samw 	int ret = SMBD_SMF_OK;
4785331Samw 	scf_value_t *value;
4795331Samw 	scf_transaction_entry_t *entry;
4805331Samw 
4815331Samw 	if (handle == NULL)
4825331Samw 		return (SMBD_SMF_SYSTEM_ERR);
4835331Samw 
4845331Samw 	/*
4855331Samw 	 * properties must be set in transactions and don't take
4865331Samw 	 * effect until the transaction has been ended/committed.
4875331Samw 	 */
4885331Samw 	value = scf_value_create(handle->scf_handle);
4895331Samw 	entry = scf_entry_create(handle->scf_handle);
4905331Samw 	if (value != NULL && entry != NULL) {
4915331Samw 		if (scf_transaction_property_change(handle->scf_trans, entry,
4925331Samw 		    propname, SCF_TYPE_OPAQUE) == 0 ||
4935331Samw 		    scf_transaction_property_new(handle->scf_trans, entry,
4945331Samw 		    propname, SCF_TYPE_OPAQUE) == 0) {
4955331Samw 			if (scf_value_set_opaque(value, voidval, sz) == 0) {
4965331Samw 				if (scf_entry_add_value(entry, value) != 0) {
4975331Samw 					ret = SMBD_SMF_SYSTEM_ERR;
4985331Samw 					scf_value_destroy(value);
4995331Samw 				}
5005331Samw 				/* the value is in the transaction */
5015331Samw 				value = NULL;
5025331Samw 			} else {
5035331Samw 				/* value couldn't be constructed */
5045331Samw 				ret = SMBD_SMF_SYSTEM_ERR;
5055331Samw 			}
5065331Samw 			/* the entry is in the transaction */
5075331Samw 			entry = NULL;
5085331Samw 		} else {
5095331Samw 			ret = SMBD_SMF_SYSTEM_ERR;
5105331Samw 		}
5115331Samw 	} else {
5125331Samw 		ret = SMBD_SMF_SYSTEM_ERR;
5135331Samw 	}
5145331Samw 	if (ret == SMBD_SMF_SYSTEM_ERR) {
5155331Samw 		switch (scf_error()) {
5165331Samw 		case SCF_ERROR_PERMISSION_DENIED:
5175331Samw 			ret = SMBD_SMF_NO_PERMISSION;
5185331Samw 			break;
5195331Samw 		}
5205331Samw 	}
5215331Samw 	/*
5225331Samw 	 * cleanup if there were any errors that didn't leave these
5235331Samw 	 * values where they would be cleaned up later.
5245331Samw 	 */
5255331Samw 	if (value != NULL)
5265331Samw 		scf_value_destroy(value);
5275331Samw 	if (entry != NULL)
5285331Samw 		scf_entry_destroy(entry);
5295331Samw 	return (ret);
5305331Samw }
5315331Samw 
5325331Samw /*
5335331Samw  * Gets a blob property value.
5345331Samw  * Caller is responsible to have enough memory allocated.
5355331Samw  */
5365331Samw int
5375331Samw smb_smf_get_opaque_property(smb_scfhandle_t *handle, char *propname,
5385331Samw     void *v, size_t sz)
5395331Samw {
5405331Samw 	int ret = SMBD_SMF_OK;
5415331Samw 	scf_value_t *value = NULL;
5425331Samw 	scf_property_t *prop = NULL;
5435331Samw 
5445331Samw 	if (handle == NULL)
5455331Samw 		return (SMBD_SMF_SYSTEM_ERR);
5465331Samw 
5475331Samw 	value = scf_value_create(handle->scf_handle);
5485331Samw 	prop = scf_property_create(handle->scf_handle);
5495331Samw 	if ((prop) && (value) &&
5505331Samw 	    (scf_pg_get_property(handle->scf_pg, propname, prop) == 0)) {
5515331Samw 		if (scf_property_get_value(prop, value) == 0) {
5525331Samw 			if (scf_value_get_opaque(value, (char *)v, sz) != sz) {
5535331Samw 				ret = SMBD_SMF_SYSTEM_ERR;
5545331Samw 			}
5555331Samw 		} else {
5565331Samw 			ret = SMBD_SMF_SYSTEM_ERR;
5575331Samw 		}
5585331Samw 	} else {
5595331Samw 		ret = SMBD_SMF_SYSTEM_ERR;
5605331Samw 	}
5615331Samw 	if (value != NULL)
5625331Samw 		scf_value_destroy(value);
5635331Samw 	if (prop != NULL)
5645331Samw 		scf_property_destroy(prop);
5655331Samw 	return (ret);
5665331Samw }
5675331Samw 
5685331Samw /*
5695331Samw  * smb_smf_scf_init()
5705331Samw  *
5715331Samw  * must be called before using any of the SCF functions.
5725331Samw  * Returns smb_scfhandle_t pointer if success.
5735331Samw  */
5745331Samw smb_scfhandle_t *
5755331Samw smb_smf_scf_init(char *svc_name)
5765331Samw {
5775331Samw 	smb_scfhandle_t *handle;
5785331Samw 
5795331Samw 	handle = malloc(sizeof (smb_scfhandle_t));
5805331Samw 	if (handle != NULL) {
5815331Samw 		bzero((char *)handle, sizeof (smb_scfhandle_t));
5825331Samw 		handle->scf_state = SCH_STATE_INITIALIZING;
5835331Samw 		handle->scf_handle = scf_handle_create(SCF_VERSION);
5845331Samw 		if (handle->scf_handle != NULL) {
5855331Samw 			if (scf_handle_bind(handle->scf_handle) == 0) {
5865331Samw 				handle->scf_scope =
5875331Samw 				    scf_scope_create(handle->scf_handle);
588*6030Sjb150015 
589*6030Sjb150015 				if (handle->scf_scope == NULL)
590*6030Sjb150015 					goto err;
591*6030Sjb150015 
5925331Samw 				if (scf_handle_get_local_scope(
5935331Samw 				    handle->scf_handle, handle->scf_scope) != 0)
5945331Samw 					goto err;
5955331Samw 
5965331Samw 				handle->scf_service =
5975331Samw 				    scf_service_create(handle->scf_handle);
5985331Samw 
599*6030Sjb150015 				if (handle->scf_service == NULL)
600*6030Sjb150015 					goto err;
601*6030Sjb150015 
6025331Samw 				if (scf_scope_get_service(handle->scf_scope,
6035331Samw 				    svc_name, handle->scf_service)
6045331Samw 				    != SCF_SUCCESS) {
6055331Samw 					goto err;
6065331Samw 				}
6075331Samw 				handle->scf_pg =
6085331Samw 				    scf_pg_create(handle->scf_handle);
609*6030Sjb150015 
610*6030Sjb150015 				if (handle->scf_pg == NULL)
611*6030Sjb150015 					goto err;
612*6030Sjb150015 
6135331Samw 				handle->scf_state = SCH_STATE_INIT;
6145331Samw 			} else {
6155331Samw 				goto err;
6165331Samw 			}
6175331Samw 		} else {
6185331Samw 			free(handle);
6195331Samw 			handle = NULL;
6205331Samw 			smb_smf_scf_log_error("Could not access SMF "
6215331Samw 			    "repository: %s\n");
6225331Samw 		}
6235331Samw 	}
6245331Samw 	return (handle);
6255331Samw 
6265331Samw 	/* error handling/unwinding */
6275331Samw err:
6285331Samw 	(void) smb_smf_scf_fini(handle);
6295331Samw 	(void) smb_smf_scf_log_error("SMF initialization problem: %s\n");
6305331Samw 	return (NULL);
6315331Samw }
6325331Samw 
6335331Samw /*
6345331Samw  * smb_smf_scf_fini(handle)
6355331Samw  *
6365331Samw  * must be called when done. Called with the handle allocated in
6375331Samw  * smb_smf_scf_init(), it cleans up the state and frees any SCF resources
6385331Samw  * still in use.
6395331Samw  */
6405331Samw void
6415331Samw smb_smf_scf_fini(smb_scfhandle_t *handle)
6425331Samw {
6435331Samw 	if (handle != NULL) {
6445331Samw 		int unbind = 0;
6455331Samw 		scf_iter_destroy(handle->scf_pg_iter);
6465331Samw 		handle->scf_pg_iter = NULL;
6475331Samw 
6485331Samw 		scf_iter_destroy(handle->scf_inst_iter);
6495331Samw 		handle->scf_inst_iter = NULL;
6505331Samw 
6515331Samw 		unbind = 1;
6525331Samw 		scf_scope_destroy(handle->scf_scope);
6535331Samw 		handle->scf_scope = NULL;
6545331Samw 
6555331Samw 		scf_instance_destroy(handle->scf_instance);
6565331Samw 		handle->scf_instance = NULL;
6575331Samw 
6585331Samw 		scf_service_destroy(handle->scf_service);
6595331Samw 		handle->scf_service = NULL;
6605331Samw 
6615331Samw 		scf_pg_destroy(handle->scf_pg);
6625331Samw 		handle->scf_pg = NULL;
6635331Samw 
6645331Samw 		handle->scf_state = SCH_STATE_UNINIT;
6655331Samw 		if (unbind)
6665331Samw 			(void) scf_handle_unbind(handle->scf_handle);
6675331Samw 		scf_handle_destroy(handle->scf_handle);
6685331Samw 		handle->scf_handle = NULL;
6695331Samw 
6705331Samw 		free(handle);
6715331Samw 	}
6725331Samw }
673