14bff34e3Sthurlow /*
24bff34e3Sthurlow  * CDDL HEADER START
34bff34e3Sthurlow  *
44bff34e3Sthurlow  * The contents of this file are subject to the terms of the
54bff34e3Sthurlow  * Common Development and Distribution License (the "License").
64bff34e3Sthurlow  * You may not use this file except in compliance with the License.
74bff34e3Sthurlow  *
84bff34e3Sthurlow  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
94bff34e3Sthurlow  * or http://www.opensolaris.org/os/licensing.
104bff34e3Sthurlow  * See the License for the specific language governing permissions
114bff34e3Sthurlow  * and limitations under the License.
124bff34e3Sthurlow  *
134bff34e3Sthurlow  * When distributing Covered Code, include this CDDL HEADER in each
144bff34e3Sthurlow  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
154bff34e3Sthurlow  * If applicable, add the following below this CDDL HEADER, with the
164bff34e3Sthurlow  * fields enclosed by brackets "[]" replaced with your own identifying
174bff34e3Sthurlow  * information: Portions Copyright [yyyy] [name of copyright owner]
184bff34e3Sthurlow  *
194bff34e3Sthurlow  * CDDL HEADER END
204bff34e3Sthurlow  */
214bff34e3Sthurlow 
224bff34e3Sthurlow /*
234bff34e3Sthurlow  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
244bff34e3Sthurlow  * Use is subject to license terms.
25c79c9de5SAndy Fiddaman  *
26327e8b4bSAndy Fiddaman  * Copyright 2023 Oxide Computer Company
274bff34e3Sthurlow  */
284bff34e3Sthurlow 
294bff34e3Sthurlow /* helper functions for using libscf with CIFS */
304bff34e3Sthurlow 
314bff34e3Sthurlow #include <libscf.h>
324bff34e3Sthurlow #include <string.h>
334bff34e3Sthurlow #include <stdio.h>
344bff34e3Sthurlow #include <stdlib.h>
354bff34e3Sthurlow #include <syslog.h>
364bff34e3Sthurlow #include <errno.h>
374bff34e3Sthurlow #include <uuid/uuid.h>
384bff34e3Sthurlow #include <sys/param.h>
394bff34e3Sthurlow #include <libintl.h>
404bff34e3Sthurlow #include <assert.h>
414bff34e3Sthurlow #include <strings.h>
424bff34e3Sthurlow 
434bff34e3Sthurlow #include "libshare.h"
444bff34e3Sthurlow #include "libshare_smbfs.h"
454bff34e3Sthurlow 
464bff34e3Sthurlow /*
474bff34e3Sthurlow  * smb_smf_scf_log_error(msg)
484bff34e3Sthurlow  * Logs error messages from scf API's
494bff34e3Sthurlow  */
504bff34e3Sthurlow static void
smb_smf_scf_log_error(char * msg)514bff34e3Sthurlow smb_smf_scf_log_error(char *msg)
524bff34e3Sthurlow {
53c79c9de5SAndy Fiddaman 	if (msg == NULL)
54c79c9de5SAndy Fiddaman 		msg = "SMBC SMF problem";
55c79c9de5SAndy Fiddaman 
56c79c9de5SAndy Fiddaman 	syslog(LOG_ERR, "%s: %s", msg, scf_strerror(scf_error()));
574bff34e3Sthurlow }
584bff34e3Sthurlow 
594bff34e3Sthurlow /*
604bff34e3Sthurlow  * smb_smf_scf_fini(handle)
614bff34e3Sthurlow  *
624bff34e3Sthurlow  * must be called when done. Called with the handle allocated in
634bff34e3Sthurlow  * smb_smf_scf_init(), it cleans up the state and frees any SCF resources
644bff34e3Sthurlow  * still in use.
654bff34e3Sthurlow  */
664bff34e3Sthurlow void
smb_smf_scf_fini(smb_scfhandle_t * handle)674bff34e3Sthurlow smb_smf_scf_fini(smb_scfhandle_t *handle)
684bff34e3Sthurlow {
694bff34e3Sthurlow 	if (handle != NULL) {
704bff34e3Sthurlow 		int unbind = 0;
714bff34e3Sthurlow 		if (handle->scf_pg_iter != NULL) {
724bff34e3Sthurlow 			scf_iter_destroy(handle->scf_pg_iter);
734bff34e3Sthurlow 			handle->scf_pg_iter = NULL;
744bff34e3Sthurlow 		}
754bff34e3Sthurlow 		if (handle->scf_inst_iter != NULL) {
764bff34e3Sthurlow 			scf_iter_destroy(handle->scf_inst_iter);
774bff34e3Sthurlow 			handle->scf_inst_iter = NULL;
784bff34e3Sthurlow 		}
794bff34e3Sthurlow 		if (handle->scf_scope != NULL) {
804bff34e3Sthurlow 			unbind = 1;
814bff34e3Sthurlow 			scf_scope_destroy(handle->scf_scope);
824bff34e3Sthurlow 			handle->scf_scope = NULL;
834bff34e3Sthurlow 		}
844bff34e3Sthurlow 		if (handle->scf_instance != NULL) {
854bff34e3Sthurlow 			scf_instance_destroy(handle->scf_instance);
864bff34e3Sthurlow 			handle->scf_instance = NULL;
874bff34e3Sthurlow 		}
884bff34e3Sthurlow 		if (handle->scf_service != NULL) {
894bff34e3Sthurlow 			scf_service_destroy(handle->scf_service);
904bff34e3Sthurlow 			handle->scf_service = NULL;
914bff34e3Sthurlow 		}
924bff34e3Sthurlow 		if (handle->scf_pg != NULL) {
934bff34e3Sthurlow 			scf_pg_destroy(handle->scf_pg);
944bff34e3Sthurlow 			handle->scf_pg = NULL;
954bff34e3Sthurlow 		}
964bff34e3Sthurlow 		if (handle->scf_handle != NULL) {
974bff34e3Sthurlow 			handle->scf_state = SCH_STATE_UNINIT;
984bff34e3Sthurlow 			if (unbind)
994bff34e3Sthurlow 				(void) scf_handle_unbind(handle->scf_handle);
1004bff34e3Sthurlow 			scf_handle_destroy(handle->scf_handle);
1014bff34e3Sthurlow 			handle->scf_handle = NULL;
1024bff34e3Sthurlow 		}
1034bff34e3Sthurlow 		free(handle);
1044bff34e3Sthurlow 	}
1054bff34e3Sthurlow }
1064bff34e3Sthurlow 
1074bff34e3Sthurlow 
1084bff34e3Sthurlow /*
1094bff34e3Sthurlow  * Check if instance with given name exists for a service.
1104bff34e3Sthurlow  * Returns 0 is instance exist
1114bff34e3Sthurlow  */
1124bff34e3Sthurlow int
smb_smf_instance_exists(smb_scfhandle_t * handle,char * inst_name)1134bff34e3Sthurlow smb_smf_instance_exists(smb_scfhandle_t *handle, char *inst_name)
1144bff34e3Sthurlow {
1154bff34e3Sthurlow 	int ret = SMBC_SMF_OK;
1164bff34e3Sthurlow 	if (handle == NULL) {
1174bff34e3Sthurlow 		return (SMBC_SMF_SYSTEM_ERR);
1184bff34e3Sthurlow 	}
1194bff34e3Sthurlow 
1204bff34e3Sthurlow 	handle->scf_instance = scf_instance_create(handle->scf_handle);
1214bff34e3Sthurlow 	if (scf_service_get_instance(handle->scf_service, inst_name,
1224bff34e3Sthurlow 	    handle->scf_instance) != SCF_SUCCESS) {
1234bff34e3Sthurlow 		ret = SMBC_SMF_SYSTEM_ERR;
1244bff34e3Sthurlow 	}
1254bff34e3Sthurlow 	scf_instance_destroy(handle->scf_instance);
1264bff34e3Sthurlow 	handle->scf_instance = NULL;
1274bff34e3Sthurlow 	return (ret);
1284bff34e3Sthurlow }
1294bff34e3Sthurlow 
1304bff34e3Sthurlow /*
1314bff34e3Sthurlow  * Create a service instance. returns 0 if successful.
1324bff34e3Sthurlow  * If instance already exists enable it.
1334bff34e3Sthurlow  */
1344bff34e3Sthurlow int
smb_smf_instance_create(smb_scfhandle_t * handle,char * serv_prefix,char * inst_name)1354bff34e3Sthurlow smb_smf_instance_create(smb_scfhandle_t *handle, char *serv_prefix,
136c79c9de5SAndy Fiddaman     char *inst_name)
1374bff34e3Sthurlow {
1384bff34e3Sthurlow 	char *instance;
1394bff34e3Sthurlow 	int ret = SMBC_SMF_OK;
1404bff34e3Sthurlow 	int sz;
1414bff34e3Sthurlow 
1424bff34e3Sthurlow 	if (handle == NULL) {
1434bff34e3Sthurlow 		return (SMBC_SMF_SYSTEM_ERR);
1444bff34e3Sthurlow 	}
1454bff34e3Sthurlow 
1464bff34e3Sthurlow 	if (!serv_prefix || !inst_name) {
1474bff34e3Sthurlow 		return (SMBC_SMF_SYSTEM_ERR);
1484bff34e3Sthurlow 	}
1494bff34e3Sthurlow 	sz = strlen(serv_prefix) + strlen(inst_name) + 2;
1504bff34e3Sthurlow 	instance = malloc(sz);
1514bff34e3Sthurlow 	if (!instance) {
1524bff34e3Sthurlow 		return (SMBC_SMF_SYSTEM_ERR);
1534bff34e3Sthurlow 	}
1544bff34e3Sthurlow 	(void) snprintf(instance, sz, "%s:%s", serv_prefix, inst_name);
1554bff34e3Sthurlow 	handle->scf_instance = scf_instance_create(handle->scf_handle);
1564bff34e3Sthurlow 	if (scf_service_get_instance(handle->scf_service, inst_name,
1574bff34e3Sthurlow 	    handle->scf_instance) != SCF_SUCCESS) {
1584bff34e3Sthurlow 		if (scf_service_add_instance(handle->scf_service,
1594bff34e3Sthurlow 		    inst_name, handle->scf_instance) == SCF_SUCCESS) {
1604bff34e3Sthurlow 			if (smf_enable_instance(instance, 0))
1614bff34e3Sthurlow 				ret = SMBC_SMF_SYSTEM_ERR;
1624bff34e3Sthurlow 		} else {
1634bff34e3Sthurlow 			ret = SMBC_SMF_SYSTEM_ERR;
1644bff34e3Sthurlow 		}
1654bff34e3Sthurlow 	} else {
1664bff34e3Sthurlow 		if (smf_enable_instance(instance, 0))
1674bff34e3Sthurlow 			ret = SMBC_SMF_SYSTEM_ERR;
1684bff34e3Sthurlow 	}
1694bff34e3Sthurlow 	free(instance);
1704bff34e3Sthurlow 	return (ret);
1714bff34e3Sthurlow }
1724bff34e3Sthurlow 
1734bff34e3Sthurlow /*
1744bff34e3Sthurlow  * Delete a specified instance. Return SMBC_SMF_OK for success.
1754bff34e3Sthurlow  */
1764bff34e3Sthurlow int
smb_smf_instance_delete(smb_scfhandle_t * handle,char * inst_name)1774bff34e3Sthurlow smb_smf_instance_delete(smb_scfhandle_t *handle, char *inst_name)
1784bff34e3Sthurlow {
1794bff34e3Sthurlow 	int ret = SMBC_SMF_OK;
1804bff34e3Sthurlow 
1814bff34e3Sthurlow 	if (handle == NULL) {
1824bff34e3Sthurlow 		return (SMBC_SMF_SYSTEM_ERR);
1834bff34e3Sthurlow 	}
1844bff34e3Sthurlow 
1854bff34e3Sthurlow 	handle->scf_instance = scf_instance_create(handle->scf_handle);
1864bff34e3Sthurlow 	if (scf_service_get_instance(handle->scf_service, inst_name,
1874bff34e3Sthurlow 	    handle->scf_instance) == SCF_SUCCESS) {
1884bff34e3Sthurlow 		if (scf_instance_delete(handle->scf_instance) == SCF_SUCCESS) {
1894bff34e3Sthurlow 			return (ret);
1904bff34e3Sthurlow 		} else {
1914bff34e3Sthurlow 			ret = SMBC_SMF_SYSTEM_ERR;
1924bff34e3Sthurlow 		}
1934bff34e3Sthurlow 	} else {
1944bff34e3Sthurlow 		smb_smf_scf_log_error(NULL);
1954bff34e3Sthurlow 		ret = SMBC_SMF_SYSTEM_ERR;
1964bff34e3Sthurlow 	}
1974bff34e3Sthurlow 	return (ret);
1984bff34e3Sthurlow }
1994bff34e3Sthurlow 
2004bff34e3Sthurlow /*
2014bff34e3Sthurlow  * smb_smf_scf_init()
2024bff34e3Sthurlow  *
2034bff34e3Sthurlow  * must be called before using any of the SCF functions.
2044bff34e3Sthurlow  * Returns smb_scfhandle_t pointer if success.
2054bff34e3Sthurlow  */
2064bff34e3Sthurlow smb_scfhandle_t *
smb_smf_scf_init(char * svc_name)2074bff34e3Sthurlow smb_smf_scf_init(char *svc_name)
2084bff34e3Sthurlow {
2094bff34e3Sthurlow 	smb_scfhandle_t *handle;
2104bff34e3Sthurlow 
2114bff34e3Sthurlow 	handle = malloc(sizeof (smb_scfhandle_t));
2124bff34e3Sthurlow 	if (handle != NULL) {
2134bff34e3Sthurlow 		bzero((char *)handle, sizeof (smb_scfhandle_t));
2144bff34e3Sthurlow 		handle->scf_state = SCH_STATE_INITIALIZING;
2154bff34e3Sthurlow 		handle->scf_handle = scf_handle_create(SCF_VERSION);
2164bff34e3Sthurlow 		if (handle->scf_handle != NULL) {
2174bff34e3Sthurlow 			if (scf_handle_bind(handle->scf_handle) == 0) {
2184bff34e3Sthurlow 				handle->scf_scope =
2194bff34e3Sthurlow 				    scf_scope_create(handle->scf_handle);
2204bff34e3Sthurlow 				if (scf_handle_get_local_scope(
2214bff34e3Sthurlow 				    handle->scf_handle, handle->scf_scope) != 0)
2224bff34e3Sthurlow 					goto err;
2234bff34e3Sthurlow 
2244bff34e3Sthurlow 				handle->scf_service =
2254bff34e3Sthurlow 				    scf_service_create(handle->scf_handle);
2264bff34e3Sthurlow 
2274bff34e3Sthurlow 				if (scf_scope_get_service(handle->scf_scope,
2284bff34e3Sthurlow 				    svc_name, handle->scf_service)
2294bff34e3Sthurlow 				    != SCF_SUCCESS) {
2304bff34e3Sthurlow 					goto err;
2314bff34e3Sthurlow 				}
2324bff34e3Sthurlow 				handle->scf_pg =
2334bff34e3Sthurlow 				    scf_pg_create(handle->scf_handle);
2344bff34e3Sthurlow 				handle->scf_state = SCH_STATE_INIT;
2354bff34e3Sthurlow 			} else {
2364bff34e3Sthurlow 				goto err;
2374bff34e3Sthurlow 			}
2384bff34e3Sthurlow 		} else {
2394bff34e3Sthurlow 			free(handle);
2404bff34e3Sthurlow 			handle = NULL;
241c79c9de5SAndy Fiddaman 			smb_smf_scf_log_error(
242c79c9de5SAndy Fiddaman 			    "Could not access SMF repository");
2434bff34e3Sthurlow 		}
2444bff34e3Sthurlow 	}
2454bff34e3Sthurlow 	return (handle);
2464bff34e3Sthurlow 
2474bff34e3Sthurlow 	/* error handling/unwinding */
2484bff34e3Sthurlow err:
2494bff34e3Sthurlow 	(void) smb_smf_scf_fini(handle);
250327e8b4bSAndy Fiddaman 	if (scf_error() != SCF_ERROR_NOT_FOUND)
251327e8b4bSAndy Fiddaman 		(void) smb_smf_scf_log_error("SMF initialization problem");
2524bff34e3Sthurlow 	return (NULL);
2534bff34e3Sthurlow }
2544bff34e3Sthurlow 
2554bff34e3Sthurlow /*
2564bff34e3Sthurlow  * smb_smf_create_service_pgroup(handle, pgroup)
2574bff34e3Sthurlow  *
2584bff34e3Sthurlow  * create a new property group at service level.
2594bff34e3Sthurlow  */
2604bff34e3Sthurlow int
smb_smf_create_service_pgroup(smb_scfhandle_t * handle,char * pgroup)2614bff34e3Sthurlow smb_smf_create_service_pgroup(smb_scfhandle_t *handle, char *pgroup)
2624bff34e3Sthurlow {
2634bff34e3Sthurlow 	int ret = SMBC_SMF_OK;
2644bff34e3Sthurlow 	int err;
2654bff34e3Sthurlow 
2664bff34e3Sthurlow 	if (handle == NULL) {
2674bff34e3Sthurlow 		return (SMBC_SMF_SYSTEM_ERR);
2684bff34e3Sthurlow 	}
2694bff34e3Sthurlow 
2704bff34e3Sthurlow 	/*
2714bff34e3Sthurlow 	 * only create a handle if it doesn't exist. It is ok to exist
2724bff34e3Sthurlow 	 * since the pg handle will be set as a side effect.
2734bff34e3Sthurlow 	 */
2744bff34e3Sthurlow 	if (handle->scf_pg == NULL) {
2754bff34e3Sthurlow 		handle->scf_pg = scf_pg_create(handle->scf_handle);
2764bff34e3Sthurlow 	}
2774bff34e3Sthurlow 	/*
2784bff34e3Sthurlow 	 * if the pgroup exists, we are done. If it doesn't, then we
2794bff34e3Sthurlow 	 * need to actually add one to the service instance.
2804bff34e3Sthurlow 	 */
2814bff34e3Sthurlow 	if (scf_service_get_pg(handle->scf_service,
2824bff34e3Sthurlow 	    pgroup, handle->scf_pg) != 0) {
2834bff34e3Sthurlow 		/* doesn't exist so create one */
2844bff34e3Sthurlow 		if (scf_service_add_pg(handle->scf_service, pgroup,
2854bff34e3Sthurlow 		    SCF_GROUP_FRAMEWORK, 0, handle->scf_pg) != 0) {
2864bff34e3Sthurlow 			err = scf_error();
2874bff34e3Sthurlow 			if (err != SCF_ERROR_NONE)
2884bff34e3Sthurlow 				smb_smf_scf_log_error(NULL);
2894bff34e3Sthurlow 			switch (err) {
2904bff34e3Sthurlow 			case SCF_ERROR_PERMISSION_DENIED:
2914bff34e3Sthurlow 				ret = SMBC_SMF_NO_PERMISSION;
2924bff34e3Sthurlow 				break;
2934bff34e3Sthurlow 			default:
2944bff34e3Sthurlow 				ret = SMBC_SMF_SYSTEM_ERR;
2954bff34e3Sthurlow 				break;
2964bff34e3Sthurlow 			}
2974bff34e3Sthurlow 		}
2984bff34e3Sthurlow 	}
2994bff34e3Sthurlow 	return (ret);
3004bff34e3Sthurlow }
3014bff34e3Sthurlow 
3024bff34e3Sthurlow /*
3034bff34e3Sthurlow  * smb_smf_create_instance_pgroup(handle, pgroup)
3044bff34e3Sthurlow  *
3054bff34e3Sthurlow  * create a new property group at instance level.
3064bff34e3Sthurlow  */
3074bff34e3Sthurlow int
smb_smf_create_instance_pgroup(smb_scfhandle_t * handle,char * pgroup)3084bff34e3Sthurlow smb_smf_create_instance_pgroup(smb_scfhandle_t *handle, char *pgroup)
3094bff34e3Sthurlow {
3104bff34e3Sthurlow 	int ret = SMBC_SMF_OK;
3114bff34e3Sthurlow 	int err;
3124bff34e3Sthurlow 
3134bff34e3Sthurlow 	if (handle == NULL) {
3144bff34e3Sthurlow 		return (SMBC_SMF_SYSTEM_ERR);
3154bff34e3Sthurlow 	}
3164bff34e3Sthurlow 
3174bff34e3Sthurlow 	/*
3184bff34e3Sthurlow 	 * only create a handle if it doesn't exist. It is ok to exist
3194bff34e3Sthurlow 	 * since the pg handle will be set as a side effect.
3204bff34e3Sthurlow 	 */
3214bff34e3Sthurlow 	if (handle->scf_pg == NULL) {
3224bff34e3Sthurlow 		handle->scf_pg = scf_pg_create(handle->scf_handle);
3234bff34e3Sthurlow 	}
3244bff34e3Sthurlow 
3254bff34e3Sthurlow 	/*
3264bff34e3Sthurlow 	 * if the pgroup exists, we are done. If it doesn't, then we
3274bff34e3Sthurlow 	 * need to actually add one to the service instance.
3284bff34e3Sthurlow 	 */
3294bff34e3Sthurlow 	if (scf_instance_get_pg(handle->scf_instance,
3304bff34e3Sthurlow 	    pgroup, handle->scf_pg) != 0) {
3314bff34e3Sthurlow 		/* doesn't exist so create one */
3324bff34e3Sthurlow 		if (scf_instance_add_pg(handle->scf_instance, pgroup,
3334bff34e3Sthurlow 		    SCF_GROUP_APPLICATION, 0, handle->scf_pg) != 0) {
3344bff34e3Sthurlow 			err = scf_error();
3354bff34e3Sthurlow 			if (err != SCF_ERROR_NONE)
3364bff34e3Sthurlow 				smb_smf_scf_log_error(NULL);
3374bff34e3Sthurlow 			switch (err) {
3384bff34e3Sthurlow 			case SCF_ERROR_PERMISSION_DENIED:
3394bff34e3Sthurlow 				ret = SMBC_SMF_NO_PERMISSION;
3404bff34e3Sthurlow 				break;
3414bff34e3Sthurlow 			default:
3424bff34e3Sthurlow 				ret = SMBC_SMF_SYSTEM_ERR;
3434bff34e3Sthurlow 				break;
3444bff34e3Sthurlow 			}
3454bff34e3Sthurlow 		}
3464bff34e3Sthurlow 	}
3474bff34e3Sthurlow 	return (ret);
3484bff34e3Sthurlow }
3494bff34e3Sthurlow 
3504bff34e3Sthurlow /*
3514bff34e3Sthurlow  * smb_smf_delete_service_pgroup(handle, pgroup)
3524bff34e3Sthurlow  *
3534bff34e3Sthurlow  * remove the property group from the current service.
3544bff34e3Sthurlow  * but only if it actually exists.
3554bff34e3Sthurlow  */
3564bff34e3Sthurlow int
smb_smf_delete_service_pgroup(smb_scfhandle_t * handle,char * pgroup)3574bff34e3Sthurlow smb_smf_delete_service_pgroup(smb_scfhandle_t *handle, char *pgroup)
3584bff34e3Sthurlow {
3594bff34e3Sthurlow 	int ret = SMBC_SMF_OK;
3604bff34e3Sthurlow 	int err;
3614bff34e3Sthurlow 
3624bff34e3Sthurlow 	if (handle == NULL) {
3634bff34e3Sthurlow 		return (SMBC_SMF_SYSTEM_ERR);
3644bff34e3Sthurlow 	}
3654bff34e3Sthurlow 
3664bff34e3Sthurlow 	/*
3674bff34e3Sthurlow 	 * only create a handle if it doesn't exist. It is ok to exist
3684bff34e3Sthurlow 	 * since the pg handle will be set as a side effect.
3694bff34e3Sthurlow 	 */
3704bff34e3Sthurlow 	if (handle->scf_pg == NULL) {
3714bff34e3Sthurlow 		handle->scf_pg = scf_pg_create(handle->scf_handle);
3724bff34e3Sthurlow 	}
3734bff34e3Sthurlow 
3744bff34e3Sthurlow 	/*
3754bff34e3Sthurlow 	 * only delete if it does exist.
3764bff34e3Sthurlow 	 */
3774bff34e3Sthurlow 	if (scf_service_get_pg(handle->scf_service,
3784bff34e3Sthurlow 	    pgroup, handle->scf_pg) == 0) {
3794bff34e3Sthurlow 		/* does exist so delete it */
3804bff34e3Sthurlow 		if (scf_pg_delete(handle->scf_pg) != 0) {
3814bff34e3Sthurlow 			ret = SMBC_SMF_SYSTEM_ERR;
3824bff34e3Sthurlow 			err = scf_error();
3834bff34e3Sthurlow 			if (err != SCF_ERROR_NONE) {
384c79c9de5SAndy Fiddaman 				smb_smf_scf_log_error("SMF delpg problem");
3854bff34e3Sthurlow 			}
3864bff34e3Sthurlow 		}
3874bff34e3Sthurlow 	} else {
3884bff34e3Sthurlow 		err = scf_error();
3894bff34e3Sthurlow 		if (err != SCF_ERROR_NONE)
390c79c9de5SAndy Fiddaman 			smb_smf_scf_log_error("SMF getpg problem");
3914bff34e3Sthurlow 		ret = SMBC_SMF_SYSTEM_ERR;
3924bff34e3Sthurlow 	}
3934bff34e3Sthurlow 	if (ret == SMBC_SMF_SYSTEM_ERR &&
3944bff34e3Sthurlow 	    scf_error() == SCF_ERROR_PERMISSION_DENIED) {
3954bff34e3Sthurlow 		ret = SMBC_SMF_NO_PERMISSION;
3964bff34e3Sthurlow 	}
3974bff34e3Sthurlow 	return (ret);
3984bff34e3Sthurlow }
3994bff34e3Sthurlow 
4004bff34e3Sthurlow /*
4014bff34e3Sthurlow  * smb_smf_delete_instance_pgroup(handle, pgroup)
4024bff34e3Sthurlow  *
4034bff34e3Sthurlow  * remove the property group from the current instance.
4044bff34e3Sthurlow  * but only if it actually exists.
4054bff34e3Sthurlow  */
4064bff34e3Sthurlow int
smb_smf_delete_instance_pgroup(smb_scfhandle_t * handle,char * pgroup)4074bff34e3Sthurlow smb_smf_delete_instance_pgroup(smb_scfhandle_t *handle, char *pgroup)
4084bff34e3Sthurlow {
4094bff34e3Sthurlow 	int ret = SMBC_SMF_OK;
4104bff34e3Sthurlow 	int err;
4114bff34e3Sthurlow 
4124bff34e3Sthurlow 	if (handle == NULL) {
4134bff34e3Sthurlow 		return (SMBC_SMF_SYSTEM_ERR);
4144bff34e3Sthurlow 	}
4154bff34e3Sthurlow 
4164bff34e3Sthurlow 	/*
4174bff34e3Sthurlow 	 * only create a handle if it doesn't exist. It is ok to exist
4184bff34e3Sthurlow 	 * since the pg handle will be set as a side effect.
4194bff34e3Sthurlow 	 */
4204bff34e3Sthurlow 	if (handle->scf_pg == NULL) {
4214bff34e3Sthurlow 		handle->scf_pg = scf_pg_create(handle->scf_handle);
4224bff34e3Sthurlow 	}
4234bff34e3Sthurlow 
4244bff34e3Sthurlow 	/*
4254bff34e3Sthurlow 	 * only delete if it does exist.
4264bff34e3Sthurlow 	 */
4274bff34e3Sthurlow 	if (scf_instance_get_pg(handle->scf_instance,
4284bff34e3Sthurlow 	    pgroup, handle->scf_pg) == 0) {
4294bff34e3Sthurlow 		/* does exist so delete it */
4304bff34e3Sthurlow 		if (scf_pg_delete(handle->scf_pg) != 0) {
4314bff34e3Sthurlow 			ret = SMBC_SMF_SYSTEM_ERR;
4324bff34e3Sthurlow 			err = scf_error();
4334bff34e3Sthurlow 			if (err != SCF_ERROR_NONE) {
434c79c9de5SAndy Fiddaman 				smb_smf_scf_log_error("SMF delpg problem");
4354bff34e3Sthurlow 			}
4364bff34e3Sthurlow 		}
4374bff34e3Sthurlow 	} else {
4384bff34e3Sthurlow 		err = scf_error();
4394bff34e3Sthurlow 		if (err != SCF_ERROR_NONE)
440c79c9de5SAndy Fiddaman 			smb_smf_scf_log_error("SMF getpg problem");
4414bff34e3Sthurlow 		ret = SMBC_SMF_SYSTEM_ERR;
4424bff34e3Sthurlow 	}
4434bff34e3Sthurlow 	if (ret == SMBC_SMF_SYSTEM_ERR &&
4444bff34e3Sthurlow 	    scf_error() == SCF_ERROR_PERMISSION_DENIED) {
4454bff34e3Sthurlow 		ret = SMBC_SMF_NO_PERMISSION;
4464bff34e3Sthurlow 	}
4474bff34e3Sthurlow 	return (ret);
4484bff34e3Sthurlow }
4494bff34e3Sthurlow 
4504bff34e3Sthurlow /*
4514bff34e3Sthurlow  * Start transaction on current pg in handle.
4524bff34e3Sthurlow  * The pg could be service or instance level.
4534bff34e3Sthurlow  * Must be called after pg handle is obtained
4544bff34e3Sthurlow  * from create or get.
4554bff34e3Sthurlow  */
4564bff34e3Sthurlow int
smb_smf_start_transaction(smb_scfhandle_t * handle)4574bff34e3Sthurlow smb_smf_start_transaction(smb_scfhandle_t *handle)
4584bff34e3Sthurlow {
4594bff34e3Sthurlow 	int ret = SMBC_SMF_OK;
4604bff34e3Sthurlow 
4614bff34e3Sthurlow 	if (!handle || (!handle->scf_pg)) {
4624bff34e3Sthurlow 		return (SMBC_SMF_SYSTEM_ERR);
4634bff34e3Sthurlow 	}
4644bff34e3Sthurlow 	/*
4654bff34e3Sthurlow 	 * lookup the property group and create it if it doesn't already
4664bff34e3Sthurlow 	 * exist.
4674bff34e3Sthurlow 	 */
4684bff34e3Sthurlow 	if (handle->scf_state == SCH_STATE_INIT) {
4694bff34e3Sthurlow 		if (ret == SMBC_SMF_OK) {
4704bff34e3Sthurlow 			handle->scf_trans =
4714bff34e3Sthurlow 			    scf_transaction_create(handle->scf_handle);
4724bff34e3Sthurlow 			if (handle->scf_trans != NULL) {
4734bff34e3Sthurlow 				if (scf_transaction_start(handle->scf_trans,
4744bff34e3Sthurlow 				    handle->scf_pg) != 0) {
4754bff34e3Sthurlow 					ret = SMBC_SMF_SYSTEM_ERR;
4764bff34e3Sthurlow 					scf_transaction_destroy(
4774bff34e3Sthurlow 					    handle->scf_trans);
4784bff34e3Sthurlow 					handle->scf_trans = NULL;
4794bff34e3Sthurlow 				}
4804bff34e3Sthurlow 			} else {
4814bff34e3Sthurlow 				ret = SMBC_SMF_SYSTEM_ERR;
4824bff34e3Sthurlow 			}
4834bff34e3Sthurlow 		}
4844bff34e3Sthurlow 	}
4854bff34e3Sthurlow 	if (ret == SMBC_SMF_SYSTEM_ERR &&
4864bff34e3Sthurlow 	    scf_error() == SCF_ERROR_PERMISSION_DENIED) {
4874bff34e3Sthurlow 		ret = SMBC_SMF_NO_PERMISSION;
4884bff34e3Sthurlow 	}
4894bff34e3Sthurlow 	return (ret);
4904bff34e3Sthurlow }
4914bff34e3Sthurlow 
4924bff34e3Sthurlow /*
4934bff34e3Sthurlow  * smb_smf_end_transaction(handle)
4944bff34e3Sthurlow  *
4954bff34e3Sthurlow  * Commit the changes that were added to the transaction in the
4964bff34e3Sthurlow  * handle. Do all necessary cleanup.
4974bff34e3Sthurlow  */
4984bff34e3Sthurlow int
smb_smf_end_transaction(smb_scfhandle_t * handle)4994bff34e3Sthurlow smb_smf_end_transaction(smb_scfhandle_t *handle)
5004bff34e3Sthurlow {
5014bff34e3Sthurlow 	int ret = SMBC_SMF_OK;
5024bff34e3Sthurlow 
5034bff34e3Sthurlow 	if (handle == NULL) {
5044bff34e3Sthurlow 		return (SMBC_SMF_SYSTEM_ERR);
5054bff34e3Sthurlow 	}
5064bff34e3Sthurlow 
5074bff34e3Sthurlow 	if (handle->scf_trans == NULL) {
5084bff34e3Sthurlow 		ret = SMBC_SMF_SYSTEM_ERR;
5094bff34e3Sthurlow 	} else {
5104bff34e3Sthurlow 		if (scf_transaction_commit(handle->scf_trans) < 0) {
5114bff34e3Sthurlow 			ret = SMBC_SMF_SYSTEM_ERR;
512c79c9de5SAndy Fiddaman 			smb_smf_scf_log_error("Failed to commit transaction");
5134bff34e3Sthurlow 		}
5144bff34e3Sthurlow 		scf_transaction_destroy_children(handle->scf_trans);
5154bff34e3Sthurlow 		scf_transaction_destroy(handle->scf_trans);
5164bff34e3Sthurlow 		handle->scf_trans = NULL;
5174bff34e3Sthurlow 	}
5184bff34e3Sthurlow 	return (ret);
5194bff34e3Sthurlow }
5204bff34e3Sthurlow 
5214bff34e3Sthurlow /*
5224bff34e3Sthurlow  * Deletes property in current pg
5234bff34e3Sthurlow  */
5244bff34e3Sthurlow int
smb_smf_delete_property(smb_scfhandle_t * handle,char * propname)5254bff34e3Sthurlow smb_smf_delete_property(smb_scfhandle_t *handle, char *propname)
5264bff34e3Sthurlow {
5274bff34e3Sthurlow 	int ret = SMBC_SMF_OK;
5284bff34e3Sthurlow 	scf_transaction_entry_t *entry = NULL;
5294bff34e3Sthurlow 
5304bff34e3Sthurlow 	if (handle == NULL) {
5314bff34e3Sthurlow 		return (SMBC_SMF_SYSTEM_ERR);
5324bff34e3Sthurlow 	}
5334bff34e3Sthurlow 
5344bff34e3Sthurlow 	/*
5354bff34e3Sthurlow 	 * properties must be set in transactions and don't take
5364bff34e3Sthurlow 	 * effect until the transaction has been ended/committed.
5374bff34e3Sthurlow 	 */
5384bff34e3Sthurlow 	entry = scf_entry_create(handle->scf_handle);
5394bff34e3Sthurlow 	if (entry != NULL) {
5404bff34e3Sthurlow 		if (scf_transaction_property_delete(handle->scf_trans, entry,
5414bff34e3Sthurlow 		    propname) != 0) {
5424bff34e3Sthurlow 			ret = SMBC_SMF_SYSTEM_ERR;
5434bff34e3Sthurlow 		}
5444bff34e3Sthurlow 	} else {
5454bff34e3Sthurlow 		ret = SMBC_SMF_SYSTEM_ERR;
5464bff34e3Sthurlow 	}
5474bff34e3Sthurlow 	if (ret == SMBC_SMF_SYSTEM_ERR) {
548*2bc647a2SToomas Soome 		if (scf_error() == SCF_ERROR_PERMISSION_DENIED) {
5494bff34e3Sthurlow 			ret = SMBC_SMF_NO_PERMISSION;
5504bff34e3Sthurlow 		}
5514bff34e3Sthurlow 	}
5524bff34e3Sthurlow 
5534bff34e3Sthurlow 	/*
5544bff34e3Sthurlow 	 * cleanup if there were any errors that didn't leave these
5554bff34e3Sthurlow 	 * values where they would be cleaned up later.
5564bff34e3Sthurlow 	 */
5574bff34e3Sthurlow 	if ((ret != SMBC_SMF_OK) && (entry != NULL)) {
5584bff34e3Sthurlow 		scf_entry_destroy(entry);
5594bff34e3Sthurlow 	}
5604bff34e3Sthurlow 	return (ret);
5614bff34e3Sthurlow }
5624bff34e3Sthurlow 
5634bff34e3Sthurlow /*
5644bff34e3Sthurlow  * Sets string property in current pg
5654bff34e3Sthurlow  */
5664bff34e3Sthurlow int
smb_smf_set_string_property(smb_scfhandle_t * handle,char * propname,char * valstr)5674bff34e3Sthurlow smb_smf_set_string_property(smb_scfhandle_t *handle,
5684bff34e3Sthurlow     char *propname, char *valstr)
5694bff34e3Sthurlow {
5704bff34e3Sthurlow 	int ret = SMBC_SMF_OK;
5714bff34e3Sthurlow 	scf_value_t *value = NULL;
5724bff34e3Sthurlow 	scf_transaction_entry_t *entry = NULL;
5734bff34e3Sthurlow 
5744bff34e3Sthurlow 	if (handle == NULL) {
5754bff34e3Sthurlow 		return (SMBC_SMF_SYSTEM_ERR);
5764bff34e3Sthurlow 	}
5774bff34e3Sthurlow 
5784bff34e3Sthurlow 	/*
5794bff34e3Sthurlow 	 * properties must be set in transactions and don't take
5804bff34e3Sthurlow 	 * effect until the transaction has been ended/committed.
5814bff34e3Sthurlow 	 */
5824bff34e3Sthurlow 	value = scf_value_create(handle->scf_handle);
5834bff34e3Sthurlow 	entry = scf_entry_create(handle->scf_handle);
5844bff34e3Sthurlow 	if (value != NULL && entry != NULL) {
5854bff34e3Sthurlow 		if (scf_transaction_property_change(handle->scf_trans, entry,
5864bff34e3Sthurlow 		    propname, SCF_TYPE_ASTRING) == 0 ||
5874bff34e3Sthurlow 		    scf_transaction_property_new(handle->scf_trans, entry,
5884bff34e3Sthurlow 		    propname, SCF_TYPE_ASTRING) == 0) {
5894bff34e3Sthurlow 			if (scf_value_set_astring(value, valstr) == 0) {
5904bff34e3Sthurlow 				if (scf_entry_add_value(entry, value) != 0) {
5914bff34e3Sthurlow 					ret = SMBC_SMF_SYSTEM_ERR;
5924bff34e3Sthurlow 					scf_value_destroy(value);
5934bff34e3Sthurlow 				}
5944bff34e3Sthurlow 				/* the value is in the transaction */
5954bff34e3Sthurlow 				value = NULL;
5964bff34e3Sthurlow 			} else {
5974bff34e3Sthurlow 				/* value couldn't be constructed */
5984bff34e3Sthurlow 				ret = SMBC_SMF_SYSTEM_ERR;
5994bff34e3Sthurlow 			}
6004bff34e3Sthurlow 			/* the entry is in the transaction */
6014bff34e3Sthurlow 			entry = NULL;
6024bff34e3Sthurlow 		} else {
6034bff34e3Sthurlow 			ret = SMBC_SMF_SYSTEM_ERR;
6044bff34e3Sthurlow 		}
6054bff34e3Sthurlow 	} else {
6064bff34e3Sthurlow 		ret = SMBC_SMF_SYSTEM_ERR;
6074bff34e3Sthurlow 	}
6084bff34e3Sthurlow 	if (ret == SMBC_SMF_SYSTEM_ERR) {
609*2bc647a2SToomas Soome 		if (scf_error() == SCF_ERROR_PERMISSION_DENIED) {
6104bff34e3Sthurlow 			ret = SMBC_SMF_NO_PERMISSION;
6114bff34e3Sthurlow 		}
6124bff34e3Sthurlow 	}
6134bff34e3Sthurlow 
6144bff34e3Sthurlow 	/*
6154bff34e3Sthurlow 	 * cleanup if there were any errors that didn't leave these
6164bff34e3Sthurlow 	 * values where they would be cleaned up later.
6174bff34e3Sthurlow 	 */
6184bff34e3Sthurlow 	if (value != NULL)
6194bff34e3Sthurlow 		scf_value_destroy(value);
6204bff34e3Sthurlow 	if (entry != NULL)
6214bff34e3Sthurlow 		scf_entry_destroy(entry);
6224bff34e3Sthurlow 	return (ret);
6234bff34e3Sthurlow }
6244bff34e3Sthurlow 
6254bff34e3Sthurlow /*
6264bff34e3Sthurlow  * Gets string property value.upto sz size.
6274bff34e3Sthurlow  * Caller is responsible to have enough memory allocated.
6284bff34e3Sthurlow  */
6294bff34e3Sthurlow int
smb_smf_get_string_property(smb_scfhandle_t * handle,char * propname,char * valstr,size_t sz)6304bff34e3Sthurlow smb_smf_get_string_property(smb_scfhandle_t *handle, char *propname,
6314bff34e3Sthurlow     char *valstr, size_t sz)
6324bff34e3Sthurlow {
6334bff34e3Sthurlow 	int ret = SMBC_SMF_OK;
6344bff34e3Sthurlow 	scf_value_t *value;
6354bff34e3Sthurlow 	scf_property_t *prop;
6364bff34e3Sthurlow 
6374bff34e3Sthurlow 	if (handle == NULL) {
6384bff34e3Sthurlow 		return (SMBC_SMF_SYSTEM_ERR);
6394bff34e3Sthurlow 	}
6404bff34e3Sthurlow 
6414bff34e3Sthurlow 	value = scf_value_create(handle->scf_handle);
6424bff34e3Sthurlow 	prop = scf_property_create(handle->scf_handle);
6434bff34e3Sthurlow 	if (value && prop &&
6444bff34e3Sthurlow 	    (scf_pg_get_property(handle->scf_pg, propname, prop) == 0)) {
6454bff34e3Sthurlow 		if (scf_property_get_value(prop, value) == 0) {
6464bff34e3Sthurlow 			if (scf_value_get_astring(value, valstr, sz) < 0) {
6474bff34e3Sthurlow 				ret = SMBC_SMF_SYSTEM_ERR;
6484bff34e3Sthurlow 			}
6494bff34e3Sthurlow 		} else {
6504bff34e3Sthurlow 			ret = SMBC_SMF_SYSTEM_ERR;
6514bff34e3Sthurlow 		}
6524bff34e3Sthurlow 	} else {
6534bff34e3Sthurlow 		ret = SMBC_SMF_SYSTEM_ERR;
6544bff34e3Sthurlow 	}
6554bff34e3Sthurlow 	if (value != NULL)
6564bff34e3Sthurlow 		scf_value_destroy(value);
6574bff34e3Sthurlow 	if (prop != NULL)
6584bff34e3Sthurlow 		scf_property_destroy(prop);
6594bff34e3Sthurlow 	return (ret);
6604bff34e3Sthurlow }
6614bff34e3Sthurlow 
6624bff34e3Sthurlow /*
6634bff34e3Sthurlow  * Get integer value of property.
6644bff34e3Sthurlow  * The value is returned as int64_t value
6654bff34e3Sthurlow  * Caller ensures appropriate translation.
6664bff34e3Sthurlow  */
6674bff34e3Sthurlow int
smb_smf_set_integer_property(smb_scfhandle_t * handle,char * propname,int64_t valint)6684bff34e3Sthurlow smb_smf_set_integer_property(smb_scfhandle_t *handle, char *propname,
6694bff34e3Sthurlow     int64_t valint)
6704bff34e3Sthurlow {
6714bff34e3Sthurlow 	int ret = SMBC_SMF_OK;
6724bff34e3Sthurlow 	scf_value_t *value = NULL;
6734bff34e3Sthurlow 	scf_transaction_entry_t *entry = NULL;
6744bff34e3Sthurlow 
6754bff34e3Sthurlow 	if (handle == NULL) {
6764bff34e3Sthurlow 		return (SMBC_SMF_SYSTEM_ERR);
6774bff34e3Sthurlow 	}
6784bff34e3Sthurlow 
6794bff34e3Sthurlow 	/*
6804bff34e3Sthurlow 	 * properties must be set in transactions and don't take
6814bff34e3Sthurlow 	 * effect until the transaction has been ended/committed.
6824bff34e3Sthurlow 	 */
6834bff34e3Sthurlow 	value = scf_value_create(handle->scf_handle);
6844bff34e3Sthurlow 	entry = scf_entry_create(handle->scf_handle);
6854bff34e3Sthurlow 	if (value != NULL && entry != NULL) {
6864bff34e3Sthurlow 		if (scf_transaction_property_change(handle->scf_trans, entry,
6874bff34e3Sthurlow 		    propname, SCF_TYPE_INTEGER) == 0 ||
6884bff34e3Sthurlow 		    scf_transaction_property_new(handle->scf_trans, entry,
6894bff34e3Sthurlow 		    propname, SCF_TYPE_INTEGER) == 0) {
6904bff34e3Sthurlow 			scf_value_set_integer(value, valint);
6914bff34e3Sthurlow 			if (scf_entry_add_value(entry, value) != 0) {
6924bff34e3Sthurlow 				ret = SMBC_SMF_SYSTEM_ERR;
6934bff34e3Sthurlow 				scf_value_destroy(value);
6944bff34e3Sthurlow 			}
6954bff34e3Sthurlow 			/* the value is in the transaction */
6964bff34e3Sthurlow 			value = NULL;
6974bff34e3Sthurlow 		}
6984bff34e3Sthurlow 		/* the entry is in the transaction */
6994bff34e3Sthurlow 		entry = NULL;
7004bff34e3Sthurlow 	} else {
7014bff34e3Sthurlow 		ret = SMBC_SMF_SYSTEM_ERR;
7024bff34e3Sthurlow 	}
7034bff34e3Sthurlow 	if (ret == SMBC_SMF_SYSTEM_ERR) {
704*2bc647a2SToomas Soome 		if (scf_error() == SCF_ERROR_PERMISSION_DENIED) {
7054bff34e3Sthurlow 			ret = SMBC_SMF_NO_PERMISSION;
7064bff34e3Sthurlow 		}
7074bff34e3Sthurlow 	}
7084bff34e3Sthurlow 	/*
7094bff34e3Sthurlow 	 * cleanup if there were any errors that didn't leave these
7104bff34e3Sthurlow 	 * values where they would be cleaned up later.
7114bff34e3Sthurlow 	 */
7124bff34e3Sthurlow 	if (value != NULL)
7134bff34e3Sthurlow 		scf_value_destroy(value);
7144bff34e3Sthurlow 	if (entry != NULL)
7154bff34e3Sthurlow 		scf_entry_destroy(entry);
7164bff34e3Sthurlow 	return (ret);
7174bff34e3Sthurlow }
7184bff34e3Sthurlow 
7194bff34e3Sthurlow /*
7204bff34e3Sthurlow  * Sets integer property value.
7214bff34e3Sthurlow  * Caller is responsible to have enough memory allocated.
7224bff34e3Sthurlow  */
7234bff34e3Sthurlow int
smb_smf_get_integer_property(smb_scfhandle_t * handle,char * propname,int64_t * valint)7244bff34e3Sthurlow smb_smf_get_integer_property(smb_scfhandle_t *handle, char *propname,
7254bff34e3Sthurlow     int64_t *valint)
7264bff34e3Sthurlow {
7274bff34e3Sthurlow 	int ret = SMBC_SMF_OK;
7284bff34e3Sthurlow 	scf_value_t *value = NULL;
7294bff34e3Sthurlow 	scf_property_t *prop = NULL;
7304bff34e3Sthurlow 
7314bff34e3Sthurlow 	if (handle == NULL) {
7324bff34e3Sthurlow 		return (SMBC_SMF_SYSTEM_ERR);
7334bff34e3Sthurlow 	}
7344bff34e3Sthurlow 
7354bff34e3Sthurlow 	value = scf_value_create(handle->scf_handle);
7364bff34e3Sthurlow 	prop = scf_property_create(handle->scf_handle);
7374bff34e3Sthurlow 	if ((prop) && (value) &&
7384bff34e3Sthurlow 	    (scf_pg_get_property(handle->scf_pg, propname, prop) == 0)) {
7394bff34e3Sthurlow 		if (scf_property_get_value(prop, value) == 0) {
7404bff34e3Sthurlow 			if (scf_value_get_integer(value,
7414bff34e3Sthurlow 			    valint) != 0) {
7424bff34e3Sthurlow 				ret = SMBC_SMF_SYSTEM_ERR;
7434bff34e3Sthurlow 			}
7444bff34e3Sthurlow 		} else {
7454bff34e3Sthurlow 			ret = SMBC_SMF_SYSTEM_ERR;
7464bff34e3Sthurlow 		}
7474bff34e3Sthurlow 	} else {
7484bff34e3Sthurlow 		ret = SMBC_SMF_SYSTEM_ERR;
7494bff34e3Sthurlow 	}
7504bff34e3Sthurlow 	if (value != NULL)
7514bff34e3Sthurlow 		scf_value_destroy(value);
7524bff34e3Sthurlow 	if (prop != NULL)
7534bff34e3Sthurlow 		scf_property_destroy(prop);
7544bff34e3Sthurlow 	return (ret);
7554bff34e3Sthurlow }
7564bff34e3Sthurlow 
7574bff34e3Sthurlow /*
7584bff34e3Sthurlow  * Get boolean value of property.
7594bff34e3Sthurlow  * The value is returned as int64_t value
7604bff34e3Sthurlow  * Caller ensures appropriate translation.
7614bff34e3Sthurlow  */
7624bff34e3Sthurlow int
smb_smf_set_boolean_property(smb_scfhandle_t * handle,char * propname,uint8_t valbool)7634bff34e3Sthurlow smb_smf_set_boolean_property(smb_scfhandle_t *handle, char *propname,
7644bff34e3Sthurlow     uint8_t valbool)
7654bff34e3Sthurlow {
7664bff34e3Sthurlow 	int ret = SMBC_SMF_OK;
7674bff34e3Sthurlow 	scf_value_t *value = NULL;
7684bff34e3Sthurlow 	scf_transaction_entry_t *entry = NULL;
7694bff34e3Sthurlow 
7704bff34e3Sthurlow 	if (handle == NULL) {
7714bff34e3Sthurlow 		return (SMBC_SMF_SYSTEM_ERR);
7724bff34e3Sthurlow 	}
7734bff34e3Sthurlow 
7744bff34e3Sthurlow 	/*
7754bff34e3Sthurlow 	 * properties must be set in transactions and don't take
7764bff34e3Sthurlow 	 * effect until the transaction has been ended/committed.
7774bff34e3Sthurlow 	 */
7784bff34e3Sthurlow 	value = scf_value_create(handle->scf_handle);
7794bff34e3Sthurlow 	entry = scf_entry_create(handle->scf_handle);
7804bff34e3Sthurlow 	if (value != NULL && entry != NULL) {
7814bff34e3Sthurlow 		if (scf_transaction_property_change(handle->scf_trans, entry,
7824bff34e3Sthurlow 		    propname, SCF_TYPE_BOOLEAN) == 0 ||
7834bff34e3Sthurlow 		    scf_transaction_property_new(handle->scf_trans, entry,
7844bff34e3Sthurlow 		    propname, SCF_TYPE_BOOLEAN) == 0) {
7854bff34e3Sthurlow 			scf_value_set_boolean(value, valbool);
7864bff34e3Sthurlow 			if (scf_entry_add_value(entry, value) != 0) {
7874bff34e3Sthurlow 				ret = SMBC_SMF_SYSTEM_ERR;
7884bff34e3Sthurlow 				scf_value_destroy(value);
7894bff34e3Sthurlow 			}
7904bff34e3Sthurlow 			/* the value is in the transaction */
7914bff34e3Sthurlow 			value = NULL;
7924bff34e3Sthurlow 		}
7934bff34e3Sthurlow 		/* the entry is in the transaction */
7944bff34e3Sthurlow 		entry = NULL;
7954bff34e3Sthurlow 	} else {
7964bff34e3Sthurlow 		ret = SMBC_SMF_SYSTEM_ERR;
7974bff34e3Sthurlow 	}
7984bff34e3Sthurlow 	if (ret == SMBC_SMF_SYSTEM_ERR) {
799*2bc647a2SToomas Soome 		if (scf_error() == SCF_ERROR_PERMISSION_DENIED) {
8004bff34e3Sthurlow 			ret = SMBC_SMF_NO_PERMISSION;
8014bff34e3Sthurlow 		}
8024bff34e3Sthurlow 	}
8034bff34e3Sthurlow 	/*
8044bff34e3Sthurlow 	 * cleanup if there were any errors that didn't leave these
8054bff34e3Sthurlow 	 * values where they would be cleaned up later.
8064bff34e3Sthurlow 	 */
8074bff34e3Sthurlow 	if (value != NULL)
8084bff34e3Sthurlow 		scf_value_destroy(value);
8094bff34e3Sthurlow 	if (entry != NULL)
8104bff34e3Sthurlow 		scf_entry_destroy(entry);
8114bff34e3Sthurlow 	return (ret);
8124bff34e3Sthurlow }
8134bff34e3Sthurlow 
8144bff34e3Sthurlow /*
8154bff34e3Sthurlow  * Sets boolean property value.
8164bff34e3Sthurlow  * Caller is responsible to have enough memory allocated.
8174bff34e3Sthurlow  */
8184bff34e3Sthurlow int
smb_smf_get_boolean_property(smb_scfhandle_t * handle,char * propname,uint8_t * valbool)8194bff34e3Sthurlow smb_smf_get_boolean_property(smb_scfhandle_t *handle, char *propname,
8204bff34e3Sthurlow     uint8_t *valbool)
8214bff34e3Sthurlow {
8224bff34e3Sthurlow 	int ret = SMBC_SMF_OK;
8234bff34e3Sthurlow 	scf_value_t *value = NULL;
8244bff34e3Sthurlow 	scf_property_t *prop = NULL;
8254bff34e3Sthurlow 
8264bff34e3Sthurlow 	if (handle == NULL) {
8274bff34e3Sthurlow 		return (SMBC_SMF_SYSTEM_ERR);
8284bff34e3Sthurlow 	}
8294bff34e3Sthurlow 
8304bff34e3Sthurlow 	value = scf_value_create(handle->scf_handle);
8314bff34e3Sthurlow 	prop = scf_property_create(handle->scf_handle);
8324bff34e3Sthurlow 	if ((prop) && (value) &&
8334bff34e3Sthurlow 	    (scf_pg_get_property(handle->scf_pg, propname, prop) == 0)) {
8344bff34e3Sthurlow 		if (scf_property_get_value(prop, value) == 0) {
8354bff34e3Sthurlow 			if (scf_value_get_boolean(value,
8364bff34e3Sthurlow 			    valbool) != 0) {
8374bff34e3Sthurlow 				ret = SMBC_SMF_SYSTEM_ERR;
8384bff34e3Sthurlow 			}
8394bff34e3Sthurlow 		} else {
8404bff34e3Sthurlow 			ret = SMBC_SMF_SYSTEM_ERR;
8414bff34e3Sthurlow 		}
8424bff34e3Sthurlow 	} else {
8434bff34e3Sthurlow 		ret = SMBC_SMF_SYSTEM_ERR;
8444bff34e3Sthurlow 	}
8454bff34e3Sthurlow 	if (value != NULL)
8464bff34e3Sthurlow 		scf_value_destroy(value);
8474bff34e3Sthurlow 	if (prop != NULL)
8484bff34e3Sthurlow 		scf_property_destroy(prop);
8494bff34e3Sthurlow 	return (ret);
8504bff34e3Sthurlow }
8514bff34e3Sthurlow 
8524bff34e3Sthurlow /*
8534bff34e3Sthurlow  * Sets a blob property value.
8544bff34e3Sthurlow  */
8554bff34e3Sthurlow int
smb_smf_set_opaque_property(smb_scfhandle_t * handle,char * propname,void * voidval,size_t sz)8564bff34e3Sthurlow smb_smf_set_opaque_property(smb_scfhandle_t *handle, char *propname,
8574bff34e3Sthurlow     void *voidval, size_t sz)
8584bff34e3Sthurlow {
8594bff34e3Sthurlow 	int ret = SMBC_SMF_OK;
8604bff34e3Sthurlow 	scf_value_t *value;
8614bff34e3Sthurlow 	scf_transaction_entry_t *entry;
8624bff34e3Sthurlow 
8634bff34e3Sthurlow 	if (handle == NULL) {
8644bff34e3Sthurlow 		return (SMBC_SMF_SYSTEM_ERR);
8654bff34e3Sthurlow 	}
8664bff34e3Sthurlow 
8674bff34e3Sthurlow 	/*
8684bff34e3Sthurlow 	 * properties must be set in transactions and don't take
8694bff34e3Sthurlow 	 * effect until the transaction has been ended/committed.
8704bff34e3Sthurlow 	 */
8714bff34e3Sthurlow 	value = scf_value_create(handle->scf_handle);
8724bff34e3Sthurlow 	entry = scf_entry_create(handle->scf_handle);
8734bff34e3Sthurlow 	if (value != NULL && entry != NULL) {
8744bff34e3Sthurlow 		if (scf_transaction_property_change(handle->scf_trans, entry,
8754bff34e3Sthurlow 		    propname, SCF_TYPE_OPAQUE) == 0 ||
8764bff34e3Sthurlow 		    scf_transaction_property_new(handle->scf_trans, entry,
8774bff34e3Sthurlow 		    propname, SCF_TYPE_OPAQUE) == 0) {
8784bff34e3Sthurlow 			if (scf_value_set_opaque(value, voidval, sz) == 0) {
8794bff34e3Sthurlow 				if (scf_entry_add_value(entry, value) != 0) {
8804bff34e3Sthurlow 					ret = SMBC_SMF_SYSTEM_ERR;
8814bff34e3Sthurlow 					scf_value_destroy(value);
8824bff34e3Sthurlow 				}
8834bff34e3Sthurlow 				/* the value is in the transaction */
8844bff34e3Sthurlow 				value = NULL;
8854bff34e3Sthurlow 			} else {
8864bff34e3Sthurlow 				/* value couldn't be constructed */
8874bff34e3Sthurlow 				ret = SMBC_SMF_SYSTEM_ERR;
8884bff34e3Sthurlow 			}
8894bff34e3Sthurlow 			/* the entry is in the transaction */
8904bff34e3Sthurlow 			entry = NULL;
8914bff34e3Sthurlow 		} else {
8924bff34e3Sthurlow 			ret = SMBC_SMF_SYSTEM_ERR;
8934bff34e3Sthurlow 		}
8944bff34e3Sthurlow 	} else {
8954bff34e3Sthurlow 		ret = SMBC_SMF_SYSTEM_ERR;
8964bff34e3Sthurlow 	}
8974bff34e3Sthurlow 	if (ret == SMBC_SMF_SYSTEM_ERR) {
898*2bc647a2SToomas Soome 		if (scf_error() == SCF_ERROR_PERMISSION_DENIED) {
8994bff34e3Sthurlow 			ret = SMBC_SMF_NO_PERMISSION;
9004bff34e3Sthurlow 		}
9014bff34e3Sthurlow 	}
9024bff34e3Sthurlow 	/*
9034bff34e3Sthurlow 	 * cleanup if there were any errors that didn't leave these
9044bff34e3Sthurlow 	 * values where they would be cleaned up later.
9054bff34e3Sthurlow 	 */
9064bff34e3Sthurlow 	if (value != NULL)
9074bff34e3Sthurlow 		scf_value_destroy(value);
9084bff34e3Sthurlow 	if (entry != NULL)
9094bff34e3Sthurlow 		scf_entry_destroy(entry);
9104bff34e3Sthurlow 	return (ret);
9114bff34e3Sthurlow }
9124bff34e3Sthurlow 
9134bff34e3Sthurlow /*
9144bff34e3Sthurlow  * Gets a blob property value.
9154bff34e3Sthurlow  * Caller is responsible to have enough memory allocated.
9164bff34e3Sthurlow  */
9174bff34e3Sthurlow int
smb_smf_get_opaque_property(smb_scfhandle_t * handle,char * propname,void * v,size_t sz)9184bff34e3Sthurlow smb_smf_get_opaque_property(smb_scfhandle_t *handle, char *propname,
9194bff34e3Sthurlow     void *v, size_t sz)
9204bff34e3Sthurlow {
9214bff34e3Sthurlow 	int ret = SMBC_SMF_OK;
9224bff34e3Sthurlow 	scf_value_t *value = NULL;
9234bff34e3Sthurlow 	scf_property_t *prop = NULL;
9244bff34e3Sthurlow 
9254bff34e3Sthurlow 	if (handle == NULL) {
9264bff34e3Sthurlow 		return (SMBC_SMF_SYSTEM_ERR);
9274bff34e3Sthurlow 	}
9284bff34e3Sthurlow 
9294bff34e3Sthurlow 	value = scf_value_create(handle->scf_handle);
9304bff34e3Sthurlow 	prop = scf_property_create(handle->scf_handle);
9314bff34e3Sthurlow 	if ((prop) && (value) &&
9324bff34e3Sthurlow 	    (scf_pg_get_property(handle->scf_pg, propname, prop) == 0)) {
9334bff34e3Sthurlow 		if (scf_property_get_value(prop, value) == 0) {
9344bff34e3Sthurlow 			if (scf_value_get_opaque(value, (char *)v, sz) != sz) {
9354bff34e3Sthurlow 				ret = SMBC_SMF_SYSTEM_ERR;
9364bff34e3Sthurlow 			}
9374bff34e3Sthurlow 		} else {
9384bff34e3Sthurlow 			ret = SMBC_SMF_SYSTEM_ERR;
9394bff34e3Sthurlow 		}
9404bff34e3Sthurlow 	} else {
9414bff34e3Sthurlow 		ret = SMBC_SMF_SYSTEM_ERR;
9424bff34e3Sthurlow 	}
9434bff34e3Sthurlow 	if (value != NULL)
9444bff34e3Sthurlow 		scf_value_destroy(value);
9454bff34e3Sthurlow 	if (prop != NULL)
9464bff34e3Sthurlow 		scf_property_destroy(prop);
9474bff34e3Sthurlow 	return (ret);
9484bff34e3Sthurlow }
9494bff34e3Sthurlow 
9504bff34e3Sthurlow /*
9514bff34e3Sthurlow  * Gets an instance iterator for the service specified.
9524bff34e3Sthurlow  */
9534bff34e3Sthurlow smb_scfhandle_t *
smb_smf_get_iterator(char * svc_name)9544bff34e3Sthurlow smb_smf_get_iterator(char *svc_name)
9554bff34e3Sthurlow {
9564bff34e3Sthurlow 	smb_scfhandle_t *handle = NULL;
9574bff34e3Sthurlow 
9584bff34e3Sthurlow 	handle = smb_smf_scf_init(svc_name);
9594bff34e3Sthurlow 	if (!handle) {
9604bff34e3Sthurlow 		return (NULL);
9614bff34e3Sthurlow 	}
9624bff34e3Sthurlow 
9634bff34e3Sthurlow 	handle->scf_inst_iter = scf_iter_create(handle->scf_handle);
9644bff34e3Sthurlow 	if (handle->scf_inst_iter) {
9654bff34e3Sthurlow 		if (scf_iter_service_instances(handle->scf_inst_iter,
9664bff34e3Sthurlow 		    handle->scf_service) != 0) {
9674bff34e3Sthurlow 			smb_smf_scf_fini(handle);
9684bff34e3Sthurlow 			handle = NULL;
9694bff34e3Sthurlow 		} else {
9704bff34e3Sthurlow 			handle->scf_instance = NULL;
9714bff34e3Sthurlow 		}
9724bff34e3Sthurlow 	} else {
9734bff34e3Sthurlow 		smb_smf_scf_fini(handle);
9744bff34e3Sthurlow 		handle = NULL;
9754bff34e3Sthurlow 	}
9764bff34e3Sthurlow 	return (handle);
9774bff34e3Sthurlow }
978