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 /* 236ba597c5SAnurag S. Maskey * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 24d71dbb73Sjbeck * Use is subject to license terms. 25d71dbb73Sjbeck */ 26d71dbb73Sjbeck 27d71dbb73Sjbeck /* 286ba597c5SAnurag S. Maskey * util.c contains a set of miscellaneous utility functions which, 296ba597c5SAnurag S. Maskey * among other things: 30d71dbb73Sjbeck * - start a child process 31d71dbb73Sjbeck * - look up the zone name 326ba597c5SAnurag S. Maskey * - look up/set SMF properties 336ba597c5SAnurag S. Maskey * - drop/escalate privs 34d71dbb73Sjbeck */ 35d71dbb73Sjbeck 366ba597c5SAnurag S. Maskey #include <assert.h> 376ba597c5SAnurag S. Maskey #include <errno.h> 386ba597c5SAnurag S. Maskey #include <inetcfg.h> 396ba597c5SAnurag S. Maskey #include <libdllink.h> 406ba597c5SAnurag S. Maskey #include <limits.h> 416ba597c5SAnurag S. Maskey #include <libscf.h> 426ba597c5SAnurag S. Maskey #include <net/if.h> 436ba597c5SAnurag S. Maskey #include <pthread.h> 446ba597c5SAnurag S. Maskey #include <pwd.h> 456ba597c5SAnurag S. Maskey #include <spawn.h> 46d71dbb73Sjbeck #include <stdarg.h> 47d71dbb73Sjbeck #include <stdio.h> 48d71dbb73Sjbeck #include <stdlib.h> 49d71dbb73Sjbeck #include <string.h> 506ba597c5SAnurag S. Maskey #include <strings.h> 51d71dbb73Sjbeck #include <stropts.h> 52d71dbb73Sjbeck #include <sys/socket.h> 536ba597c5SAnurag S. Maskey #include <sys/sockio.h> 546ba597c5SAnurag S. Maskey #include <sys/types.h> 556ba597c5SAnurag S. Maskey #include <unistd.h> 56d71dbb73Sjbeck #include <wait.h> 57d71dbb73Sjbeck #include <zone.h> 58d71dbb73Sjbeck 596ba597c5SAnurag S. Maskey #include "util.h" 606ba597c5SAnurag S. Maskey #include "llp.h" 61d71dbb73Sjbeck 62d71dbb73Sjbeck extern char **environ; 636ba597c5SAnurag S. Maskey extern sigset_t original_sigmask; 64d71dbb73Sjbeck 656ba597c5SAnurag S. Maskey /* 666ba597c5SAnurag S. Maskey * A holder for all the resources needed to get a property value 676ba597c5SAnurag S. Maskey * using libscf. 686ba597c5SAnurag S. Maskey */ 696ba597c5SAnurag S. Maskey typedef struct scf_resources { 706ba597c5SAnurag S. Maskey scf_handle_t *sr_handle; 716ba597c5SAnurag S. Maskey scf_instance_t *sr_inst; 726ba597c5SAnurag S. Maskey scf_snapshot_t *sr_snap; 736ba597c5SAnurag S. Maskey scf_propertygroup_t *sr_pg; 746ba597c5SAnurag S. Maskey scf_property_t *sr_prop; 756ba597c5SAnurag S. Maskey scf_value_t *sr_val; 766ba597c5SAnurag S. Maskey scf_transaction_t *sr_tx; 776ba597c5SAnurag S. Maskey scf_transaction_entry_t *sr_ent; 786ba597c5SAnurag S. Maskey } scf_resources_t; 796ba597c5SAnurag S. Maskey 806ba597c5SAnurag S. Maskey static pthread_mutex_t uid_mutex = PTHREAD_MUTEX_INITIALIZER; 816ba597c5SAnurag S. Maskey static uid_t uid; 826ba597c5SAnurag S. Maskey static int uid_cnt; 83d71dbb73Sjbeck 846ba597c5SAnurag S. Maskey void 85*38f140aaSMichael Hunter nwamd_escalate(void) { 86*38f140aaSMichael Hunter priv_set_t *priv_set; 87*38f140aaSMichael Hunter priv_set = priv_str_to_set("zone", ",", NULL); 88*38f140aaSMichael Hunter 89*38f140aaSMichael Hunter if (priv_set == NULL) 90*38f140aaSMichael Hunter pfail("creating privilege set: %s", strerror(errno)); 91*38f140aaSMichael Hunter 926ba597c5SAnurag S. Maskey (void) pthread_mutex_lock(&uid_mutex); 936ba597c5SAnurag S. Maskey if (uid == 0) 946ba597c5SAnurag S. Maskey uid = getuid(); 956ba597c5SAnurag S. Maskey if (uid_cnt++ == 0) { 96*38f140aaSMichael Hunter if (setppriv(PRIV_SET, PRIV_EFFECTIVE, priv_set) == -1) { 97*38f140aaSMichael Hunter priv_freeset(priv_set); 98*38f140aaSMichael Hunter pfail("setppriv effective: %s", strerror(errno)); 99*38f140aaSMichael Hunter } 1006ba597c5SAnurag S. Maskey if (setuid(0) == -1) 1016ba597c5SAnurag S. Maskey nlog(LOG_ERR, "setuid(0) failed %s", strerror(errno)); 102d71dbb73Sjbeck } 1036ba597c5SAnurag S. Maskey (void) pthread_mutex_unlock(&uid_mutex); 104*38f140aaSMichael Hunter 105*38f140aaSMichael Hunter priv_freeset(priv_set); 106d71dbb73Sjbeck } 107d71dbb73Sjbeck 108b00044a2SJames Carlson void 109*38f140aaSMichael Hunter nwamd_deescalate(void) { 110*38f140aaSMichael Hunter priv_set_t *priv_set, *allpriv_set; 111*38f140aaSMichael Hunter 1126ba597c5SAnurag S. Maskey (void) pthread_mutex_lock(&uid_mutex); 1136ba597c5SAnurag S. Maskey assert(uid_cnt > 0); 1146ba597c5SAnurag S. Maskey if (--uid_cnt == 0) { 1156ba597c5SAnurag S. Maskey if (setuid(uid) == -1) 1166ba597c5SAnurag S. Maskey nlog(LOG_ERR, "setuid(%d) failed %s", uid, 1176ba597c5SAnurag S. Maskey strerror(errno)); 118*38f140aaSMichael Hunter 119*38f140aaSMichael Hunter /* build up our minimal set of privs. */ 120*38f140aaSMichael Hunter priv_set = priv_str_to_set("basic", ",", NULL); 121*38f140aaSMichael Hunter allpriv_set = priv_str_to_set("zone", ",", NULL); 122*38f140aaSMichael Hunter if (priv_set == NULL || allpriv_set == NULL) 123*38f140aaSMichael Hunter pfail("converting privilege sets: %s", strerror(errno)); 124*38f140aaSMichael Hunter 125*38f140aaSMichael Hunter (void) priv_addset(priv_set, PRIV_FILE_CHOWN_SELF); 126*38f140aaSMichael Hunter (void) priv_addset(priv_set, PRIV_FILE_DAC_READ); 127*38f140aaSMichael Hunter (void) priv_addset(priv_set, PRIV_FILE_DAC_WRITE); 128*38f140aaSMichael Hunter (void) priv_addset(priv_set, PRIV_NET_RAWACCESS); 129*38f140aaSMichael Hunter (void) priv_addset(priv_set, PRIV_NET_PRIVADDR); 130*38f140aaSMichael Hunter (void) priv_addset(priv_set, PRIV_PROC_AUDIT); 131*38f140aaSMichael Hunter (void) priv_addset(priv_set, PRIV_PROC_OWNER); 132*38f140aaSMichael Hunter (void) priv_addset(priv_set, PRIV_PROC_SETID); 133*38f140aaSMichael Hunter (void) priv_addset(priv_set, PRIV_SYS_CONFIG); 134*38f140aaSMichael Hunter (void) priv_addset(priv_set, PRIV_SYS_IP_CONFIG); 135*38f140aaSMichael Hunter (void) priv_addset(priv_set, PRIV_SYS_IPC_CONFIG); 136*38f140aaSMichael Hunter (void) priv_addset(priv_set, PRIV_SYS_MOUNT); 137*38f140aaSMichael Hunter (void) priv_addset(priv_set, PRIV_SYS_NET_CONFIG); 138*38f140aaSMichael Hunter (void) priv_addset(priv_set, PRIV_SYS_RES_CONFIG); 139*38f140aaSMichael Hunter (void) priv_addset(priv_set, PRIV_SYS_RESOURCE); 140*38f140aaSMichael Hunter 141*38f140aaSMichael Hunter /* 142*38f140aaSMichael Hunter * Since our zone might not have all these privs, 143*38f140aaSMichael Hunter * just ask for those that are available. 144*38f140aaSMichael Hunter */ 145*38f140aaSMichael Hunter priv_intersect(allpriv_set, priv_set); 146*38f140aaSMichael Hunter 147*38f140aaSMichael Hunter if (setppriv(PRIV_SET, PRIV_INHERITABLE, priv_set) == -1) { 148*38f140aaSMichael Hunter priv_freeset(allpriv_set); 149*38f140aaSMichael Hunter priv_freeset(priv_set); 150*38f140aaSMichael Hunter pfail("setppriv inheritable: %s", strerror(errno)); 151*38f140aaSMichael Hunter } 152*38f140aaSMichael Hunter /* 153*38f140aaSMichael Hunter * Need to ensure permitted set contains all privs so we can 154*38f140aaSMichael Hunter * escalate later. 155*38f140aaSMichael Hunter */ 156*38f140aaSMichael Hunter if (setppriv(PRIV_SET, PRIV_PERMITTED, allpriv_set) == -1) { 157*38f140aaSMichael Hunter priv_freeset(allpriv_set); 158*38f140aaSMichael Hunter priv_freeset(priv_set); 159*38f140aaSMichael Hunter pfail("setppriv permitted: %s", strerror(errno)); 160*38f140aaSMichael Hunter } 161*38f140aaSMichael Hunter /* 162*38f140aaSMichael Hunter * We need to find a smaller set of privs that are important to 163*38f140aaSMichael Hunter * us. Otherwise we really are not gaining much by doing this. 164*38f140aaSMichael Hunter */ 165*38f140aaSMichael Hunter if (setppriv(PRIV_SET, PRIV_EFFECTIVE, priv_set) == -1) { 166*38f140aaSMichael Hunter priv_freeset(allpriv_set); 167*38f140aaSMichael Hunter priv_freeset(priv_set); 168*38f140aaSMichael Hunter pfail("setppriv effective: %s", strerror(errno)); 169*38f140aaSMichael Hunter } 1706ba597c5SAnurag S. Maskey } 1716ba597c5SAnurag S. Maskey (void) pthread_mutex_unlock(&uid_mutex); 172*38f140aaSMichael Hunter 173*38f140aaSMichael Hunter priv_freeset(priv_set); 174*38f140aaSMichael Hunter priv_freeset(allpriv_set); 175b00044a2SJames Carlson } 176b00044a2SJames Carlson 177d71dbb73Sjbeck /* 178d71dbb73Sjbeck * 179d71dbb73Sjbeck * This starts a child process determined by command. If command contains a 180d71dbb73Sjbeck * slash then it is assumed to be a full path; otherwise the path is searched 181d71dbb73Sjbeck * for an executable file with the name command. Command is also used as 182d71dbb73Sjbeck * argv[0] of the new process. The rest of the arguments of the function 183d71dbb73Sjbeck * up to the first NULL make up pointers to arguments of the new process. 184d71dbb73Sjbeck * 185d71dbb73Sjbeck * This function returns child exit status on success and -1 on failure. 186d71dbb73Sjbeck * 187d71dbb73Sjbeck * NOTE: original_sigmask must be set before this function is called. 188d71dbb73Sjbeck */ 189d71dbb73Sjbeck int 1906ba597c5SAnurag S. Maskey nwamd_start_childv(const char *command, char const * const *argv) 191d71dbb73Sjbeck { 192d71dbb73Sjbeck posix_spawnattr_t attr; 193d71dbb73Sjbeck sigset_t fullset; 194d71dbb73Sjbeck int i, rc, status, n; 195d71dbb73Sjbeck pid_t pid; 196d71dbb73Sjbeck char vbuf[1024]; 197d71dbb73Sjbeck 198d71dbb73Sjbeck vbuf[0] = 0; 199d71dbb73Sjbeck n = sizeof (vbuf); 200d71dbb73Sjbeck for (i = 1; argv[i] != NULL && n > 2; i++) { 201d71dbb73Sjbeck n -= strlcat(vbuf, " ", n); 202d71dbb73Sjbeck n -= strlcat(vbuf, argv[i], n); 203d71dbb73Sjbeck } 204d71dbb73Sjbeck if (argv[i] != NULL || n < 0) 2056ba597c5SAnurag S. Maskey nlog(LOG_ERR, "nwamd_start_childv can't log full arg vector"); 206d71dbb73Sjbeck 207d71dbb73Sjbeck if ((rc = posix_spawnattr_init(&attr)) != 0) { 2086ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "posix_spawnattr_init %d %s\n", 2096ba597c5SAnurag S. Maskey rc, strerror(rc)); 210d71dbb73Sjbeck return (-1); 211d71dbb73Sjbeck } 212d71dbb73Sjbeck (void) sigfillset(&fullset); 213d71dbb73Sjbeck if ((rc = posix_spawnattr_setsigdefault(&attr, &fullset)) != 0) { 2146ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "setsigdefault %d %s\n", rc, strerror(rc)); 215d71dbb73Sjbeck return (-1); 216d71dbb73Sjbeck } 217d71dbb73Sjbeck if ((rc = posix_spawnattr_setsigmask(&attr, &original_sigmask)) != 0) { 2186ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "setsigmask %d %s\n", rc, strerror(rc)); 219d71dbb73Sjbeck return (-1); 220d71dbb73Sjbeck } 221d71dbb73Sjbeck if ((rc = posix_spawnattr_setflags(&attr, 222d71dbb73Sjbeck POSIX_SPAWN_SETSIGDEF|POSIX_SPAWN_SETSIGMASK)) != 0) { 2236ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "setflags %d %s\n", rc, strerror(rc)); 224d71dbb73Sjbeck return (-1); 225d71dbb73Sjbeck } 226d71dbb73Sjbeck 227d71dbb73Sjbeck if ((rc = posix_spawnp(&pid, command, NULL, &attr, (char * const *)argv, 228d71dbb73Sjbeck environ)) > 0) { 2296ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "posix_spawnp failed errno %d", rc); 230d71dbb73Sjbeck return (-1); 231d71dbb73Sjbeck } 232d71dbb73Sjbeck 233d71dbb73Sjbeck if ((rc = posix_spawnattr_destroy(&attr)) != 0) { 2346ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "posix_spawn_attr_destroy %d %s\n", 2356ba597c5SAnurag S. Maskey rc, strerror(rc)); 236d71dbb73Sjbeck return (-1); 237d71dbb73Sjbeck } 238d71dbb73Sjbeck 239d71dbb73Sjbeck (void) waitpid(pid, &status, 0); 240d71dbb73Sjbeck if (WIFSIGNALED(status) || WIFSTOPPED(status)) { 241d71dbb73Sjbeck i = WIFSIGNALED(status) ? WTERMSIG(status) : WSTOPSIG(status); 2426ba597c5SAnurag S. Maskey nlog(LOG_ERR, "'%s%s' %s with signal %d (%s)", command, vbuf, 243d71dbb73Sjbeck (WIFSIGNALED(status) ? "terminated" : "stopped"), i, 244d71dbb73Sjbeck strsignal(i)); 245d71dbb73Sjbeck return (-2); 246d71dbb73Sjbeck } else { 2476ba597c5SAnurag S. Maskey nlog(LOG_INFO, "'%s%s' completed normally: %d", command, vbuf, 248d71dbb73Sjbeck WEXITSTATUS(status)); 249d71dbb73Sjbeck return (WEXITSTATUS(status)); 250d71dbb73Sjbeck } 251d71dbb73Sjbeck } 252d71dbb73Sjbeck 2536ba597c5SAnurag S. Maskey /* 2546ba597c5SAnurag S. Maskey * For global zone, check if the link is used by a non-global 2556ba597c5SAnurag S. Maskey * zone, note that the non-global zones doesn't need this check, 2566ba597c5SAnurag S. Maskey * because zoneadm has taken care of this when the zone boots. 2576ba597c5SAnurag S. Maskey * In the global zone, we ignore events for local-zone-owned links 2586ba597c5SAnurag S. Maskey * since these are taken care of by the local zone's network 2596ba597c5SAnurag S. Maskey * configuration services. 2606ba597c5SAnurag S. Maskey */ 2616ba597c5SAnurag S. Maskey boolean_t 2626ba597c5SAnurag S. Maskey nwamd_link_belongs_to_this_zone(const char *linkname) 263d71dbb73Sjbeck { 2646ba597c5SAnurag S. Maskey zoneid_t zoneid; 2656ba597c5SAnurag S. Maskey char zonename[ZONENAME_MAX]; 2666ba597c5SAnurag S. Maskey int ret; 2676ba597c5SAnurag S. Maskey 2686ba597c5SAnurag S. Maskey zoneid = getzoneid(); 2696ba597c5SAnurag S. Maskey if (zoneid == GLOBAL_ZONEID) { 2706ba597c5SAnurag S. Maskey datalink_id_t linkid; 2716ba597c5SAnurag S. Maskey dladm_status_t status; 2726ba597c5SAnurag S. Maskey char errstr[DLADM_STRSIZE]; 2736ba597c5SAnurag S. Maskey 2746ba597c5SAnurag S. Maskey if ((status = dladm_name2info(dld_handle, linkname, &linkid, 2756ba597c5SAnurag S. Maskey NULL, NULL, NULL)) != DLADM_STATUS_OK) { 2766ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_link_belongs_to_this_zone: " 2776ba597c5SAnurag S. Maskey "could not get linkid for %s: %s", 2786ba597c5SAnurag S. Maskey linkname, dladm_status2str(status, errstr)); 2796ba597c5SAnurag S. Maskey return (B_FALSE); 2806ba597c5SAnurag S. Maskey } 2816ba597c5SAnurag S. Maskey zoneid = ALL_ZONES; 2826ba597c5SAnurag S. Maskey ret = zone_check_datalink(&zoneid, linkid); 2836ba597c5SAnurag S. Maskey if (ret == 0) { 2846ba597c5SAnurag S. Maskey (void) getzonenamebyid(zoneid, zonename, ZONENAME_MAX); 2856ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_link_belongs_to_this_zone: " 2866ba597c5SAnurag S. Maskey "%s is used by non-global zone: %s", 2876ba597c5SAnurag S. Maskey linkname, zonename); 2886ba597c5SAnurag S. Maskey return (B_FALSE); 289d71dbb73Sjbeck } 2906ba597c5SAnurag S. Maskey } 2916ba597c5SAnurag S. Maskey return (B_TRUE); 2926ba597c5SAnurag S. Maskey } 293d71dbb73Sjbeck 2946ba597c5SAnurag S. Maskey /* 2956ba597c5SAnurag S. Maskey * Inputs: 2966ba597c5SAnurag S. Maskey * res is a pointer to the scf_resources_t to be released. 2976ba597c5SAnurag S. Maskey */ 2986ba597c5SAnurag S. Maskey static void 2996ba597c5SAnurag S. Maskey release_scf_resources(scf_resources_t *res) 3006ba597c5SAnurag S. Maskey { 3016ba597c5SAnurag S. Maskey scf_entry_destroy(res->sr_ent); 3026ba597c5SAnurag S. Maskey scf_transaction_destroy(res->sr_tx); 3036ba597c5SAnurag S. Maskey scf_value_destroy(res->sr_val); 3046ba597c5SAnurag S. Maskey scf_property_destroy(res->sr_prop); 3056ba597c5SAnurag S. Maskey scf_pg_destroy(res->sr_pg); 3066ba597c5SAnurag S. Maskey scf_snapshot_destroy(res->sr_snap); 3076ba597c5SAnurag S. Maskey scf_instance_destroy(res->sr_inst); 3086ba597c5SAnurag S. Maskey (void) scf_handle_unbind(res->sr_handle); 3096ba597c5SAnurag S. Maskey scf_handle_destroy(res->sr_handle); 3106ba597c5SAnurag S. Maskey } 311d71dbb73Sjbeck 312d71dbb73Sjbeck /* 3136ba597c5SAnurag S. Maskey * Inputs: 3146ba597c5SAnurag S. Maskey * fmri is the instance to look up 3156ba597c5SAnurag S. Maskey * Outputs: 3166ba597c5SAnurag S. Maskey * res is a pointer to an scf_resources_t. This is an internal 3176ba597c5SAnurag S. Maskey * structure that holds all the handles needed to get a specific 3186ba597c5SAnurag S. Maskey * property from the running snapshot; on a successful return it 3196ba597c5SAnurag S. Maskey * contains the scf_value_t that should be passed to the desired 3206ba597c5SAnurag S. Maskey * scf_value_get_foo() function, and must be freed after use by 3216ba597c5SAnurag S. Maskey * calling release_scf_resources(). On a failure return, any 3226ba597c5SAnurag S. Maskey * resources that may have been assigned to res are released, so 3236ba597c5SAnurag S. Maskey * the caller does not need to do any cleanup in the failure case. 3246ba597c5SAnurag S. Maskey * Returns: 3256ba597c5SAnurag S. Maskey * 0 on success 3266ba597c5SAnurag S. Maskey * -1 on failure 327d71dbb73Sjbeck */ 3286ba597c5SAnurag S. Maskey 3296ba597c5SAnurag S. Maskey static int 3306ba597c5SAnurag S. Maskey create_scf_resources(const char *fmri, scf_resources_t *res) 3316ba597c5SAnurag S. Maskey { 3326ba597c5SAnurag S. Maskey res->sr_tx = NULL; 3336ba597c5SAnurag S. Maskey res->sr_ent = NULL; 3346ba597c5SAnurag S. Maskey res->sr_inst = NULL; 3356ba597c5SAnurag S. Maskey res->sr_snap = NULL; 3366ba597c5SAnurag S. Maskey res->sr_pg = NULL; 3376ba597c5SAnurag S. Maskey res->sr_prop = NULL; 3386ba597c5SAnurag S. Maskey res->sr_val = NULL; 3396ba597c5SAnurag S. Maskey 3406ba597c5SAnurag S. Maskey if ((res->sr_handle = scf_handle_create(SCF_VERSION)) == NULL) { 3416ba597c5SAnurag S. Maskey return (-1); 3426ba597c5SAnurag S. Maskey } 3436ba597c5SAnurag S. Maskey 3446ba597c5SAnurag S. Maskey if (scf_handle_bind(res->sr_handle) != 0) { 3456ba597c5SAnurag S. Maskey scf_handle_destroy(res->sr_handle); 3466ba597c5SAnurag S. Maskey return (-1); 3476ba597c5SAnurag S. Maskey } 3486ba597c5SAnurag S. Maskey if ((res->sr_inst = scf_instance_create(res->sr_handle)) == NULL) { 3496ba597c5SAnurag S. Maskey goto failure; 3506ba597c5SAnurag S. Maskey } 3516ba597c5SAnurag S. Maskey if (scf_handle_decode_fmri(res->sr_handle, fmri, NULL, NULL, 3526ba597c5SAnurag S. Maskey res->sr_inst, NULL, NULL, SCF_DECODE_FMRI_REQUIRE_INSTANCE) != 0) { 3536ba597c5SAnurag S. Maskey goto failure; 3546ba597c5SAnurag S. Maskey } 3556ba597c5SAnurag S. Maskey if ((res->sr_snap = scf_snapshot_create(res->sr_handle)) == NULL) { 3566ba597c5SAnurag S. Maskey goto failure; 3576ba597c5SAnurag S. Maskey } 3586ba597c5SAnurag S. Maskey if (scf_instance_get_snapshot(res->sr_inst, "running", 3596ba597c5SAnurag S. Maskey res->sr_snap) != 0) { 3606ba597c5SAnurag S. Maskey goto failure; 3616ba597c5SAnurag S. Maskey } 3626ba597c5SAnurag S. Maskey if ((res->sr_pg = scf_pg_create(res->sr_handle)) == NULL) { 3636ba597c5SAnurag S. Maskey goto failure; 3646ba597c5SAnurag S. Maskey } 3656ba597c5SAnurag S. Maskey if ((res->sr_prop = scf_property_create(res->sr_handle)) == NULL) { 3666ba597c5SAnurag S. Maskey goto failure; 3676ba597c5SAnurag S. Maskey } 3686ba597c5SAnurag S. Maskey if ((res->sr_val = scf_value_create(res->sr_handle)) == NULL) { 3696ba597c5SAnurag S. Maskey goto failure; 3706ba597c5SAnurag S. Maskey } 3716ba597c5SAnurag S. Maskey if ((res->sr_tx = scf_transaction_create(res->sr_handle)) == NULL) { 3726ba597c5SAnurag S. Maskey goto failure; 3736ba597c5SAnurag S. Maskey } 3746ba597c5SAnurag S. Maskey if ((res->sr_ent = scf_entry_create(res->sr_handle)) == NULL) { 3756ba597c5SAnurag S. Maskey goto failure; 3766ba597c5SAnurag S. Maskey } 3776ba597c5SAnurag S. Maskey return (0); 3786ba597c5SAnurag S. Maskey 3796ba597c5SAnurag S. Maskey failure: 3806ba597c5SAnurag S. Maskey nlog(LOG_ERR, "create_scf_resources failed: %s", 3816ba597c5SAnurag S. Maskey scf_strerror(scf_error())); 3826ba597c5SAnurag S. Maskey release_scf_resources(res); 3836ba597c5SAnurag S. Maskey return (-1); 3846ba597c5SAnurag S. Maskey } 3856ba597c5SAnurag S. Maskey 3866ba597c5SAnurag S. Maskey /* 3876ba597c5SAnurag S. Maskey * Inputs: 3886ba597c5SAnurag S. Maskey * fmri is the instance to look up 3896ba597c5SAnurag S. Maskey * pg is the property group to look up 3906ba597c5SAnurag S. Maskey * prop is the property within that group to look up 3916ba597c5SAnurag S. Maskey * running specifies if running snapshot is to be used 3926ba597c5SAnurag S. Maskey * Outputs: 3936ba597c5SAnurag S. Maskey * res is a pointer to an scf_resources_t. This is an internal 3946ba597c5SAnurag S. Maskey * structure that holds all the handles needed to get a specific 3956ba597c5SAnurag S. Maskey * property from the running snapshot; on a successful return it 3966ba597c5SAnurag S. Maskey * contains the scf_value_t that should be passed to the desired 3976ba597c5SAnurag S. Maskey * scf_value_get_foo() function, and must be freed after use by 3986ba597c5SAnurag S. Maskey * calling release_scf_resources(). On a failure return, any 3996ba597c5SAnurag S. Maskey * resources that may have been assigned to res are released, so 4006ba597c5SAnurag S. Maskey * the caller does not need to do any cleanup in the failure case. 4016ba597c5SAnurag S. Maskey * Returns: 4026ba597c5SAnurag S. Maskey * 0 on success 4036ba597c5SAnurag S. Maskey * -1 on failure 4046ba597c5SAnurag S. Maskey */ 4056ba597c5SAnurag S. Maskey static int 4066ba597c5SAnurag S. Maskey get_property_value(const char *fmri, const char *pg, const char *prop, 4076ba597c5SAnurag S. Maskey boolean_t running, scf_resources_t *res) 408d71dbb73Sjbeck { 4096ba597c5SAnurag S. Maskey if (create_scf_resources(fmri, res) != 0) 4106ba597c5SAnurag S. Maskey return (-1); 4116ba597c5SAnurag S. Maskey 4126ba597c5SAnurag S. Maskey if (scf_instance_get_pg_composed(res->sr_inst, 4136ba597c5SAnurag S. Maskey running ? res->sr_snap : NULL, pg, res->sr_pg) != 0) { 4146ba597c5SAnurag S. Maskey goto failure; 4156ba597c5SAnurag S. Maskey } 4166ba597c5SAnurag S. Maskey if (scf_pg_get_property(res->sr_pg, prop, res->sr_prop) != 0) { 4176ba597c5SAnurag S. Maskey goto failure; 4186ba597c5SAnurag S. Maskey } 4196ba597c5SAnurag S. Maskey if (scf_property_get_value(res->sr_prop, res->sr_val) != 0) { 4206ba597c5SAnurag S. Maskey goto failure; 4216ba597c5SAnurag S. Maskey } 4226ba597c5SAnurag S. Maskey return (0); 423d71dbb73Sjbeck 4246ba597c5SAnurag S. Maskey failure: 4256ba597c5SAnurag S. Maskey release_scf_resources(res); 4266ba597c5SAnurag S. Maskey return (-1); 427d71dbb73Sjbeck } 428d71dbb73Sjbeck 4296ba597c5SAnurag S. Maskey /* 4306ba597c5SAnurag S. Maskey * Inputs: 4316ba597c5SAnurag S. Maskey * lfmri is the instance fmri to look up 4326ba597c5SAnurag S. Maskey * lpg is the property group to look up 4336ba597c5SAnurag S. Maskey * lprop is the property within that group to look up 4346ba597c5SAnurag S. Maskey * Outputs: 4356ba597c5SAnurag S. Maskey * answer is a pointer to the property value 4366ba597c5SAnurag S. Maskey * Returns: 4376ba597c5SAnurag S. Maskey * 0 on success 4386ba597c5SAnurag S. Maskey * -1 on failure 4396ba597c5SAnurag S. Maskey * If successful, the property value is retured in *answer. 4406ba597c5SAnurag S. Maskey * Otherwise, *answer is undefined, and it is up to the caller to decide 4416ba597c5SAnurag S. Maskey * how to handle that case. 4426ba597c5SAnurag S. Maskey */ 4436ba597c5SAnurag S. Maskey int 4446ba597c5SAnurag S. Maskey nwamd_lookup_boolean_property(const char *lfmri, const char *lpg, 4456ba597c5SAnurag S. Maskey const char *lprop, boolean_t *answer) 4466ba597c5SAnurag S. Maskey { 4476ba597c5SAnurag S. Maskey int result = -1; 4486ba597c5SAnurag S. Maskey scf_resources_t res; 4496ba597c5SAnurag S. Maskey uint8_t prop_val; 4506ba597c5SAnurag S. Maskey 4516ba597c5SAnurag S. Maskey if (get_property_value(lfmri, lpg, lprop, B_TRUE, &res) != 0) { 4526ba597c5SAnurag S. Maskey 4536ba597c5SAnurag S. Maskey /* 4546ba597c5SAnurag S. Maskey * an error was already logged by get_property_value, 4556ba597c5SAnurag S. Maskey * and it released any resources assigned to res before 4566ba597c5SAnurag S. Maskey * returning. 4576ba597c5SAnurag S. Maskey */ 4586ba597c5SAnurag S. Maskey return (result); 4596ba597c5SAnurag S. Maskey } 4606ba597c5SAnurag S. Maskey if (scf_value_get_boolean(res.sr_val, &prop_val) != 0) { 4616ba597c5SAnurag S. Maskey goto cleanup; 4626ba597c5SAnurag S. Maskey } 4636ba597c5SAnurag S. Maskey *answer = (boolean_t)prop_val; 4646ba597c5SAnurag S. Maskey result = 0; 4656ba597c5SAnurag S. Maskey cleanup: 4666ba597c5SAnurag S. Maskey release_scf_resources(&res); 4676ba597c5SAnurag S. Maskey return (result); 4686ba597c5SAnurag S. Maskey } 4696ba597c5SAnurag S. Maskey 4706ba597c5SAnurag S. Maskey /* 4716ba597c5SAnurag S. Maskey * Inputs: 4726ba597c5SAnurag S. Maskey * lfmri is the instance fmri to look up 4736ba597c5SAnurag S. Maskey * lpg is the property group to look up 4746ba597c5SAnurag S. Maskey * lprop is the property within that group to look up 4756ba597c5SAnurag S. Maskey * buf is the place to put the answer 4766ba597c5SAnurag S. Maskey * bufsz is the size of buf 4776ba597c5SAnurag S. Maskey * Outputs: 4786ba597c5SAnurag S. Maskey * 4796ba597c5SAnurag S. Maskey * Returns: 4806ba597c5SAnurag S. Maskey * 0 on success 4816ba597c5SAnurag S. Maskey * -1 on failure 4826ba597c5SAnurag S. Maskey * If successful, the property value is retured in buf. 4836ba597c5SAnurag S. Maskey * Otherwise, buf is undefined, and it is up to the caller to decide 4846ba597c5SAnurag S. Maskey * how to handle that case. 4856ba597c5SAnurag S. Maskey */ 4866ba597c5SAnurag S. Maskey int 4876ba597c5SAnurag S. Maskey nwamd_lookup_string_property(const char *lfmri, const char *lpg, 4886ba597c5SAnurag S. Maskey const char *lprop, char *buf, size_t bufsz) 489d71dbb73Sjbeck { 4906ba597c5SAnurag S. Maskey int result = -1; 4916ba597c5SAnurag S. Maskey scf_resources_t res; 4926ba597c5SAnurag S. Maskey 4936ba597c5SAnurag S. Maskey if (get_property_value(lfmri, lpg, lprop, B_TRUE, &res) != 0) { 4946ba597c5SAnurag S. Maskey /* 4956ba597c5SAnurag S. Maskey * The above function fails when trying to get a 4966ba597c5SAnurag S. Maskey * non-persistent property group from the running snapshot. 4976ba597c5SAnurag S. Maskey * Try going for the non-running snapshot. 4986ba597c5SAnurag S. Maskey */ 4996ba597c5SAnurag S. Maskey if (get_property_value(lfmri, lpg, lprop, B_FALSE, &res) != 0) { 5006ba597c5SAnurag S. Maskey /* 5016ba597c5SAnurag S. Maskey * an error was already logged by get_property_value, 5026ba597c5SAnurag S. Maskey * and it released any resources assigned to res before 5036ba597c5SAnurag S. Maskey * returning. 5046ba597c5SAnurag S. Maskey */ 5056ba597c5SAnurag S. Maskey return (result); 5066ba597c5SAnurag S. Maskey } 5076ba597c5SAnurag S. Maskey } 5086ba597c5SAnurag S. Maskey if (scf_value_get_astring(res.sr_val, buf, bufsz) == 0) 5096ba597c5SAnurag S. Maskey goto cleanup; 5106ba597c5SAnurag S. Maskey 5116ba597c5SAnurag S. Maskey result = 0; 5126ba597c5SAnurag S. Maskey cleanup: 5136ba597c5SAnurag S. Maskey release_scf_resources(&res); 5146ba597c5SAnurag S. Maskey return (result); 5156ba597c5SAnurag S. Maskey } 516d71dbb73Sjbeck 5176ba597c5SAnurag S. Maskey /* 5186ba597c5SAnurag S. Maskey * Inputs: 5196ba597c5SAnurag S. Maskey * lfmri is the instance fmri to look up 5206ba597c5SAnurag S. Maskey * lpg is the property group to look up 5216ba597c5SAnurag S. Maskey * lprop is the property within that group to look up 5226ba597c5SAnurag S. Maskey * Outputs: 5236ba597c5SAnurag S. Maskey * answer is a pointer to the property value 5246ba597c5SAnurag S. Maskey * Returns: 5256ba597c5SAnurag S. Maskey * 0 on success 5266ba597c5SAnurag S. Maskey * -1 on failure 5276ba597c5SAnurag S. Maskey * If successful, the property value is retured in *answer. 5286ba597c5SAnurag S. Maskey * Otherwise, *answer is undefined, and it is up to the caller to decide 5296ba597c5SAnurag S. Maskey * how to handle that case. 5306ba597c5SAnurag S. Maskey */ 5316ba597c5SAnurag S. Maskey int 5326ba597c5SAnurag S. Maskey nwamd_lookup_count_property(const char *lfmri, const char *lpg, 5336ba597c5SAnurag S. Maskey const char *lprop, uint64_t *answer) 5346ba597c5SAnurag S. Maskey { 5356ba597c5SAnurag S. Maskey int result = -1; 5366ba597c5SAnurag S. Maskey scf_resources_t res; 5376ba597c5SAnurag S. Maskey 5386ba597c5SAnurag S. Maskey if (get_property_value(lfmri, lpg, lprop, B_TRUE, &res) != 0) { 5396ba597c5SAnurag S. Maskey 5406ba597c5SAnurag S. Maskey /* 5416ba597c5SAnurag S. Maskey * an error was already logged by get_property_value, 5426ba597c5SAnurag S. Maskey * and it released any resources assigned to res before 5436ba597c5SAnurag S. Maskey * returning. 5446ba597c5SAnurag S. Maskey */ 5456ba597c5SAnurag S. Maskey return (result); 5466ba597c5SAnurag S. Maskey } 5476ba597c5SAnurag S. Maskey if (scf_value_get_count(res.sr_val, answer) != 0) { 5486ba597c5SAnurag S. Maskey goto cleanup; 5496ba597c5SAnurag S. Maskey } 5506ba597c5SAnurag S. Maskey result = 0; 5516ba597c5SAnurag S. Maskey cleanup: 5526ba597c5SAnurag S. Maskey release_scf_resources(&res); 5536ba597c5SAnurag S. Maskey return (result); 5546ba597c5SAnurag S. Maskey } 5556ba597c5SAnurag S. Maskey 5566ba597c5SAnurag S. Maskey static int 5576ba597c5SAnurag S. Maskey set_property_value(scf_resources_t *res, const char *propname, 5586ba597c5SAnurag S. Maskey scf_type_t proptype) 5596ba597c5SAnurag S. Maskey { 5606ba597c5SAnurag S. Maskey int result = -1; 5616ba597c5SAnurag S. Maskey boolean_t new; 5626ba597c5SAnurag S. Maskey 5636ba597c5SAnurag S. Maskey retry: 5646ba597c5SAnurag S. Maskey new = (scf_pg_get_property(res->sr_pg, propname, res->sr_prop) != 0); 5656ba597c5SAnurag S. Maskey 5666ba597c5SAnurag S. Maskey if (scf_transaction_start(res->sr_tx, res->sr_pg) == -1) { 5676ba597c5SAnurag S. Maskey goto failure; 5686ba597c5SAnurag S. Maskey } 5696ba597c5SAnurag S. Maskey if (new) { 5706ba597c5SAnurag S. Maskey if (scf_transaction_property_new(res->sr_tx, res->sr_ent, 5716ba597c5SAnurag S. Maskey propname, proptype) == -1) { 5726ba597c5SAnurag S. Maskey goto failure; 5736ba597c5SAnurag S. Maskey } 5746ba597c5SAnurag S. Maskey } else { 5756ba597c5SAnurag S. Maskey if (scf_transaction_property_change(res->sr_tx, res->sr_ent, 5766ba597c5SAnurag S. Maskey propname, proptype) == -1) { 5776ba597c5SAnurag S. Maskey goto failure; 5786ba597c5SAnurag S. Maskey } 5796ba597c5SAnurag S. Maskey } 5806ba597c5SAnurag S. Maskey 5816ba597c5SAnurag S. Maskey if (scf_entry_add_value(res->sr_ent, res->sr_val) != 0) { 5826ba597c5SAnurag S. Maskey goto failure; 5836ba597c5SAnurag S. Maskey } 5846ba597c5SAnurag S. Maskey 5856ba597c5SAnurag S. Maskey result = scf_transaction_commit(res->sr_tx); 5866ba597c5SAnurag S. Maskey if (result == 0) { 5876ba597c5SAnurag S. Maskey scf_transaction_reset(res->sr_tx); 5886ba597c5SAnurag S. Maskey if (scf_pg_update(res->sr_pg) == -1) { 5896ba597c5SAnurag S. Maskey goto failure; 5906ba597c5SAnurag S. Maskey } 5916ba597c5SAnurag S. Maskey nlog(LOG_INFO, "set_property_value: transaction commit failed " 5926ba597c5SAnurag S. Maskey "for %s; retrying", propname); 5936ba597c5SAnurag S. Maskey goto retry; 5946ba597c5SAnurag S. Maskey } 5956ba597c5SAnurag S. Maskey if (result == -1) 5966ba597c5SAnurag S. Maskey goto failure; 5976ba597c5SAnurag S. Maskey return (0); 5986ba597c5SAnurag S. Maskey 5996ba597c5SAnurag S. Maskey failure: 6006ba597c5SAnurag S. Maskey return (-1); 6016ba597c5SAnurag S. Maskey } 6026ba597c5SAnurag S. Maskey 6036ba597c5SAnurag S. Maskey int 6046ba597c5SAnurag S. Maskey nwamd_set_count_property(const char *fmri, const char *pg, const char *prop, 6056ba597c5SAnurag S. Maskey uint64_t count) 6066ba597c5SAnurag S. Maskey { 6076ba597c5SAnurag S. Maskey scf_resources_t res; 6086ba597c5SAnurag S. Maskey 6096ba597c5SAnurag S. Maskey if (create_scf_resources(fmri, &res) != 0) 6106ba597c5SAnurag S. Maskey return (-1); 6116ba597c5SAnurag S. Maskey 6126ba597c5SAnurag S. Maskey if (scf_instance_add_pg(res.sr_inst, pg, SCF_GROUP_APPLICATION, 6136ba597c5SAnurag S. Maskey SCF_PG_FLAG_NONPERSISTENT, res.sr_pg) != 0) { 6146ba597c5SAnurag S. Maskey if (scf_error() != SCF_ERROR_EXISTS) 6156ba597c5SAnurag S. Maskey goto failure; 6166ba597c5SAnurag S. Maskey if (scf_instance_get_pg_composed(res.sr_inst, NULL, pg, 6176ba597c5SAnurag S. Maskey res.sr_pg) != 0) 6186ba597c5SAnurag S. Maskey goto failure; 6196ba597c5SAnurag S. Maskey } 6206ba597c5SAnurag S. Maskey 6216ba597c5SAnurag S. Maskey scf_value_set_count(res.sr_val, (uint64_t)count); 6226ba597c5SAnurag S. Maskey 6236ba597c5SAnurag S. Maskey if (set_property_value(&res, prop, SCF_TYPE_COUNT) != 0) 6246ba597c5SAnurag S. Maskey goto failure; 6256ba597c5SAnurag S. Maskey 6266ba597c5SAnurag S. Maskey release_scf_resources(&res); 6276ba597c5SAnurag S. Maskey return (0); 6286ba597c5SAnurag S. Maskey 6296ba597c5SAnurag S. Maskey failure: 6306ba597c5SAnurag S. Maskey nlog(LOG_INFO, "nwamd_set_count_property: scf failure %s while " 6316ba597c5SAnurag S. Maskey "setting %s", scf_strerror(scf_error()), prop); 6326ba597c5SAnurag S. Maskey release_scf_resources(&res); 6336ba597c5SAnurag S. Maskey return (-1); 6346ba597c5SAnurag S. Maskey } 6356ba597c5SAnurag S. Maskey 6366ba597c5SAnurag S. Maskey int 6376ba597c5SAnurag S. Maskey nwamd_set_string_property(const char *fmri, const char *pg, const char *prop, 6386ba597c5SAnurag S. Maskey const char *str) 6396ba597c5SAnurag S. Maskey { 6406ba597c5SAnurag S. Maskey scf_resources_t res; 6416ba597c5SAnurag S. Maskey 6426ba597c5SAnurag S. Maskey if (create_scf_resources(fmri, &res) != 0) 6436ba597c5SAnurag S. Maskey return (-1); 6446ba597c5SAnurag S. Maskey 6456ba597c5SAnurag S. Maskey if (scf_instance_add_pg(res.sr_inst, pg, SCF_GROUP_APPLICATION, 6466ba597c5SAnurag S. Maskey SCF_PG_FLAG_NONPERSISTENT, res.sr_pg) != 0) { 6476ba597c5SAnurag S. Maskey if (scf_error() != SCF_ERROR_EXISTS) 6486ba597c5SAnurag S. Maskey goto failure; 6496ba597c5SAnurag S. Maskey if (scf_instance_get_pg_composed(res.sr_inst, NULL, pg, 6506ba597c5SAnurag S. Maskey res.sr_pg) != 0) 6516ba597c5SAnurag S. Maskey goto failure; 6526ba597c5SAnurag S. Maskey } 6536ba597c5SAnurag S. Maskey 6546ba597c5SAnurag S. Maskey if (scf_value_set_astring(res.sr_val, str) != 0) 6556ba597c5SAnurag S. Maskey goto failure; 6566ba597c5SAnurag S. Maskey 6576ba597c5SAnurag S. Maskey if (set_property_value(&res, prop, SCF_TYPE_ASTRING) != 0) 6586ba597c5SAnurag S. Maskey goto failure; 6596ba597c5SAnurag S. Maskey 6606ba597c5SAnurag S. Maskey release_scf_resources(&res); 6616ba597c5SAnurag S. Maskey return (0); 6626ba597c5SAnurag S. Maskey 6636ba597c5SAnurag S. Maskey failure: 6646ba597c5SAnurag S. Maskey nlog(LOG_INFO, "nwamd_set_string_property: scf failure %s while " 6656ba597c5SAnurag S. Maskey "setting %s", scf_strerror(scf_error()), prop); 6666ba597c5SAnurag S. Maskey release_scf_resources(&res); 6676ba597c5SAnurag S. Maskey return (-1); 6686ba597c5SAnurag S. Maskey } 6696ba597c5SAnurag S. Maskey 6706ba597c5SAnurag S. Maskey /* 6716ba597c5SAnurag S. Maskey * Deletes property prop from property group pg in SMF instance fmri. 6726ba597c5SAnurag S. Maskey * Returns 0 on success, -1 on failure. 6736ba597c5SAnurag S. Maskey */ 6746ba597c5SAnurag S. Maskey int 6756ba597c5SAnurag S. Maskey nwamd_delete_scf_property(const char *fmri, const char *pg, const char *prop) 6766ba597c5SAnurag S. Maskey { 6776ba597c5SAnurag S. Maskey scf_resources_t res; 6786ba597c5SAnurag S. Maskey int result = -1; 6796ba597c5SAnurag S. Maskey 6806ba597c5SAnurag S. Maskey if (create_scf_resources(fmri, &res) != 0) 6816ba597c5SAnurag S. Maskey return (-1); 6826ba597c5SAnurag S. Maskey 6836ba597c5SAnurag S. Maskey if (scf_instance_add_pg(res.sr_inst, pg, SCF_GROUP_APPLICATION, 6846ba597c5SAnurag S. Maskey SCF_PG_FLAG_NONPERSISTENT, res.sr_pg) != 0) { 6856ba597c5SAnurag S. Maskey if (scf_error() != SCF_ERROR_EXISTS) 6866ba597c5SAnurag S. Maskey goto failure; 6876ba597c5SAnurag S. Maskey if (scf_instance_get_pg_composed(res.sr_inst, NULL, pg, 6886ba597c5SAnurag S. Maskey res.sr_pg) != 0) 6896ba597c5SAnurag S. Maskey goto failure; 6906ba597c5SAnurag S. Maskey } 6916ba597c5SAnurag S. Maskey 6926ba597c5SAnurag S. Maskey if (scf_pg_get_property(res.sr_pg, prop, res.sr_prop) != 0) 6936ba597c5SAnurag S. Maskey goto failure; 6946ba597c5SAnurag S. Maskey retry: 6956ba597c5SAnurag S. Maskey if (scf_transaction_start(res.sr_tx, res.sr_pg) == -1) 6966ba597c5SAnurag S. Maskey goto failure; 6976ba597c5SAnurag S. Maskey 6986ba597c5SAnurag S. Maskey if (scf_transaction_property_delete(res.sr_tx, res.sr_ent, prop) == -1) 6996ba597c5SAnurag S. Maskey goto failure; 7006ba597c5SAnurag S. Maskey 7016ba597c5SAnurag S. Maskey result = scf_transaction_commit(res.sr_tx); 7026ba597c5SAnurag S. Maskey if (result == 0) { 7036ba597c5SAnurag S. Maskey scf_transaction_reset(res.sr_tx); 7046ba597c5SAnurag S. Maskey if (scf_pg_update(res.sr_pg) == -1) 7056ba597c5SAnurag S. Maskey goto failure; 7066ba597c5SAnurag S. Maskey goto retry; 7076ba597c5SAnurag S. Maskey } 7086ba597c5SAnurag S. Maskey if (result == -1) 7096ba597c5SAnurag S. Maskey goto failure; 7106ba597c5SAnurag S. Maskey 7116ba597c5SAnurag S. Maskey release_scf_resources(&res); 7126ba597c5SAnurag S. Maskey return (0); 7136ba597c5SAnurag S. Maskey failure: 7146ba597c5SAnurag S. Maskey release_scf_resources(&res); 7156ba597c5SAnurag S. Maskey return (-1); 716d71dbb73Sjbeck } 717