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 /* 2311767SAnurag.Maskey@Sun.COM * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 243938Sjbeck * Use is subject to license terms. 253938Sjbeck */ 263938Sjbeck 273938Sjbeck /* 2811767SAnurag.Maskey@Sun.COM * util.c contains a set of miscellaneous utility functions which, 2911767SAnurag.Maskey@Sun.COM * among other things: 303938Sjbeck * - start a child process 313938Sjbeck * - look up the zone name 3211767SAnurag.Maskey@Sun.COM * - look up/set SMF properties 3311767SAnurag.Maskey@Sun.COM * - drop/escalate privs 343938Sjbeck */ 353938Sjbeck 3611767SAnurag.Maskey@Sun.COM #include <assert.h> 3711767SAnurag.Maskey@Sun.COM #include <errno.h> 3811767SAnurag.Maskey@Sun.COM #include <inetcfg.h> 3911767SAnurag.Maskey@Sun.COM #include <libdllink.h> 4011767SAnurag.Maskey@Sun.COM #include <limits.h> 4111767SAnurag.Maskey@Sun.COM #include <libscf.h> 4211767SAnurag.Maskey@Sun.COM #include <net/if.h> 4311767SAnurag.Maskey@Sun.COM #include <pthread.h> 4411767SAnurag.Maskey@Sun.COM #include <pwd.h> 4511767SAnurag.Maskey@Sun.COM #include <spawn.h> 463938Sjbeck #include <stdarg.h> 473938Sjbeck #include <stdio.h> 483938Sjbeck #include <stdlib.h> 493938Sjbeck #include <string.h> 5011767SAnurag.Maskey@Sun.COM #include <strings.h> 513938Sjbeck #include <stropts.h> 523938Sjbeck #include <sys/socket.h> 5311767SAnurag.Maskey@Sun.COM #include <sys/sockio.h> 5411767SAnurag.Maskey@Sun.COM #include <sys/types.h> 5511767SAnurag.Maskey@Sun.COM #include <unistd.h> 563938Sjbeck #include <wait.h> 573938Sjbeck #include <zone.h> 583938Sjbeck 5911767SAnurag.Maskey@Sun.COM #include "util.h" 6011767SAnurag.Maskey@Sun.COM #include "llp.h" 613938Sjbeck 623938Sjbeck extern char **environ; 6311767SAnurag.Maskey@Sun.COM extern sigset_t original_sigmask; 643938Sjbeck 6511767SAnurag.Maskey@Sun.COM /* 6611767SAnurag.Maskey@Sun.COM * A holder for all the resources needed to get a property value 6711767SAnurag.Maskey@Sun.COM * using libscf. 6811767SAnurag.Maskey@Sun.COM */ 6911767SAnurag.Maskey@Sun.COM typedef struct scf_resources { 7011767SAnurag.Maskey@Sun.COM scf_handle_t *sr_handle; 7111767SAnurag.Maskey@Sun.COM scf_instance_t *sr_inst; 7211767SAnurag.Maskey@Sun.COM scf_snapshot_t *sr_snap; 7311767SAnurag.Maskey@Sun.COM scf_propertygroup_t *sr_pg; 7411767SAnurag.Maskey@Sun.COM scf_property_t *sr_prop; 7511767SAnurag.Maskey@Sun.COM scf_value_t *sr_val; 7611767SAnurag.Maskey@Sun.COM scf_transaction_t *sr_tx; 7711767SAnurag.Maskey@Sun.COM scf_transaction_entry_t *sr_ent; 7811767SAnurag.Maskey@Sun.COM } scf_resources_t; 7911767SAnurag.Maskey@Sun.COM 8011767SAnurag.Maskey@Sun.COM static pthread_mutex_t uid_mutex = PTHREAD_MUTEX_INITIALIZER; 8111767SAnurag.Maskey@Sun.COM static uid_t uid; 8211767SAnurag.Maskey@Sun.COM static int uid_cnt; 8311767SAnurag.Maskey@Sun.COM 843938Sjbeck void 85*11918SMichael.Hunter@Sun.COM nwamd_escalate(void) { 86*11918SMichael.Hunter@Sun.COM priv_set_t *priv_set; 87*11918SMichael.Hunter@Sun.COM priv_set = priv_str_to_set("zone", ",", NULL); 88*11918SMichael.Hunter@Sun.COM 89*11918SMichael.Hunter@Sun.COM if (priv_set == NULL) 90*11918SMichael.Hunter@Sun.COM pfail("creating privilege set: %s", strerror(errno)); 91*11918SMichael.Hunter@Sun.COM 9211767SAnurag.Maskey@Sun.COM (void) pthread_mutex_lock(&uid_mutex); 9311767SAnurag.Maskey@Sun.COM if (uid == 0) 9411767SAnurag.Maskey@Sun.COM uid = getuid(); 9511767SAnurag.Maskey@Sun.COM if (uid_cnt++ == 0) { 96*11918SMichael.Hunter@Sun.COM if (setppriv(PRIV_SET, PRIV_EFFECTIVE, priv_set) == -1) { 97*11918SMichael.Hunter@Sun.COM priv_freeset(priv_set); 98*11918SMichael.Hunter@Sun.COM pfail("setppriv effective: %s", strerror(errno)); 99*11918SMichael.Hunter@Sun.COM } 10011767SAnurag.Maskey@Sun.COM if (setuid(0) == -1) 10111767SAnurag.Maskey@Sun.COM nlog(LOG_ERR, "setuid(0) failed %s", strerror(errno)); 1023938Sjbeck } 10311767SAnurag.Maskey@Sun.COM (void) pthread_mutex_unlock(&uid_mutex); 104*11918SMichael.Hunter@Sun.COM 105*11918SMichael.Hunter@Sun.COM priv_freeset(priv_set); 1063938Sjbeck } 1073938Sjbeck 10811767SAnurag.Maskey@Sun.COM void 109*11918SMichael.Hunter@Sun.COM nwamd_deescalate(void) { 110*11918SMichael.Hunter@Sun.COM priv_set_t *priv_set, *allpriv_set; 111*11918SMichael.Hunter@Sun.COM 11211767SAnurag.Maskey@Sun.COM (void) pthread_mutex_lock(&uid_mutex); 11311767SAnurag.Maskey@Sun.COM assert(uid_cnt > 0); 11411767SAnurag.Maskey@Sun.COM if (--uid_cnt == 0) { 11511767SAnurag.Maskey@Sun.COM if (setuid(uid) == -1) 11611767SAnurag.Maskey@Sun.COM nlog(LOG_ERR, "setuid(%d) failed %s", uid, 11711767SAnurag.Maskey@Sun.COM strerror(errno)); 118*11918SMichael.Hunter@Sun.COM 119*11918SMichael.Hunter@Sun.COM /* build up our minimal set of privs. */ 120*11918SMichael.Hunter@Sun.COM priv_set = priv_str_to_set("basic", ",", NULL); 121*11918SMichael.Hunter@Sun.COM allpriv_set = priv_str_to_set("zone", ",", NULL); 122*11918SMichael.Hunter@Sun.COM if (priv_set == NULL || allpriv_set == NULL) 123*11918SMichael.Hunter@Sun.COM pfail("converting privilege sets: %s", strerror(errno)); 124*11918SMichael.Hunter@Sun.COM 125*11918SMichael.Hunter@Sun.COM (void) priv_addset(priv_set, PRIV_FILE_CHOWN_SELF); 126*11918SMichael.Hunter@Sun.COM (void) priv_addset(priv_set, PRIV_FILE_DAC_READ); 127*11918SMichael.Hunter@Sun.COM (void) priv_addset(priv_set, PRIV_FILE_DAC_WRITE); 128*11918SMichael.Hunter@Sun.COM (void) priv_addset(priv_set, PRIV_NET_RAWACCESS); 129*11918SMichael.Hunter@Sun.COM (void) priv_addset(priv_set, PRIV_NET_PRIVADDR); 130*11918SMichael.Hunter@Sun.COM (void) priv_addset(priv_set, PRIV_PROC_AUDIT); 131*11918SMichael.Hunter@Sun.COM (void) priv_addset(priv_set, PRIV_PROC_OWNER); 132*11918SMichael.Hunter@Sun.COM (void) priv_addset(priv_set, PRIV_PROC_SETID); 133*11918SMichael.Hunter@Sun.COM (void) priv_addset(priv_set, PRIV_SYS_CONFIG); 134*11918SMichael.Hunter@Sun.COM (void) priv_addset(priv_set, PRIV_SYS_IP_CONFIG); 135*11918SMichael.Hunter@Sun.COM (void) priv_addset(priv_set, PRIV_SYS_IPC_CONFIG); 136*11918SMichael.Hunter@Sun.COM (void) priv_addset(priv_set, PRIV_SYS_MOUNT); 137*11918SMichael.Hunter@Sun.COM (void) priv_addset(priv_set, PRIV_SYS_NET_CONFIG); 138*11918SMichael.Hunter@Sun.COM (void) priv_addset(priv_set, PRIV_SYS_RES_CONFIG); 139*11918SMichael.Hunter@Sun.COM (void) priv_addset(priv_set, PRIV_SYS_RESOURCE); 140*11918SMichael.Hunter@Sun.COM 141*11918SMichael.Hunter@Sun.COM /* 142*11918SMichael.Hunter@Sun.COM * Since our zone might not have all these privs, 143*11918SMichael.Hunter@Sun.COM * just ask for those that are available. 144*11918SMichael.Hunter@Sun.COM */ 145*11918SMichael.Hunter@Sun.COM priv_intersect(allpriv_set, priv_set); 146*11918SMichael.Hunter@Sun.COM 147*11918SMichael.Hunter@Sun.COM if (setppriv(PRIV_SET, PRIV_INHERITABLE, priv_set) == -1) { 148*11918SMichael.Hunter@Sun.COM priv_freeset(allpriv_set); 149*11918SMichael.Hunter@Sun.COM priv_freeset(priv_set); 150*11918SMichael.Hunter@Sun.COM pfail("setppriv inheritable: %s", strerror(errno)); 151*11918SMichael.Hunter@Sun.COM } 152*11918SMichael.Hunter@Sun.COM /* 153*11918SMichael.Hunter@Sun.COM * Need to ensure permitted set contains all privs so we can 154*11918SMichael.Hunter@Sun.COM * escalate later. 155*11918SMichael.Hunter@Sun.COM */ 156*11918SMichael.Hunter@Sun.COM if (setppriv(PRIV_SET, PRIV_PERMITTED, allpriv_set) == -1) { 157*11918SMichael.Hunter@Sun.COM priv_freeset(allpriv_set); 158*11918SMichael.Hunter@Sun.COM priv_freeset(priv_set); 159*11918SMichael.Hunter@Sun.COM pfail("setppriv permitted: %s", strerror(errno)); 160*11918SMichael.Hunter@Sun.COM } 161*11918SMichael.Hunter@Sun.COM /* 162*11918SMichael.Hunter@Sun.COM * We need to find a smaller set of privs that are important to 163*11918SMichael.Hunter@Sun.COM * us. Otherwise we really are not gaining much by doing this. 164*11918SMichael.Hunter@Sun.COM */ 165*11918SMichael.Hunter@Sun.COM if (setppriv(PRIV_SET, PRIV_EFFECTIVE, priv_set) == -1) { 166*11918SMichael.Hunter@Sun.COM priv_freeset(allpriv_set); 167*11918SMichael.Hunter@Sun.COM priv_freeset(priv_set); 168*11918SMichael.Hunter@Sun.COM pfail("setppriv effective: %s", strerror(errno)); 169*11918SMichael.Hunter@Sun.COM } 1703938Sjbeck } 17111767SAnurag.Maskey@Sun.COM (void) pthread_mutex_unlock(&uid_mutex); 172*11918SMichael.Hunter@Sun.COM 173*11918SMichael.Hunter@Sun.COM priv_freeset(priv_set); 174*11918SMichael.Hunter@Sun.COM priv_freeset(allpriv_set); 1757645Sjames.d.carlson@sun.com } 1767645Sjames.d.carlson@sun.com 1773938Sjbeck /* 1783938Sjbeck * 1793938Sjbeck * This starts a child process determined by command. If command contains a 1803938Sjbeck * slash then it is assumed to be a full path; otherwise the path is searched 1813938Sjbeck * for an executable file with the name command. Command is also used as 1823938Sjbeck * argv[0] of the new process. The rest of the arguments of the function 1833938Sjbeck * up to the first NULL make up pointers to arguments of the new process. 1843938Sjbeck * 1853938Sjbeck * This function returns child exit status on success and -1 on failure. 1863938Sjbeck * 1873938Sjbeck * NOTE: original_sigmask must be set before this function is called. 1883938Sjbeck */ 1893938Sjbeck int 19011767SAnurag.Maskey@Sun.COM nwamd_start_childv(const char *command, char const * const *argv) 1913938Sjbeck { 1923938Sjbeck posix_spawnattr_t attr; 1933938Sjbeck sigset_t fullset; 1943938Sjbeck int i, rc, status, n; 1953938Sjbeck pid_t pid; 1963938Sjbeck char vbuf[1024]; 1973938Sjbeck 1983938Sjbeck vbuf[0] = 0; 1993938Sjbeck n = sizeof (vbuf); 2003938Sjbeck for (i = 1; argv[i] != NULL && n > 2; i++) { 2013938Sjbeck n -= strlcat(vbuf, " ", n); 2023938Sjbeck n -= strlcat(vbuf, argv[i], n); 2033938Sjbeck } 2043938Sjbeck if (argv[i] != NULL || n < 0) 20511767SAnurag.Maskey@Sun.COM nlog(LOG_ERR, "nwamd_start_childv can't log full arg vector"); 2063938Sjbeck 2073938Sjbeck if ((rc = posix_spawnattr_init(&attr)) != 0) { 20811767SAnurag.Maskey@Sun.COM nlog(LOG_DEBUG, "posix_spawnattr_init %d %s\n", 20911767SAnurag.Maskey@Sun.COM rc, strerror(rc)); 2103938Sjbeck return (-1); 2113938Sjbeck } 2123938Sjbeck (void) sigfillset(&fullset); 2133938Sjbeck if ((rc = posix_spawnattr_setsigdefault(&attr, &fullset)) != 0) { 21411767SAnurag.Maskey@Sun.COM nlog(LOG_DEBUG, "setsigdefault %d %s\n", rc, strerror(rc)); 2153938Sjbeck return (-1); 2163938Sjbeck } 2173938Sjbeck if ((rc = posix_spawnattr_setsigmask(&attr, &original_sigmask)) != 0) { 21811767SAnurag.Maskey@Sun.COM nlog(LOG_DEBUG, "setsigmask %d %s\n", rc, strerror(rc)); 2193938Sjbeck return (-1); 2203938Sjbeck } 2213938Sjbeck if ((rc = posix_spawnattr_setflags(&attr, 2223938Sjbeck POSIX_SPAWN_SETSIGDEF|POSIX_SPAWN_SETSIGMASK)) != 0) { 22311767SAnurag.Maskey@Sun.COM nlog(LOG_DEBUG, "setflags %d %s\n", rc, strerror(rc)); 2243938Sjbeck return (-1); 2253938Sjbeck } 2263938Sjbeck 2273938Sjbeck if ((rc = posix_spawnp(&pid, command, NULL, &attr, (char * const *)argv, 2283938Sjbeck environ)) > 0) { 22911767SAnurag.Maskey@Sun.COM nlog(LOG_DEBUG, "posix_spawnp failed errno %d", rc); 2303938Sjbeck return (-1); 2313938Sjbeck } 2323938Sjbeck 2333938Sjbeck if ((rc = posix_spawnattr_destroy(&attr)) != 0) { 23411767SAnurag.Maskey@Sun.COM nlog(LOG_DEBUG, "posix_spawn_attr_destroy %d %s\n", 23511767SAnurag.Maskey@Sun.COM rc, strerror(rc)); 2363938Sjbeck return (-1); 2373938Sjbeck } 2383938Sjbeck 2393938Sjbeck (void) waitpid(pid, &status, 0); 2403938Sjbeck if (WIFSIGNALED(status) || WIFSTOPPED(status)) { 2413938Sjbeck i = WIFSIGNALED(status) ? WTERMSIG(status) : WSTOPSIG(status); 24211767SAnurag.Maskey@Sun.COM nlog(LOG_ERR, "'%s%s' %s with signal %d (%s)", command, vbuf, 2433938Sjbeck (WIFSIGNALED(status) ? "terminated" : "stopped"), i, 2443938Sjbeck strsignal(i)); 2453938Sjbeck return (-2); 2463938Sjbeck } else { 24711767SAnurag.Maskey@Sun.COM nlog(LOG_INFO, "'%s%s' completed normally: %d", command, vbuf, 2483938Sjbeck WEXITSTATUS(status)); 2493938Sjbeck return (WEXITSTATUS(status)); 2503938Sjbeck } 2513938Sjbeck } 2523938Sjbeck 25311767SAnurag.Maskey@Sun.COM /* 25411767SAnurag.Maskey@Sun.COM * For global zone, check if the link is used by a non-global 25511767SAnurag.Maskey@Sun.COM * zone, note that the non-global zones doesn't need this check, 25611767SAnurag.Maskey@Sun.COM * because zoneadm has taken care of this when the zone boots. 25711767SAnurag.Maskey@Sun.COM * In the global zone, we ignore events for local-zone-owned links 25811767SAnurag.Maskey@Sun.COM * since these are taken care of by the local zone's network 25911767SAnurag.Maskey@Sun.COM * configuration services. 26011767SAnurag.Maskey@Sun.COM */ 26111767SAnurag.Maskey@Sun.COM boolean_t 26211767SAnurag.Maskey@Sun.COM nwamd_link_belongs_to_this_zone(const char *linkname) 2633938Sjbeck { 26411767SAnurag.Maskey@Sun.COM zoneid_t zoneid; 26511767SAnurag.Maskey@Sun.COM char zonename[ZONENAME_MAX]; 26611767SAnurag.Maskey@Sun.COM int ret; 2673938Sjbeck 26811767SAnurag.Maskey@Sun.COM zoneid = getzoneid(); 26911767SAnurag.Maskey@Sun.COM if (zoneid == GLOBAL_ZONEID) { 27011767SAnurag.Maskey@Sun.COM datalink_id_t linkid; 27111767SAnurag.Maskey@Sun.COM dladm_status_t status; 27211767SAnurag.Maskey@Sun.COM char errstr[DLADM_STRSIZE]; 27311767SAnurag.Maskey@Sun.COM 27411767SAnurag.Maskey@Sun.COM if ((status = dladm_name2info(dld_handle, linkname, &linkid, 27511767SAnurag.Maskey@Sun.COM NULL, NULL, NULL)) != DLADM_STATUS_OK) { 27611767SAnurag.Maskey@Sun.COM nlog(LOG_DEBUG, "nwamd_link_belongs_to_this_zone: " 27711767SAnurag.Maskey@Sun.COM "could not get linkid for %s: %s", 27811767SAnurag.Maskey@Sun.COM linkname, dladm_status2str(status, errstr)); 27911767SAnurag.Maskey@Sun.COM return (B_FALSE); 2803938Sjbeck } 28111767SAnurag.Maskey@Sun.COM zoneid = ALL_ZONES; 28211767SAnurag.Maskey@Sun.COM ret = zone_check_datalink(&zoneid, linkid); 28311767SAnurag.Maskey@Sun.COM if (ret == 0) { 28411767SAnurag.Maskey@Sun.COM (void) getzonenamebyid(zoneid, zonename, ZONENAME_MAX); 28511767SAnurag.Maskey@Sun.COM nlog(LOG_DEBUG, "nwamd_link_belongs_to_this_zone: " 28611767SAnurag.Maskey@Sun.COM "%s is used by non-global zone: %s", 28711767SAnurag.Maskey@Sun.COM linkname, zonename); 28811767SAnurag.Maskey@Sun.COM return (B_FALSE); 28911767SAnurag.Maskey@Sun.COM } 29011767SAnurag.Maskey@Sun.COM } 29111767SAnurag.Maskey@Sun.COM return (B_TRUE); 2923938Sjbeck } 2933938Sjbeck 29411767SAnurag.Maskey@Sun.COM /* 29511767SAnurag.Maskey@Sun.COM * Inputs: 29611767SAnurag.Maskey@Sun.COM * res is a pointer to the scf_resources_t to be released. 29711767SAnurag.Maskey@Sun.COM */ 29811767SAnurag.Maskey@Sun.COM static void 29911767SAnurag.Maskey@Sun.COM release_scf_resources(scf_resources_t *res) 30011767SAnurag.Maskey@Sun.COM { 30111767SAnurag.Maskey@Sun.COM scf_entry_destroy(res->sr_ent); 30211767SAnurag.Maskey@Sun.COM scf_transaction_destroy(res->sr_tx); 30311767SAnurag.Maskey@Sun.COM scf_value_destroy(res->sr_val); 30411767SAnurag.Maskey@Sun.COM scf_property_destroy(res->sr_prop); 30511767SAnurag.Maskey@Sun.COM scf_pg_destroy(res->sr_pg); 30611767SAnurag.Maskey@Sun.COM scf_snapshot_destroy(res->sr_snap); 30711767SAnurag.Maskey@Sun.COM scf_instance_destroy(res->sr_inst); 30811767SAnurag.Maskey@Sun.COM (void) scf_handle_unbind(res->sr_handle); 30911767SAnurag.Maskey@Sun.COM scf_handle_destroy(res->sr_handle); 31011767SAnurag.Maskey@Sun.COM } 31111767SAnurag.Maskey@Sun.COM 31211767SAnurag.Maskey@Sun.COM /* 31311767SAnurag.Maskey@Sun.COM * Inputs: 31411767SAnurag.Maskey@Sun.COM * fmri is the instance to look up 31511767SAnurag.Maskey@Sun.COM * Outputs: 31611767SAnurag.Maskey@Sun.COM * res is a pointer to an scf_resources_t. This is an internal 31711767SAnurag.Maskey@Sun.COM * structure that holds all the handles needed to get a specific 31811767SAnurag.Maskey@Sun.COM * property from the running snapshot; on a successful return it 31911767SAnurag.Maskey@Sun.COM * contains the scf_value_t that should be passed to the desired 32011767SAnurag.Maskey@Sun.COM * scf_value_get_foo() function, and must be freed after use by 32111767SAnurag.Maskey@Sun.COM * calling release_scf_resources(). On a failure return, any 32211767SAnurag.Maskey@Sun.COM * resources that may have been assigned to res are released, so 32311767SAnurag.Maskey@Sun.COM * the caller does not need to do any cleanup in the failure case. 32411767SAnurag.Maskey@Sun.COM * Returns: 32511767SAnurag.Maskey@Sun.COM * 0 on success 32611767SAnurag.Maskey@Sun.COM * -1 on failure 32711767SAnurag.Maskey@Sun.COM */ 32811767SAnurag.Maskey@Sun.COM 32911767SAnurag.Maskey@Sun.COM static int 33011767SAnurag.Maskey@Sun.COM create_scf_resources(const char *fmri, scf_resources_t *res) 3313938Sjbeck { 33211767SAnurag.Maskey@Sun.COM res->sr_tx = NULL; 33311767SAnurag.Maskey@Sun.COM res->sr_ent = NULL; 33411767SAnurag.Maskey@Sun.COM res->sr_inst = NULL; 33511767SAnurag.Maskey@Sun.COM res->sr_snap = NULL; 33611767SAnurag.Maskey@Sun.COM res->sr_pg = NULL; 33711767SAnurag.Maskey@Sun.COM res->sr_prop = NULL; 33811767SAnurag.Maskey@Sun.COM res->sr_val = NULL; 33911767SAnurag.Maskey@Sun.COM 34011767SAnurag.Maskey@Sun.COM if ((res->sr_handle = scf_handle_create(SCF_VERSION)) == NULL) { 34111767SAnurag.Maskey@Sun.COM return (-1); 34211767SAnurag.Maskey@Sun.COM } 34311767SAnurag.Maskey@Sun.COM 34411767SAnurag.Maskey@Sun.COM if (scf_handle_bind(res->sr_handle) != 0) { 34511767SAnurag.Maskey@Sun.COM scf_handle_destroy(res->sr_handle); 34611767SAnurag.Maskey@Sun.COM return (-1); 34711767SAnurag.Maskey@Sun.COM } 34811767SAnurag.Maskey@Sun.COM if ((res->sr_inst = scf_instance_create(res->sr_handle)) == NULL) { 34911767SAnurag.Maskey@Sun.COM goto failure; 35011767SAnurag.Maskey@Sun.COM } 35111767SAnurag.Maskey@Sun.COM if (scf_handle_decode_fmri(res->sr_handle, fmri, NULL, NULL, 35211767SAnurag.Maskey@Sun.COM res->sr_inst, NULL, NULL, SCF_DECODE_FMRI_REQUIRE_INSTANCE) != 0) { 35311767SAnurag.Maskey@Sun.COM goto failure; 35411767SAnurag.Maskey@Sun.COM } 35511767SAnurag.Maskey@Sun.COM if ((res->sr_snap = scf_snapshot_create(res->sr_handle)) == NULL) { 35611767SAnurag.Maskey@Sun.COM goto failure; 35711767SAnurag.Maskey@Sun.COM } 35811767SAnurag.Maskey@Sun.COM if (scf_instance_get_snapshot(res->sr_inst, "running", 35911767SAnurag.Maskey@Sun.COM res->sr_snap) != 0) { 36011767SAnurag.Maskey@Sun.COM goto failure; 36111767SAnurag.Maskey@Sun.COM } 36211767SAnurag.Maskey@Sun.COM if ((res->sr_pg = scf_pg_create(res->sr_handle)) == NULL) { 36311767SAnurag.Maskey@Sun.COM goto failure; 36411767SAnurag.Maskey@Sun.COM } 36511767SAnurag.Maskey@Sun.COM if ((res->sr_prop = scf_property_create(res->sr_handle)) == NULL) { 36611767SAnurag.Maskey@Sun.COM goto failure; 36711767SAnurag.Maskey@Sun.COM } 36811767SAnurag.Maskey@Sun.COM if ((res->sr_val = scf_value_create(res->sr_handle)) == NULL) { 36911767SAnurag.Maskey@Sun.COM goto failure; 37011767SAnurag.Maskey@Sun.COM } 37111767SAnurag.Maskey@Sun.COM if ((res->sr_tx = scf_transaction_create(res->sr_handle)) == NULL) { 37211767SAnurag.Maskey@Sun.COM goto failure; 37311767SAnurag.Maskey@Sun.COM } 37411767SAnurag.Maskey@Sun.COM if ((res->sr_ent = scf_entry_create(res->sr_handle)) == NULL) { 37511767SAnurag.Maskey@Sun.COM goto failure; 37611767SAnurag.Maskey@Sun.COM } 37711767SAnurag.Maskey@Sun.COM return (0); 37811767SAnurag.Maskey@Sun.COM 37911767SAnurag.Maskey@Sun.COM failure: 38011767SAnurag.Maskey@Sun.COM nlog(LOG_ERR, "create_scf_resources failed: %s", 38111767SAnurag.Maskey@Sun.COM scf_strerror(scf_error())); 38211767SAnurag.Maskey@Sun.COM release_scf_resources(res); 38311767SAnurag.Maskey@Sun.COM return (-1); 38411767SAnurag.Maskey@Sun.COM } 38511767SAnurag.Maskey@Sun.COM 38611767SAnurag.Maskey@Sun.COM /* 38711767SAnurag.Maskey@Sun.COM * Inputs: 38811767SAnurag.Maskey@Sun.COM * fmri is the instance to look up 38911767SAnurag.Maskey@Sun.COM * pg is the property group to look up 39011767SAnurag.Maskey@Sun.COM * prop is the property within that group to look up 39111767SAnurag.Maskey@Sun.COM * running specifies if running snapshot is to be used 39211767SAnurag.Maskey@Sun.COM * Outputs: 39311767SAnurag.Maskey@Sun.COM * res is a pointer to an scf_resources_t. This is an internal 39411767SAnurag.Maskey@Sun.COM * structure that holds all the handles needed to get a specific 39511767SAnurag.Maskey@Sun.COM * property from the running snapshot; on a successful return it 39611767SAnurag.Maskey@Sun.COM * contains the scf_value_t that should be passed to the desired 39711767SAnurag.Maskey@Sun.COM * scf_value_get_foo() function, and must be freed after use by 39811767SAnurag.Maskey@Sun.COM * calling release_scf_resources(). On a failure return, any 39911767SAnurag.Maskey@Sun.COM * resources that may have been assigned to res are released, so 40011767SAnurag.Maskey@Sun.COM * the caller does not need to do any cleanup in the failure case. 40111767SAnurag.Maskey@Sun.COM * Returns: 40211767SAnurag.Maskey@Sun.COM * 0 on success 40311767SAnurag.Maskey@Sun.COM * -1 on failure 40411767SAnurag.Maskey@Sun.COM */ 40511767SAnurag.Maskey@Sun.COM static int 40611767SAnurag.Maskey@Sun.COM get_property_value(const char *fmri, const char *pg, const char *prop, 40711767SAnurag.Maskey@Sun.COM boolean_t running, scf_resources_t *res) 40811767SAnurag.Maskey@Sun.COM { 40911767SAnurag.Maskey@Sun.COM if (create_scf_resources(fmri, res) != 0) 41011767SAnurag.Maskey@Sun.COM return (-1); 41111767SAnurag.Maskey@Sun.COM 41211767SAnurag.Maskey@Sun.COM if (scf_instance_get_pg_composed(res->sr_inst, 41311767SAnurag.Maskey@Sun.COM running ? res->sr_snap : NULL, pg, res->sr_pg) != 0) { 41411767SAnurag.Maskey@Sun.COM goto failure; 41511767SAnurag.Maskey@Sun.COM } 41611767SAnurag.Maskey@Sun.COM if (scf_pg_get_property(res->sr_pg, prop, res->sr_prop) != 0) { 41711767SAnurag.Maskey@Sun.COM goto failure; 41811767SAnurag.Maskey@Sun.COM } 41911767SAnurag.Maskey@Sun.COM if (scf_property_get_value(res->sr_prop, res->sr_val) != 0) { 42011767SAnurag.Maskey@Sun.COM goto failure; 42111767SAnurag.Maskey@Sun.COM } 42211767SAnurag.Maskey@Sun.COM return (0); 42311767SAnurag.Maskey@Sun.COM 42411767SAnurag.Maskey@Sun.COM failure: 42511767SAnurag.Maskey@Sun.COM release_scf_resources(res); 42611767SAnurag.Maskey@Sun.COM return (-1); 42711767SAnurag.Maskey@Sun.COM } 42811767SAnurag.Maskey@Sun.COM 42911767SAnurag.Maskey@Sun.COM /* 43011767SAnurag.Maskey@Sun.COM * Inputs: 43111767SAnurag.Maskey@Sun.COM * lfmri is the instance fmri to look up 43211767SAnurag.Maskey@Sun.COM * lpg is the property group to look up 43311767SAnurag.Maskey@Sun.COM * lprop is the property within that group to look up 43411767SAnurag.Maskey@Sun.COM * Outputs: 43511767SAnurag.Maskey@Sun.COM * answer is a pointer to the property value 43611767SAnurag.Maskey@Sun.COM * Returns: 43711767SAnurag.Maskey@Sun.COM * 0 on success 43811767SAnurag.Maskey@Sun.COM * -1 on failure 43911767SAnurag.Maskey@Sun.COM * If successful, the property value is retured in *answer. 44011767SAnurag.Maskey@Sun.COM * Otherwise, *answer is undefined, and it is up to the caller to decide 44111767SAnurag.Maskey@Sun.COM * how to handle that case. 44211767SAnurag.Maskey@Sun.COM */ 44311767SAnurag.Maskey@Sun.COM int 44411767SAnurag.Maskey@Sun.COM nwamd_lookup_boolean_property(const char *lfmri, const char *lpg, 44511767SAnurag.Maskey@Sun.COM const char *lprop, boolean_t *answer) 44611767SAnurag.Maskey@Sun.COM { 44711767SAnurag.Maskey@Sun.COM int result = -1; 44811767SAnurag.Maskey@Sun.COM scf_resources_t res; 44911767SAnurag.Maskey@Sun.COM uint8_t prop_val; 45011767SAnurag.Maskey@Sun.COM 45111767SAnurag.Maskey@Sun.COM if (get_property_value(lfmri, lpg, lprop, B_TRUE, &res) != 0) { 45211767SAnurag.Maskey@Sun.COM 45311767SAnurag.Maskey@Sun.COM /* 45411767SAnurag.Maskey@Sun.COM * an error was already logged by get_property_value, 45511767SAnurag.Maskey@Sun.COM * and it released any resources assigned to res before 45611767SAnurag.Maskey@Sun.COM * returning. 45711767SAnurag.Maskey@Sun.COM */ 45811767SAnurag.Maskey@Sun.COM return (result); 45911767SAnurag.Maskey@Sun.COM } 46011767SAnurag.Maskey@Sun.COM if (scf_value_get_boolean(res.sr_val, &prop_val) != 0) { 46111767SAnurag.Maskey@Sun.COM goto cleanup; 46211767SAnurag.Maskey@Sun.COM } 46311767SAnurag.Maskey@Sun.COM *answer = (boolean_t)prop_val; 46411767SAnurag.Maskey@Sun.COM result = 0; 46511767SAnurag.Maskey@Sun.COM cleanup: 46611767SAnurag.Maskey@Sun.COM release_scf_resources(&res); 46711767SAnurag.Maskey@Sun.COM return (result); 46811767SAnurag.Maskey@Sun.COM } 46911767SAnurag.Maskey@Sun.COM 47011767SAnurag.Maskey@Sun.COM /* 47111767SAnurag.Maskey@Sun.COM * Inputs: 47211767SAnurag.Maskey@Sun.COM * lfmri is the instance fmri to look up 47311767SAnurag.Maskey@Sun.COM * lpg is the property group to look up 47411767SAnurag.Maskey@Sun.COM * lprop is the property within that group to look up 47511767SAnurag.Maskey@Sun.COM * buf is the place to put the answer 47611767SAnurag.Maskey@Sun.COM * bufsz is the size of buf 47711767SAnurag.Maskey@Sun.COM * Outputs: 47811767SAnurag.Maskey@Sun.COM * 47911767SAnurag.Maskey@Sun.COM * Returns: 48011767SAnurag.Maskey@Sun.COM * 0 on success 48111767SAnurag.Maskey@Sun.COM * -1 on failure 48211767SAnurag.Maskey@Sun.COM * If successful, the property value is retured in buf. 48311767SAnurag.Maskey@Sun.COM * Otherwise, buf is undefined, and it is up to the caller to decide 48411767SAnurag.Maskey@Sun.COM * how to handle that case. 48511767SAnurag.Maskey@Sun.COM */ 48611767SAnurag.Maskey@Sun.COM int 48711767SAnurag.Maskey@Sun.COM nwamd_lookup_string_property(const char *lfmri, const char *lpg, 48811767SAnurag.Maskey@Sun.COM const char *lprop, char *buf, size_t bufsz) 48911767SAnurag.Maskey@Sun.COM { 49011767SAnurag.Maskey@Sun.COM int result = -1; 49111767SAnurag.Maskey@Sun.COM scf_resources_t res; 4923938Sjbeck 49311767SAnurag.Maskey@Sun.COM if (get_property_value(lfmri, lpg, lprop, B_TRUE, &res) != 0) { 49411767SAnurag.Maskey@Sun.COM /* 49511767SAnurag.Maskey@Sun.COM * The above function fails when trying to get a 49611767SAnurag.Maskey@Sun.COM * non-persistent property group from the running snapshot. 49711767SAnurag.Maskey@Sun.COM * Try going for the non-running snapshot. 49811767SAnurag.Maskey@Sun.COM */ 49911767SAnurag.Maskey@Sun.COM if (get_property_value(lfmri, lpg, lprop, B_FALSE, &res) != 0) { 50011767SAnurag.Maskey@Sun.COM /* 50111767SAnurag.Maskey@Sun.COM * an error was already logged by get_property_value, 50211767SAnurag.Maskey@Sun.COM * and it released any resources assigned to res before 50311767SAnurag.Maskey@Sun.COM * returning. 50411767SAnurag.Maskey@Sun.COM */ 50511767SAnurag.Maskey@Sun.COM return (result); 50611767SAnurag.Maskey@Sun.COM } 50711767SAnurag.Maskey@Sun.COM } 50811767SAnurag.Maskey@Sun.COM if (scf_value_get_astring(res.sr_val, buf, bufsz) == 0) 50911767SAnurag.Maskey@Sun.COM goto cleanup; 51011767SAnurag.Maskey@Sun.COM 51111767SAnurag.Maskey@Sun.COM result = 0; 51211767SAnurag.Maskey@Sun.COM cleanup: 51311767SAnurag.Maskey@Sun.COM release_scf_resources(&res); 51411767SAnurag.Maskey@Sun.COM return (result); 51511767SAnurag.Maskey@Sun.COM } 51611767SAnurag.Maskey@Sun.COM 51711767SAnurag.Maskey@Sun.COM /* 51811767SAnurag.Maskey@Sun.COM * Inputs: 51911767SAnurag.Maskey@Sun.COM * lfmri is the instance fmri to look up 52011767SAnurag.Maskey@Sun.COM * lpg is the property group to look up 52111767SAnurag.Maskey@Sun.COM * lprop is the property within that group to look up 52211767SAnurag.Maskey@Sun.COM * Outputs: 52311767SAnurag.Maskey@Sun.COM * answer is a pointer to the property value 52411767SAnurag.Maskey@Sun.COM * Returns: 52511767SAnurag.Maskey@Sun.COM * 0 on success 52611767SAnurag.Maskey@Sun.COM * -1 on failure 52711767SAnurag.Maskey@Sun.COM * If successful, the property value is retured in *answer. 52811767SAnurag.Maskey@Sun.COM * Otherwise, *answer is undefined, and it is up to the caller to decide 52911767SAnurag.Maskey@Sun.COM * how to handle that case. 53011767SAnurag.Maskey@Sun.COM */ 53111767SAnurag.Maskey@Sun.COM int 53211767SAnurag.Maskey@Sun.COM nwamd_lookup_count_property(const char *lfmri, const char *lpg, 53311767SAnurag.Maskey@Sun.COM const char *lprop, uint64_t *answer) 53411767SAnurag.Maskey@Sun.COM { 53511767SAnurag.Maskey@Sun.COM int result = -1; 53611767SAnurag.Maskey@Sun.COM scf_resources_t res; 53711767SAnurag.Maskey@Sun.COM 53811767SAnurag.Maskey@Sun.COM if (get_property_value(lfmri, lpg, lprop, B_TRUE, &res) != 0) { 53911767SAnurag.Maskey@Sun.COM 54011767SAnurag.Maskey@Sun.COM /* 54111767SAnurag.Maskey@Sun.COM * an error was already logged by get_property_value, 54211767SAnurag.Maskey@Sun.COM * and it released any resources assigned to res before 54311767SAnurag.Maskey@Sun.COM * returning. 54411767SAnurag.Maskey@Sun.COM */ 54511767SAnurag.Maskey@Sun.COM return (result); 54611767SAnurag.Maskey@Sun.COM } 54711767SAnurag.Maskey@Sun.COM if (scf_value_get_count(res.sr_val, answer) != 0) { 54811767SAnurag.Maskey@Sun.COM goto cleanup; 54911767SAnurag.Maskey@Sun.COM } 55011767SAnurag.Maskey@Sun.COM result = 0; 55111767SAnurag.Maskey@Sun.COM cleanup: 55211767SAnurag.Maskey@Sun.COM release_scf_resources(&res); 55311767SAnurag.Maskey@Sun.COM return (result); 55411767SAnurag.Maskey@Sun.COM } 55511767SAnurag.Maskey@Sun.COM 55611767SAnurag.Maskey@Sun.COM static int 55711767SAnurag.Maskey@Sun.COM set_property_value(scf_resources_t *res, const char *propname, 55811767SAnurag.Maskey@Sun.COM scf_type_t proptype) 55911767SAnurag.Maskey@Sun.COM { 56011767SAnurag.Maskey@Sun.COM int result = -1; 56111767SAnurag.Maskey@Sun.COM boolean_t new; 56211767SAnurag.Maskey@Sun.COM 56311767SAnurag.Maskey@Sun.COM retry: 56411767SAnurag.Maskey@Sun.COM new = (scf_pg_get_property(res->sr_pg, propname, res->sr_prop) != 0); 56511767SAnurag.Maskey@Sun.COM 56611767SAnurag.Maskey@Sun.COM if (scf_transaction_start(res->sr_tx, res->sr_pg) == -1) { 56711767SAnurag.Maskey@Sun.COM goto failure; 56811767SAnurag.Maskey@Sun.COM } 56911767SAnurag.Maskey@Sun.COM if (new) { 57011767SAnurag.Maskey@Sun.COM if (scf_transaction_property_new(res->sr_tx, res->sr_ent, 57111767SAnurag.Maskey@Sun.COM propname, proptype) == -1) { 57211767SAnurag.Maskey@Sun.COM goto failure; 57311767SAnurag.Maskey@Sun.COM } 57411767SAnurag.Maskey@Sun.COM } else { 57511767SAnurag.Maskey@Sun.COM if (scf_transaction_property_change(res->sr_tx, res->sr_ent, 57611767SAnurag.Maskey@Sun.COM propname, proptype) == -1) { 57711767SAnurag.Maskey@Sun.COM goto failure; 57811767SAnurag.Maskey@Sun.COM } 57911767SAnurag.Maskey@Sun.COM } 58011767SAnurag.Maskey@Sun.COM 58111767SAnurag.Maskey@Sun.COM if (scf_entry_add_value(res->sr_ent, res->sr_val) != 0) { 58211767SAnurag.Maskey@Sun.COM goto failure; 58311767SAnurag.Maskey@Sun.COM } 58411767SAnurag.Maskey@Sun.COM 58511767SAnurag.Maskey@Sun.COM result = scf_transaction_commit(res->sr_tx); 58611767SAnurag.Maskey@Sun.COM if (result == 0) { 58711767SAnurag.Maskey@Sun.COM scf_transaction_reset(res->sr_tx); 58811767SAnurag.Maskey@Sun.COM if (scf_pg_update(res->sr_pg) == -1) { 58911767SAnurag.Maskey@Sun.COM goto failure; 59011767SAnurag.Maskey@Sun.COM } 59111767SAnurag.Maskey@Sun.COM nlog(LOG_INFO, "set_property_value: transaction commit failed " 59211767SAnurag.Maskey@Sun.COM "for %s; retrying", propname); 59311767SAnurag.Maskey@Sun.COM goto retry; 59411767SAnurag.Maskey@Sun.COM } 59511767SAnurag.Maskey@Sun.COM if (result == -1) 59611767SAnurag.Maskey@Sun.COM goto failure; 59711767SAnurag.Maskey@Sun.COM return (0); 59811767SAnurag.Maskey@Sun.COM 59911767SAnurag.Maskey@Sun.COM failure: 60011767SAnurag.Maskey@Sun.COM return (-1); 6013938Sjbeck } 60211767SAnurag.Maskey@Sun.COM 60311767SAnurag.Maskey@Sun.COM int 60411767SAnurag.Maskey@Sun.COM nwamd_set_count_property(const char *fmri, const char *pg, const char *prop, 60511767SAnurag.Maskey@Sun.COM uint64_t count) 60611767SAnurag.Maskey@Sun.COM { 60711767SAnurag.Maskey@Sun.COM scf_resources_t res; 60811767SAnurag.Maskey@Sun.COM 60911767SAnurag.Maskey@Sun.COM if (create_scf_resources(fmri, &res) != 0) 61011767SAnurag.Maskey@Sun.COM return (-1); 61111767SAnurag.Maskey@Sun.COM 61211767SAnurag.Maskey@Sun.COM if (scf_instance_add_pg(res.sr_inst, pg, SCF_GROUP_APPLICATION, 61311767SAnurag.Maskey@Sun.COM SCF_PG_FLAG_NONPERSISTENT, res.sr_pg) != 0) { 61411767SAnurag.Maskey@Sun.COM if (scf_error() != SCF_ERROR_EXISTS) 61511767SAnurag.Maskey@Sun.COM goto failure; 61611767SAnurag.Maskey@Sun.COM if (scf_instance_get_pg_composed(res.sr_inst, NULL, pg, 61711767SAnurag.Maskey@Sun.COM res.sr_pg) != 0) 61811767SAnurag.Maskey@Sun.COM goto failure; 61911767SAnurag.Maskey@Sun.COM } 62011767SAnurag.Maskey@Sun.COM 62111767SAnurag.Maskey@Sun.COM scf_value_set_count(res.sr_val, (uint64_t)count); 62211767SAnurag.Maskey@Sun.COM 62311767SAnurag.Maskey@Sun.COM if (set_property_value(&res, prop, SCF_TYPE_COUNT) != 0) 62411767SAnurag.Maskey@Sun.COM goto failure; 62511767SAnurag.Maskey@Sun.COM 62611767SAnurag.Maskey@Sun.COM release_scf_resources(&res); 62711767SAnurag.Maskey@Sun.COM return (0); 62811767SAnurag.Maskey@Sun.COM 62911767SAnurag.Maskey@Sun.COM failure: 63011767SAnurag.Maskey@Sun.COM nlog(LOG_INFO, "nwamd_set_count_property: scf failure %s while " 63111767SAnurag.Maskey@Sun.COM "setting %s", scf_strerror(scf_error()), prop); 63211767SAnurag.Maskey@Sun.COM release_scf_resources(&res); 63311767SAnurag.Maskey@Sun.COM return (-1); 63411767SAnurag.Maskey@Sun.COM } 63511767SAnurag.Maskey@Sun.COM 63611767SAnurag.Maskey@Sun.COM int 63711767SAnurag.Maskey@Sun.COM nwamd_set_string_property(const char *fmri, const char *pg, const char *prop, 63811767SAnurag.Maskey@Sun.COM const char *str) 63911767SAnurag.Maskey@Sun.COM { 64011767SAnurag.Maskey@Sun.COM scf_resources_t res; 64111767SAnurag.Maskey@Sun.COM 64211767SAnurag.Maskey@Sun.COM if (create_scf_resources(fmri, &res) != 0) 64311767SAnurag.Maskey@Sun.COM return (-1); 64411767SAnurag.Maskey@Sun.COM 64511767SAnurag.Maskey@Sun.COM if (scf_instance_add_pg(res.sr_inst, pg, SCF_GROUP_APPLICATION, 64611767SAnurag.Maskey@Sun.COM SCF_PG_FLAG_NONPERSISTENT, res.sr_pg) != 0) { 64711767SAnurag.Maskey@Sun.COM if (scf_error() != SCF_ERROR_EXISTS) 64811767SAnurag.Maskey@Sun.COM goto failure; 64911767SAnurag.Maskey@Sun.COM if (scf_instance_get_pg_composed(res.sr_inst, NULL, pg, 65011767SAnurag.Maskey@Sun.COM res.sr_pg) != 0) 65111767SAnurag.Maskey@Sun.COM goto failure; 65211767SAnurag.Maskey@Sun.COM } 65311767SAnurag.Maskey@Sun.COM 65411767SAnurag.Maskey@Sun.COM if (scf_value_set_astring(res.sr_val, str) != 0) 65511767SAnurag.Maskey@Sun.COM goto failure; 65611767SAnurag.Maskey@Sun.COM 65711767SAnurag.Maskey@Sun.COM if (set_property_value(&res, prop, SCF_TYPE_ASTRING) != 0) 65811767SAnurag.Maskey@Sun.COM goto failure; 65911767SAnurag.Maskey@Sun.COM 66011767SAnurag.Maskey@Sun.COM release_scf_resources(&res); 66111767SAnurag.Maskey@Sun.COM return (0); 66211767SAnurag.Maskey@Sun.COM 66311767SAnurag.Maskey@Sun.COM failure: 66411767SAnurag.Maskey@Sun.COM nlog(LOG_INFO, "nwamd_set_string_property: scf failure %s while " 66511767SAnurag.Maskey@Sun.COM "setting %s", scf_strerror(scf_error()), prop); 66611767SAnurag.Maskey@Sun.COM release_scf_resources(&res); 66711767SAnurag.Maskey@Sun.COM return (-1); 66811767SAnurag.Maskey@Sun.COM } 66911767SAnurag.Maskey@Sun.COM 67011767SAnurag.Maskey@Sun.COM /* 67111767SAnurag.Maskey@Sun.COM * Deletes property prop from property group pg in SMF instance fmri. 67211767SAnurag.Maskey@Sun.COM * Returns 0 on success, -1 on failure. 67311767SAnurag.Maskey@Sun.COM */ 67411767SAnurag.Maskey@Sun.COM int 67511767SAnurag.Maskey@Sun.COM nwamd_delete_scf_property(const char *fmri, const char *pg, const char *prop) 67611767SAnurag.Maskey@Sun.COM { 67711767SAnurag.Maskey@Sun.COM scf_resources_t res; 67811767SAnurag.Maskey@Sun.COM int result = -1; 67911767SAnurag.Maskey@Sun.COM 68011767SAnurag.Maskey@Sun.COM if (create_scf_resources(fmri, &res) != 0) 68111767SAnurag.Maskey@Sun.COM return (-1); 68211767SAnurag.Maskey@Sun.COM 68311767SAnurag.Maskey@Sun.COM if (scf_instance_add_pg(res.sr_inst, pg, SCF_GROUP_APPLICATION, 68411767SAnurag.Maskey@Sun.COM SCF_PG_FLAG_NONPERSISTENT, res.sr_pg) != 0) { 68511767SAnurag.Maskey@Sun.COM if (scf_error() != SCF_ERROR_EXISTS) 68611767SAnurag.Maskey@Sun.COM goto failure; 68711767SAnurag.Maskey@Sun.COM if (scf_instance_get_pg_composed(res.sr_inst, NULL, pg, 68811767SAnurag.Maskey@Sun.COM res.sr_pg) != 0) 68911767SAnurag.Maskey@Sun.COM goto failure; 69011767SAnurag.Maskey@Sun.COM } 69111767SAnurag.Maskey@Sun.COM 69211767SAnurag.Maskey@Sun.COM if (scf_pg_get_property(res.sr_pg, prop, res.sr_prop) != 0) 69311767SAnurag.Maskey@Sun.COM goto failure; 69411767SAnurag.Maskey@Sun.COM retry: 69511767SAnurag.Maskey@Sun.COM if (scf_transaction_start(res.sr_tx, res.sr_pg) == -1) 69611767SAnurag.Maskey@Sun.COM goto failure; 69711767SAnurag.Maskey@Sun.COM 69811767SAnurag.Maskey@Sun.COM if (scf_transaction_property_delete(res.sr_tx, res.sr_ent, prop) == -1) 69911767SAnurag.Maskey@Sun.COM goto failure; 70011767SAnurag.Maskey@Sun.COM 70111767SAnurag.Maskey@Sun.COM result = scf_transaction_commit(res.sr_tx); 70211767SAnurag.Maskey@Sun.COM if (result == 0) { 70311767SAnurag.Maskey@Sun.COM scf_transaction_reset(res.sr_tx); 70411767SAnurag.Maskey@Sun.COM if (scf_pg_update(res.sr_pg) == -1) 70511767SAnurag.Maskey@Sun.COM goto failure; 70611767SAnurag.Maskey@Sun.COM goto retry; 70711767SAnurag.Maskey@Sun.COM } 70811767SAnurag.Maskey@Sun.COM if (result == -1) 70911767SAnurag.Maskey@Sun.COM goto failure; 71011767SAnurag.Maskey@Sun.COM 71111767SAnurag.Maskey@Sun.COM release_scf_resources(&res); 71211767SAnurag.Maskey@Sun.COM return (0); 71311767SAnurag.Maskey@Sun.COM failure: 71411767SAnurag.Maskey@Sun.COM release_scf_resources(&res); 71511767SAnurag.Maskey@Sun.COM return (-1); 71611767SAnurag.Maskey@Sun.COM } 717