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