xref: /onnv-gate/usr/src/lib/smbsrv/libsmb/common/smb_scfutil.c (revision 5772:237ac22142fe)
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 /*
22*5772Sas200622  * 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 
735331Samw 	if (handle == NULL) {
745331Samw 		return (SMBD_SMF_SYSTEM_ERR);
755331Samw 	}
765331Samw 
775331Samw 	/*
785331Samw 	 * only create a handle if it doesn't exist. It is ok to exist
795331Samw 	 * since the pg handle will be set as a side effect.
805331Samw 	 */
815331Samw 	if (handle->scf_pg == NULL)
825331Samw 		handle->scf_pg = scf_pg_create(handle->scf_handle);
835331Samw 
845331Samw 	/*
855331Samw 	 * if the pgroup exists, we are done. If it doesn't, then we
865331Samw 	 * need to actually add one to the service instance.
875331Samw 	 */
885331Samw 	if (scf_service_get_pg(handle->scf_service,
895331Samw 	    pgroup, handle->scf_pg) != 0) {
905331Samw 		/* doesn't exist so create one */
915331Samw 		if (scf_service_add_pg(handle->scf_service, pgroup,
925331Samw 		    SCF_GROUP_APPLICATION, 0, handle->scf_pg) != 0) {
935331Samw 			err = scf_error();
945331Samw 			if (err != SCF_ERROR_NONE)
955331Samw 				smb_smf_scf_log_error(NULL);
965331Samw 			switch (err) {
975331Samw 			case SCF_ERROR_PERMISSION_DENIED:
985331Samw 				ret = SMBD_SMF_NO_PERMISSION;
995331Samw 				break;
1005331Samw 			default:
1015331Samw 				ret = SMBD_SMF_SYSTEM_ERR;
1025331Samw 				break;
1035331Samw 			}
1045331Samw 		}
1055331Samw 	}
1065331Samw 	return (ret);
1075331Samw }
1085331Samw 
1095331Samw /*
1105331Samw  * Start transaction on current pg in handle.
1115331Samw  * The pg could be service or instance level.
1125331Samw  * Must be called after pg handle is obtained
1135331Samw  * from create or get.
1145331Samw  */
1155331Samw int
1165331Samw smb_smf_start_transaction(smb_scfhandle_t *handle)
1175331Samw {
1185331Samw 	int ret = SMBD_SMF_OK;
1195331Samw 
1205331Samw 	if (!handle || (!handle->scf_pg))
1215331Samw 		return (SMBD_SMF_SYSTEM_ERR);
1225331Samw 
1235331Samw 	/*
1245331Samw 	 * lookup the property group and create it if it doesn't already
1255331Samw 	 * exist.
1265331Samw 	 */
1275331Samw 	if (handle->scf_state == SCH_STATE_INIT) {
1285331Samw 		if (ret == SMBD_SMF_OK) {
1295331Samw 			handle->scf_trans =
1305331Samw 			    scf_transaction_create(handle->scf_handle);
1315331Samw 			if (handle->scf_trans != NULL) {
1325331Samw 				if (scf_transaction_start(handle->scf_trans,
1335331Samw 				    handle->scf_pg) != 0) {
1345331Samw 					ret = SMBD_SMF_SYSTEM_ERR;
1355331Samw 					scf_transaction_destroy(
1365331Samw 					    handle->scf_trans);
1375331Samw 					handle->scf_trans = NULL;
1385331Samw 				}
1395331Samw 			} else {
1405331Samw 				ret = SMBD_SMF_SYSTEM_ERR;
1415331Samw 			}
1425331Samw 		}
1435331Samw 	}
1445331Samw 	if (ret == SMBD_SMF_SYSTEM_ERR &&
1455331Samw 	    scf_error() == SCF_ERROR_PERMISSION_DENIED)
1465331Samw 		ret = SMBD_SMF_NO_PERMISSION;
1475331Samw 
1485331Samw 	return (ret);
1495331Samw }
1505331Samw 
1515331Samw /*
1525331Samw  * smb_smf_end_transaction(handle)
1535331Samw  *
1545331Samw  * Commit the changes that were added to the transaction in the
1555331Samw  * handle. Do all necessary cleanup.
1565331Samw  */
1575331Samw int
1585331Samw smb_smf_end_transaction(smb_scfhandle_t *handle)
1595331Samw {
1605331Samw 	int ret = SMBD_SMF_OK;
1615331Samw 
1625331Samw 	if (handle == NULL)
1635331Samw 		return (SMBD_SMF_SYSTEM_ERR);
1645331Samw 
1655331Samw 	if (handle->scf_trans == NULL) {
1665331Samw 		ret = SMBD_SMF_SYSTEM_ERR;
1675331Samw 	} else {
1685331Samw 		if (scf_transaction_commit(handle->scf_trans) < 0) {
1695331Samw 			ret = SMBD_SMF_SYSTEM_ERR;
1705331Samw 			smb_smf_scf_log_error("Failed to commit "
1715331Samw 			    "transaction: %s");
1725331Samw 		}
1735331Samw 		scf_transaction_destroy_children(handle->scf_trans);
1745331Samw 		scf_transaction_destroy(handle->scf_trans);
1755331Samw 		handle->scf_trans = NULL;
1765331Samw 	}
1775331Samw 	return (ret);
1785331Samw }
1795331Samw 
1805331Samw /*
1815331Samw  * Sets string property in current pg
1825331Samw  */
1835331Samw int
1845331Samw smb_smf_set_string_property(smb_scfhandle_t *handle,
1855331Samw     char *propname, char *valstr)
1865331Samw {
1875331Samw 	int ret = SMBD_SMF_OK;
1885331Samw 	scf_value_t *value = NULL;
1895331Samw 	scf_transaction_entry_t *entry = NULL;
1905331Samw 
1915331Samw 	if (handle == NULL)
1925331Samw 		return (SMBD_SMF_SYSTEM_ERR);
1935331Samw 
1945331Samw 	/*
1955331Samw 	 * properties must be set in transactions and don't take
1965331Samw 	 * effect until the transaction has been ended/committed.
1975331Samw 	 */
1985331Samw 	value = scf_value_create(handle->scf_handle);
1995331Samw 	entry = scf_entry_create(handle->scf_handle);
2005331Samw 	if (value != NULL && entry != NULL) {
2015331Samw 		if (scf_transaction_property_change(handle->scf_trans, entry,
2025331Samw 		    propname, SCF_TYPE_ASTRING) == 0 ||
2035331Samw 		    scf_transaction_property_new(handle->scf_trans, entry,
2045331Samw 		    propname, SCF_TYPE_ASTRING) == 0) {
2055331Samw 			if (scf_value_set_astring(value, valstr) == 0) {
2065331Samw 				if (scf_entry_add_value(entry, value) != 0) {
2075331Samw 					ret = SMBD_SMF_SYSTEM_ERR;
2085331Samw 					scf_value_destroy(value);
2095331Samw 				}
2105331Samw 				/* the value is in the transaction */
2115331Samw 				value = NULL;
2125331Samw 			} else {
2135331Samw 				/* value couldn't be constructed */
2145331Samw 				ret = SMBD_SMF_SYSTEM_ERR;
2155331Samw 			}
2165331Samw 			/* the entry is in the transaction */
2175331Samw 			entry = NULL;
2185331Samw 		} else {
2195331Samw 			ret = SMBD_SMF_SYSTEM_ERR;
2205331Samw 		}
2215331Samw 	} else {
2225331Samw 		ret = SMBD_SMF_SYSTEM_ERR;
2235331Samw 	}
2245331Samw 	if (ret == SMBD_SMF_SYSTEM_ERR) {
2255331Samw 		switch (scf_error()) {
2265331Samw 		case SCF_ERROR_PERMISSION_DENIED:
2275331Samw 			ret = SMBD_SMF_NO_PERMISSION;
2285331Samw 			break;
2295331Samw 		}
2305331Samw 	}
2315331Samw 
2325331Samw 	/*
2335331Samw 	 * cleanup if there were any errors that didn't leave these
2345331Samw 	 * values where they would be cleaned up later.
2355331Samw 	 */
2365331Samw 	if (value != NULL)
2375331Samw 		scf_value_destroy(value);
2385331Samw 	if (entry != NULL)
2395331Samw 		scf_entry_destroy(entry);
2405331Samw 	return (ret);
2415331Samw }
2425331Samw 
2435331Samw /*
2445331Samw  * Gets string property value.upto sz size.
2455331Samw  * Caller is responsible to have enough memory allocated.
2465331Samw  */
2475331Samw int
2485331Samw smb_smf_get_string_property(smb_scfhandle_t *handle, char *propname,
2495331Samw     char *valstr, size_t sz)
2505331Samw {
2515331Samw 	int ret = SMBD_SMF_OK;
2525331Samw 	scf_value_t *value;
2535331Samw 	scf_property_t *prop;
2545331Samw 
2555331Samw 	if (handle == NULL)
2565331Samw 		return (SMBD_SMF_SYSTEM_ERR);
2575331Samw 
2585331Samw 	value = scf_value_create(handle->scf_handle);
2595331Samw 	prop = scf_property_create(handle->scf_handle);
2605331Samw 	if (value && prop &&
2615331Samw 	    (scf_pg_get_property(handle->scf_pg, propname, prop) == 0)) {
2625331Samw 		if (scf_property_get_value(prop, value) == 0) {
2635331Samw 			if (scf_value_get_astring(value, valstr, sz) < 0) {
2645331Samw 				ret = SMBD_SMF_SYSTEM_ERR;
2655331Samw 			}
2665331Samw 		} else {
2675331Samw 			ret = SMBD_SMF_SYSTEM_ERR;
2685331Samw 		}
2695331Samw 	} else {
2705331Samw 		ret = SMBD_SMF_SYSTEM_ERR;
2715331Samw 	}
2725331Samw 	if (value != NULL)
2735331Samw 		scf_value_destroy(value);
2745331Samw 	if (prop != NULL)
2755331Samw 		scf_property_destroy(prop);
2765331Samw 	return (ret);
2775331Samw }
2785331Samw 
2795331Samw /*
2805331Samw  * Set integer value of property.
2815331Samw  * The value is returned as int64_t value
2825331Samw  * Caller ensures appropriate translation.
2835331Samw  */
2845331Samw int
2855331Samw smb_smf_set_integer_property(smb_scfhandle_t *handle, char *propname,
2865331Samw     int64_t valint)
2875331Samw {
2885331Samw 	int ret = SMBD_SMF_OK;
2895331Samw 	scf_value_t *value = NULL;
2905331Samw 	scf_transaction_entry_t *entry = NULL;
2915331Samw 
2925331Samw 	if (handle == NULL)
2935331Samw 		return (SMBD_SMF_SYSTEM_ERR);
2945331Samw 
2955331Samw 	/*
2965331Samw 	 * properties must be set in transactions and don't take
2975331Samw 	 * effect until the transaction has been ended/committed.
2985331Samw 	 */
2995331Samw 	value = scf_value_create(handle->scf_handle);
3005331Samw 	entry = scf_entry_create(handle->scf_handle);
3015331Samw 	if (value != NULL && entry != NULL) {
3025331Samw 		if (scf_transaction_property_change(handle->scf_trans, entry,
3035331Samw 		    propname, SCF_TYPE_INTEGER) == 0 ||
3045331Samw 		    scf_transaction_property_new(handle->scf_trans, entry,
3055331Samw 		    propname, SCF_TYPE_INTEGER) == 0) {
3065331Samw 			scf_value_set_integer(value, valint);
3075331Samw 			if (scf_entry_add_value(entry, value) != 0) {
3085331Samw 				ret = SMBD_SMF_SYSTEM_ERR;
3095331Samw 				scf_value_destroy(value);
3105331Samw 			}
3115331Samw 			/* the value is in the transaction */
3125331Samw 			value = NULL;
3135331Samw 		}
3145331Samw 		/* the entry is in the transaction */
3155331Samw 		entry = NULL;
3165331Samw 	} else {
3175331Samw 		ret = SMBD_SMF_SYSTEM_ERR;
3185331Samw 	}
3195331Samw 	if (ret == SMBD_SMF_SYSTEM_ERR) {
3205331Samw 		switch (scf_error()) {
3215331Samw 		case SCF_ERROR_PERMISSION_DENIED:
3225331Samw 			ret = SMBD_SMF_NO_PERMISSION;
3235331Samw 			break;
3245331Samw 		}
3255331Samw 	}
3265331Samw 	/*
3275331Samw 	 * cleanup if there were any errors that didn't leave these
3285331Samw 	 * values where they would be cleaned up later.
3295331Samw 	 */
3305331Samw 	if (value != NULL)
3315331Samw 		scf_value_destroy(value);
3325331Samw 	if (entry != NULL)
3335331Samw 		scf_entry_destroy(entry);
3345331Samw 	return (ret);
3355331Samw }
3365331Samw 
3375331Samw /*
3385331Samw  * Gets integer property value.
3395331Samw  * Caller is responsible to have enough memory allocated.
3405331Samw  */
3415331Samw int
3425331Samw smb_smf_get_integer_property(smb_scfhandle_t *handle, char *propname,
3435331Samw     int64_t *valint)
3445331Samw {
3455331Samw 	int ret = SMBD_SMF_OK;
3465331Samw 	scf_value_t *value = NULL;
3475331Samw 	scf_property_t *prop = NULL;
3485331Samw 
3495331Samw 	if (handle == NULL)
3505331Samw 		return (SMBD_SMF_SYSTEM_ERR);
3515331Samw 
3525331Samw 	value = scf_value_create(handle->scf_handle);
3535331Samw 	prop = scf_property_create(handle->scf_handle);
3545331Samw 	if ((prop) && (value) &&
3555331Samw 	    (scf_pg_get_property(handle->scf_pg, propname, prop) == 0)) {
3565331Samw 		if (scf_property_get_value(prop, value) == 0) {
3575331Samw 			if (scf_value_get_integer(value,
3585331Samw 			    valint) != 0) {
3595331Samw 				ret = SMBD_SMF_SYSTEM_ERR;
3605331Samw 			}
3615331Samw 		} else {
3625331Samw 			ret = SMBD_SMF_SYSTEM_ERR;
3635331Samw 		}
3645331Samw 	} else {
3655331Samw 		ret = SMBD_SMF_SYSTEM_ERR;
3665331Samw 	}
3675331Samw 	if (value != NULL)
3685331Samw 		scf_value_destroy(value);
3695331Samw 	if (prop != NULL)
3705331Samw 		scf_property_destroy(prop);
3715331Samw 	return (ret);
3725331Samw }
3735331Samw 
3745331Samw /*
3755331Samw  * Set boolean value of property.
3765331Samw  * The value is returned as int64_t value
3775331Samw  * Caller ensures appropriate translation.
3785331Samw  */
3795331Samw int
3805331Samw smb_smf_set_boolean_property(smb_scfhandle_t *handle, char *propname,
3815331Samw     uint8_t valbool)
3825331Samw {
3835331Samw 	int ret = SMBD_SMF_OK;
3845331Samw 	scf_value_t *value = NULL;
3855331Samw 	scf_transaction_entry_t *entry = NULL;
3865331Samw 
3875331Samw 	if (handle == NULL)
3885331Samw 		return (SMBD_SMF_SYSTEM_ERR);
3895331Samw 
3905331Samw 	/*
3915331Samw 	 * properties must be set in transactions and don't take
3925331Samw 	 * effect until the transaction has been ended/committed.
3935331Samw 	 */
3945331Samw 	value = scf_value_create(handle->scf_handle);
3955331Samw 	entry = scf_entry_create(handle->scf_handle);
3965331Samw 	if (value != NULL && entry != NULL) {
3975331Samw 		if (scf_transaction_property_change(handle->scf_trans, entry,
3985331Samw 		    propname, SCF_TYPE_BOOLEAN) == 0 ||
3995331Samw 		    scf_transaction_property_new(handle->scf_trans, entry,
4005331Samw 		    propname, SCF_TYPE_BOOLEAN) == 0) {
4015331Samw 			scf_value_set_boolean(value, valbool);
4025331Samw 			if (scf_entry_add_value(entry, value) != 0) {
4035331Samw 				ret = SMBD_SMF_SYSTEM_ERR;
4045331Samw 				scf_value_destroy(value);
4055331Samw 			}
4065331Samw 			/* the value is in the transaction */
4075331Samw 			value = NULL;
4085331Samw 		}
4095331Samw 		/* the entry is in the transaction */
4105331Samw 		entry = NULL;
4115331Samw 	} else {
4125331Samw 		ret = SMBD_SMF_SYSTEM_ERR;
4135331Samw 	}
4145331Samw 	if (ret == SMBD_SMF_SYSTEM_ERR) {
4155331Samw 		switch (scf_error()) {
4165331Samw 		case SCF_ERROR_PERMISSION_DENIED:
4175331Samw 			ret = SMBD_SMF_NO_PERMISSION;
4185331Samw 			break;
4195331Samw 		}
4205331Samw 	}
4215331Samw 	/*
4225331Samw 	 * cleanup if there were any errors that didn't leave these
4235331Samw 	 * values where they would be cleaned up later.
4245331Samw 	 */
4255331Samw 	if (value != NULL)
4265331Samw 		scf_value_destroy(value);
4275331Samw 	if (entry != NULL)
4285331Samw 		scf_entry_destroy(entry);
4295331Samw 	return (ret);
4305331Samw }
4315331Samw 
4325331Samw /*
4335331Samw  * Gets boolean property value.
4345331Samw  * Caller is responsible to have enough memory allocated.
4355331Samw  */
4365331Samw int
4375331Samw smb_smf_get_boolean_property(smb_scfhandle_t *handle, char *propname,
4385331Samw     uint8_t *valbool)
4395331Samw {
4405331Samw 	int ret = SMBD_SMF_OK;
4415331Samw 	scf_value_t *value = NULL;
4425331Samw 	scf_property_t *prop = NULL;
4435331Samw 
4445331Samw 	if (handle == NULL)
4455331Samw 		return (SMBD_SMF_SYSTEM_ERR);
4465331Samw 
4475331Samw 	value = scf_value_create(handle->scf_handle);
4485331Samw 	prop = scf_property_create(handle->scf_handle);
4495331Samw 	if ((prop) && (value) &&
4505331Samw 	    (scf_pg_get_property(handle->scf_pg, propname, prop) == 0)) {
4515331Samw 		if (scf_property_get_value(prop, value) == 0) {
4525331Samw 			if (scf_value_get_boolean(value,
4535331Samw 			    valbool) != 0) {
4545331Samw 				ret = SMBD_SMF_SYSTEM_ERR;
4555331Samw 			}
4565331Samw 		} else {
4575331Samw 			ret = SMBD_SMF_SYSTEM_ERR;
4585331Samw 		}
4595331Samw 	} else {
4605331Samw 		ret = SMBD_SMF_SYSTEM_ERR;
4615331Samw 	}
4625331Samw 	if (value != NULL)
4635331Samw 		scf_value_destroy(value);
4645331Samw 	if (prop != NULL)
4655331Samw 		scf_property_destroy(prop);
4665331Samw 	return (ret);
4675331Samw }
4685331Samw 
4695331Samw /*
4705331Samw  * Sets a blob property value.
4715331Samw  */
4725331Samw int
4735331Samw smb_smf_set_opaque_property(smb_scfhandle_t *handle, char *propname,
4745331Samw     void *voidval, size_t sz)
4755331Samw {
4765331Samw 	int ret = SMBD_SMF_OK;
4775331Samw 	scf_value_t *value;
4785331Samw 	scf_transaction_entry_t *entry;
4795331Samw 
4805331Samw 	if (handle == NULL)
4815331Samw 		return (SMBD_SMF_SYSTEM_ERR);
4825331Samw 
4835331Samw 	/*
4845331Samw 	 * properties must be set in transactions and don't take
4855331Samw 	 * effect until the transaction has been ended/committed.
4865331Samw 	 */
4875331Samw 	value = scf_value_create(handle->scf_handle);
4885331Samw 	entry = scf_entry_create(handle->scf_handle);
4895331Samw 	if (value != NULL && entry != NULL) {
4905331Samw 		if (scf_transaction_property_change(handle->scf_trans, entry,
4915331Samw 		    propname, SCF_TYPE_OPAQUE) == 0 ||
4925331Samw 		    scf_transaction_property_new(handle->scf_trans, entry,
4935331Samw 		    propname, SCF_TYPE_OPAQUE) == 0) {
4945331Samw 			if (scf_value_set_opaque(value, voidval, sz) == 0) {
4955331Samw 				if (scf_entry_add_value(entry, value) != 0) {
4965331Samw 					ret = SMBD_SMF_SYSTEM_ERR;
4975331Samw 					scf_value_destroy(value);
4985331Samw 				}
4995331Samw 				/* the value is in the transaction */
5005331Samw 				value = NULL;
5015331Samw 			} else {
5025331Samw 				/* value couldn't be constructed */
5035331Samw 				ret = SMBD_SMF_SYSTEM_ERR;
5045331Samw 			}
5055331Samw 			/* the entry is in the transaction */
5065331Samw 			entry = NULL;
5075331Samw 		} else {
5085331Samw 			ret = SMBD_SMF_SYSTEM_ERR;
5095331Samw 		}
5105331Samw 	} else {
5115331Samw 		ret = SMBD_SMF_SYSTEM_ERR;
5125331Samw 	}
5135331Samw 	if (ret == SMBD_SMF_SYSTEM_ERR) {
5145331Samw 		switch (scf_error()) {
5155331Samw 		case SCF_ERROR_PERMISSION_DENIED:
5165331Samw 			ret = SMBD_SMF_NO_PERMISSION;
5175331Samw 			break;
5185331Samw 		}
5195331Samw 	}
5205331Samw 	/*
5215331Samw 	 * cleanup if there were any errors that didn't leave these
5225331Samw 	 * values where they would be cleaned up later.
5235331Samw 	 */
5245331Samw 	if (value != NULL)
5255331Samw 		scf_value_destroy(value);
5265331Samw 	if (entry != NULL)
5275331Samw 		scf_entry_destroy(entry);
5285331Samw 	return (ret);
5295331Samw }
5305331Samw 
5315331Samw /*
5325331Samw  * Gets a blob property value.
5335331Samw  * Caller is responsible to have enough memory allocated.
5345331Samw  */
5355331Samw int
5365331Samw smb_smf_get_opaque_property(smb_scfhandle_t *handle, char *propname,
5375331Samw     void *v, size_t sz)
5385331Samw {
5395331Samw 	int ret = SMBD_SMF_OK;
5405331Samw 	scf_value_t *value = NULL;
5415331Samw 	scf_property_t *prop = NULL;
5425331Samw 
5435331Samw 	if (handle == NULL)
5445331Samw 		return (SMBD_SMF_SYSTEM_ERR);
5455331Samw 
5465331Samw 	value = scf_value_create(handle->scf_handle);
5475331Samw 	prop = scf_property_create(handle->scf_handle);
5485331Samw 	if ((prop) && (value) &&
5495331Samw 	    (scf_pg_get_property(handle->scf_pg, propname, prop) == 0)) {
5505331Samw 		if (scf_property_get_value(prop, value) == 0) {
5515331Samw 			if (scf_value_get_opaque(value, (char *)v, sz) != sz) {
5525331Samw 				ret = SMBD_SMF_SYSTEM_ERR;
5535331Samw 			}
5545331Samw 		} else {
5555331Samw 			ret = SMBD_SMF_SYSTEM_ERR;
5565331Samw 		}
5575331Samw 	} else {
5585331Samw 		ret = SMBD_SMF_SYSTEM_ERR;
5595331Samw 	}
5605331Samw 	if (value != NULL)
5615331Samw 		scf_value_destroy(value);
5625331Samw 	if (prop != NULL)
5635331Samw 		scf_property_destroy(prop);
5645331Samw 	return (ret);
5655331Samw }
5665331Samw 
5675331Samw /*
5685331Samw  * smb_smf_scf_init()
5695331Samw  *
5705331Samw  * must be called before using any of the SCF functions.
5715331Samw  * Returns smb_scfhandle_t pointer if success.
5725331Samw  */
5735331Samw smb_scfhandle_t *
5745331Samw smb_smf_scf_init(char *svc_name)
5755331Samw {
5765331Samw 	smb_scfhandle_t *handle;
5775331Samw 
5785331Samw 	handle = malloc(sizeof (smb_scfhandle_t));
5795331Samw 	if (handle != NULL) {
5805331Samw 		bzero((char *)handle, sizeof (smb_scfhandle_t));
5815331Samw 		handle->scf_state = SCH_STATE_INITIALIZING;
5825331Samw 		handle->scf_handle = scf_handle_create(SCF_VERSION);
5835331Samw 		if (handle->scf_handle != NULL) {
5845331Samw 			if (scf_handle_bind(handle->scf_handle) == 0) {
5855331Samw 				handle->scf_scope =
5865331Samw 				    scf_scope_create(handle->scf_handle);
5875331Samw 				if (scf_handle_get_local_scope(
5885331Samw 				    handle->scf_handle, handle->scf_scope) != 0)
5895331Samw 					goto err;
5905331Samw 
5915331Samw 				handle->scf_service =
5925331Samw 				    scf_service_create(handle->scf_handle);
5935331Samw 
5945331Samw 				if (scf_scope_get_service(handle->scf_scope,
5955331Samw 				    svc_name, handle->scf_service)
5965331Samw 				    != SCF_SUCCESS) {
5975331Samw 					goto err;
5985331Samw 				}
5995331Samw 				handle->scf_pg =
6005331Samw 				    scf_pg_create(handle->scf_handle);
6015331Samw 				handle->scf_state = SCH_STATE_INIT;
6025331Samw 			} else {
6035331Samw 				goto err;
6045331Samw 			}
6055331Samw 		} else {
6065331Samw 			free(handle);
6075331Samw 			handle = NULL;
6085331Samw 			smb_smf_scf_log_error("Could not access SMF "
6095331Samw 			    "repository: %s\n");
6105331Samw 		}
6115331Samw 	}
6125331Samw 	return (handle);
6135331Samw 
6145331Samw 	/* error handling/unwinding */
6155331Samw err:
6165331Samw 	(void) smb_smf_scf_fini(handle);
6175331Samw 	(void) smb_smf_scf_log_error("SMF initialization problem: %s\n");
6185331Samw 	return (NULL);
6195331Samw }
6205331Samw 
6215331Samw /*
6225331Samw  * smb_smf_scf_fini(handle)
6235331Samw  *
6245331Samw  * must be called when done. Called with the handle allocated in
6255331Samw  * smb_smf_scf_init(), it cleans up the state and frees any SCF resources
6265331Samw  * still in use.
6275331Samw  */
6285331Samw void
6295331Samw smb_smf_scf_fini(smb_scfhandle_t *handle)
6305331Samw {
6315331Samw 	if (handle != NULL) {
6325331Samw 		int unbind = 0;
6335331Samw 		scf_iter_destroy(handle->scf_pg_iter);
6345331Samw 		handle->scf_pg_iter = NULL;
6355331Samw 
6365331Samw 		scf_iter_destroy(handle->scf_inst_iter);
6375331Samw 		handle->scf_inst_iter = NULL;
6385331Samw 
6395331Samw 		unbind = 1;
6405331Samw 		scf_scope_destroy(handle->scf_scope);
6415331Samw 		handle->scf_scope = NULL;
6425331Samw 
6435331Samw 		scf_instance_destroy(handle->scf_instance);
6445331Samw 		handle->scf_instance = NULL;
6455331Samw 
6465331Samw 		scf_service_destroy(handle->scf_service);
6475331Samw 		handle->scf_service = NULL;
6485331Samw 
6495331Samw 		scf_pg_destroy(handle->scf_pg);
6505331Samw 		handle->scf_pg = NULL;
6515331Samw 
6525331Samw 		handle->scf_state = SCH_STATE_UNINIT;
6535331Samw 		if (unbind)
6545331Samw 			(void) scf_handle_unbind(handle->scf_handle);
6555331Samw 		scf_handle_destroy(handle->scf_handle);
6565331Samw 		handle->scf_handle = NULL;
6575331Samw 
6585331Samw 		free(handle);
6595331Samw 	}
6605331Samw }
661