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*f093add7SJan 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*f093add7SJan 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 *);
81*f093add7SJan 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 {
97*f093add7SJan Kryl int rc = smf_refresh_instance(NDMP_INST);
982654012fSReza Sabdar
99*f093add7SJan Kryl if (rc != 0)
1002654012fSReza Sabdar ndmp_errno = ENDMP_SMF_INTERNAL;
101*f093add7SJan 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 {
112*f093add7SJan Kryl ndmp_scfhandle_t *handle;
113*f093add7SJan Kryl char *lval;
1142654012fSReza Sabdar char *pgname;
1152654012fSReza Sabdar
116*f093add7SJan 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*f093add7SJan 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*f093add7SJan Kryl return (-1);
128*f093add7SJan Kryl }
129*f093add7SJan Kryl if ((lval = malloc(NDMP_PROP_LEN)) == NULL) {
130*f093add7SJan Kryl ndmp_smf_scf_fini(handle);
131*f093add7SJan 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 {
148*f093add7SJan Kryl ndmp_scfhandle_t *handle;
1492654012fSReza Sabdar char *pgname;
150*f093add7SJan 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*f093add7SJan Kryl ndmp_smf_scf_fini(handle);
1572654012fSReza Sabdar ndmp_errno = ENDMP_SMF_PROP_GRP;
1582654012fSReza Sabdar return (-1);
1592654012fSReza Sabdar }
1602654012fSReza Sabdar
161*f093add7SJan Kryl if (ndmp_smf_create_service_pgroup(handle, pgname)) {
162*f093add7SJan Kryl ndmp_smf_scf_fini(handle);
1632654012fSReza Sabdar return (-1);
1642654012fSReza Sabdar }
1652654012fSReza Sabdar
166*f093add7SJan Kryl if (ndmp_smf_start_transaction(handle)) {
167*f093add7SJan Kryl ndmp_smf_scf_fini(handle);
1682654012fSReza Sabdar return (-1);
169*f093add7SJan Kryl }
1702654012fSReza Sabdar
171*f093add7SJan Kryl if (env_val)
172*f093add7SJan Kryl rc = ndmp_smf_set_property(handle, env, env_val);
173*f093add7SJan Kryl else
174*f093add7SJan Kryl rc = ndmp_smf_delete_property(handle, env);
175*f093add7SJan Kryl
176*f093add7SJan Kryl if (ndmp_config_saveenv(handle, (rc == 0)) == 0)
177*f093add7SJan Kryl return (rc);
178*f093add7SJan Kryl else
179*f093add7SJan 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)223*f093add7SJan Kryl ndmp_config_saveenv(ndmp_scfhandle_t *handle, boolean_t commit)
2242654012fSReza Sabdar {
2252654012fSReza Sabdar int ret = 0;
2262654012fSReza Sabdar
227*f093add7SJan 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*f093add7SJan Kryl if (handle == NULL)
242*f093add7SJan Kryl return;
243*f093add7SJan 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)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 =
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*f093add7SJan Kryl ndmp_smf_end_transaction(ndmp_scfhandle_t *handle, boolean_t commit)
3882654012fSReza Sabdar {
389*f093add7SJan Kryl int rc = 0;
390*f093add7SJan Kryl
391*f093add7SJan Kryl if (commit) {
3922654012fSReza Sabdar if (scf_transaction_commit(handle->scf_trans) < 0) {
3932654012fSReza Sabdar ndmp_errno = ENDMP_SMF_INTERNAL;
394*f093add7SJan Kryl rc = -1;
395*f093add7SJan 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*f093add7SJan 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)4098b87c155SJan 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*f093add7SJan Kryl ndmp_smf_set_property(ndmp_scfhandle_t *handle, const char *propname,
442*f093add7SJan 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*f093add7SJan 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*f093add7SJan Kryl if (((value = scf_value_create(handle->scf_handle)) == NULL) ||
457*f093add7SJan Kryl ((entry = scf_entry_create(handle->scf_handle)) == NULL) ||
458*f093add7SJan Kryl ((prop = scf_property_create(handle->scf_handle)) == NULL) ||
459*f093add7SJan Kryl (scf_pg_get_property(handle->scf_pg, propname, prop) != 0) ||
460*f093add7SJan Kryl (scf_property_get_value(prop, value) != 0)) {
461*f093add7SJan Kryl ret = -1;
462*f093add7SJan Kryl goto out;
463*f093add7SJan Kryl }
464*f093add7SJan Kryl
4652654012fSReza Sabdar type = scf_value_type(value);
466*f093add7SJan Kryl if ((scf_transaction_property_change(handle->scf_trans, entry, propname,
467*f093add7SJan Kryl type) != 0) &&
468*f093add7SJan Kryl (scf_transaction_property_new(handle->scf_trans, entry, propname,
469*f093add7SJan Kryl type) != 0)) {
470*f093add7SJan Kryl ret = -1;
471*f093add7SJan Kryl goto out;
472*f093add7SJan Kryl }
473*f093add7SJan Kryl
4742654012fSReza Sabdar switch (type) {
4752654012fSReza Sabdar case SCF_TYPE_ASTRING:
476*f093add7SJan 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*f093add7SJan 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*f093add7SJan Kryl scf_value_set_boolean(value, valbool);
4892654012fSReza Sabdar break;
4902654012fSReza Sabdar default:
4912654012fSReza Sabdar ret = -1;
4922654012fSReza Sabdar }
493*f093add7SJan Kryl if (scf_entry_add_value(entry, value) == 0) {
4942654012fSReza Sabdar /* The value is in the transaction */
4952654012fSReza Sabdar value = NULL;
496*f093add7SJan Kryl } else {
497*f093add7SJan Kryl ret = -1;
4982654012fSReza Sabdar }
4992654012fSReza Sabdar /* The entry is in the transaction */
5002654012fSReza Sabdar entry = NULL;
501*f093add7SJan Kryl
502*f093add7SJan 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*f093add7SJan 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)5208b87c155SJan 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*f093add7SJan Kryl scf_value_t *value = NULL;
525*f093add7SJan 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