1d71dbb73Sjbeck /*
2d71dbb73Sjbeck * CDDL HEADER START
3d71dbb73Sjbeck *
4d71dbb73Sjbeck * The contents of this file are subject to the terms of the
5d71dbb73Sjbeck * Common Development and Distribution License (the "License").
6d71dbb73Sjbeck * You may not use this file except in compliance with the License.
7d71dbb73Sjbeck *
8d71dbb73Sjbeck * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9d71dbb73Sjbeck * or http://www.opensolaris.org/os/licensing.
10d71dbb73Sjbeck * See the License for the specific language governing permissions
11d71dbb73Sjbeck * and limitations under the License.
12d71dbb73Sjbeck *
13d71dbb73Sjbeck * When distributing Covered Code, include this CDDL HEADER in each
14d71dbb73Sjbeck * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15d71dbb73Sjbeck * If applicable, add the following below this CDDL HEADER, with the
16d71dbb73Sjbeck * fields enclosed by brackets "[]" replaced with your own identifying
17d71dbb73Sjbeck * information: Portions Copyright [yyyy] [name of copyright owner]
18d71dbb73Sjbeck *
19d71dbb73Sjbeck * CDDL HEADER END
20d71dbb73Sjbeck */
21d71dbb73Sjbeck
22d71dbb73Sjbeck /*
23*f6da83d4SAnurag S. Maskey * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
24d71dbb73Sjbeck */
25d71dbb73Sjbeck
26d71dbb73Sjbeck /*
276ba597c5SAnurag S. Maskey * util.c contains a set of miscellaneous utility functions which,
286ba597c5SAnurag S. Maskey * among other things:
29d71dbb73Sjbeck * - start a child process
30d71dbb73Sjbeck * - look up the zone name
316ba597c5SAnurag S. Maskey * - look up/set SMF properties
326ba597c5SAnurag S. Maskey * - drop/escalate privs
33d71dbb73Sjbeck */
34d71dbb73Sjbeck
356ba597c5SAnurag S. Maskey #include <assert.h>
366ba597c5SAnurag S. Maskey #include <errno.h>
376ba597c5SAnurag S. Maskey #include <libdllink.h>
386ba597c5SAnurag S. Maskey #include <limits.h>
396ba597c5SAnurag S. Maskey #include <libscf.h>
406ba597c5SAnurag S. Maskey #include <net/if.h>
416ba597c5SAnurag S. Maskey #include <pthread.h>
426ba597c5SAnurag S. Maskey #include <pwd.h>
436ba597c5SAnurag S. Maskey #include <spawn.h>
44d71dbb73Sjbeck #include <stdarg.h>
45d71dbb73Sjbeck #include <stdio.h>
46d71dbb73Sjbeck #include <stdlib.h>
47d71dbb73Sjbeck #include <string.h>
486ba597c5SAnurag S. Maskey #include <strings.h>
49d71dbb73Sjbeck #include <stropts.h>
50d71dbb73Sjbeck #include <sys/socket.h>
516ba597c5SAnurag S. Maskey #include <sys/sockio.h>
526ba597c5SAnurag S. Maskey #include <sys/types.h>
536ba597c5SAnurag S. Maskey #include <unistd.h>
54d71dbb73Sjbeck #include <wait.h>
55d71dbb73Sjbeck #include <zone.h>
56d71dbb73Sjbeck
576ba597c5SAnurag S. Maskey #include "util.h"
586ba597c5SAnurag S. Maskey #include "llp.h"
59d71dbb73Sjbeck
60d71dbb73Sjbeck extern char **environ;
616ba597c5SAnurag S. Maskey extern sigset_t original_sigmask;
62d71dbb73Sjbeck
63d71dbb73Sjbeck /*
646ba597c5SAnurag S. Maskey * A holder for all the resources needed to get a property value
656ba597c5SAnurag S. Maskey * using libscf.
66d71dbb73Sjbeck */
676ba597c5SAnurag S. Maskey typedef struct scf_resources {
686ba597c5SAnurag S. Maskey scf_handle_t *sr_handle;
696ba597c5SAnurag S. Maskey scf_instance_t *sr_inst;
706ba597c5SAnurag S. Maskey scf_snapshot_t *sr_snap;
716ba597c5SAnurag S. Maskey scf_propertygroup_t *sr_pg;
726ba597c5SAnurag S. Maskey scf_property_t *sr_prop;
736ba597c5SAnurag S. Maskey scf_value_t *sr_val;
746ba597c5SAnurag S. Maskey scf_transaction_t *sr_tx;
756ba597c5SAnurag S. Maskey scf_transaction_entry_t *sr_ent;
766ba597c5SAnurag S. Maskey } scf_resources_t;
77d71dbb73Sjbeck
786ba597c5SAnurag S. Maskey static pthread_mutex_t uid_mutex = PTHREAD_MUTEX_INITIALIZER;
796ba597c5SAnurag S. Maskey static uid_t uid;
806ba597c5SAnurag S. Maskey static int uid_cnt;
81d71dbb73Sjbeck
82b00044a2SJames Carlson void
nwamd_escalate(void)8338f140aaSMichael Hunter nwamd_escalate(void) {
8438f140aaSMichael Hunter priv_set_t *priv_set;
8538f140aaSMichael Hunter priv_set = priv_str_to_set("zone", ",", NULL);
8638f140aaSMichael Hunter
8738f140aaSMichael Hunter if (priv_set == NULL)
8838f140aaSMichael Hunter pfail("creating privilege set: %s", strerror(errno));
8938f140aaSMichael Hunter
906ba597c5SAnurag S. Maskey (void) pthread_mutex_lock(&uid_mutex);
916ba597c5SAnurag S. Maskey if (uid == 0)
926ba597c5SAnurag S. Maskey uid = getuid();
936ba597c5SAnurag S. Maskey if (uid_cnt++ == 0) {
9438f140aaSMichael Hunter if (setppriv(PRIV_SET, PRIV_EFFECTIVE, priv_set) == -1) {
9538f140aaSMichael Hunter priv_freeset(priv_set);
9638f140aaSMichael Hunter pfail("setppriv effective: %s", strerror(errno));
9738f140aaSMichael Hunter }
98b00044a2SJames Carlson }
996ba597c5SAnurag S. Maskey (void) pthread_mutex_unlock(&uid_mutex);
10038f140aaSMichael Hunter
10138f140aaSMichael Hunter priv_freeset(priv_set);
1026ba597c5SAnurag S. Maskey }
1036ba597c5SAnurag S. Maskey
1046ba597c5SAnurag S. Maskey void
nwamd_deescalate(void)10538f140aaSMichael Hunter nwamd_deescalate(void) {
1066ba597c5SAnurag S. Maskey (void) pthread_mutex_lock(&uid_mutex);
1073773ed2dSAnurag S. Maskey
1086ba597c5SAnurag S. Maskey assert(uid_cnt > 0);
1096ba597c5SAnurag S. Maskey if (--uid_cnt == 0) {
1103773ed2dSAnurag S. Maskey priv_set_t *priv_set, *allpriv_set;
1113773ed2dSAnurag S. Maskey
11238f140aaSMichael Hunter /* build up our minimal set of privs. */
11338f140aaSMichael Hunter priv_set = priv_str_to_set("basic", ",", NULL);
11438f140aaSMichael Hunter allpriv_set = priv_str_to_set("zone", ",", NULL);
11538f140aaSMichael Hunter if (priv_set == NULL || allpriv_set == NULL)
11638f140aaSMichael Hunter pfail("converting privilege sets: %s", strerror(errno));
11738f140aaSMichael Hunter
11838f140aaSMichael Hunter (void) priv_addset(priv_set, PRIV_FILE_CHOWN_SELF);
11938f140aaSMichael Hunter (void) priv_addset(priv_set, PRIV_FILE_DAC_READ);
12038f140aaSMichael Hunter (void) priv_addset(priv_set, PRIV_FILE_DAC_WRITE);
12138f140aaSMichael Hunter (void) priv_addset(priv_set, PRIV_NET_RAWACCESS);
12238f140aaSMichael Hunter (void) priv_addset(priv_set, PRIV_NET_PRIVADDR);
12338f140aaSMichael Hunter (void) priv_addset(priv_set, PRIV_PROC_AUDIT);
12438f140aaSMichael Hunter (void) priv_addset(priv_set, PRIV_PROC_OWNER);
12538f140aaSMichael Hunter (void) priv_addset(priv_set, PRIV_PROC_SETID);
12638f140aaSMichael Hunter (void) priv_addset(priv_set, PRIV_SYS_CONFIG);
12738f140aaSMichael Hunter (void) priv_addset(priv_set, PRIV_SYS_IP_CONFIG);
12838f140aaSMichael Hunter (void) priv_addset(priv_set, PRIV_SYS_IPC_CONFIG);
12938f140aaSMichael Hunter (void) priv_addset(priv_set, PRIV_SYS_MOUNT);
13038f140aaSMichael Hunter (void) priv_addset(priv_set, PRIV_SYS_NET_CONFIG);
13138f140aaSMichael Hunter (void) priv_addset(priv_set, PRIV_SYS_RES_CONFIG);
13238f140aaSMichael Hunter (void) priv_addset(priv_set, PRIV_SYS_RESOURCE);
13338f140aaSMichael Hunter
13438f140aaSMichael Hunter /*
13538f140aaSMichael Hunter * Since our zone might not have all these privs,
13638f140aaSMichael Hunter * just ask for those that are available.
13738f140aaSMichael Hunter */
13838f140aaSMichael Hunter priv_intersect(allpriv_set, priv_set);
13938f140aaSMichael Hunter
14038f140aaSMichael Hunter if (setppriv(PRIV_SET, PRIV_INHERITABLE, priv_set) == -1) {
14138f140aaSMichael Hunter priv_freeset(allpriv_set);
14238f140aaSMichael Hunter priv_freeset(priv_set);
14338f140aaSMichael Hunter pfail("setppriv inheritable: %s", strerror(errno));
14438f140aaSMichael Hunter }
14538f140aaSMichael Hunter /*
14638f140aaSMichael Hunter * Need to ensure permitted set contains all privs so we can
14738f140aaSMichael Hunter * escalate later.
14838f140aaSMichael Hunter */
14938f140aaSMichael Hunter if (setppriv(PRIV_SET, PRIV_PERMITTED, allpriv_set) == -1) {
15038f140aaSMichael Hunter priv_freeset(allpriv_set);
15138f140aaSMichael Hunter priv_freeset(priv_set);
15238f140aaSMichael Hunter pfail("setppriv permitted: %s", strerror(errno));
15338f140aaSMichael Hunter }
15438f140aaSMichael Hunter /*
15538f140aaSMichael Hunter * We need to find a smaller set of privs that are important to
15638f140aaSMichael Hunter * us. Otherwise we really are not gaining much by doing this.
15738f140aaSMichael Hunter */
15838f140aaSMichael Hunter if (setppriv(PRIV_SET, PRIV_EFFECTIVE, priv_set) == -1) {
15938f140aaSMichael Hunter priv_freeset(allpriv_set);
16038f140aaSMichael Hunter priv_freeset(priv_set);
16138f140aaSMichael Hunter pfail("setppriv effective: %s", strerror(errno));
16238f140aaSMichael Hunter }
16338f140aaSMichael Hunter
16438f140aaSMichael Hunter priv_freeset(priv_set);
16538f140aaSMichael Hunter priv_freeset(allpriv_set);
166b00044a2SJames Carlson }
1673773ed2dSAnurag S. Maskey (void) pthread_mutex_unlock(&uid_mutex);
1683773ed2dSAnurag S. Maskey }
169b00044a2SJames Carlson
170d71dbb73Sjbeck /*
171d71dbb73Sjbeck *
172d71dbb73Sjbeck * This starts a child process determined by command. If command contains a
173d71dbb73Sjbeck * slash then it is assumed to be a full path; otherwise the path is searched
174d71dbb73Sjbeck * for an executable file with the name command. Command is also used as
175d71dbb73Sjbeck * argv[0] of the new process. The rest of the arguments of the function
176d71dbb73Sjbeck * up to the first NULL make up pointers to arguments of the new process.
177d71dbb73Sjbeck *
178d71dbb73Sjbeck * This function returns child exit status on success and -1 on failure.
179d71dbb73Sjbeck *
180d71dbb73Sjbeck * NOTE: original_sigmask must be set before this function is called.
181d71dbb73Sjbeck */
182d71dbb73Sjbeck int
nwamd_start_childv(const char * command,char const * const * argv)1836ba597c5SAnurag S. Maskey nwamd_start_childv(const char *command, char const * const *argv)
184d71dbb73Sjbeck {
185d71dbb73Sjbeck posix_spawnattr_t attr;
186d71dbb73Sjbeck sigset_t fullset;
187d71dbb73Sjbeck int i, rc, status, n;
188d71dbb73Sjbeck pid_t pid;
189d71dbb73Sjbeck char vbuf[1024];
190d71dbb73Sjbeck
191d71dbb73Sjbeck vbuf[0] = 0;
192d71dbb73Sjbeck n = sizeof (vbuf);
193d71dbb73Sjbeck for (i = 1; argv[i] != NULL && n > 2; i++) {
194d71dbb73Sjbeck n -= strlcat(vbuf, " ", n);
195d71dbb73Sjbeck n -= strlcat(vbuf, argv[i], n);
196d71dbb73Sjbeck }
197d71dbb73Sjbeck if (argv[i] != NULL || n < 0)
1986ba597c5SAnurag S. Maskey nlog(LOG_ERR, "nwamd_start_childv can't log full arg vector");
199d71dbb73Sjbeck
200d71dbb73Sjbeck if ((rc = posix_spawnattr_init(&attr)) != 0) {
2016ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "posix_spawnattr_init %d %s\n",
2026ba597c5SAnurag S. Maskey rc, strerror(rc));
203d71dbb73Sjbeck return (-1);
204d71dbb73Sjbeck }
205d71dbb73Sjbeck (void) sigfillset(&fullset);
206d71dbb73Sjbeck if ((rc = posix_spawnattr_setsigdefault(&attr, &fullset)) != 0) {
2076ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "setsigdefault %d %s\n", rc, strerror(rc));
208d71dbb73Sjbeck return (-1);
209d71dbb73Sjbeck }
210d71dbb73Sjbeck if ((rc = posix_spawnattr_setsigmask(&attr, &original_sigmask)) != 0) {
2116ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "setsigmask %d %s\n", rc, strerror(rc));
212d71dbb73Sjbeck return (-1);
213d71dbb73Sjbeck }
214d71dbb73Sjbeck if ((rc = posix_spawnattr_setflags(&attr,
215d71dbb73Sjbeck POSIX_SPAWN_SETSIGDEF|POSIX_SPAWN_SETSIGMASK)) != 0) {
2166ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "setflags %d %s\n", rc, strerror(rc));
217d71dbb73Sjbeck return (-1);
218d71dbb73Sjbeck }
219d71dbb73Sjbeck
220d71dbb73Sjbeck if ((rc = posix_spawnp(&pid, command, NULL, &attr, (char * const *)argv,
221d71dbb73Sjbeck environ)) > 0) {
2226ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "posix_spawnp failed errno %d", rc);
223d71dbb73Sjbeck return (-1);
224d71dbb73Sjbeck }
225d71dbb73Sjbeck
226d71dbb73Sjbeck if ((rc = posix_spawnattr_destroy(&attr)) != 0) {
2276ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "posix_spawn_attr_destroy %d %s\n",
2286ba597c5SAnurag S. Maskey rc, strerror(rc));
229d71dbb73Sjbeck return (-1);
230d71dbb73Sjbeck }
231d71dbb73Sjbeck
232d71dbb73Sjbeck (void) waitpid(pid, &status, 0);
233d71dbb73Sjbeck if (WIFSIGNALED(status) || WIFSTOPPED(status)) {
234d71dbb73Sjbeck i = WIFSIGNALED(status) ? WTERMSIG(status) : WSTOPSIG(status);
2356ba597c5SAnurag S. Maskey nlog(LOG_ERR, "'%s%s' %s with signal %d (%s)", command, vbuf,
236d71dbb73Sjbeck (WIFSIGNALED(status) ? "terminated" : "stopped"), i,
237d71dbb73Sjbeck strsignal(i));
238d71dbb73Sjbeck return (-2);
239d71dbb73Sjbeck } else {
2406ba597c5SAnurag S. Maskey nlog(LOG_INFO, "'%s%s' completed normally: %d", command, vbuf,
241d71dbb73Sjbeck WEXITSTATUS(status));
242d71dbb73Sjbeck return (WEXITSTATUS(status));
243d71dbb73Sjbeck }
244d71dbb73Sjbeck }
245d71dbb73Sjbeck
2466ba597c5SAnurag S. Maskey /*
2476ba597c5SAnurag S. Maskey * For global zone, check if the link is used by a non-global
2486ba597c5SAnurag S. Maskey * zone, note that the non-global zones doesn't need this check,
2496ba597c5SAnurag S. Maskey * because zoneadm has taken care of this when the zone boots.
2506ba597c5SAnurag S. Maskey * In the global zone, we ignore events for local-zone-owned links
2516ba597c5SAnurag S. Maskey * since these are taken care of by the local zone's network
2526ba597c5SAnurag S. Maskey * configuration services.
2536ba597c5SAnurag S. Maskey */
2546ba597c5SAnurag S. Maskey boolean_t
nwamd_link_belongs_to_this_zone(const char * linkname)2556ba597c5SAnurag S. Maskey nwamd_link_belongs_to_this_zone(const char *linkname)
256d71dbb73Sjbeck {
2576ba597c5SAnurag S. Maskey zoneid_t zoneid;
2586ba597c5SAnurag S. Maskey char zonename[ZONENAME_MAX];
2596ba597c5SAnurag S. Maskey int ret;
260d71dbb73Sjbeck
2616ba597c5SAnurag S. Maskey zoneid = getzoneid();
2626ba597c5SAnurag S. Maskey if (zoneid == GLOBAL_ZONEID) {
2636ba597c5SAnurag S. Maskey datalink_id_t linkid;
2646ba597c5SAnurag S. Maskey dladm_status_t status;
2656ba597c5SAnurag S. Maskey char errstr[DLADM_STRSIZE];
266d71dbb73Sjbeck
2676ba597c5SAnurag S. Maskey if ((status = dladm_name2info(dld_handle, linkname, &linkid,
2686ba597c5SAnurag S. Maskey NULL, NULL, NULL)) != DLADM_STATUS_OK) {
2696ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_link_belongs_to_this_zone: "
2706ba597c5SAnurag S. Maskey "could not get linkid for %s: %s",
2716ba597c5SAnurag S. Maskey linkname, dladm_status2str(status, errstr));
2726ba597c5SAnurag S. Maskey return (B_FALSE);
2736ba597c5SAnurag S. Maskey }
2746ba597c5SAnurag S. Maskey zoneid = ALL_ZONES;
2756ba597c5SAnurag S. Maskey ret = zone_check_datalink(&zoneid, linkid);
2766ba597c5SAnurag S. Maskey if (ret == 0) {
2776ba597c5SAnurag S. Maskey (void) getzonenamebyid(zoneid, zonename, ZONENAME_MAX);
2786ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_link_belongs_to_this_zone: "
2796ba597c5SAnurag S. Maskey "%s is used by non-global zone: %s",
2806ba597c5SAnurag S. Maskey linkname, zonename);
2816ba597c5SAnurag S. Maskey return (B_FALSE);
282d71dbb73Sjbeck }
283d71dbb73Sjbeck }
2846ba597c5SAnurag S. Maskey return (B_TRUE);
285d71dbb73Sjbeck }
286d71dbb73Sjbeck
2876ba597c5SAnurag S. Maskey /*
2886ba597c5SAnurag S. Maskey * Inputs:
2896ba597c5SAnurag S. Maskey * res is a pointer to the scf_resources_t to be released.
2906ba597c5SAnurag S. Maskey */
2916ba597c5SAnurag S. Maskey static void
release_scf_resources(scf_resources_t * res)2926ba597c5SAnurag S. Maskey release_scf_resources(scf_resources_t *res)
2936ba597c5SAnurag S. Maskey {
2946ba597c5SAnurag S. Maskey scf_entry_destroy(res->sr_ent);
2956ba597c5SAnurag S. Maskey scf_transaction_destroy(res->sr_tx);
2966ba597c5SAnurag S. Maskey scf_value_destroy(res->sr_val);
2976ba597c5SAnurag S. Maskey scf_property_destroy(res->sr_prop);
2986ba597c5SAnurag S. Maskey scf_pg_destroy(res->sr_pg);
2996ba597c5SAnurag S. Maskey scf_snapshot_destroy(res->sr_snap);
3006ba597c5SAnurag S. Maskey scf_instance_destroy(res->sr_inst);
3016ba597c5SAnurag S. Maskey (void) scf_handle_unbind(res->sr_handle);
3026ba597c5SAnurag S. Maskey scf_handle_destroy(res->sr_handle);
3036ba597c5SAnurag S. Maskey }
3046ba597c5SAnurag S. Maskey
3056ba597c5SAnurag S. Maskey /*
3066ba597c5SAnurag S. Maskey * Inputs:
3076ba597c5SAnurag S. Maskey * fmri is the instance to look up
3086ba597c5SAnurag S. Maskey * Outputs:
3096ba597c5SAnurag S. Maskey * res is a pointer to an scf_resources_t. This is an internal
3106ba597c5SAnurag S. Maskey * structure that holds all the handles needed to get a specific
3116ba597c5SAnurag S. Maskey * property from the running snapshot; on a successful return it
3126ba597c5SAnurag S. Maskey * contains the scf_value_t that should be passed to the desired
3136ba597c5SAnurag S. Maskey * scf_value_get_foo() function, and must be freed after use by
3146ba597c5SAnurag S. Maskey * calling release_scf_resources(). On a failure return, any
3156ba597c5SAnurag S. Maskey * resources that may have been assigned to res are released, so
3166ba597c5SAnurag S. Maskey * the caller does not need to do any cleanup in the failure case.
3176ba597c5SAnurag S. Maskey * Returns:
3186ba597c5SAnurag S. Maskey * 0 on success
3196ba597c5SAnurag S. Maskey * -1 on failure
3206ba597c5SAnurag S. Maskey */
3216ba597c5SAnurag S. Maskey
3226ba597c5SAnurag S. Maskey static int
create_scf_resources(const char * fmri,scf_resources_t * res)3236ba597c5SAnurag S. Maskey create_scf_resources(const char *fmri, scf_resources_t *res)
3246ba597c5SAnurag S. Maskey {
3256ba597c5SAnurag S. Maskey res->sr_tx = NULL;
3266ba597c5SAnurag S. Maskey res->sr_ent = NULL;
3276ba597c5SAnurag S. Maskey res->sr_inst = NULL;
3286ba597c5SAnurag S. Maskey res->sr_snap = NULL;
3296ba597c5SAnurag S. Maskey res->sr_pg = NULL;
3306ba597c5SAnurag S. Maskey res->sr_prop = NULL;
3316ba597c5SAnurag S. Maskey res->sr_val = NULL;
3326ba597c5SAnurag S. Maskey
3336ba597c5SAnurag S. Maskey if ((res->sr_handle = scf_handle_create(SCF_VERSION)) == NULL) {
3346ba597c5SAnurag S. Maskey return (-1);
3356ba597c5SAnurag S. Maskey }
3366ba597c5SAnurag S. Maskey
3376ba597c5SAnurag S. Maskey if (scf_handle_bind(res->sr_handle) != 0) {
3386ba597c5SAnurag S. Maskey scf_handle_destroy(res->sr_handle);
3396ba597c5SAnurag S. Maskey return (-1);
3406ba597c5SAnurag S. Maskey }
3416ba597c5SAnurag S. Maskey if ((res->sr_inst = scf_instance_create(res->sr_handle)) == NULL) {
3426ba597c5SAnurag S. Maskey goto failure;
3436ba597c5SAnurag S. Maskey }
3446ba597c5SAnurag S. Maskey if (scf_handle_decode_fmri(res->sr_handle, fmri, NULL, NULL,
3456ba597c5SAnurag S. Maskey res->sr_inst, NULL, NULL, SCF_DECODE_FMRI_REQUIRE_INSTANCE) != 0) {
3466ba597c5SAnurag S. Maskey goto failure;
3476ba597c5SAnurag S. Maskey }
3486ba597c5SAnurag S. Maskey if ((res->sr_snap = scf_snapshot_create(res->sr_handle)) == NULL) {
3496ba597c5SAnurag S. Maskey goto failure;
3506ba597c5SAnurag S. Maskey }
3516ba597c5SAnurag S. Maskey if (scf_instance_get_snapshot(res->sr_inst, "running",
3526ba597c5SAnurag S. Maskey res->sr_snap) != 0) {
3536ba597c5SAnurag S. Maskey goto failure;
3546ba597c5SAnurag S. Maskey }
3556ba597c5SAnurag S. Maskey if ((res->sr_pg = scf_pg_create(res->sr_handle)) == NULL) {
3566ba597c5SAnurag S. Maskey goto failure;
3576ba597c5SAnurag S. Maskey }
3586ba597c5SAnurag S. Maskey if ((res->sr_prop = scf_property_create(res->sr_handle)) == NULL) {
3596ba597c5SAnurag S. Maskey goto failure;
3606ba597c5SAnurag S. Maskey }
3616ba597c5SAnurag S. Maskey if ((res->sr_val = scf_value_create(res->sr_handle)) == NULL) {
3626ba597c5SAnurag S. Maskey goto failure;
3636ba597c5SAnurag S. Maskey }
3646ba597c5SAnurag S. Maskey if ((res->sr_tx = scf_transaction_create(res->sr_handle)) == NULL) {
3656ba597c5SAnurag S. Maskey goto failure;
3666ba597c5SAnurag S. Maskey }
3676ba597c5SAnurag S. Maskey if ((res->sr_ent = scf_entry_create(res->sr_handle)) == NULL) {
3686ba597c5SAnurag S. Maskey goto failure;
3696ba597c5SAnurag S. Maskey }
3706ba597c5SAnurag S. Maskey return (0);
3716ba597c5SAnurag S. Maskey
3726ba597c5SAnurag S. Maskey failure:
3736ba597c5SAnurag S. Maskey nlog(LOG_ERR, "create_scf_resources failed: %s",
3746ba597c5SAnurag S. Maskey scf_strerror(scf_error()));
3756ba597c5SAnurag S. Maskey release_scf_resources(res);
3766ba597c5SAnurag S. Maskey return (-1);
3776ba597c5SAnurag S. Maskey }
3786ba597c5SAnurag S. Maskey
3796ba597c5SAnurag S. Maskey /*
3806ba597c5SAnurag S. Maskey * Inputs:
3816ba597c5SAnurag S. Maskey * fmri is the instance to look up
3826ba597c5SAnurag S. Maskey * pg is the property group to look up
3836ba597c5SAnurag S. Maskey * prop is the property within that group to look up
3846ba597c5SAnurag S. Maskey * running specifies if running snapshot is to be used
3856ba597c5SAnurag S. Maskey * Outputs:
3866ba597c5SAnurag S. Maskey * res is a pointer to an scf_resources_t. This is an internal
3876ba597c5SAnurag S. Maskey * structure that holds all the handles needed to get a specific
3886ba597c5SAnurag S. Maskey * property from the running snapshot; on a successful return it
3896ba597c5SAnurag S. Maskey * contains the scf_value_t that should be passed to the desired
3906ba597c5SAnurag S. Maskey * scf_value_get_foo() function, and must be freed after use by
3916ba597c5SAnurag S. Maskey * calling release_scf_resources(). On a failure return, any
3926ba597c5SAnurag S. Maskey * resources that may have been assigned to res are released, so
3936ba597c5SAnurag S. Maskey * the caller does not need to do any cleanup in the failure case.
3946ba597c5SAnurag S. Maskey * Returns:
3956ba597c5SAnurag S. Maskey * 0 on success
3966ba597c5SAnurag S. Maskey * -1 on failure
3976ba597c5SAnurag S. Maskey */
3986ba597c5SAnurag S. Maskey static int
get_property_value(const char * fmri,const char * pg,const char * prop,boolean_t running,scf_resources_t * res)3996ba597c5SAnurag S. Maskey get_property_value(const char *fmri, const char *pg, const char *prop,
4006ba597c5SAnurag S. Maskey boolean_t running, scf_resources_t *res)
4016ba597c5SAnurag S. Maskey {
4026ba597c5SAnurag S. Maskey if (create_scf_resources(fmri, res) != 0)
4036ba597c5SAnurag S. Maskey return (-1);
4046ba597c5SAnurag S. Maskey
4056ba597c5SAnurag S. Maskey if (scf_instance_get_pg_composed(res->sr_inst,
4066ba597c5SAnurag S. Maskey running ? res->sr_snap : NULL, pg, res->sr_pg) != 0) {
4076ba597c5SAnurag S. Maskey goto failure;
4086ba597c5SAnurag S. Maskey }
4096ba597c5SAnurag S. Maskey if (scf_pg_get_property(res->sr_pg, prop, res->sr_prop) != 0) {
4106ba597c5SAnurag S. Maskey goto failure;
4116ba597c5SAnurag S. Maskey }
4126ba597c5SAnurag S. Maskey if (scf_property_get_value(res->sr_prop, res->sr_val) != 0) {
4136ba597c5SAnurag S. Maskey goto failure;
4146ba597c5SAnurag S. Maskey }
4156ba597c5SAnurag S. Maskey return (0);
4166ba597c5SAnurag S. Maskey
4176ba597c5SAnurag S. Maskey failure:
4186ba597c5SAnurag S. Maskey release_scf_resources(res);
4196ba597c5SAnurag S. Maskey return (-1);
4206ba597c5SAnurag S. Maskey }
4216ba597c5SAnurag S. Maskey
4226ba597c5SAnurag S. Maskey /*
4236ba597c5SAnurag S. Maskey * Inputs:
4246ba597c5SAnurag S. Maskey * lfmri is the instance fmri to look up
4256ba597c5SAnurag S. Maskey * lpg is the property group to look up
4266ba597c5SAnurag S. Maskey * lprop is the property within that group to look up
4276ba597c5SAnurag S. Maskey * Outputs:
4286ba597c5SAnurag S. Maskey * answer is a pointer to the property value
4296ba597c5SAnurag S. Maskey * Returns:
4306ba597c5SAnurag S. Maskey * 0 on success
4316ba597c5SAnurag S. Maskey * -1 on failure
4326ba597c5SAnurag S. Maskey * If successful, the property value is retured in *answer.
4336ba597c5SAnurag S. Maskey * Otherwise, *answer is undefined, and it is up to the caller to decide
4346ba597c5SAnurag S. Maskey * how to handle that case.
4356ba597c5SAnurag S. Maskey */
4366ba597c5SAnurag S. Maskey int
nwamd_lookup_boolean_property(const char * lfmri,const char * lpg,const char * lprop,boolean_t * answer)4376ba597c5SAnurag S. Maskey nwamd_lookup_boolean_property(const char *lfmri, const char *lpg,
4386ba597c5SAnurag S. Maskey const char *lprop, boolean_t *answer)
4396ba597c5SAnurag S. Maskey {
4406ba597c5SAnurag S. Maskey int result = -1;
4416ba597c5SAnurag S. Maskey scf_resources_t res;
4426ba597c5SAnurag S. Maskey uint8_t prop_val;
4436ba597c5SAnurag S. Maskey
4446ba597c5SAnurag S. Maskey if (get_property_value(lfmri, lpg, lprop, B_TRUE, &res) != 0) {
4456ba597c5SAnurag S. Maskey
4466ba597c5SAnurag S. Maskey /*
4476ba597c5SAnurag S. Maskey * an error was already logged by get_property_value,
4486ba597c5SAnurag S. Maskey * and it released any resources assigned to res before
4496ba597c5SAnurag S. Maskey * returning.
4506ba597c5SAnurag S. Maskey */
4516ba597c5SAnurag S. Maskey return (result);
4526ba597c5SAnurag S. Maskey }
4536ba597c5SAnurag S. Maskey if (scf_value_get_boolean(res.sr_val, &prop_val) != 0) {
4546ba597c5SAnurag S. Maskey goto cleanup;
4556ba597c5SAnurag S. Maskey }
4566ba597c5SAnurag S. Maskey *answer = (boolean_t)prop_val;
4576ba597c5SAnurag S. Maskey result = 0;
4586ba597c5SAnurag S. Maskey cleanup:
4596ba597c5SAnurag S. Maskey release_scf_resources(&res);
4606ba597c5SAnurag S. Maskey return (result);
4616ba597c5SAnurag S. Maskey }
4626ba597c5SAnurag S. Maskey
4636ba597c5SAnurag S. Maskey /*
4646ba597c5SAnurag S. Maskey * Inputs:
4656ba597c5SAnurag S. Maskey * lfmri is the instance fmri to look up
4666ba597c5SAnurag S. Maskey * lpg is the property group to look up
4676ba597c5SAnurag S. Maskey * lprop is the property within that group to look up
4686ba597c5SAnurag S. Maskey * buf is the place to put the answer
4696ba597c5SAnurag S. Maskey * bufsz is the size of buf
4706ba597c5SAnurag S. Maskey * Outputs:
4716ba597c5SAnurag S. Maskey *
4726ba597c5SAnurag S. Maskey * Returns:
4736ba597c5SAnurag S. Maskey * 0 on success
4746ba597c5SAnurag S. Maskey * -1 on failure
4756ba597c5SAnurag S. Maskey * If successful, the property value is retured in buf.
4766ba597c5SAnurag S. Maskey * Otherwise, buf is undefined, and it is up to the caller to decide
4776ba597c5SAnurag S. Maskey * how to handle that case.
4786ba597c5SAnurag S. Maskey */
4796ba597c5SAnurag S. Maskey int
nwamd_lookup_string_property(const char * lfmri,const char * lpg,const char * lprop,char * buf,size_t bufsz)4806ba597c5SAnurag S. Maskey nwamd_lookup_string_property(const char *lfmri, const char *lpg,
4816ba597c5SAnurag S. Maskey const char *lprop, char *buf, size_t bufsz)
4826ba597c5SAnurag S. Maskey {
4836ba597c5SAnurag S. Maskey int result = -1;
4846ba597c5SAnurag S. Maskey scf_resources_t res;
4856ba597c5SAnurag S. Maskey
4866ba597c5SAnurag S. Maskey if (get_property_value(lfmri, lpg, lprop, B_TRUE, &res) != 0) {
4876ba597c5SAnurag S. Maskey /*
4886ba597c5SAnurag S. Maskey * The above function fails when trying to get a
4896ba597c5SAnurag S. Maskey * non-persistent property group from the running snapshot.
4906ba597c5SAnurag S. Maskey * Try going for the non-running snapshot.
4916ba597c5SAnurag S. Maskey */
4926ba597c5SAnurag S. Maskey if (get_property_value(lfmri, lpg, lprop, B_FALSE, &res) != 0) {
4936ba597c5SAnurag S. Maskey /*
4946ba597c5SAnurag S. Maskey * an error was already logged by get_property_value,
4956ba597c5SAnurag S. Maskey * and it released any resources assigned to res before
4966ba597c5SAnurag S. Maskey * returning.
4976ba597c5SAnurag S. Maskey */
4986ba597c5SAnurag S. Maskey return (result);
4996ba597c5SAnurag S. Maskey }
5006ba597c5SAnurag S. Maskey }
5016ba597c5SAnurag S. Maskey if (scf_value_get_astring(res.sr_val, buf, bufsz) == 0)
5026ba597c5SAnurag S. Maskey goto cleanup;
5036ba597c5SAnurag S. Maskey
5046ba597c5SAnurag S. Maskey result = 0;
5056ba597c5SAnurag S. Maskey cleanup:
5066ba597c5SAnurag S. Maskey release_scf_resources(&res);
5076ba597c5SAnurag S. Maskey return (result);
5086ba597c5SAnurag S. Maskey }
5096ba597c5SAnurag S. Maskey
5106ba597c5SAnurag S. Maskey /*
5116ba597c5SAnurag S. Maskey * Inputs:
5126ba597c5SAnurag S. Maskey * lfmri is the instance fmri to look up
5136ba597c5SAnurag S. Maskey * lpg is the property group to look up
5146ba597c5SAnurag S. Maskey * lprop is the property within that group to look up
5156ba597c5SAnurag S. Maskey * Outputs:
5166ba597c5SAnurag S. Maskey * answer is a pointer to the property value
5176ba597c5SAnurag S. Maskey * Returns:
5186ba597c5SAnurag S. Maskey * 0 on success
5196ba597c5SAnurag S. Maskey * -1 on failure
5206ba597c5SAnurag S. Maskey * If successful, the property value is retured in *answer.
5216ba597c5SAnurag S. Maskey * Otherwise, *answer is undefined, and it is up to the caller to decide
5226ba597c5SAnurag S. Maskey * how to handle that case.
5236ba597c5SAnurag S. Maskey */
5246ba597c5SAnurag S. Maskey int
nwamd_lookup_count_property(const char * lfmri,const char * lpg,const char * lprop,uint64_t * answer)5256ba597c5SAnurag S. Maskey nwamd_lookup_count_property(const char *lfmri, const char *lpg,
5266ba597c5SAnurag S. Maskey const char *lprop, uint64_t *answer)
5276ba597c5SAnurag S. Maskey {
5286ba597c5SAnurag S. Maskey int result = -1;
5296ba597c5SAnurag S. Maskey scf_resources_t res;
5306ba597c5SAnurag S. Maskey
5316ba597c5SAnurag S. Maskey if (get_property_value(lfmri, lpg, lprop, B_TRUE, &res) != 0) {
5326ba597c5SAnurag S. Maskey
5336ba597c5SAnurag S. Maskey /*
5346ba597c5SAnurag S. Maskey * an error was already logged by get_property_value,
5356ba597c5SAnurag S. Maskey * and it released any resources assigned to res before
5366ba597c5SAnurag S. Maskey * returning.
5376ba597c5SAnurag S. Maskey */
5386ba597c5SAnurag S. Maskey return (result);
5396ba597c5SAnurag S. Maskey }
5406ba597c5SAnurag S. Maskey if (scf_value_get_count(res.sr_val, answer) != 0) {
5416ba597c5SAnurag S. Maskey goto cleanup;
5426ba597c5SAnurag S. Maskey }
5436ba597c5SAnurag S. Maskey result = 0;
5446ba597c5SAnurag S. Maskey cleanup:
5456ba597c5SAnurag S. Maskey release_scf_resources(&res);
5466ba597c5SAnurag S. Maskey return (result);
5476ba597c5SAnurag S. Maskey }
5486ba597c5SAnurag S. Maskey
5496ba597c5SAnurag S. Maskey static int
set_property_value(scf_resources_t * res,const char * propname,scf_type_t proptype)5506ba597c5SAnurag S. Maskey set_property_value(scf_resources_t *res, const char *propname,
5516ba597c5SAnurag S. Maskey scf_type_t proptype)
5526ba597c5SAnurag S. Maskey {
5536ba597c5SAnurag S. Maskey int result = -1;
5546ba597c5SAnurag S. Maskey boolean_t new;
5556ba597c5SAnurag S. Maskey
5566ba597c5SAnurag S. Maskey retry:
5576ba597c5SAnurag S. Maskey new = (scf_pg_get_property(res->sr_pg, propname, res->sr_prop) != 0);
5586ba597c5SAnurag S. Maskey
5596ba597c5SAnurag S. Maskey if (scf_transaction_start(res->sr_tx, res->sr_pg) == -1) {
5606ba597c5SAnurag S. Maskey goto failure;
5616ba597c5SAnurag S. Maskey }
5626ba597c5SAnurag S. Maskey if (new) {
5636ba597c5SAnurag S. Maskey if (scf_transaction_property_new(res->sr_tx, res->sr_ent,
5646ba597c5SAnurag S. Maskey propname, proptype) == -1) {
5656ba597c5SAnurag S. Maskey goto failure;
5666ba597c5SAnurag S. Maskey }
5676ba597c5SAnurag S. Maskey } else {
5686ba597c5SAnurag S. Maskey if (scf_transaction_property_change(res->sr_tx, res->sr_ent,
5696ba597c5SAnurag S. Maskey propname, proptype) == -1) {
5706ba597c5SAnurag S. Maskey goto failure;
5716ba597c5SAnurag S. Maskey }
5726ba597c5SAnurag S. Maskey }
5736ba597c5SAnurag S. Maskey
5746ba597c5SAnurag S. Maskey if (scf_entry_add_value(res->sr_ent, res->sr_val) != 0) {
5756ba597c5SAnurag S. Maskey goto failure;
5766ba597c5SAnurag S. Maskey }
5776ba597c5SAnurag S. Maskey
5786ba597c5SAnurag S. Maskey result = scf_transaction_commit(res->sr_tx);
5796ba597c5SAnurag S. Maskey if (result == 0) {
5806ba597c5SAnurag S. Maskey scf_transaction_reset(res->sr_tx);
5816ba597c5SAnurag S. Maskey if (scf_pg_update(res->sr_pg) == -1) {
5826ba597c5SAnurag S. Maskey goto failure;
5836ba597c5SAnurag S. Maskey }
5846ba597c5SAnurag S. Maskey nlog(LOG_INFO, "set_property_value: transaction commit failed "
5856ba597c5SAnurag S. Maskey "for %s; retrying", propname);
5866ba597c5SAnurag S. Maskey goto retry;
5876ba597c5SAnurag S. Maskey }
5886ba597c5SAnurag S. Maskey if (result == -1)
5896ba597c5SAnurag S. Maskey goto failure;
5906ba597c5SAnurag S. Maskey return (0);
5916ba597c5SAnurag S. Maskey
5926ba597c5SAnurag S. Maskey failure:
5936ba597c5SAnurag S. Maskey return (-1);
5946ba597c5SAnurag S. Maskey }
5956ba597c5SAnurag S. Maskey
5966ba597c5SAnurag S. Maskey int
nwamd_set_count_property(const char * fmri,const char * pg,const char * prop,uint64_t count)5976ba597c5SAnurag S. Maskey nwamd_set_count_property(const char *fmri, const char *pg, const char *prop,
5986ba597c5SAnurag S. Maskey uint64_t count)
5996ba597c5SAnurag S. Maskey {
6006ba597c5SAnurag S. Maskey scf_resources_t res;
6016ba597c5SAnurag S. Maskey
6026ba597c5SAnurag S. Maskey if (create_scf_resources(fmri, &res) != 0)
6036ba597c5SAnurag S. Maskey return (-1);
6046ba597c5SAnurag S. Maskey
6056ba597c5SAnurag S. Maskey if (scf_instance_add_pg(res.sr_inst, pg, SCF_GROUP_APPLICATION,
6066ba597c5SAnurag S. Maskey SCF_PG_FLAG_NONPERSISTENT, res.sr_pg) != 0) {
6076ba597c5SAnurag S. Maskey if (scf_error() != SCF_ERROR_EXISTS)
6086ba597c5SAnurag S. Maskey goto failure;
6096ba597c5SAnurag S. Maskey if (scf_instance_get_pg_composed(res.sr_inst, NULL, pg,
6106ba597c5SAnurag S. Maskey res.sr_pg) != 0)
6116ba597c5SAnurag S. Maskey goto failure;
6126ba597c5SAnurag S. Maskey }
6136ba597c5SAnurag S. Maskey
6146ba597c5SAnurag S. Maskey scf_value_set_count(res.sr_val, (uint64_t)count);
6156ba597c5SAnurag S. Maskey
6166ba597c5SAnurag S. Maskey if (set_property_value(&res, prop, SCF_TYPE_COUNT) != 0)
6176ba597c5SAnurag S. Maskey goto failure;
6186ba597c5SAnurag S. Maskey
6196ba597c5SAnurag S. Maskey release_scf_resources(&res);
6206ba597c5SAnurag S. Maskey return (0);
6216ba597c5SAnurag S. Maskey
6226ba597c5SAnurag S. Maskey failure:
6236ba597c5SAnurag S. Maskey nlog(LOG_INFO, "nwamd_set_count_property: scf failure %s while "
6246ba597c5SAnurag S. Maskey "setting %s", scf_strerror(scf_error()), prop);
6256ba597c5SAnurag S. Maskey release_scf_resources(&res);
6266ba597c5SAnurag S. Maskey return (-1);
6276ba597c5SAnurag S. Maskey }
6286ba597c5SAnurag S. Maskey
6296ba597c5SAnurag S. Maskey int
nwamd_set_string_property(const char * fmri,const char * pg,const char * prop,const char * str)6306ba597c5SAnurag S. Maskey nwamd_set_string_property(const char *fmri, const char *pg, const char *prop,
6316ba597c5SAnurag S. Maskey const char *str)
6326ba597c5SAnurag S. Maskey {
6336ba597c5SAnurag S. Maskey scf_resources_t res;
6346ba597c5SAnurag S. Maskey
6356ba597c5SAnurag S. Maskey if (create_scf_resources(fmri, &res) != 0)
6366ba597c5SAnurag S. Maskey return (-1);
6376ba597c5SAnurag S. Maskey
6386ba597c5SAnurag S. Maskey if (scf_instance_add_pg(res.sr_inst, pg, SCF_GROUP_APPLICATION,
6396ba597c5SAnurag S. Maskey SCF_PG_FLAG_NONPERSISTENT, res.sr_pg) != 0) {
6406ba597c5SAnurag S. Maskey if (scf_error() != SCF_ERROR_EXISTS)
6416ba597c5SAnurag S. Maskey goto failure;
6426ba597c5SAnurag S. Maskey if (scf_instance_get_pg_composed(res.sr_inst, NULL, pg,
6436ba597c5SAnurag S. Maskey res.sr_pg) != 0)
6446ba597c5SAnurag S. Maskey goto failure;
6456ba597c5SAnurag S. Maskey }
6466ba597c5SAnurag S. Maskey
6476ba597c5SAnurag S. Maskey if (scf_value_set_astring(res.sr_val, str) != 0)
6486ba597c5SAnurag S. Maskey goto failure;
6496ba597c5SAnurag S. Maskey
6506ba597c5SAnurag S. Maskey if (set_property_value(&res, prop, SCF_TYPE_ASTRING) != 0)
6516ba597c5SAnurag S. Maskey goto failure;
6526ba597c5SAnurag S. Maskey
6536ba597c5SAnurag S. Maskey release_scf_resources(&res);
6546ba597c5SAnurag S. Maskey return (0);
6556ba597c5SAnurag S. Maskey
6566ba597c5SAnurag S. Maskey failure:
6576ba597c5SAnurag S. Maskey nlog(LOG_INFO, "nwamd_set_string_property: scf failure %s while "
6586ba597c5SAnurag S. Maskey "setting %s", scf_strerror(scf_error()), prop);
6596ba597c5SAnurag S. Maskey release_scf_resources(&res);
6606ba597c5SAnurag S. Maskey return (-1);
6616ba597c5SAnurag S. Maskey }
6626ba597c5SAnurag S. Maskey
6636ba597c5SAnurag S. Maskey /*
6646ba597c5SAnurag S. Maskey * Deletes property prop from property group pg in SMF instance fmri.
6656ba597c5SAnurag S. Maskey * Returns 0 on success, -1 on failure.
6666ba597c5SAnurag S. Maskey */
6676ba597c5SAnurag S. Maskey int
nwamd_delete_scf_property(const char * fmri,const char * pg,const char * prop)6686ba597c5SAnurag S. Maskey nwamd_delete_scf_property(const char *fmri, const char *pg, const char *prop)
6696ba597c5SAnurag S. Maskey {
6706ba597c5SAnurag S. Maskey scf_resources_t res;
6716ba597c5SAnurag S. Maskey int result = -1;
6726ba597c5SAnurag S. Maskey
6736ba597c5SAnurag S. Maskey if (create_scf_resources(fmri, &res) != 0)
6746ba597c5SAnurag S. Maskey return (-1);
6756ba597c5SAnurag S. Maskey
6766ba597c5SAnurag S. Maskey if (scf_instance_add_pg(res.sr_inst, pg, SCF_GROUP_APPLICATION,
6776ba597c5SAnurag S. Maskey SCF_PG_FLAG_NONPERSISTENT, res.sr_pg) != 0) {
6786ba597c5SAnurag S. Maskey if (scf_error() != SCF_ERROR_EXISTS)
6796ba597c5SAnurag S. Maskey goto failure;
6806ba597c5SAnurag S. Maskey if (scf_instance_get_pg_composed(res.sr_inst, NULL, pg,
6816ba597c5SAnurag S. Maskey res.sr_pg) != 0)
6826ba597c5SAnurag S. Maskey goto failure;
6836ba597c5SAnurag S. Maskey }
6846ba597c5SAnurag S. Maskey
6856ba597c5SAnurag S. Maskey if (scf_pg_get_property(res.sr_pg, prop, res.sr_prop) != 0)
6866ba597c5SAnurag S. Maskey goto failure;
6876ba597c5SAnurag S. Maskey retry:
6886ba597c5SAnurag S. Maskey if (scf_transaction_start(res.sr_tx, res.sr_pg) == -1)
6896ba597c5SAnurag S. Maskey goto failure;
6906ba597c5SAnurag S. Maskey
6916ba597c5SAnurag S. Maskey if (scf_transaction_property_delete(res.sr_tx, res.sr_ent, prop) == -1)
6926ba597c5SAnurag S. Maskey goto failure;
6936ba597c5SAnurag S. Maskey
6946ba597c5SAnurag S. Maskey result = scf_transaction_commit(res.sr_tx);
6956ba597c5SAnurag S. Maskey if (result == 0) {
6966ba597c5SAnurag S. Maskey scf_transaction_reset(res.sr_tx);
6976ba597c5SAnurag S. Maskey if (scf_pg_update(res.sr_pg) == -1)
6986ba597c5SAnurag S. Maskey goto failure;
6996ba597c5SAnurag S. Maskey goto retry;
7006ba597c5SAnurag S. Maskey }
7016ba597c5SAnurag S. Maskey if (result == -1)
7026ba597c5SAnurag S. Maskey goto failure;
7036ba597c5SAnurag S. Maskey
7046ba597c5SAnurag S. Maskey release_scf_resources(&res);
7056ba597c5SAnurag S. Maskey return (0);
7066ba597c5SAnurag S. Maskey failure:
7076ba597c5SAnurag S. Maskey release_scf_resources(&res);
7086ba597c5SAnurag S. Maskey return (-1);
709d71dbb73Sjbeck }
710