xref: /titanic_41/usr/src/lib/libndmp/common/libndmp_prop.c (revision 7bdf82c2e56142cdb289b3bc3152b784004f67ed)
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.
5*7bdf82c2SJan 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 
77*7bdf82c2SJan Kryl static int ndmp_config_saveenv(ndmp_scfhandle_t *, boolean_t);
787e808d38SJan 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 *);
81*7bdf82c2SJan Kryl static int ndmp_smf_end_transaction(ndmp_scfhandle_t *, boolean_t);
827e808d38SJan Kryl static int ndmp_smf_set_property(ndmp_scfhandle_t *, const char *,
837e808d38SJan Kryl 		const char *);
847e808d38SJan Kryl static int ndmp_smf_get_property(ndmp_scfhandle_t *, const char *, char *,
857e808d38SJan Kryl 		size_t);
867e808d38SJan Kryl static int ndmp_smf_create_service_pgroup(ndmp_scfhandle_t *, const char *);
877e808d38SJan Kryl static int ndmp_smf_delete_property(ndmp_scfhandle_t *, const char *);
887e808d38SJan 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 {
97*7bdf82c2SJan Kryl 	int rc = smf_refresh_instance(NDMP_INST);
982654012fSReza Sabdar 
99*7bdf82c2SJan Kryl 	if (rc != 0)
1002654012fSReza Sabdar 		ndmp_errno = ENDMP_SMF_INTERNAL;
101*7bdf82c2SJan 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)1107e808d38SJan Kryl ndmp_get_prop(const char *prop, char **value)
1112654012fSReza Sabdar {
112*7bdf82c2SJan Kryl 	ndmp_scfhandle_t *handle;
113*7bdf82c2SJan Kryl 	char *lval;
1142654012fSReza Sabdar 	char *pgname;
1152654012fSReza Sabdar 
116*7bdf82c2SJan 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)) {
121*7bdf82c2SJan 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);
127*7bdf82c2SJan Kryl 		return (-1);
128*7bdf82c2SJan Kryl 	}
129*7bdf82c2SJan Kryl 	if ((lval = malloc(NDMP_PROP_LEN)) == NULL) {
130*7bdf82c2SJan Kryl 		ndmp_smf_scf_fini(handle);
131*7bdf82c2SJan 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)1467e808d38SJan Kryl ndmp_set_prop(const char *env, const char *env_val)
1472654012fSReza Sabdar {
148*7bdf82c2SJan Kryl 	ndmp_scfhandle_t *handle;
1492654012fSReza Sabdar 	char *pgname;
150*7bdf82c2SJan 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)) {
156*7bdf82c2SJan Kryl 		ndmp_smf_scf_fini(handle);
1572654012fSReza Sabdar 		ndmp_errno = ENDMP_SMF_PROP_GRP;
1582654012fSReza Sabdar 		return (-1);
1592654012fSReza Sabdar 	}
1602654012fSReza Sabdar 
161*7bdf82c2SJan Kryl 	if (ndmp_smf_create_service_pgroup(handle, pgname)) {
162*7bdf82c2SJan Kryl 		ndmp_smf_scf_fini(handle);
1632654012fSReza Sabdar 		return (-1);
1642654012fSReza Sabdar 	}
1652654012fSReza Sabdar 
166*7bdf82c2SJan Kryl 	if (ndmp_smf_start_transaction(handle)) {
167*7bdf82c2SJan Kryl 		ndmp_smf_scf_fini(handle);
1682654012fSReza Sabdar 		return (-1);
169*7bdf82c2SJan Kryl 	}
1702654012fSReza Sabdar 
171*7bdf82c2SJan Kryl 	if (env_val)
172*7bdf82c2SJan Kryl 		rc = ndmp_smf_set_property(handle, env, env_val);
173*7bdf82c2SJan Kryl 	else
174*7bdf82c2SJan Kryl 		rc = ndmp_smf_delete_property(handle, env);
175*7bdf82c2SJan Kryl 
176*7bdf82c2SJan Kryl 	if (ndmp_config_saveenv(handle, (rc == 0)) == 0)
177*7bdf82c2SJan Kryl 		return (rc);
178*7bdf82c2SJan Kryl 	else
179*7bdf82c2SJan 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)1837e808d38SJan 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)223*7bdf82c2SJan Kryl ndmp_config_saveenv(ndmp_scfhandle_t *handle, boolean_t commit)
2242654012fSReza Sabdar {
2252654012fSReza Sabdar 	int ret = 0;
2262654012fSReza Sabdar 
227*7bdf82c2SJan 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 {
241*7bdf82c2SJan Kryl 	if (handle == NULL)
242*7bdf82c2SJan Kryl 		return;
243*7bdf82c2SJan Kryl 
2442654012fSReza Sabdar 	scf_scope_destroy(handle->scf_scope);
2452654012fSReza Sabdar 	scf_service_destroy(handle->scf_service);
2462654012fSReza Sabdar 	scf_pg_destroy(handle->scf_pg);
2472654012fSReza Sabdar 	handle->scf_state = NDMP_SCH_STATE_UNINIT;
2482654012fSReza Sabdar 	(void) scf_handle_unbind(handle->scf_handle);
2492654012fSReza Sabdar 	scf_handle_destroy(handle->scf_handle);
2502654012fSReza Sabdar 	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)2587e808d38SJan 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)3097e808d38SJan 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 =
3192654012fSReza Sabdar 		    scf_pg_create(handle->scf_handle)) == NULL)
3202654012fSReza Sabdar 			ndmp_errno = ENDMP_SMF_INTERNAL;
3212654012fSReza Sabdar 			return (-1);
3222654012fSReza Sabdar 	}
3232654012fSReza Sabdar 
3242654012fSReza Sabdar 	/*
3252654012fSReza Sabdar 	 * If the pgroup exists, we are done. If it doesn't, then we need to
3262654012fSReza Sabdar 	 * actually add one to the service instance.
3272654012fSReza Sabdar 	 */
3282654012fSReza Sabdar 	if (scf_service_get_pg(handle->scf_service,
3292654012fSReza Sabdar 	    pgroup, handle->scf_pg) != 0) {
3302654012fSReza Sabdar 		/* Doesn't exist so create one */
3312654012fSReza Sabdar 		if (scf_service_add_pg(handle->scf_service, pgroup,
3322654012fSReza Sabdar 		    SCF_GROUP_FRAMEWORK, 0, handle->scf_pg) != 0) {
3332654012fSReza Sabdar 			err = scf_error();
3342654012fSReza Sabdar 			switch (err) {
3352654012fSReza Sabdar 			case SCF_ERROR_PERMISSION_DENIED:
3362654012fSReza Sabdar 				ndmp_errno = ENDMP_SMF_PERM;
3372654012fSReza Sabdar 				return (-1);
3382654012fSReza Sabdar 			default:
3392654012fSReza Sabdar 				ndmp_errno = ENDMP_SMF_INTERNAL;
3402654012fSReza Sabdar 				return (-1);
3412654012fSReza Sabdar 			}
3422654012fSReza Sabdar 		}
3432654012fSReza Sabdar 	}
3442654012fSReza Sabdar 	return (0);
3452654012fSReza Sabdar }
3462654012fSReza Sabdar 
3472654012fSReza Sabdar /*
3482654012fSReza Sabdar  * Start transaction on current pg in handle. The pg could be service or
3492654012fSReza Sabdar  * instance level. Must be called after pg handle is obtained from create or
3502654012fSReza Sabdar  * get.
3512654012fSReza Sabdar  */
3522654012fSReza Sabdar static int
ndmp_smf_start_transaction(ndmp_scfhandle_t * handle)3532654012fSReza Sabdar ndmp_smf_start_transaction(ndmp_scfhandle_t *handle)
3542654012fSReza Sabdar {
3552654012fSReza Sabdar 	/*
3562654012fSReza Sabdar 	 * Lookup the property group and create it if it doesn't already
3572654012fSReza Sabdar 	 * exist.
3582654012fSReza Sabdar 	 */
3592654012fSReza Sabdar 	if (handle->scf_state == NDMP_SCH_STATE_INIT) {
3602654012fSReza Sabdar 		if ((handle->scf_trans =
3612654012fSReza Sabdar 		    scf_transaction_create(handle->scf_handle)) != NULL) {
3622654012fSReza Sabdar 			if (scf_transaction_start(handle->scf_trans,
3632654012fSReza Sabdar 			    handle->scf_pg) != 0) {
3642654012fSReza Sabdar 				scf_transaction_destroy(handle->scf_trans);
3652654012fSReza Sabdar 				handle->scf_trans = NULL;
3662654012fSReza Sabdar 				ndmp_errno = ENDMP_SMF_INTERNAL;
3672654012fSReza Sabdar 				return (-1);
3682654012fSReza Sabdar 			}
3692654012fSReza Sabdar 		} else {
3702654012fSReza Sabdar 			ndmp_errno = ENDMP_SMF_INTERNAL;
3712654012fSReza Sabdar 			return (-1);
3722654012fSReza Sabdar 		}
3732654012fSReza Sabdar 	}
3742654012fSReza Sabdar 	if (scf_error() == SCF_ERROR_PERMISSION_DENIED) {
3752654012fSReza Sabdar 		ndmp_errno = ENDMP_SMF_PERM;
3762654012fSReza Sabdar 		return (-1);
3772654012fSReza Sabdar 	}
3782654012fSReza Sabdar 
3792654012fSReza Sabdar 	return (0);
3802654012fSReza Sabdar }
3812654012fSReza Sabdar 
3822654012fSReza Sabdar /*
3832654012fSReza Sabdar  * Commit the changes that were added to the transaction in the handle. Do all
3842654012fSReza Sabdar  * necessary cleanup.
3852654012fSReza Sabdar  */
3862654012fSReza Sabdar static int
ndmp_smf_end_transaction(ndmp_scfhandle_t * handle,boolean_t commit)387*7bdf82c2SJan Kryl ndmp_smf_end_transaction(ndmp_scfhandle_t *handle, boolean_t commit)
3882654012fSReza Sabdar {
389*7bdf82c2SJan Kryl 	int rc = 0;
390*7bdf82c2SJan Kryl 
391*7bdf82c2SJan Kryl 	if (commit) {
3922654012fSReza Sabdar 		if (scf_transaction_commit(handle->scf_trans) < 0) {
3932654012fSReza Sabdar 			ndmp_errno = ENDMP_SMF_INTERNAL;
394*7bdf82c2SJan Kryl 			rc = -1;
395*7bdf82c2SJan Kryl 		}
3962654012fSReza Sabdar 	}
3972654012fSReza Sabdar 
3982654012fSReza Sabdar 	scf_transaction_destroy_children(handle->scf_trans);
3992654012fSReza Sabdar 	scf_transaction_destroy(handle->scf_trans);
4002654012fSReza Sabdar 	handle->scf_trans = NULL;
4012654012fSReza Sabdar 
402*7bdf82c2SJan Kryl 	return (rc);
4032654012fSReza Sabdar }
4042654012fSReza Sabdar 
4052654012fSReza Sabdar /*
4062654012fSReza Sabdar  * Deletes property in current pg
4072654012fSReza Sabdar  */
4082654012fSReza Sabdar static int
ndmp_smf_delete_property(ndmp_scfhandle_t * handle,const char * propname)4097e808d38SJan Kryl ndmp_smf_delete_property(ndmp_scfhandle_t *handle, const char *propname)
4102654012fSReza Sabdar {
4112654012fSReza Sabdar 	scf_transaction_entry_t *entry = NULL;
4122654012fSReza Sabdar 
4132654012fSReza Sabdar 	/*
4142654012fSReza Sabdar 	 * Properties must be set in transactions and don't take effect until
4152654012fSReza Sabdar 	 * the transaction has been ended/committed.
4162654012fSReza Sabdar 	 */
4172654012fSReza Sabdar 	if ((entry = scf_entry_create(handle->scf_handle)) != NULL) {
4182654012fSReza Sabdar 		if (scf_transaction_property_delete(handle->scf_trans, entry,
4192654012fSReza Sabdar 		    propname) != 0) {
4202654012fSReza Sabdar 			scf_entry_destroy(entry);
4212654012fSReza Sabdar 			ndmp_errno = ENDMP_SMF_INTERNAL;
4222654012fSReza Sabdar 			return (-1);
4232654012fSReza Sabdar 		}
4242654012fSReza Sabdar 	} else {
4252654012fSReza Sabdar 		ndmp_errno = ENDMP_SMF_INTERNAL;
4262654012fSReza Sabdar 		return (-1);
4272654012fSReza Sabdar 	}
4282654012fSReza Sabdar 	if ((scf_error()) == SCF_ERROR_PERMISSION_DENIED) {
4292654012fSReza Sabdar 		ndmp_errno = ENDMP_SMF_PERM;
4302654012fSReza Sabdar 		scf_entry_destroy(entry);
4312654012fSReza Sabdar 		return (-1);
4322654012fSReza Sabdar 	}
4332654012fSReza Sabdar 
4342654012fSReza Sabdar 	return (0);
4352654012fSReza Sabdar }
4362654012fSReza Sabdar 
4372654012fSReza Sabdar /*
4382654012fSReza Sabdar  * Sets property in current pg
4392654012fSReza Sabdar  */
4402654012fSReza Sabdar static int
ndmp_smf_set_property(ndmp_scfhandle_t * handle,const char * propname,const char * valstr)441*7bdf82c2SJan Kryl ndmp_smf_set_property(ndmp_scfhandle_t *handle, const char *propname,
442*7bdf82c2SJan Kryl     const char *valstr)
4432654012fSReza Sabdar {
4442654012fSReza Sabdar 	int ret = 0;
4452654012fSReza Sabdar 	scf_value_t *value = NULL;
4462654012fSReza Sabdar 	scf_transaction_entry_t *entry = NULL;
447*7bdf82c2SJan Kryl 	scf_property_t *prop = NULL;
4482654012fSReza Sabdar 	scf_type_t type;
4492654012fSReza Sabdar 	int64_t valint;
4502654012fSReza Sabdar 	uint8_t valbool;
4512654012fSReza Sabdar 
4522654012fSReza Sabdar 	/*
4532654012fSReza Sabdar 	 * Properties must be set in transactions and don't take effect until
4542654012fSReza Sabdar 	 * the transaction has been ended/committed.
4552654012fSReza Sabdar 	 */
456*7bdf82c2SJan Kryl 	if (((value = scf_value_create(handle->scf_handle)) == NULL) ||
457*7bdf82c2SJan Kryl 	    ((entry = scf_entry_create(handle->scf_handle)) == NULL) ||
458*7bdf82c2SJan Kryl 	    ((prop = scf_property_create(handle->scf_handle)) == NULL) ||
459*7bdf82c2SJan Kryl 	    (scf_pg_get_property(handle->scf_pg, propname, prop) != 0) ||
460*7bdf82c2SJan Kryl 	    (scf_property_get_value(prop, value) != 0)) {
461*7bdf82c2SJan Kryl 		ret = -1;
462*7bdf82c2SJan Kryl 		goto out;
463*7bdf82c2SJan Kryl 	}
464*7bdf82c2SJan Kryl 
4652654012fSReza Sabdar 	type = scf_value_type(value);
466*7bdf82c2SJan Kryl 	if ((scf_transaction_property_change(handle->scf_trans, entry, propname,
467*7bdf82c2SJan Kryl 	    type) != 0) &&
468*7bdf82c2SJan Kryl 	    (scf_transaction_property_new(handle->scf_trans, entry, propname,
469*7bdf82c2SJan Kryl 	    type) != 0)) {
470*7bdf82c2SJan Kryl 		ret = -1;
471*7bdf82c2SJan Kryl 		goto out;
472*7bdf82c2SJan Kryl 	}
473*7bdf82c2SJan Kryl 
4742654012fSReza Sabdar 	switch (type) {
4752654012fSReza Sabdar 	case SCF_TYPE_ASTRING:
476*7bdf82c2SJan Kryl 		if ((scf_value_set_astring(value, valstr)) != SCF_SUCCESS)
4772654012fSReza Sabdar 			ret = -1;
4782654012fSReza Sabdar 		break;
4792654012fSReza Sabdar 	case SCF_TYPE_INTEGER:
4802654012fSReza Sabdar 		valint = strtoll(valstr, 0, 0);
481*7bdf82c2SJan Kryl 		scf_value_set_integer(value, valint);
4822654012fSReza Sabdar 		break;
4832654012fSReza Sabdar 	case SCF_TYPE_BOOLEAN:
4842654012fSReza Sabdar 		if (strncmp(valstr, "yes", 3))
4852654012fSReza Sabdar 			valbool = 0;
4862654012fSReza Sabdar 		else
4872654012fSReza Sabdar 			valbool = 1;
488*7bdf82c2SJan Kryl 		scf_value_set_boolean(value, valbool);
4892654012fSReza Sabdar 		break;
4902654012fSReza Sabdar 	default:
4912654012fSReza Sabdar 		ret = -1;
4922654012fSReza Sabdar 	}
493*7bdf82c2SJan Kryl 	if (scf_entry_add_value(entry, value) == 0) {
4942654012fSReza Sabdar 		/* The value is in the transaction */
4952654012fSReza Sabdar 		value = NULL;
496*7bdf82c2SJan Kryl 	} else {
497*7bdf82c2SJan Kryl 		ret = -1;
4982654012fSReza Sabdar 	}
4992654012fSReza Sabdar 	/* The entry is in the transaction */
5002654012fSReza Sabdar 	entry = NULL;
501*7bdf82c2SJan Kryl 
502*7bdf82c2SJan Kryl out:
5032654012fSReza Sabdar 	if (ret == -1) {
5042654012fSReza Sabdar 		if ((scf_error() == SCF_ERROR_PERMISSION_DENIED))
5052654012fSReza Sabdar 			ndmp_errno = ENDMP_SMF_PERM;
5062654012fSReza Sabdar 		else
5072654012fSReza Sabdar 			ndmp_errno = ENDMP_SMF_INTERNAL;
5082654012fSReza Sabdar 	}
509*7bdf82c2SJan Kryl 	scf_property_destroy(prop);
5102654012fSReza Sabdar 	scf_value_destroy(value);
5112654012fSReza Sabdar 	scf_entry_destroy(entry);
5122654012fSReza Sabdar 	return (ret);
5132654012fSReza Sabdar }
5142654012fSReza Sabdar 
5152654012fSReza Sabdar /*
5162654012fSReza Sabdar  * Gets a property value.upto sz size. Caller is responsible to have enough
5172654012fSReza Sabdar  * memory allocated.
5182654012fSReza Sabdar  */
5192654012fSReza Sabdar static int
ndmp_smf_get_property(ndmp_scfhandle_t * handle,const char * propname,char * valstr,size_t sz)5207e808d38SJan Kryl ndmp_smf_get_property(ndmp_scfhandle_t *handle, const char *propname,
5212654012fSReza Sabdar     char *valstr, size_t sz)
5222654012fSReza Sabdar {
5232654012fSReza Sabdar 	int ret = 0;
524*7bdf82c2SJan Kryl 	scf_value_t *value = NULL;
525*7bdf82c2SJan Kryl 	scf_property_t *prop = NULL;
5262654012fSReza Sabdar 	scf_type_t type;
5272654012fSReza Sabdar 	int64_t valint;
5282654012fSReza Sabdar 	uint8_t valbool;
5292654012fSReza Sabdar 	char valstrbuf[NDMP_PROP_LEN];
5302654012fSReza Sabdar 
5312654012fSReza Sabdar 	if (((value = scf_value_create(handle->scf_handle)) != NULL) &&
5322654012fSReza Sabdar 	    ((prop = scf_property_create(handle->scf_handle)) != NULL) &&
5332654012fSReza Sabdar 	    (scf_pg_get_property(handle->scf_pg, propname, prop) == 0)) {
5342654012fSReza Sabdar 		if (scf_property_get_value(prop, value) == 0) {
5352654012fSReza Sabdar 			type = scf_value_type(value);
5362654012fSReza Sabdar 			switch (type) {
5372654012fSReza Sabdar 			case SCF_TYPE_ASTRING:
5382654012fSReza Sabdar 				if (scf_value_get_astring(value, valstr,
5392654012fSReza Sabdar 				    sz) < 0) {
5402654012fSReza Sabdar 					ret = -1;
5412654012fSReza Sabdar 				}
5422654012fSReza Sabdar 				break;
5432654012fSReza Sabdar 			case SCF_TYPE_INTEGER:
5442654012fSReza Sabdar 				if (scf_value_get_integer(value,
5452654012fSReza Sabdar 				    &valint) != 0) {
5462654012fSReza Sabdar 					ret = -1;
5472654012fSReza Sabdar 					break;
5482654012fSReza Sabdar 				}
5492654012fSReza Sabdar 				valstrbuf[NDMP_PROP_LEN - 1] = '\0';
5502654012fSReza Sabdar 				(void) strncpy(valstr, lltostr(valint,
5512654012fSReza Sabdar 				    &valstrbuf[NDMP_PROP_LEN - 1]),
5522654012fSReza Sabdar 				    NDMP_PROP_LEN);
5532654012fSReza Sabdar 				break;
5542654012fSReza Sabdar 			case SCF_TYPE_BOOLEAN:
5552654012fSReza Sabdar 				if (scf_value_get_boolean(value,
5562654012fSReza Sabdar 				    &valbool) != 0) {
5572654012fSReza Sabdar 					ret = -1;
5582654012fSReza Sabdar 					break;
5592654012fSReza Sabdar 				}
5602654012fSReza Sabdar 				if (valbool == 1)
5612654012fSReza Sabdar 					(void) strncpy(valstr, "yes", 4);
5622654012fSReza Sabdar 				else
5632654012fSReza Sabdar 					(void) strncpy(valstr, "no", 3);
5642654012fSReza Sabdar 				break;
5652654012fSReza Sabdar 			default:
5662654012fSReza Sabdar 				ret = -1;
5672654012fSReza Sabdar 			}
5682654012fSReza Sabdar 		} else {
5692654012fSReza Sabdar 			ret = -1;
5702654012fSReza Sabdar 		}
5712654012fSReza Sabdar 	} else {
5722654012fSReza Sabdar 		ret = -1;
5732654012fSReza Sabdar 	}
5742654012fSReza Sabdar 	scf_value_destroy(value);
5752654012fSReza Sabdar 	scf_property_destroy(prop);
5762654012fSReza Sabdar 	return (ret);
5772654012fSReza Sabdar }
578