13938Sjbeck /*
23938Sjbeck * CDDL HEADER START
33938Sjbeck *
43938Sjbeck * The contents of this file are subject to the terms of the
53938Sjbeck * Common Development and Distribution License (the "License").
63938Sjbeck * You may not use this file except in compliance with the License.
73938Sjbeck *
83938Sjbeck * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
93938Sjbeck * or http://www.opensolaris.org/os/licensing.
103938Sjbeck * See the License for the specific language governing permissions
113938Sjbeck * and limitations under the License.
123938Sjbeck *
133938Sjbeck * When distributing Covered Code, include this CDDL HEADER in each
143938Sjbeck * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
153938Sjbeck * If applicable, add the following below this CDDL HEADER, with the
163938Sjbeck * fields enclosed by brackets "[]" replaced with your own identifying
173938Sjbeck * information: Portions Copyright [yyyy] [name of copyright owner]
183938Sjbeck *
193938Sjbeck * CDDL HEADER END
203938Sjbeck */
213938Sjbeck
223938Sjbeck /*
23*12576SAnurag.Maskey@Oracle.COM * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
243938Sjbeck */
253938Sjbeck
263938Sjbeck /*
2711767SAnurag.Maskey@Sun.COM * util.c contains a set of miscellaneous utility functions which,
2811767SAnurag.Maskey@Sun.COM * among other things:
293938Sjbeck * - start a child process
303938Sjbeck * - look up the zone name
3111767SAnurag.Maskey@Sun.COM * - look up/set SMF properties
3211767SAnurag.Maskey@Sun.COM * - drop/escalate privs
333938Sjbeck */
343938Sjbeck
3511767SAnurag.Maskey@Sun.COM #include <assert.h>
3611767SAnurag.Maskey@Sun.COM #include <errno.h>
3711767SAnurag.Maskey@Sun.COM #include <libdllink.h>
3811767SAnurag.Maskey@Sun.COM #include <limits.h>
3911767SAnurag.Maskey@Sun.COM #include <libscf.h>
4011767SAnurag.Maskey@Sun.COM #include <net/if.h>
4111767SAnurag.Maskey@Sun.COM #include <pthread.h>
4211767SAnurag.Maskey@Sun.COM #include <pwd.h>
4311767SAnurag.Maskey@Sun.COM #include <spawn.h>
443938Sjbeck #include <stdarg.h>
453938Sjbeck #include <stdio.h>
463938Sjbeck #include <stdlib.h>
473938Sjbeck #include <string.h>
4811767SAnurag.Maskey@Sun.COM #include <strings.h>
493938Sjbeck #include <stropts.h>
503938Sjbeck #include <sys/socket.h>
5111767SAnurag.Maskey@Sun.COM #include <sys/sockio.h>
5211767SAnurag.Maskey@Sun.COM #include <sys/types.h>
5311767SAnurag.Maskey@Sun.COM #include <unistd.h>
543938Sjbeck #include <wait.h>
553938Sjbeck #include <zone.h>
563938Sjbeck
5711767SAnurag.Maskey@Sun.COM #include "util.h"
5811767SAnurag.Maskey@Sun.COM #include "llp.h"
593938Sjbeck
603938Sjbeck extern char **environ;
6111767SAnurag.Maskey@Sun.COM extern sigset_t original_sigmask;
623938Sjbeck
6311767SAnurag.Maskey@Sun.COM /*
6411767SAnurag.Maskey@Sun.COM * A holder for all the resources needed to get a property value
6511767SAnurag.Maskey@Sun.COM * using libscf.
6611767SAnurag.Maskey@Sun.COM */
6711767SAnurag.Maskey@Sun.COM typedef struct scf_resources {
6811767SAnurag.Maskey@Sun.COM scf_handle_t *sr_handle;
6911767SAnurag.Maskey@Sun.COM scf_instance_t *sr_inst;
7011767SAnurag.Maskey@Sun.COM scf_snapshot_t *sr_snap;
7111767SAnurag.Maskey@Sun.COM scf_propertygroup_t *sr_pg;
7211767SAnurag.Maskey@Sun.COM scf_property_t *sr_prop;
7311767SAnurag.Maskey@Sun.COM scf_value_t *sr_val;
7411767SAnurag.Maskey@Sun.COM scf_transaction_t *sr_tx;
7511767SAnurag.Maskey@Sun.COM scf_transaction_entry_t *sr_ent;
7611767SAnurag.Maskey@Sun.COM } scf_resources_t;
7711767SAnurag.Maskey@Sun.COM
7811767SAnurag.Maskey@Sun.COM static pthread_mutex_t uid_mutex = PTHREAD_MUTEX_INITIALIZER;
7911767SAnurag.Maskey@Sun.COM static uid_t uid;
8011767SAnurag.Maskey@Sun.COM static int uid_cnt;
8111767SAnurag.Maskey@Sun.COM
823938Sjbeck void
nwamd_escalate(void)8311918SMichael.Hunter@Sun.COM nwamd_escalate(void) {
8411918SMichael.Hunter@Sun.COM priv_set_t *priv_set;
8511918SMichael.Hunter@Sun.COM priv_set = priv_str_to_set("zone", ",", NULL);
8611918SMichael.Hunter@Sun.COM
8711918SMichael.Hunter@Sun.COM if (priv_set == NULL)
8811918SMichael.Hunter@Sun.COM pfail("creating privilege set: %s", strerror(errno));
8911918SMichael.Hunter@Sun.COM
9011767SAnurag.Maskey@Sun.COM (void) pthread_mutex_lock(&uid_mutex);
9111767SAnurag.Maskey@Sun.COM if (uid == 0)
9211767SAnurag.Maskey@Sun.COM uid = getuid();
9311767SAnurag.Maskey@Sun.COM if (uid_cnt++ == 0) {
9411918SMichael.Hunter@Sun.COM if (setppriv(PRIV_SET, PRIV_EFFECTIVE, priv_set) == -1) {
9511918SMichael.Hunter@Sun.COM priv_freeset(priv_set);
9611918SMichael.Hunter@Sun.COM pfail("setppriv effective: %s", strerror(errno));
9711918SMichael.Hunter@Sun.COM }
983938Sjbeck }
9911767SAnurag.Maskey@Sun.COM (void) pthread_mutex_unlock(&uid_mutex);
10011918SMichael.Hunter@Sun.COM
10111918SMichael.Hunter@Sun.COM priv_freeset(priv_set);
1023938Sjbeck }
1033938Sjbeck
10411767SAnurag.Maskey@Sun.COM void
nwamd_deescalate(void)10511918SMichael.Hunter@Sun.COM nwamd_deescalate(void) {
10611941SAnurag.Maskey@Sun.COM (void) pthread_mutex_lock(&uid_mutex);
10711918SMichael.Hunter@Sun.COM
10811767SAnurag.Maskey@Sun.COM assert(uid_cnt > 0);
10911767SAnurag.Maskey@Sun.COM if (--uid_cnt == 0) {
11011941SAnurag.Maskey@Sun.COM priv_set_t *priv_set, *allpriv_set;
11111941SAnurag.Maskey@Sun.COM
11211918SMichael.Hunter@Sun.COM /* build up our minimal set of privs. */
11311918SMichael.Hunter@Sun.COM priv_set = priv_str_to_set("basic", ",", NULL);
11411918SMichael.Hunter@Sun.COM allpriv_set = priv_str_to_set("zone", ",", NULL);
11511918SMichael.Hunter@Sun.COM if (priv_set == NULL || allpriv_set == NULL)
11611918SMichael.Hunter@Sun.COM pfail("converting privilege sets: %s", strerror(errno));
11711918SMichael.Hunter@Sun.COM
11811918SMichael.Hunter@Sun.COM (void) priv_addset(priv_set, PRIV_FILE_CHOWN_SELF);
11911918SMichael.Hunter@Sun.COM (void) priv_addset(priv_set, PRIV_FILE_DAC_READ);
12011918SMichael.Hunter@Sun.COM (void) priv_addset(priv_set, PRIV_FILE_DAC_WRITE);
12111918SMichael.Hunter@Sun.COM (void) priv_addset(priv_set, PRIV_NET_RAWACCESS);
12211918SMichael.Hunter@Sun.COM (void) priv_addset(priv_set, PRIV_NET_PRIVADDR);
12311918SMichael.Hunter@Sun.COM (void) priv_addset(priv_set, PRIV_PROC_AUDIT);
12411918SMichael.Hunter@Sun.COM (void) priv_addset(priv_set, PRIV_PROC_OWNER);
12511918SMichael.Hunter@Sun.COM (void) priv_addset(priv_set, PRIV_PROC_SETID);
12611918SMichael.Hunter@Sun.COM (void) priv_addset(priv_set, PRIV_SYS_CONFIG);
12711918SMichael.Hunter@Sun.COM (void) priv_addset(priv_set, PRIV_SYS_IP_CONFIG);
12811918SMichael.Hunter@Sun.COM (void) priv_addset(priv_set, PRIV_SYS_IPC_CONFIG);
12911918SMichael.Hunter@Sun.COM (void) priv_addset(priv_set, PRIV_SYS_MOUNT);
13011918SMichael.Hunter@Sun.COM (void) priv_addset(priv_set, PRIV_SYS_NET_CONFIG);
13111918SMichael.Hunter@Sun.COM (void) priv_addset(priv_set, PRIV_SYS_RES_CONFIG);
13211918SMichael.Hunter@Sun.COM (void) priv_addset(priv_set, PRIV_SYS_RESOURCE);
13311918SMichael.Hunter@Sun.COM
13411918SMichael.Hunter@Sun.COM /*
13511918SMichael.Hunter@Sun.COM * Since our zone might not have all these privs,
13611918SMichael.Hunter@Sun.COM * just ask for those that are available.
13711918SMichael.Hunter@Sun.COM */
13811918SMichael.Hunter@Sun.COM priv_intersect(allpriv_set, priv_set);
13911918SMichael.Hunter@Sun.COM
14011918SMichael.Hunter@Sun.COM if (setppriv(PRIV_SET, PRIV_INHERITABLE, priv_set) == -1) {
14111918SMichael.Hunter@Sun.COM priv_freeset(allpriv_set);
14211918SMichael.Hunter@Sun.COM priv_freeset(priv_set);
14311918SMichael.Hunter@Sun.COM pfail("setppriv inheritable: %s", strerror(errno));
14411918SMichael.Hunter@Sun.COM }
14511918SMichael.Hunter@Sun.COM /*
14611918SMichael.Hunter@Sun.COM * Need to ensure permitted set contains all privs so we can
14711918SMichael.Hunter@Sun.COM * escalate later.
14811918SMichael.Hunter@Sun.COM */
14911918SMichael.Hunter@Sun.COM if (setppriv(PRIV_SET, PRIV_PERMITTED, allpriv_set) == -1) {
15011918SMichael.Hunter@Sun.COM priv_freeset(allpriv_set);
15111918SMichael.Hunter@Sun.COM priv_freeset(priv_set);
15211918SMichael.Hunter@Sun.COM pfail("setppriv permitted: %s", strerror(errno));
15311918SMichael.Hunter@Sun.COM }
15411918SMichael.Hunter@Sun.COM /*
15511918SMichael.Hunter@Sun.COM * We need to find a smaller set of privs that are important to
15611918SMichael.Hunter@Sun.COM * us. Otherwise we really are not gaining much by doing this.
15711918SMichael.Hunter@Sun.COM */
15811918SMichael.Hunter@Sun.COM if (setppriv(PRIV_SET, PRIV_EFFECTIVE, priv_set) == -1) {
15911918SMichael.Hunter@Sun.COM priv_freeset(allpriv_set);
16011918SMichael.Hunter@Sun.COM priv_freeset(priv_set);
16111918SMichael.Hunter@Sun.COM pfail("setppriv effective: %s", strerror(errno));
16211918SMichael.Hunter@Sun.COM }
16311941SAnurag.Maskey@Sun.COM
16411941SAnurag.Maskey@Sun.COM priv_freeset(priv_set);
16511941SAnurag.Maskey@Sun.COM priv_freeset(allpriv_set);
1663938Sjbeck }
16711767SAnurag.Maskey@Sun.COM (void) pthread_mutex_unlock(&uid_mutex);
1687645Sjames.d.carlson@sun.com }
1697645Sjames.d.carlson@sun.com
1703938Sjbeck /*
1713938Sjbeck *
1723938Sjbeck * This starts a child process determined by command. If command contains a
1733938Sjbeck * slash then it is assumed to be a full path; otherwise the path is searched
1743938Sjbeck * for an executable file with the name command. Command is also used as
1753938Sjbeck * argv[0] of the new process. The rest of the arguments of the function
1763938Sjbeck * up to the first NULL make up pointers to arguments of the new process.
1773938Sjbeck *
1783938Sjbeck * This function returns child exit status on success and -1 on failure.
1793938Sjbeck *
1803938Sjbeck * NOTE: original_sigmask must be set before this function is called.
1813938Sjbeck */
1823938Sjbeck int
nwamd_start_childv(const char * command,char const * const * argv)18311767SAnurag.Maskey@Sun.COM nwamd_start_childv(const char *command, char const * const *argv)
1843938Sjbeck {
1853938Sjbeck posix_spawnattr_t attr;
1863938Sjbeck sigset_t fullset;
1873938Sjbeck int i, rc, status, n;
1883938Sjbeck pid_t pid;
1893938Sjbeck char vbuf[1024];
1903938Sjbeck
1913938Sjbeck vbuf[0] = 0;
1923938Sjbeck n = sizeof (vbuf);
1933938Sjbeck for (i = 1; argv[i] != NULL && n > 2; i++) {
1943938Sjbeck n -= strlcat(vbuf, " ", n);
1953938Sjbeck n -= strlcat(vbuf, argv[i], n);
1963938Sjbeck }
1973938Sjbeck if (argv[i] != NULL || n < 0)
19811767SAnurag.Maskey@Sun.COM nlog(LOG_ERR, "nwamd_start_childv can't log full arg vector");
1993938Sjbeck
2003938Sjbeck if ((rc = posix_spawnattr_init(&attr)) != 0) {
20111767SAnurag.Maskey@Sun.COM nlog(LOG_DEBUG, "posix_spawnattr_init %d %s\n",
20211767SAnurag.Maskey@Sun.COM rc, strerror(rc));
2033938Sjbeck return (-1);
2043938Sjbeck }
2053938Sjbeck (void) sigfillset(&fullset);
2063938Sjbeck if ((rc = posix_spawnattr_setsigdefault(&attr, &fullset)) != 0) {
20711767SAnurag.Maskey@Sun.COM nlog(LOG_DEBUG, "setsigdefault %d %s\n", rc, strerror(rc));
2083938Sjbeck return (-1);
2093938Sjbeck }
2103938Sjbeck if ((rc = posix_spawnattr_setsigmask(&attr, &original_sigmask)) != 0) {
21111767SAnurag.Maskey@Sun.COM nlog(LOG_DEBUG, "setsigmask %d %s\n", rc, strerror(rc));
2123938Sjbeck return (-1);
2133938Sjbeck }
2143938Sjbeck if ((rc = posix_spawnattr_setflags(&attr,
2153938Sjbeck POSIX_SPAWN_SETSIGDEF|POSIX_SPAWN_SETSIGMASK)) != 0) {
21611767SAnurag.Maskey@Sun.COM nlog(LOG_DEBUG, "setflags %d %s\n", rc, strerror(rc));
2173938Sjbeck return (-1);
2183938Sjbeck }
2193938Sjbeck
2203938Sjbeck if ((rc = posix_spawnp(&pid, command, NULL, &attr, (char * const *)argv,
2213938Sjbeck environ)) > 0) {
22211767SAnurag.Maskey@Sun.COM nlog(LOG_DEBUG, "posix_spawnp failed errno %d", rc);
2233938Sjbeck return (-1);
2243938Sjbeck }
2253938Sjbeck
2263938Sjbeck if ((rc = posix_spawnattr_destroy(&attr)) != 0) {
22711767SAnurag.Maskey@Sun.COM nlog(LOG_DEBUG, "posix_spawn_attr_destroy %d %s\n",
22811767SAnurag.Maskey@Sun.COM rc, strerror(rc));
2293938Sjbeck return (-1);
2303938Sjbeck }
2313938Sjbeck
2323938Sjbeck (void) waitpid(pid, &status, 0);
2333938Sjbeck if (WIFSIGNALED(status) || WIFSTOPPED(status)) {
2343938Sjbeck i = WIFSIGNALED(status) ? WTERMSIG(status) : WSTOPSIG(status);
23511767SAnurag.Maskey@Sun.COM nlog(LOG_ERR, "'%s%s' %s with signal %d (%s)", command, vbuf,
2363938Sjbeck (WIFSIGNALED(status) ? "terminated" : "stopped"), i,
2373938Sjbeck strsignal(i));
2383938Sjbeck return (-2);
2393938Sjbeck } else {
24011767SAnurag.Maskey@Sun.COM nlog(LOG_INFO, "'%s%s' completed normally: %d", command, vbuf,
2413938Sjbeck WEXITSTATUS(status));
2423938Sjbeck return (WEXITSTATUS(status));
2433938Sjbeck }
2443938Sjbeck }
2453938Sjbeck
24611767SAnurag.Maskey@Sun.COM /*
24711767SAnurag.Maskey@Sun.COM * For global zone, check if the link is used by a non-global
24811767SAnurag.Maskey@Sun.COM * zone, note that the non-global zones doesn't need this check,
24911767SAnurag.Maskey@Sun.COM * because zoneadm has taken care of this when the zone boots.
25011767SAnurag.Maskey@Sun.COM * In the global zone, we ignore events for local-zone-owned links
25111767SAnurag.Maskey@Sun.COM * since these are taken care of by the local zone's network
25211767SAnurag.Maskey@Sun.COM * configuration services.
25311767SAnurag.Maskey@Sun.COM */
25411767SAnurag.Maskey@Sun.COM boolean_t
nwamd_link_belongs_to_this_zone(const char * linkname)25511767SAnurag.Maskey@Sun.COM nwamd_link_belongs_to_this_zone(const char *linkname)
2563938Sjbeck {
25711767SAnurag.Maskey@Sun.COM zoneid_t zoneid;
25811767SAnurag.Maskey@Sun.COM char zonename[ZONENAME_MAX];
25911767SAnurag.Maskey@Sun.COM int ret;
2603938Sjbeck
26111767SAnurag.Maskey@Sun.COM zoneid = getzoneid();
26211767SAnurag.Maskey@Sun.COM if (zoneid == GLOBAL_ZONEID) {
26311767SAnurag.Maskey@Sun.COM datalink_id_t linkid;
26411767SAnurag.Maskey@Sun.COM dladm_status_t status;
26511767SAnurag.Maskey@Sun.COM char errstr[DLADM_STRSIZE];
26611767SAnurag.Maskey@Sun.COM
26711767SAnurag.Maskey@Sun.COM if ((status = dladm_name2info(dld_handle, linkname, &linkid,
26811767SAnurag.Maskey@Sun.COM NULL, NULL, NULL)) != DLADM_STATUS_OK) {
26911767SAnurag.Maskey@Sun.COM nlog(LOG_DEBUG, "nwamd_link_belongs_to_this_zone: "
27011767SAnurag.Maskey@Sun.COM "could not get linkid for %s: %s",
27111767SAnurag.Maskey@Sun.COM linkname, dladm_status2str(status, errstr));
27211767SAnurag.Maskey@Sun.COM return (B_FALSE);
2733938Sjbeck }
27411767SAnurag.Maskey@Sun.COM zoneid = ALL_ZONES;
27511767SAnurag.Maskey@Sun.COM ret = zone_check_datalink(&zoneid, linkid);
27611767SAnurag.Maskey@Sun.COM if (ret == 0) {
27711767SAnurag.Maskey@Sun.COM (void) getzonenamebyid(zoneid, zonename, ZONENAME_MAX);
27811767SAnurag.Maskey@Sun.COM nlog(LOG_DEBUG, "nwamd_link_belongs_to_this_zone: "
27911767SAnurag.Maskey@Sun.COM "%s is used by non-global zone: %s",
28011767SAnurag.Maskey@Sun.COM linkname, zonename);
28111767SAnurag.Maskey@Sun.COM return (B_FALSE);
28211767SAnurag.Maskey@Sun.COM }
28311767SAnurag.Maskey@Sun.COM }
28411767SAnurag.Maskey@Sun.COM return (B_TRUE);
2853938Sjbeck }
2863938Sjbeck
28711767SAnurag.Maskey@Sun.COM /*
28811767SAnurag.Maskey@Sun.COM * Inputs:
28911767SAnurag.Maskey@Sun.COM * res is a pointer to the scf_resources_t to be released.
29011767SAnurag.Maskey@Sun.COM */
29111767SAnurag.Maskey@Sun.COM static void
release_scf_resources(scf_resources_t * res)29211767SAnurag.Maskey@Sun.COM release_scf_resources(scf_resources_t *res)
29311767SAnurag.Maskey@Sun.COM {
29411767SAnurag.Maskey@Sun.COM scf_entry_destroy(res->sr_ent);
29511767SAnurag.Maskey@Sun.COM scf_transaction_destroy(res->sr_tx);
29611767SAnurag.Maskey@Sun.COM scf_value_destroy(res->sr_val);
29711767SAnurag.Maskey@Sun.COM scf_property_destroy(res->sr_prop);
29811767SAnurag.Maskey@Sun.COM scf_pg_destroy(res->sr_pg);
29911767SAnurag.Maskey@Sun.COM scf_snapshot_destroy(res->sr_snap);
30011767SAnurag.Maskey@Sun.COM scf_instance_destroy(res->sr_inst);
30111767SAnurag.Maskey@Sun.COM (void) scf_handle_unbind(res->sr_handle);
30211767SAnurag.Maskey@Sun.COM scf_handle_destroy(res->sr_handle);
30311767SAnurag.Maskey@Sun.COM }
30411767SAnurag.Maskey@Sun.COM
30511767SAnurag.Maskey@Sun.COM /*
30611767SAnurag.Maskey@Sun.COM * Inputs:
30711767SAnurag.Maskey@Sun.COM * fmri is the instance to look up
30811767SAnurag.Maskey@Sun.COM * Outputs:
30911767SAnurag.Maskey@Sun.COM * res is a pointer to an scf_resources_t. This is an internal
31011767SAnurag.Maskey@Sun.COM * structure that holds all the handles needed to get a specific
31111767SAnurag.Maskey@Sun.COM * property from the running snapshot; on a successful return it
31211767SAnurag.Maskey@Sun.COM * contains the scf_value_t that should be passed to the desired
31311767SAnurag.Maskey@Sun.COM * scf_value_get_foo() function, and must be freed after use by
31411767SAnurag.Maskey@Sun.COM * calling release_scf_resources(). On a failure return, any
31511767SAnurag.Maskey@Sun.COM * resources that may have been assigned to res are released, so
31611767SAnurag.Maskey@Sun.COM * the caller does not need to do any cleanup in the failure case.
31711767SAnurag.Maskey@Sun.COM * Returns:
31811767SAnurag.Maskey@Sun.COM * 0 on success
31911767SAnurag.Maskey@Sun.COM * -1 on failure
32011767SAnurag.Maskey@Sun.COM */
32111767SAnurag.Maskey@Sun.COM
32211767SAnurag.Maskey@Sun.COM static int
create_scf_resources(const char * fmri,scf_resources_t * res)32311767SAnurag.Maskey@Sun.COM create_scf_resources(const char *fmri, scf_resources_t *res)
3243938Sjbeck {
32511767SAnurag.Maskey@Sun.COM res->sr_tx = NULL;
32611767SAnurag.Maskey@Sun.COM res->sr_ent = NULL;
32711767SAnurag.Maskey@Sun.COM res->sr_inst = NULL;
32811767SAnurag.Maskey@Sun.COM res->sr_snap = NULL;
32911767SAnurag.Maskey@Sun.COM res->sr_pg = NULL;
33011767SAnurag.Maskey@Sun.COM res->sr_prop = NULL;
33111767SAnurag.Maskey@Sun.COM res->sr_val = NULL;
33211767SAnurag.Maskey@Sun.COM
33311767SAnurag.Maskey@Sun.COM if ((res->sr_handle = scf_handle_create(SCF_VERSION)) == NULL) {
33411767SAnurag.Maskey@Sun.COM return (-1);
33511767SAnurag.Maskey@Sun.COM }
33611767SAnurag.Maskey@Sun.COM
33711767SAnurag.Maskey@Sun.COM if (scf_handle_bind(res->sr_handle) != 0) {
33811767SAnurag.Maskey@Sun.COM scf_handle_destroy(res->sr_handle);
33911767SAnurag.Maskey@Sun.COM return (-1);
34011767SAnurag.Maskey@Sun.COM }
34111767SAnurag.Maskey@Sun.COM if ((res->sr_inst = scf_instance_create(res->sr_handle)) == NULL) {
34211767SAnurag.Maskey@Sun.COM goto failure;
34311767SAnurag.Maskey@Sun.COM }
34411767SAnurag.Maskey@Sun.COM if (scf_handle_decode_fmri(res->sr_handle, fmri, NULL, NULL,
34511767SAnurag.Maskey@Sun.COM res->sr_inst, NULL, NULL, SCF_DECODE_FMRI_REQUIRE_INSTANCE) != 0) {
34611767SAnurag.Maskey@Sun.COM goto failure;
34711767SAnurag.Maskey@Sun.COM }
34811767SAnurag.Maskey@Sun.COM if ((res->sr_snap = scf_snapshot_create(res->sr_handle)) == NULL) {
34911767SAnurag.Maskey@Sun.COM goto failure;
35011767SAnurag.Maskey@Sun.COM }
35111767SAnurag.Maskey@Sun.COM if (scf_instance_get_snapshot(res->sr_inst, "running",
35211767SAnurag.Maskey@Sun.COM res->sr_snap) != 0) {
35311767SAnurag.Maskey@Sun.COM goto failure;
35411767SAnurag.Maskey@Sun.COM }
35511767SAnurag.Maskey@Sun.COM if ((res->sr_pg = scf_pg_create(res->sr_handle)) == NULL) {
35611767SAnurag.Maskey@Sun.COM goto failure;
35711767SAnurag.Maskey@Sun.COM }
35811767SAnurag.Maskey@Sun.COM if ((res->sr_prop = scf_property_create(res->sr_handle)) == NULL) {
35911767SAnurag.Maskey@Sun.COM goto failure;
36011767SAnurag.Maskey@Sun.COM }
36111767SAnurag.Maskey@Sun.COM if ((res->sr_val = scf_value_create(res->sr_handle)) == NULL) {
36211767SAnurag.Maskey@Sun.COM goto failure;
36311767SAnurag.Maskey@Sun.COM }
36411767SAnurag.Maskey@Sun.COM if ((res->sr_tx = scf_transaction_create(res->sr_handle)) == NULL) {
36511767SAnurag.Maskey@Sun.COM goto failure;
36611767SAnurag.Maskey@Sun.COM }
36711767SAnurag.Maskey@Sun.COM if ((res->sr_ent = scf_entry_create(res->sr_handle)) == NULL) {
36811767SAnurag.Maskey@Sun.COM goto failure;
36911767SAnurag.Maskey@Sun.COM }
37011767SAnurag.Maskey@Sun.COM return (0);
37111767SAnurag.Maskey@Sun.COM
37211767SAnurag.Maskey@Sun.COM failure:
37311767SAnurag.Maskey@Sun.COM nlog(LOG_ERR, "create_scf_resources failed: %s",
37411767SAnurag.Maskey@Sun.COM scf_strerror(scf_error()));
37511767SAnurag.Maskey@Sun.COM release_scf_resources(res);
37611767SAnurag.Maskey@Sun.COM return (-1);
37711767SAnurag.Maskey@Sun.COM }
37811767SAnurag.Maskey@Sun.COM
37911767SAnurag.Maskey@Sun.COM /*
38011767SAnurag.Maskey@Sun.COM * Inputs:
38111767SAnurag.Maskey@Sun.COM * fmri is the instance to look up
38211767SAnurag.Maskey@Sun.COM * pg is the property group to look up
38311767SAnurag.Maskey@Sun.COM * prop is the property within that group to look up
38411767SAnurag.Maskey@Sun.COM * running specifies if running snapshot is to be used
38511767SAnurag.Maskey@Sun.COM * Outputs:
38611767SAnurag.Maskey@Sun.COM * res is a pointer to an scf_resources_t. This is an internal
38711767SAnurag.Maskey@Sun.COM * structure that holds all the handles needed to get a specific
38811767SAnurag.Maskey@Sun.COM * property from the running snapshot; on a successful return it
38911767SAnurag.Maskey@Sun.COM * contains the scf_value_t that should be passed to the desired
39011767SAnurag.Maskey@Sun.COM * scf_value_get_foo() function, and must be freed after use by
39111767SAnurag.Maskey@Sun.COM * calling release_scf_resources(). On a failure return, any
39211767SAnurag.Maskey@Sun.COM * resources that may have been assigned to res are released, so
39311767SAnurag.Maskey@Sun.COM * the caller does not need to do any cleanup in the failure case.
39411767SAnurag.Maskey@Sun.COM * Returns:
39511767SAnurag.Maskey@Sun.COM * 0 on success
39611767SAnurag.Maskey@Sun.COM * -1 on failure
39711767SAnurag.Maskey@Sun.COM */
39811767SAnurag.Maskey@Sun.COM static int
get_property_value(const char * fmri,const char * pg,const char * prop,boolean_t running,scf_resources_t * res)39911767SAnurag.Maskey@Sun.COM get_property_value(const char *fmri, const char *pg, const char *prop,
40011767SAnurag.Maskey@Sun.COM boolean_t running, scf_resources_t *res)
40111767SAnurag.Maskey@Sun.COM {
40211767SAnurag.Maskey@Sun.COM if (create_scf_resources(fmri, res) != 0)
40311767SAnurag.Maskey@Sun.COM return (-1);
40411767SAnurag.Maskey@Sun.COM
40511767SAnurag.Maskey@Sun.COM if (scf_instance_get_pg_composed(res->sr_inst,
40611767SAnurag.Maskey@Sun.COM running ? res->sr_snap : NULL, pg, res->sr_pg) != 0) {
40711767SAnurag.Maskey@Sun.COM goto failure;
40811767SAnurag.Maskey@Sun.COM }
40911767SAnurag.Maskey@Sun.COM if (scf_pg_get_property(res->sr_pg, prop, res->sr_prop) != 0) {
41011767SAnurag.Maskey@Sun.COM goto failure;
41111767SAnurag.Maskey@Sun.COM }
41211767SAnurag.Maskey@Sun.COM if (scf_property_get_value(res->sr_prop, res->sr_val) != 0) {
41311767SAnurag.Maskey@Sun.COM goto failure;
41411767SAnurag.Maskey@Sun.COM }
41511767SAnurag.Maskey@Sun.COM return (0);
41611767SAnurag.Maskey@Sun.COM
41711767SAnurag.Maskey@Sun.COM failure:
41811767SAnurag.Maskey@Sun.COM release_scf_resources(res);
41911767SAnurag.Maskey@Sun.COM return (-1);
42011767SAnurag.Maskey@Sun.COM }
42111767SAnurag.Maskey@Sun.COM
42211767SAnurag.Maskey@Sun.COM /*
42311767SAnurag.Maskey@Sun.COM * Inputs:
42411767SAnurag.Maskey@Sun.COM * lfmri is the instance fmri to look up
42511767SAnurag.Maskey@Sun.COM * lpg is the property group to look up
42611767SAnurag.Maskey@Sun.COM * lprop is the property within that group to look up
42711767SAnurag.Maskey@Sun.COM * Outputs:
42811767SAnurag.Maskey@Sun.COM * answer is a pointer to the property value
42911767SAnurag.Maskey@Sun.COM * Returns:
43011767SAnurag.Maskey@Sun.COM * 0 on success
43111767SAnurag.Maskey@Sun.COM * -1 on failure
43211767SAnurag.Maskey@Sun.COM * If successful, the property value is retured in *answer.
43311767SAnurag.Maskey@Sun.COM * Otherwise, *answer is undefined, and it is up to the caller to decide
43411767SAnurag.Maskey@Sun.COM * how to handle that case.
43511767SAnurag.Maskey@Sun.COM */
43611767SAnurag.Maskey@Sun.COM int
nwamd_lookup_boolean_property(const char * lfmri,const char * lpg,const char * lprop,boolean_t * answer)43711767SAnurag.Maskey@Sun.COM nwamd_lookup_boolean_property(const char *lfmri, const char *lpg,
43811767SAnurag.Maskey@Sun.COM const char *lprop, boolean_t *answer)
43911767SAnurag.Maskey@Sun.COM {
44011767SAnurag.Maskey@Sun.COM int result = -1;
44111767SAnurag.Maskey@Sun.COM scf_resources_t res;
44211767SAnurag.Maskey@Sun.COM uint8_t prop_val;
44311767SAnurag.Maskey@Sun.COM
44411767SAnurag.Maskey@Sun.COM if (get_property_value(lfmri, lpg, lprop, B_TRUE, &res) != 0) {
44511767SAnurag.Maskey@Sun.COM
44611767SAnurag.Maskey@Sun.COM /*
44711767SAnurag.Maskey@Sun.COM * an error was already logged by get_property_value,
44811767SAnurag.Maskey@Sun.COM * and it released any resources assigned to res before
44911767SAnurag.Maskey@Sun.COM * returning.
45011767SAnurag.Maskey@Sun.COM */
45111767SAnurag.Maskey@Sun.COM return (result);
45211767SAnurag.Maskey@Sun.COM }
45311767SAnurag.Maskey@Sun.COM if (scf_value_get_boolean(res.sr_val, &prop_val) != 0) {
45411767SAnurag.Maskey@Sun.COM goto cleanup;
45511767SAnurag.Maskey@Sun.COM }
45611767SAnurag.Maskey@Sun.COM *answer = (boolean_t)prop_val;
45711767SAnurag.Maskey@Sun.COM result = 0;
45811767SAnurag.Maskey@Sun.COM cleanup:
45911767SAnurag.Maskey@Sun.COM release_scf_resources(&res);
46011767SAnurag.Maskey@Sun.COM return (result);
46111767SAnurag.Maskey@Sun.COM }
46211767SAnurag.Maskey@Sun.COM
46311767SAnurag.Maskey@Sun.COM /*
46411767SAnurag.Maskey@Sun.COM * Inputs:
46511767SAnurag.Maskey@Sun.COM * lfmri is the instance fmri to look up
46611767SAnurag.Maskey@Sun.COM * lpg is the property group to look up
46711767SAnurag.Maskey@Sun.COM * lprop is the property within that group to look up
46811767SAnurag.Maskey@Sun.COM * buf is the place to put the answer
46911767SAnurag.Maskey@Sun.COM * bufsz is the size of buf
47011767SAnurag.Maskey@Sun.COM * Outputs:
47111767SAnurag.Maskey@Sun.COM *
47211767SAnurag.Maskey@Sun.COM * Returns:
47311767SAnurag.Maskey@Sun.COM * 0 on success
47411767SAnurag.Maskey@Sun.COM * -1 on failure
47511767SAnurag.Maskey@Sun.COM * If successful, the property value is retured in buf.
47611767SAnurag.Maskey@Sun.COM * Otherwise, buf is undefined, and it is up to the caller to decide
47711767SAnurag.Maskey@Sun.COM * how to handle that case.
47811767SAnurag.Maskey@Sun.COM */
47911767SAnurag.Maskey@Sun.COM int
nwamd_lookup_string_property(const char * lfmri,const char * lpg,const char * lprop,char * buf,size_t bufsz)48011767SAnurag.Maskey@Sun.COM nwamd_lookup_string_property(const char *lfmri, const char *lpg,
48111767SAnurag.Maskey@Sun.COM const char *lprop, char *buf, size_t bufsz)
48211767SAnurag.Maskey@Sun.COM {
48311767SAnurag.Maskey@Sun.COM int result = -1;
48411767SAnurag.Maskey@Sun.COM scf_resources_t res;
4853938Sjbeck
48611767SAnurag.Maskey@Sun.COM if (get_property_value(lfmri, lpg, lprop, B_TRUE, &res) != 0) {
48711767SAnurag.Maskey@Sun.COM /*
48811767SAnurag.Maskey@Sun.COM * The above function fails when trying to get a
48911767SAnurag.Maskey@Sun.COM * non-persistent property group from the running snapshot.
49011767SAnurag.Maskey@Sun.COM * Try going for the non-running snapshot.
49111767SAnurag.Maskey@Sun.COM */
49211767SAnurag.Maskey@Sun.COM if (get_property_value(lfmri, lpg, lprop, B_FALSE, &res) != 0) {
49311767SAnurag.Maskey@Sun.COM /*
49411767SAnurag.Maskey@Sun.COM * an error was already logged by get_property_value,
49511767SAnurag.Maskey@Sun.COM * and it released any resources assigned to res before
49611767SAnurag.Maskey@Sun.COM * returning.
49711767SAnurag.Maskey@Sun.COM */
49811767SAnurag.Maskey@Sun.COM return (result);
49911767SAnurag.Maskey@Sun.COM }
50011767SAnurag.Maskey@Sun.COM }
50111767SAnurag.Maskey@Sun.COM if (scf_value_get_astring(res.sr_val, buf, bufsz) == 0)
50211767SAnurag.Maskey@Sun.COM goto cleanup;
50311767SAnurag.Maskey@Sun.COM
50411767SAnurag.Maskey@Sun.COM result = 0;
50511767SAnurag.Maskey@Sun.COM cleanup:
50611767SAnurag.Maskey@Sun.COM release_scf_resources(&res);
50711767SAnurag.Maskey@Sun.COM return (result);
50811767SAnurag.Maskey@Sun.COM }
50911767SAnurag.Maskey@Sun.COM
51011767SAnurag.Maskey@Sun.COM /*
51111767SAnurag.Maskey@Sun.COM * Inputs:
51211767SAnurag.Maskey@Sun.COM * lfmri is the instance fmri to look up
51311767SAnurag.Maskey@Sun.COM * lpg is the property group to look up
51411767SAnurag.Maskey@Sun.COM * lprop is the property within that group to look up
51511767SAnurag.Maskey@Sun.COM * Outputs:
51611767SAnurag.Maskey@Sun.COM * answer is a pointer to the property value
51711767SAnurag.Maskey@Sun.COM * Returns:
51811767SAnurag.Maskey@Sun.COM * 0 on success
51911767SAnurag.Maskey@Sun.COM * -1 on failure
52011767SAnurag.Maskey@Sun.COM * If successful, the property value is retured in *answer.
52111767SAnurag.Maskey@Sun.COM * Otherwise, *answer is undefined, and it is up to the caller to decide
52211767SAnurag.Maskey@Sun.COM * how to handle that case.
52311767SAnurag.Maskey@Sun.COM */
52411767SAnurag.Maskey@Sun.COM int
nwamd_lookup_count_property(const char * lfmri,const char * lpg,const char * lprop,uint64_t * answer)52511767SAnurag.Maskey@Sun.COM nwamd_lookup_count_property(const char *lfmri, const char *lpg,
52611767SAnurag.Maskey@Sun.COM const char *lprop, uint64_t *answer)
52711767SAnurag.Maskey@Sun.COM {
52811767SAnurag.Maskey@Sun.COM int result = -1;
52911767SAnurag.Maskey@Sun.COM scf_resources_t res;
53011767SAnurag.Maskey@Sun.COM
53111767SAnurag.Maskey@Sun.COM if (get_property_value(lfmri, lpg, lprop, B_TRUE, &res) != 0) {
53211767SAnurag.Maskey@Sun.COM
53311767SAnurag.Maskey@Sun.COM /*
53411767SAnurag.Maskey@Sun.COM * an error was already logged by get_property_value,
53511767SAnurag.Maskey@Sun.COM * and it released any resources assigned to res before
53611767SAnurag.Maskey@Sun.COM * returning.
53711767SAnurag.Maskey@Sun.COM */
53811767SAnurag.Maskey@Sun.COM return (result);
53911767SAnurag.Maskey@Sun.COM }
54011767SAnurag.Maskey@Sun.COM if (scf_value_get_count(res.sr_val, answer) != 0) {
54111767SAnurag.Maskey@Sun.COM goto cleanup;
54211767SAnurag.Maskey@Sun.COM }
54311767SAnurag.Maskey@Sun.COM result = 0;
54411767SAnurag.Maskey@Sun.COM cleanup:
54511767SAnurag.Maskey@Sun.COM release_scf_resources(&res);
54611767SAnurag.Maskey@Sun.COM return (result);
54711767SAnurag.Maskey@Sun.COM }
54811767SAnurag.Maskey@Sun.COM
54911767SAnurag.Maskey@Sun.COM static int
set_property_value(scf_resources_t * res,const char * propname,scf_type_t proptype)55011767SAnurag.Maskey@Sun.COM set_property_value(scf_resources_t *res, const char *propname,
55111767SAnurag.Maskey@Sun.COM scf_type_t proptype)
55211767SAnurag.Maskey@Sun.COM {
55311767SAnurag.Maskey@Sun.COM int result = -1;
55411767SAnurag.Maskey@Sun.COM boolean_t new;
55511767SAnurag.Maskey@Sun.COM
55611767SAnurag.Maskey@Sun.COM retry:
55711767SAnurag.Maskey@Sun.COM new = (scf_pg_get_property(res->sr_pg, propname, res->sr_prop) != 0);
55811767SAnurag.Maskey@Sun.COM
55911767SAnurag.Maskey@Sun.COM if (scf_transaction_start(res->sr_tx, res->sr_pg) == -1) {
56011767SAnurag.Maskey@Sun.COM goto failure;
56111767SAnurag.Maskey@Sun.COM }
56211767SAnurag.Maskey@Sun.COM if (new) {
56311767SAnurag.Maskey@Sun.COM if (scf_transaction_property_new(res->sr_tx, res->sr_ent,
56411767SAnurag.Maskey@Sun.COM propname, proptype) == -1) {
56511767SAnurag.Maskey@Sun.COM goto failure;
56611767SAnurag.Maskey@Sun.COM }
56711767SAnurag.Maskey@Sun.COM } else {
56811767SAnurag.Maskey@Sun.COM if (scf_transaction_property_change(res->sr_tx, res->sr_ent,
56911767SAnurag.Maskey@Sun.COM propname, proptype) == -1) {
57011767SAnurag.Maskey@Sun.COM goto failure;
57111767SAnurag.Maskey@Sun.COM }
57211767SAnurag.Maskey@Sun.COM }
57311767SAnurag.Maskey@Sun.COM
57411767SAnurag.Maskey@Sun.COM if (scf_entry_add_value(res->sr_ent, res->sr_val) != 0) {
57511767SAnurag.Maskey@Sun.COM goto failure;
57611767SAnurag.Maskey@Sun.COM }
57711767SAnurag.Maskey@Sun.COM
57811767SAnurag.Maskey@Sun.COM result = scf_transaction_commit(res->sr_tx);
57911767SAnurag.Maskey@Sun.COM if (result == 0) {
58011767SAnurag.Maskey@Sun.COM scf_transaction_reset(res->sr_tx);
58111767SAnurag.Maskey@Sun.COM if (scf_pg_update(res->sr_pg) == -1) {
58211767SAnurag.Maskey@Sun.COM goto failure;
58311767SAnurag.Maskey@Sun.COM }
58411767SAnurag.Maskey@Sun.COM nlog(LOG_INFO, "set_property_value: transaction commit failed "
58511767SAnurag.Maskey@Sun.COM "for %s; retrying", propname);
58611767SAnurag.Maskey@Sun.COM goto retry;
58711767SAnurag.Maskey@Sun.COM }
58811767SAnurag.Maskey@Sun.COM if (result == -1)
58911767SAnurag.Maskey@Sun.COM goto failure;
59011767SAnurag.Maskey@Sun.COM return (0);
59111767SAnurag.Maskey@Sun.COM
59211767SAnurag.Maskey@Sun.COM failure:
59311767SAnurag.Maskey@Sun.COM return (-1);
5943938Sjbeck }
59511767SAnurag.Maskey@Sun.COM
59611767SAnurag.Maskey@Sun.COM int
nwamd_set_count_property(const char * fmri,const char * pg,const char * prop,uint64_t count)59711767SAnurag.Maskey@Sun.COM nwamd_set_count_property(const char *fmri, const char *pg, const char *prop,
59811767SAnurag.Maskey@Sun.COM uint64_t count)
59911767SAnurag.Maskey@Sun.COM {
60011767SAnurag.Maskey@Sun.COM scf_resources_t res;
60111767SAnurag.Maskey@Sun.COM
60211767SAnurag.Maskey@Sun.COM if (create_scf_resources(fmri, &res) != 0)
60311767SAnurag.Maskey@Sun.COM return (-1);
60411767SAnurag.Maskey@Sun.COM
60511767SAnurag.Maskey@Sun.COM if (scf_instance_add_pg(res.sr_inst, pg, SCF_GROUP_APPLICATION,
60611767SAnurag.Maskey@Sun.COM SCF_PG_FLAG_NONPERSISTENT, res.sr_pg) != 0) {
60711767SAnurag.Maskey@Sun.COM if (scf_error() != SCF_ERROR_EXISTS)
60811767SAnurag.Maskey@Sun.COM goto failure;
60911767SAnurag.Maskey@Sun.COM if (scf_instance_get_pg_composed(res.sr_inst, NULL, pg,
61011767SAnurag.Maskey@Sun.COM res.sr_pg) != 0)
61111767SAnurag.Maskey@Sun.COM goto failure;
61211767SAnurag.Maskey@Sun.COM }
61311767SAnurag.Maskey@Sun.COM
61411767SAnurag.Maskey@Sun.COM scf_value_set_count(res.sr_val, (uint64_t)count);
61511767SAnurag.Maskey@Sun.COM
61611767SAnurag.Maskey@Sun.COM if (set_property_value(&res, prop, SCF_TYPE_COUNT) != 0)
61711767SAnurag.Maskey@Sun.COM goto failure;
61811767SAnurag.Maskey@Sun.COM
61911767SAnurag.Maskey@Sun.COM release_scf_resources(&res);
62011767SAnurag.Maskey@Sun.COM return (0);
62111767SAnurag.Maskey@Sun.COM
62211767SAnurag.Maskey@Sun.COM failure:
62311767SAnurag.Maskey@Sun.COM nlog(LOG_INFO, "nwamd_set_count_property: scf failure %s while "
62411767SAnurag.Maskey@Sun.COM "setting %s", scf_strerror(scf_error()), prop);
62511767SAnurag.Maskey@Sun.COM release_scf_resources(&res);
62611767SAnurag.Maskey@Sun.COM return (-1);
62711767SAnurag.Maskey@Sun.COM }
62811767SAnurag.Maskey@Sun.COM
62911767SAnurag.Maskey@Sun.COM int
nwamd_set_string_property(const char * fmri,const char * pg,const char * prop,const char * str)63011767SAnurag.Maskey@Sun.COM nwamd_set_string_property(const char *fmri, const char *pg, const char *prop,
63111767SAnurag.Maskey@Sun.COM const char *str)
63211767SAnurag.Maskey@Sun.COM {
63311767SAnurag.Maskey@Sun.COM scf_resources_t res;
63411767SAnurag.Maskey@Sun.COM
63511767SAnurag.Maskey@Sun.COM if (create_scf_resources(fmri, &res) != 0)
63611767SAnurag.Maskey@Sun.COM return (-1);
63711767SAnurag.Maskey@Sun.COM
63811767SAnurag.Maskey@Sun.COM if (scf_instance_add_pg(res.sr_inst, pg, SCF_GROUP_APPLICATION,
63911767SAnurag.Maskey@Sun.COM SCF_PG_FLAG_NONPERSISTENT, res.sr_pg) != 0) {
64011767SAnurag.Maskey@Sun.COM if (scf_error() != SCF_ERROR_EXISTS)
64111767SAnurag.Maskey@Sun.COM goto failure;
64211767SAnurag.Maskey@Sun.COM if (scf_instance_get_pg_composed(res.sr_inst, NULL, pg,
64311767SAnurag.Maskey@Sun.COM res.sr_pg) != 0)
64411767SAnurag.Maskey@Sun.COM goto failure;
64511767SAnurag.Maskey@Sun.COM }
64611767SAnurag.Maskey@Sun.COM
64711767SAnurag.Maskey@Sun.COM if (scf_value_set_astring(res.sr_val, str) != 0)
64811767SAnurag.Maskey@Sun.COM goto failure;
64911767SAnurag.Maskey@Sun.COM
65011767SAnurag.Maskey@Sun.COM if (set_property_value(&res, prop, SCF_TYPE_ASTRING) != 0)
65111767SAnurag.Maskey@Sun.COM goto failure;
65211767SAnurag.Maskey@Sun.COM
65311767SAnurag.Maskey@Sun.COM release_scf_resources(&res);
65411767SAnurag.Maskey@Sun.COM return (0);
65511767SAnurag.Maskey@Sun.COM
65611767SAnurag.Maskey@Sun.COM failure:
65711767SAnurag.Maskey@Sun.COM nlog(LOG_INFO, "nwamd_set_string_property: scf failure %s while "
65811767SAnurag.Maskey@Sun.COM "setting %s", scf_strerror(scf_error()), prop);
65911767SAnurag.Maskey@Sun.COM release_scf_resources(&res);
66011767SAnurag.Maskey@Sun.COM return (-1);
66111767SAnurag.Maskey@Sun.COM }
66211767SAnurag.Maskey@Sun.COM
66311767SAnurag.Maskey@Sun.COM /*
66411767SAnurag.Maskey@Sun.COM * Deletes property prop from property group pg in SMF instance fmri.
66511767SAnurag.Maskey@Sun.COM * Returns 0 on success, -1 on failure.
66611767SAnurag.Maskey@Sun.COM */
66711767SAnurag.Maskey@Sun.COM int
nwamd_delete_scf_property(const char * fmri,const char * pg,const char * prop)66811767SAnurag.Maskey@Sun.COM nwamd_delete_scf_property(const char *fmri, const char *pg, const char *prop)
66911767SAnurag.Maskey@Sun.COM {
67011767SAnurag.Maskey@Sun.COM scf_resources_t res;
67111767SAnurag.Maskey@Sun.COM int result = -1;
67211767SAnurag.Maskey@Sun.COM
67311767SAnurag.Maskey@Sun.COM if (create_scf_resources(fmri, &res) != 0)
67411767SAnurag.Maskey@Sun.COM return (-1);
67511767SAnurag.Maskey@Sun.COM
67611767SAnurag.Maskey@Sun.COM if (scf_instance_add_pg(res.sr_inst, pg, SCF_GROUP_APPLICATION,
67711767SAnurag.Maskey@Sun.COM SCF_PG_FLAG_NONPERSISTENT, res.sr_pg) != 0) {
67811767SAnurag.Maskey@Sun.COM if (scf_error() != SCF_ERROR_EXISTS)
67911767SAnurag.Maskey@Sun.COM goto failure;
68011767SAnurag.Maskey@Sun.COM if (scf_instance_get_pg_composed(res.sr_inst, NULL, pg,
68111767SAnurag.Maskey@Sun.COM res.sr_pg) != 0)
68211767SAnurag.Maskey@Sun.COM goto failure;
68311767SAnurag.Maskey@Sun.COM }
68411767SAnurag.Maskey@Sun.COM
68511767SAnurag.Maskey@Sun.COM if (scf_pg_get_property(res.sr_pg, prop, res.sr_prop) != 0)
68611767SAnurag.Maskey@Sun.COM goto failure;
68711767SAnurag.Maskey@Sun.COM retry:
68811767SAnurag.Maskey@Sun.COM if (scf_transaction_start(res.sr_tx, res.sr_pg) == -1)
68911767SAnurag.Maskey@Sun.COM goto failure;
69011767SAnurag.Maskey@Sun.COM
69111767SAnurag.Maskey@Sun.COM if (scf_transaction_property_delete(res.sr_tx, res.sr_ent, prop) == -1)
69211767SAnurag.Maskey@Sun.COM goto failure;
69311767SAnurag.Maskey@Sun.COM
69411767SAnurag.Maskey@Sun.COM result = scf_transaction_commit(res.sr_tx);
69511767SAnurag.Maskey@Sun.COM if (result == 0) {
69611767SAnurag.Maskey@Sun.COM scf_transaction_reset(res.sr_tx);
69711767SAnurag.Maskey@Sun.COM if (scf_pg_update(res.sr_pg) == -1)
69811767SAnurag.Maskey@Sun.COM goto failure;
69911767SAnurag.Maskey@Sun.COM goto retry;
70011767SAnurag.Maskey@Sun.COM }
70111767SAnurag.Maskey@Sun.COM if (result == -1)
70211767SAnurag.Maskey@Sun.COM goto failure;
70311767SAnurag.Maskey@Sun.COM
70411767SAnurag.Maskey@Sun.COM release_scf_resources(&res);
70511767SAnurag.Maskey@Sun.COM return (0);
70611767SAnurag.Maskey@Sun.COM failure:
70711767SAnurag.Maskey@Sun.COM release_scf_resources(&res);
70811767SAnurag.Maskey@Sun.COM return (-1);
70911767SAnurag.Maskey@Sun.COM }
710