12654012fSReza Sabdar /*
22654012fSReza Sabdar  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
32654012fSReza Sabdar  * Use is subject to license terms.
433f5ff17SMilan Jurik  * Copyright 2012 Milan Jurik. All rights reserved.
5f093add7SJan Kryl  * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
62654012fSReza Sabdar  */
72654012fSReza Sabdar 
82654012fSReza Sabdar /*
92654012fSReza Sabdar  * BSD 3 Clause License
102654012fSReza Sabdar  *
112654012fSReza Sabdar  * Copyright (c) 2007, The Storage Networking Industry Association.
122654012fSReza Sabdar  *
132654012fSReza Sabdar  * Redistribution and use in source and binary forms, with or without
142654012fSReza Sabdar  * modification, are permitted provided that the following conditions
152654012fSReza Sabdar  * are met:
162654012fSReza Sabdar  * 	- Redistributions of source code must retain the above copyright
172654012fSReza Sabdar  *	  notice, this list of conditions and the following disclaimer.
182654012fSReza Sabdar  *
192654012fSReza Sabdar  * 	- Redistributions in binary form must reproduce the above copyright
202654012fSReza Sabdar  *	  notice, this list of conditions and the following disclaimer in
212654012fSReza Sabdar  *	  the documentation and/or other materials provided with the
222654012fSReza Sabdar  *	  distribution.
232654012fSReza Sabdar  *
242654012fSReza Sabdar  *	- Neither the name of The Storage Networking Industry Association (SNIA)
252654012fSReza Sabdar  *	  nor the names of its contributors may be used to endorse or promote
262654012fSReza Sabdar  *	  products derived from this software without specific prior written
272654012fSReza Sabdar  *	  permission.
282654012fSReza Sabdar  *
292654012fSReza Sabdar  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
302654012fSReza Sabdar  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
312654012fSReza Sabdar  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
322654012fSReza Sabdar  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
332654012fSReza Sabdar  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
342654012fSReza Sabdar  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
352654012fSReza Sabdar  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
362654012fSReza Sabdar  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
372654012fSReza Sabdar  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
382654012fSReza Sabdar  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
392654012fSReza Sabdar  * POSSIBILITY OF SUCH DAMAGE.
402654012fSReza Sabdar  */
412654012fSReza Sabdar 
422654012fSReza Sabdar /*
432654012fSReza Sabdar  * NDMP configuration management
442654012fSReza Sabdar  */
452654012fSReza Sabdar #include <stdio.h>
462654012fSReza Sabdar #include <stdlib.h>
472654012fSReza Sabdar #include <synch.h>
482654012fSReza Sabdar #include <libintl.h>
492654012fSReza Sabdar #include <strings.h>
502654012fSReza Sabdar #include <libndmp.h>
512654012fSReza Sabdar 
522654012fSReza Sabdar /* NDMP properties configuration */
532654012fSReza Sabdar #define	NDMP_GROUP_FMRI_PREFIX	"system/ndmpd"
542654012fSReza Sabdar #define	NDMP_INST		"svc:/system/ndmpd:default"
552654012fSReza Sabdar #define	NDMP_PROP_LEN		600
562654012fSReza Sabdar static char *ndmp_pg[] = {
572654012fSReza Sabdar 	"ndmpd",
582654012fSReza Sabdar 	"read"
592654012fSReza Sabdar };
602654012fSReza Sabdar #define	NPG	(sizeof (ndmp_pg) / sizeof (ndmp_pg[0]))
612654012fSReza Sabdar 
622654012fSReza Sabdar /* Handle Init states */
632654012fSReza Sabdar #define	NDMP_SCH_STATE_UNINIT		0
642654012fSReza Sabdar #define	NDMP_SCH_STATE_INITIALIZING	1
652654012fSReza Sabdar #define	NDMP_SCH_STATE_INIT		2
662654012fSReza Sabdar 
672654012fSReza Sabdar /* NDMP scf handle structure */
682654012fSReza Sabdar typedef struct ndmp_scfhandle {
692654012fSReza Sabdar 	scf_handle_t *scf_handle;
702654012fSReza Sabdar 	int scf_state;
712654012fSReza Sabdar 	scf_service_t *scf_service;
722654012fSReza Sabdar 	scf_scope_t *scf_scope;
732654012fSReza Sabdar 	scf_transaction_t *scf_trans;
742654012fSReza Sabdar 	scf_propertygroup_t *scf_pg;
752654012fSReza Sabdar } ndmp_scfhandle_t;
762654012fSReza Sabdar 
77f093add7SJan Kryl static int ndmp_config_saveenv(ndmp_scfhandle_t *, boolean_t);
788b87c155SJan Kryl static ndmp_scfhandle_t *ndmp_smf_scf_init(const char *);
792654012fSReza Sabdar static void ndmp_smf_scf_fini(ndmp_scfhandle_t *);
802654012fSReza Sabdar static int ndmp_smf_start_transaction(ndmp_scfhandle_t *);
81f093add7SJan Kryl static int ndmp_smf_end_transaction(ndmp_scfhandle_t *, boolean_t);
828b87c155SJan Kryl static int ndmp_smf_set_property(ndmp_scfhandle_t *, const char *,
838b87c155SJan Kryl 		const char *);
848b87c155SJan Kryl static int ndmp_smf_get_property(ndmp_scfhandle_t *, const char *, char *,
858b87c155SJan Kryl 		size_t);
868b87c155SJan Kryl static int ndmp_smf_create_service_pgroup(ndmp_scfhandle_t *, const char *);
878b87c155SJan Kryl static int ndmp_smf_delete_property(ndmp_scfhandle_t *, const char *);
888b87c155SJan Kryl static int ndmp_smf_get_pg_name(ndmp_scfhandle_t *, const char *, char **);
892654012fSReza Sabdar 
902654012fSReza Sabdar /*
912654012fSReza Sabdar  * This routine send a refresh signal to ndmpd service which cause ndmpd
922654012fSReza Sabdar  * property table to be refeshed with current ndmpd properties value from SMF.
932654012fSReza Sabdar  */
942654012fSReza Sabdar int
ndmp_service_refresh(void)952654012fSReza Sabdar ndmp_service_refresh(void)
962654012fSReza Sabdar {
97f093add7SJan Kryl 	int rc = smf_refresh_instance(NDMP_INST);
982654012fSReza Sabdar 
99f093add7SJan Kryl 	if (rc != 0)
100f093add7SJan Kryl 		ndmp_errno = ENDMP_SMF_INTERNAL;
101f093add7SJan Kryl 	return (rc);
1022654012fSReza Sabdar }
1032654012fSReza Sabdar 
1042654012fSReza Sabdar /*
1052654012fSReza Sabdar  * Returns value of the specified variable/property. The return value is a
1062654012fSReza Sabdar  * string pointer to the locally allocated memory if the config param is
1072654012fSReza Sabdar  * defined otherwise it would be NULL.
1082654012fSReza Sabdar  */
1092654012fSReza Sabdar int
ndmp_get_prop(const char * prop,char ** value)1108b87c155SJan Kryl ndmp_get_prop(const char *prop, char **value)
1112654012fSReza Sabdar {
112f093add7SJan Kryl 	ndmp_scfhandle_t *handle;
113f093add7SJan Kryl 	char *lval;
1142654012fSReza Sabdar 	char *pgname;
1152654012fSReza Sabdar 
116f093add7SJan Kryl 	*value = NULL;
1172654012fSReza Sabdar 	if ((handle = ndmp_smf_scf_init(NDMP_GROUP_FMRI_PREFIX)) == NULL) {
1182654012fSReza Sabdar 		return (-1);
1192654012fSReza Sabdar 	}
1202654012fSReza Sabdar 	if (ndmp_smf_get_pg_name(handle, prop, &pgname)) {
121f093add7SJan Kryl 		ndmp_smf_scf_fini(handle);
1222654012fSReza Sabdar 		ndmp_errno = ENDMP_SMF_PROP_GRP;
1232654012fSReza Sabdar 		return (-1);
1242654012fSReza Sabdar 	}
1252654012fSReza Sabdar 	if (ndmp_smf_create_service_pgroup(handle, pgname)) {
1262654012fSReza Sabdar 		ndmp_smf_scf_fini(handle);
127f093add7SJan Kryl 		return (-1);
128f093add7SJan Kryl 	}
129f093add7SJan Kryl 	if ((lval = malloc(NDMP_PROP_LEN)) == NULL) {
130f093add7SJan Kryl 		ndmp_smf_scf_fini(handle);
131f093add7SJan Kryl 		ndmp_errno = ENDMP_MEM_ALLOC;
1322654012fSReza Sabdar 		return (-1);
1332654012fSReza Sabdar 	}
1342654012fSReza Sabdar 	if (ndmp_smf_get_property(handle, prop, lval, NDMP_PROP_LEN) != 0) {
1352654012fSReza Sabdar 		ndmp_smf_scf_fini(handle);
1362654012fSReza Sabdar 		free(lval);
1372654012fSReza Sabdar 		ndmp_errno = ENDMP_SMF_PROP;
1382654012fSReza Sabdar 		return (-1);
1392654012fSReza Sabdar 	}
1402654012fSReza Sabdar 	*value = lval;
1412654012fSReza Sabdar 	ndmp_smf_scf_fini(handle);
1422654012fSReza Sabdar 	return (0);
1432654012fSReza Sabdar }
1442654012fSReza Sabdar 
1452654012fSReza Sabdar int
ndmp_set_prop(const char * env,const char * env_val)1468b87c155SJan Kryl ndmp_set_prop(const char *env, const char *env_val)
1472654012fSReza Sabdar {
148f093add7SJan Kryl 	ndmp_scfhandle_t *handle;
1492654012fSReza Sabdar 	char *pgname;
150f093add7SJan Kryl 	int rc;
1512654012fSReza Sabdar 
1522654012fSReza Sabdar 	if ((handle = ndmp_smf_scf_init(NDMP_GROUP_FMRI_PREFIX)) == NULL)
1532654012fSReza Sabdar 		return (-1);
1542654012fSReza Sabdar 
1552654012fSReza Sabdar 	if (ndmp_smf_get_pg_name(handle, env, &pgname)) {
156f093add7SJan Kryl 		ndmp_smf_scf_fini(handle);
1572654012fSReza Sabdar 		ndmp_errno = ENDMP_SMF_PROP_GRP;
1582654012fSReza Sabdar 		return (-1);
1592654012fSReza Sabdar 	}
1602654012fSReza Sabdar 
161f093add7SJan Kryl 	if (ndmp_smf_create_service_pgroup(handle, pgname)) {
162f093add7SJan Kryl 		ndmp_smf_scf_fini(handle);
1632654012fSReza Sabdar 		return (-1);
164f093add7SJan Kryl 	}
1652654012fSReza Sabdar 
166f093add7SJan Kryl 	if (ndmp_smf_start_transaction(handle)) {
167f093add7SJan Kryl 		ndmp_smf_scf_fini(handle);
1682654012fSReza Sabdar 		return (-1);
1692654012fSReza Sabdar 	}
1702654012fSReza Sabdar 
171f093add7SJan Kryl 	if (env_val)
172f093add7SJan Kryl 		rc = ndmp_smf_set_property(handle, env, env_val);
173f093add7SJan Kryl 	else
174f093add7SJan Kryl 		rc = ndmp_smf_delete_property(handle, env);
1752654012fSReza Sabdar 
176f093add7SJan Kryl 	if (ndmp_config_saveenv(handle, (rc == 0)) == 0)
177f093add7SJan Kryl 		return (rc);
178f093add7SJan Kryl 	else
179f093add7SJan Kryl 		return (-1);
1802654012fSReza Sabdar }
1812654012fSReza Sabdar 
1822654012fSReza Sabdar static int
ndmp_smf_get_pg_name(ndmp_scfhandle_t * h,const char * pname,char ** pgname)1838b87c155SJan Kryl ndmp_smf_get_pg_name(ndmp_scfhandle_t *h, const char *pname, char **pgname)
1842654012fSReza Sabdar {
1852654012fSReza Sabdar 	scf_value_t *value;
1862654012fSReza Sabdar 	scf_property_t *prop;
1872654012fSReza Sabdar 	int i;
1882654012fSReza Sabdar 
1892654012fSReza Sabdar 	for (i = 0; i < NPG; i++) {
1902654012fSReza Sabdar 		if (scf_service_get_pg(h->scf_service, ndmp_pg[i],
1912654012fSReza Sabdar 		    h->scf_pg) != 0)
1922654012fSReza Sabdar 			return (-1);
1932654012fSReza Sabdar 
1942654012fSReza Sabdar 		if ((value = scf_value_create(h->scf_handle)) == NULL)
1952654012fSReza Sabdar 			return (-1);
1962654012fSReza Sabdar 
1972654012fSReza Sabdar 		if ((prop = scf_property_create(h->scf_handle)) == NULL) {
1982654012fSReza Sabdar 			scf_value_destroy(value);
1992654012fSReza Sabdar 			return (-1);
2002654012fSReza Sabdar 		}
2012654012fSReza Sabdar 		/*
2022654012fSReza Sabdar 		 * This will fail if property does not exist in the property
2032654012fSReza Sabdar 		 * group. Check the next property group in case of failure.
2042654012fSReza Sabdar 		 */
2052654012fSReza Sabdar 		if ((scf_pg_get_property(h->scf_pg, pname, prop)) != 0) {
2062654012fSReza Sabdar 			scf_value_destroy(value);
2072654012fSReza Sabdar 			scf_property_destroy(prop);
2082654012fSReza Sabdar 			continue;
2092654012fSReza Sabdar 		}
2102654012fSReza Sabdar 
2112654012fSReza Sabdar 		*pgname = ndmp_pg[i];
2122654012fSReza Sabdar 		scf_value_destroy(value);
2132654012fSReza Sabdar 		scf_property_destroy(prop);
2142654012fSReza Sabdar 		return (0);
2152654012fSReza Sabdar 	}
2162654012fSReza Sabdar 	return (-1);
2172654012fSReza Sabdar }
2182654012fSReza Sabdar 
2192654012fSReza Sabdar /*
2202654012fSReza Sabdar  * Basically commit the transaction.
2212654012fSReza Sabdar  */
2222654012fSReza Sabdar static int
ndmp_config_saveenv(ndmp_scfhandle_t * handle,boolean_t commit)223f093add7SJan Kryl ndmp_config_saveenv(ndmp_scfhandle_t *handle, boolean_t commit)
2242654012fSReza Sabdar {
2252654012fSReza Sabdar 	int ret = 0;
2262654012fSReza Sabdar 
227f093add7SJan Kryl 	ret = ndmp_smf_end_transaction(handle, commit);
2282654012fSReza Sabdar 
2292654012fSReza Sabdar 	ndmp_smf_scf_fini(handle);
2302654012fSReza Sabdar 	return (ret);
2312654012fSReza Sabdar }
2322654012fSReza Sabdar 
2332654012fSReza Sabdar /*
2342654012fSReza Sabdar  * Must be called when done. Called with the handle allocated in
2352654012fSReza Sabdar  * ndmp_smf_scf_init(), it cleans up the state and frees any SCF resources
2362654012fSReza Sabdar  * still in use.
2372654012fSReza Sabdar  */
2382654012fSReza Sabdar static void
ndmp_smf_scf_fini(ndmp_scfhandle_t * handle)2392654012fSReza Sabdar ndmp_smf_scf_fini(ndmp_scfhandle_t *handle)
2402654012fSReza Sabdar {
241f093add7SJan Kryl 	if (handle == NULL)
242f093add7SJan Kryl 		return;
243f093add7SJan Kryl 
244f093add7SJan Kryl 	scf_scope_destroy(handle->scf_scope);
245f093add7SJan Kryl 	scf_service_destroy(handle->scf_service);
246f093add7SJan Kryl 	scf_pg_destroy(handle->scf_pg);
247f093add7SJan Kryl 	handle->scf_state = NDMP_SCH_STATE_UNINIT;
248f093add7SJan Kryl 	(void) scf_handle_unbind(handle->scf_handle);
249f093add7SJan Kryl 	scf_handle_destroy(handle->scf_handle);
250f093add7SJan Kryl 	free(handle);
2512654012fSReza Sabdar }
2522654012fSReza Sabdar 
2532654012fSReza Sabdar /*
2542654012fSReza Sabdar  * Must be called before using any of the SCF functions. Returns
2552654012fSReza Sabdar  * ndmp_scfhandle_t pointer if success.
2562654012fSReza Sabdar  */
2572654012fSReza Sabdar static ndmp_scfhandle_t *
ndmp_smf_scf_init(const char * svc_name)2588b87c155SJan Kryl ndmp_smf_scf_init(const char *svc_name)
2592654012fSReza Sabdar {
2602654012fSReza Sabdar 	ndmp_scfhandle_t *handle;
2612654012fSReza Sabdar 
2622654012fSReza Sabdar 	handle = (ndmp_scfhandle_t *)calloc(1, sizeof (ndmp_scfhandle_t));
2632654012fSReza Sabdar 	if (handle != NULL) {
2642654012fSReza Sabdar 		handle->scf_state = NDMP_SCH_STATE_INITIALIZING;
2652654012fSReza Sabdar 		if (((handle->scf_handle =
2662654012fSReza Sabdar 		    scf_handle_create(SCF_VERSION)) != NULL) &&
2672654012fSReza Sabdar 		    (scf_handle_bind(handle->scf_handle) == 0)) {
2682654012fSReza Sabdar 			if ((handle->scf_scope =
2692654012fSReza Sabdar 			    scf_scope_create(handle->scf_handle)) == NULL)
2702654012fSReza Sabdar 				goto err;
2712654012fSReza Sabdar 
2722654012fSReza Sabdar 			if (scf_handle_get_local_scope(handle->scf_handle,
2732654012fSReza Sabdar 			    handle->scf_scope) != 0)
2742654012fSReza Sabdar 				goto err;
2752654012fSReza Sabdar 
2762654012fSReza Sabdar 			if ((handle->scf_service =
2772654012fSReza Sabdar 			    scf_service_create(handle->scf_handle)) == NULL)
2782654012fSReza Sabdar 				goto err;
2792654012fSReza Sabdar 
2802654012fSReza Sabdar 			if (scf_scope_get_service(handle->scf_scope, svc_name,
2812654012fSReza Sabdar 			    handle->scf_service) != SCF_SUCCESS)
2822654012fSReza Sabdar 				goto err;
2832654012fSReza Sabdar 
2842654012fSReza Sabdar 			if ((handle->scf_pg =
2852654012fSReza Sabdar 			    scf_pg_create(handle->scf_handle)) == NULL)
2862654012fSReza Sabdar 				goto err;
2872654012fSReza Sabdar 
2882654012fSReza Sabdar 			handle->scf_state = NDMP_SCH_STATE_INIT;
2892654012fSReza Sabdar 		} else {
2902654012fSReza Sabdar 			goto err;
2912654012fSReza Sabdar 		}
2922654012fSReza Sabdar 	} else {
2932654012fSReza Sabdar 		ndmp_errno = ENDMP_MEM_ALLOC;
2942654012fSReza Sabdar 		handle = NULL;
2952654012fSReza Sabdar 	}
2962654012fSReza Sabdar 	return (handle);
2972654012fSReza Sabdar 
2982654012fSReza Sabdar 	/* Error handling/unwinding */
2992654012fSReza Sabdar err:
3002654012fSReza Sabdar 	(void) ndmp_smf_scf_fini(handle);
3012654012fSReza Sabdar 	ndmp_errno = ENDMP_SMF_INTERNAL;
3022654012fSReza Sabdar 	return (NULL);
3032654012fSReza Sabdar }
3042654012fSReza Sabdar 
3052654012fSReza Sabdar /*
3062654012fSReza Sabdar  * Create a new property group at service level.
3072654012fSReza Sabdar  */
3082654012fSReza Sabdar static int
ndmp_smf_create_service_pgroup(ndmp_scfhandle_t * handle,const char * pgroup)3098b87c155SJan Kryl ndmp_smf_create_service_pgroup(ndmp_scfhandle_t *handle, const char *pgroup)
3102654012fSReza Sabdar {
3112654012fSReza Sabdar 	int err;
3122654012fSReza Sabdar 
3132654012fSReza Sabdar 	/*
3142654012fSReza Sabdar 	 * Only create a handle if it doesn't exist. It is ok to exist since
3152654012fSReza Sabdar 	 * the pg handle will be set as a side effect.
3162654012fSReza Sabdar 	 */
3172654012fSReza Sabdar 	if (handle->scf_pg == NULL) {
3182654012fSReza Sabdar 		if ((handle->scf_pg =
319*faf269d3SToomas Soome 		    scf_pg_create(handle->scf_handle)) == NULL) {
3202654012fSReza Sabdar 			ndmp_errno = ENDMP_SMF_INTERNAL;
3212654012fSReza Sabdar 			return (-1);
322*faf269d3SToomas Soome 		}
3232654012fSReza Sabdar 	}
3242654012fSReza Sabdar 
3252654012fSReza Sabdar 	/*
3262654012fSReza Sabdar 	 * If the pgroup exists, we are done. If it doesn't, then we need to
3272654012fSReza Sabdar 	 * actually add one to the service instance.
3282654012fSReza Sabdar 	 */
3292654012fSReza Sabdar 	if (scf_service_get_pg(handle->scf_service,
3302654012fSReza Sabdar 	    pgroup, handle->scf_pg) != 0) {
3312654012fSReza Sabdar 		/* Doesn't exist so create one */
3322654012fSReza Sabdar 		if (scf_service_add_pg(handle->scf_service, pgroup,
3332654012fSReza Sabdar 		    SCF_GROUP_FRAMEWORK, 0, handle->scf_pg) != 0) {
3342654012fSReza Sabdar 			err = scf_error();
3352654012fSReza Sabdar 			switch (err) {
3362654012fSReza Sabdar 			case SCF_ERROR_PERMISSION_DENIED:
3372654012fSReza Sabdar 				ndmp_errno = ENDMP_SMF_PERM;
3382654012fSReza Sabdar 				return (-1);
3392654012fSReza Sabdar 			default:
3402654012fSReza Sabdar 				ndmp_errno = ENDMP_SMF_INTERNAL;
3412654012fSReza Sabdar 				return (-1);
3422654012fSReza Sabdar 			}
3432654012fSReza Sabdar 		}
3442654012fSReza Sabdar 	}
3452654012fSReza Sabdar 	return (0);
3462654012fSReza Sabdar }
3472654012fSReza Sabdar 
3482654012fSReza Sabdar /*
3492654012fSReza Sabdar  * Start transaction on current pg in handle. The pg could be service or
3502654012fSReza Sabdar  * instance level. Must be called after pg handle is obtained from create or
3512654012fSReza Sabdar  * get.
3522654012fSReza Sabdar  */
3532654012fSReza Sabdar static int
ndmp_smf_start_transaction(ndmp_scfhandle_t * handle)3542654012fSReza Sabdar ndmp_smf_start_transaction(ndmp_scfhandle_t *handle)
3552654012fSReza Sabdar {
3562654012fSReza Sabdar 	/*
3572654012fSReza Sabdar 	 * Lookup the property group and create it if it doesn't already
3582654012fSReza Sabdar 	 * exist.
3592654012fSReza Sabdar 	 */
3602654012fSReza Sabdar 	if (handle->scf_state == NDMP_SCH_STATE_INIT) {
3612654012fSReza Sabdar 		if ((handle->scf_trans =
3622654012fSReza Sabdar 		    scf_transaction_create(handle->scf_handle)) != NULL) {
3632654012fSReza Sabdar 			if (scf_transaction_start(handle->scf_trans,
3642654012fSReza Sabdar 			    handle->scf_pg) != 0) {
3652654012fSReza Sabdar 				scf_transaction_destroy(handle->scf_trans);
3662654012fSReza Sabdar 				handle->scf_trans = NULL;
3672654012fSReza Sabdar 				ndmp_errno = ENDMP_SMF_INTERNAL;
3682654012fSReza Sabdar 				return (-1);
3692654012fSReza Sabdar 			}
3702654012fSReza Sabdar 		} else {
3712654012fSReza Sabdar 			ndmp_errno = ENDMP_SMF_INTERNAL;
3722654012fSReza Sabdar 			return (-1);
3732654012fSReza Sabdar 		}
3742654012fSReza Sabdar 	}
3752654012fSReza Sabdar 	if (scf_error() == SCF_ERROR_PERMISSION_DENIED) {
3762654012fSReza Sabdar 		ndmp_errno = ENDMP_SMF_PERM;
3772654012fSReza Sabdar 		return (-1);
3782654012fSReza Sabdar 	}
3792654012fSReza Sabdar 
3802654012fSReza Sabdar 	return (0);
3812654012fSReza Sabdar }
3822654012fSReza Sabdar 
3832654012fSReza Sabdar /*
3842654012fSReza Sabdar  * Commit the changes that were added to the transaction in the handle. Do all
3852654012fSReza Sabdar  * necessary cleanup.
3862654012fSReza Sabdar  */
3872654012fSReza Sabdar static int
ndmp_smf_end_transaction(ndmp_scfhandle_t * handle,boolean_t commit)388f093add7SJan Kryl ndmp_smf_end_transaction(ndmp_scfhandle_t *handle, boolean_t commit)
3892654012fSReza Sabdar {
390f093add7SJan Kryl 	int rc = 0;
391f093add7SJan Kryl 
392f093add7SJan Kryl 	if (commit) {
393f093add7SJan Kryl 		if (scf_transaction_commit(handle->scf_trans) < 0) {
394f093add7SJan Kryl 			ndmp_errno = ENDMP_SMF_INTERNAL;
395f093add7SJan Kryl 			rc = -1;
396f093add7SJan Kryl 		}
3972654012fSReza Sabdar 	}
3982654012fSReza Sabdar 
3992654012fSReza Sabdar 	scf_transaction_destroy_children(handle->scf_trans);
4002654012fSReza Sabdar 	scf_transaction_destroy(handle->scf_trans);
4012654012fSReza Sabdar 	handle->scf_trans = NULL;
4022654012fSReza Sabdar 
403f093add7SJan Kryl 	return (rc);
4042654012fSReza Sabdar }
4052654012fSReza Sabdar 
4062654012fSReza Sabdar /*
4072654012fSReza Sabdar  * Deletes property in current pg
4082654012fSReza Sabdar  */
4092654012fSReza Sabdar static int
ndmp_smf_delete_property(ndmp_scfhandle_t * handle,const char * propname)4108b87c155SJan Kryl ndmp_smf_delete_property(ndmp_scfhandle_t *handle, const char *propname)
4112654012fSReza Sabdar {
4122654012fSReza Sabdar 	scf_transaction_entry_t *entry = NULL;
4132654012fSReza Sabdar 
4142654012fSReza Sabdar 	/*
4152654012fSReza Sabdar 	 * Properties must be set in transactions and don't take effect until
4162654012fSReza Sabdar 	 * the transaction has been ended/committed.
4172654012fSReza Sabdar 	 */
4182654012fSReza Sabdar 	if ((entry = scf_entry_create(handle->scf_handle)) != NULL) {
4192654012fSReza Sabdar 		if (scf_transaction_property_delete(handle->scf_trans, entry,
4202654012fSReza Sabdar 		    propname) != 0) {
4212654012fSReza Sabdar 			scf_entry_destroy(entry);
4222654012fSReza Sabdar 			ndmp_errno = ENDMP_SMF_INTERNAL;
4232654012fSReza Sabdar 			return (-1);
4242654012fSReza Sabdar 		}
4252654012fSReza Sabdar 	} else {
4262654012fSReza Sabdar 		ndmp_errno = ENDMP_SMF_INTERNAL;
4272654012fSReza Sabdar 		return (-1);
4282654012fSReza Sabdar 	}
4292654012fSReza Sabdar 	if ((scf_error()) == SCF_ERROR_PERMISSION_DENIED) {
4302654012fSReza Sabdar 		ndmp_errno = ENDMP_SMF_PERM;
4312654012fSReza Sabdar 		scf_entry_destroy(entry);
4322654012fSReza Sabdar 		return (-1);
4332654012fSReza Sabdar 	}
4342654012fSReza Sabdar 
4352654012fSReza Sabdar 	return (0);
4362654012fSReza Sabdar }
4372654012fSReza Sabdar 
4382654012fSReza Sabdar /*
4392654012fSReza Sabdar  * Sets property in current pg
4402654012fSReza Sabdar  */
4412654012fSReza Sabdar static int
ndmp_smf_set_property(ndmp_scfhandle_t * handle,const char * propname,const char * valstr)442f093add7SJan Kryl ndmp_smf_set_property(ndmp_scfhandle_t *handle, const char *propname,
443f093add7SJan Kryl     const char *valstr)
4442654012fSReza Sabdar {
4452654012fSReza Sabdar 	int ret = 0;
4462654012fSReza Sabdar 	scf_value_t *value = NULL;
4472654012fSReza Sabdar 	scf_transaction_entry_t *entry = NULL;
448f093add7SJan Kryl 	scf_property_t *prop = NULL;
4492654012fSReza Sabdar 	scf_type_t type;
4502654012fSReza Sabdar 	int64_t valint;
4512654012fSReza Sabdar 	uint8_t valbool;
4522654012fSReza Sabdar 
4532654012fSReza Sabdar 	/*
4542654012fSReza Sabdar 	 * Properties must be set in transactions and don't take effect until
4552654012fSReza Sabdar 	 * the transaction has been ended/committed.
4562654012fSReza Sabdar 	 */
457f093add7SJan Kryl 	if (((value = scf_value_create(handle->scf_handle)) == NULL) ||
458f093add7SJan Kryl 	    ((entry = scf_entry_create(handle->scf_handle)) == NULL) ||
459f093add7SJan Kryl 	    ((prop = scf_property_create(handle->scf_handle)) == NULL) ||
460f093add7SJan Kryl 	    (scf_pg_get_property(handle->scf_pg, propname, prop) != 0) ||
461f093add7SJan Kryl 	    (scf_property_get_value(prop, value) != 0)) {
462f093add7SJan Kryl 		ret = -1;
463f093add7SJan Kryl 		goto out;
464f093add7SJan Kryl 	}
465f093add7SJan Kryl 
466f093add7SJan Kryl 	type = scf_value_type(value);
467f093add7SJan Kryl 	if ((scf_transaction_property_change(handle->scf_trans, entry, propname,
468f093add7SJan Kryl 	    type) != 0) &&
469f093add7SJan Kryl 	    (scf_transaction_property_new(handle->scf_trans, entry, propname,
470f093add7SJan Kryl 	    type) != 0)) {
471f093add7SJan Kryl 		ret = -1;
472f093add7SJan Kryl 		goto out;
473f093add7SJan Kryl 	}
474f093add7SJan Kryl 
475f093add7SJan Kryl 	switch (type) {
476f093add7SJan Kryl 	case SCF_TYPE_ASTRING:
477f093add7SJan Kryl 		if ((scf_value_set_astring(value, valstr)) != SCF_SUCCESS)
4782654012fSReza Sabdar 			ret = -1;
479f093add7SJan Kryl 		break;
480f093add7SJan Kryl 	case SCF_TYPE_INTEGER:
481f093add7SJan Kryl 		valint = strtoll(valstr, 0, 0);
482f093add7SJan Kryl 		scf_value_set_integer(value, valint);
483f093add7SJan Kryl 		break;
484f093add7SJan Kryl 	case SCF_TYPE_BOOLEAN:
485f093add7SJan Kryl 		if (strncmp(valstr, "yes", 3))
486f093add7SJan Kryl 			valbool = 0;
487f093add7SJan Kryl 		else
488f093add7SJan Kryl 			valbool = 1;
489f093add7SJan Kryl 		scf_value_set_boolean(value, valbool);
490f093add7SJan Kryl 		break;
491f093add7SJan Kryl 	default:
492f093add7SJan Kryl 		ret = -1;
493f093add7SJan Kryl 	}
494f093add7SJan Kryl 	if (scf_entry_add_value(entry, value) == 0) {
495f093add7SJan Kryl 		/* The value is in the transaction */
496f093add7SJan Kryl 		value = NULL;
4972654012fSReza Sabdar 	} else {
4982654012fSReza Sabdar 		ret = -1;
4992654012fSReza Sabdar 	}
500f093add7SJan Kryl 	/* The entry is in the transaction */
501f093add7SJan Kryl 	entry = NULL;
502f093add7SJan Kryl 
503f093add7SJan Kryl out:
5042654012fSReza Sabdar 	if (ret == -1) {
5052654012fSReza Sabdar 		if ((scf_error() == SCF_ERROR_PERMISSION_DENIED))
5062654012fSReza Sabdar 			ndmp_errno = ENDMP_SMF_PERM;
5072654012fSReza Sabdar 		else
5082654012fSReza Sabdar 			ndmp_errno = ENDMP_SMF_INTERNAL;
5092654012fSReza Sabdar 	}
510f093add7SJan Kryl 	scf_property_destroy(prop);
5112654012fSReza Sabdar 	scf_value_destroy(value);
5122654012fSReza Sabdar 	scf_entry_destroy(entry);
5132654012fSReza Sabdar 	return (ret);
5142654012fSReza Sabdar }
5152654012fSReza Sabdar 
5162654012fSReza Sabdar /*
5172654012fSReza Sabdar  * Gets a property value.upto sz size. Caller is responsible to have enough
5182654012fSReza Sabdar  * memory allocated.
5192654012fSReza Sabdar  */
5202654012fSReza Sabdar static int
ndmp_smf_get_property(ndmp_scfhandle_t * handle,const char * propname,char * valstr,size_t sz)5218b87c155SJan Kryl ndmp_smf_get_property(ndmp_scfhandle_t *handle, const char *propname,
5222654012fSReza Sabdar     char *valstr, size_t sz)
5232654012fSReza Sabdar {
5242654012fSReza Sabdar 	int ret = 0;
525f093add7SJan Kryl 	scf_value_t *value = NULL;
526f093add7SJan Kryl 	scf_property_t *prop = NULL;
5272654012fSReza Sabdar 	scf_type_t type;
5282654012fSReza Sabdar 	int64_t valint;
5292654012fSReza Sabdar 	uint8_t valbool;
5302654012fSReza Sabdar 	char valstrbuf[NDMP_PROP_LEN];
5312654012fSReza Sabdar 
5322654012fSReza Sabdar 	if (((value = scf_value_create(handle->scf_handle)) != NULL) &&
5332654012fSReza Sabdar 	    ((prop = scf_property_create(handle->scf_handle)) != NULL) &&
5342654012fSReza Sabdar 	    (scf_pg_get_property(handle->scf_pg, propname, prop) == 0)) {
5352654012fSReza Sabdar 		if (scf_property_get_value(prop, value) == 0) {
5362654012fSReza Sabdar 			type = scf_value_type(value);
5372654012fSReza Sabdar 			switch (type) {
5382654012fSReza Sabdar 			case SCF_TYPE_ASTRING:
5392654012fSReza Sabdar 				if (scf_value_get_astring(value, valstr,
5402654012fSReza Sabdar 				    sz) < 0) {
5412654012fSReza Sabdar 					ret = -1;
5422654012fSReza Sabdar 				}
5432654012fSReza Sabdar 				break;
5442654012fSReza Sabdar 			case SCF_TYPE_INTEGER:
5452654012fSReza Sabdar 				if (scf_value_get_integer(value,
5462654012fSReza Sabdar 				    &valint) != 0) {
5472654012fSReza Sabdar 					ret = -1;
5482654012fSReza Sabdar 					break;
5492654012fSReza Sabdar 				}
5502654012fSReza Sabdar 				valstrbuf[NDMP_PROP_LEN - 1] = '\0';
5512654012fSReza Sabdar 				(void) strncpy(valstr, lltostr(valint,
5522654012fSReza Sabdar 				    &valstrbuf[NDMP_PROP_LEN - 1]),
5532654012fSReza Sabdar 				    NDMP_PROP_LEN);
5542654012fSReza Sabdar 				break;
5552654012fSReza Sabdar 			case SCF_TYPE_BOOLEAN:
5562654012fSReza Sabdar 				if (scf_value_get_boolean(value,
5572654012fSReza Sabdar 				    &valbool) != 0) {
5582654012fSReza Sabdar 					ret = -1;
5592654012fSReza Sabdar 					break;
5602654012fSReza Sabdar 				}
5612654012fSReza Sabdar 				if (valbool == 1)
5622654012fSReza Sabdar 					(void) strncpy(valstr, "yes", 4);
5632654012fSReza Sabdar 				else
5642654012fSReza Sabdar 					(void) strncpy(valstr, "no", 3);
5652654012fSReza Sabdar 				break;
5662654012fSReza Sabdar 			default:
5672654012fSReza Sabdar 				ret = -1;
5682654012fSReza Sabdar 			}
5692654012fSReza Sabdar 		} else {
5702654012fSReza Sabdar 			ret = -1;
5712654012fSReza Sabdar 		}
5722654012fSReza Sabdar 	} else {
5732654012fSReza Sabdar 		ret = -1;
5742654012fSReza Sabdar 	}
5752654012fSReza Sabdar 	scf_value_destroy(value);
5762654012fSReza Sabdar 	scf_property_destroy(prop);
5772654012fSReza Sabdar 	return (ret);
5782654012fSReza Sabdar }
579