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