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 8538f140aaSMichael Hunter nwamd_escalate(void) { 8638f140aaSMichael Hunter priv_set_t *priv_set; 8738f140aaSMichael Hunter priv_set = priv_str_to_set("zone", ",", NULL); 8838f140aaSMichael Hunter 8938f140aaSMichael Hunter if (priv_set == NULL) 9038f140aaSMichael Hunter pfail("creating privilege set: %s", strerror(errno)); 9138f140aaSMichael 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) { 9638f140aaSMichael Hunter if (setppriv(PRIV_SET, PRIV_EFFECTIVE, priv_set) == -1) { 9738f140aaSMichael Hunter priv_freeset(priv_set); 9838f140aaSMichael Hunter pfail("setppriv effective: %s", strerror(errno)); 9938f140aaSMichael 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); 10438f140aaSMichael Hunter 10538f140aaSMichael Hunter priv_freeset(priv_set); 106d71dbb73Sjbeck } 107d71dbb73Sjbeck 108b00044a2SJames Carlson void 10938f140aaSMichael Hunter nwamd_deescalate(void) { 1106ba597c5SAnurag S. Maskey (void) pthread_mutex_lock(&uid_mutex); 111*3773ed2dSAnurag S. Maskey 1126ba597c5SAnurag S. Maskey assert(uid_cnt > 0); 1136ba597c5SAnurag S. Maskey if (--uid_cnt == 0) { 114*3773ed2dSAnurag S. Maskey priv_set_t *priv_set, *allpriv_set; 115*3773ed2dSAnurag S. Maskey 1166ba597c5SAnurag S. Maskey if (setuid(uid) == -1) 1176ba597c5SAnurag S. Maskey nlog(LOG_ERR, "setuid(%d) failed %s", uid, 1186ba597c5SAnurag S. Maskey strerror(errno)); 11938f140aaSMichael Hunter 12038f140aaSMichael Hunter /* build up our minimal set of privs. */ 12138f140aaSMichael Hunter priv_set = priv_str_to_set("basic", ",", NULL); 12238f140aaSMichael Hunter allpriv_set = priv_str_to_set("zone", ",", NULL); 12338f140aaSMichael Hunter if (priv_set == NULL || allpriv_set == NULL) 12438f140aaSMichael Hunter pfail("converting privilege sets: %s", strerror(errno)); 12538f140aaSMichael Hunter 12638f140aaSMichael Hunter (void) priv_addset(priv_set, PRIV_FILE_CHOWN_SELF); 12738f140aaSMichael Hunter (void) priv_addset(priv_set, PRIV_FILE_DAC_READ); 12838f140aaSMichael Hunter (void) priv_addset(priv_set, PRIV_FILE_DAC_WRITE); 12938f140aaSMichael Hunter (void) priv_addset(priv_set, PRIV_NET_RAWACCESS); 13038f140aaSMichael Hunter (void) priv_addset(priv_set, PRIV_NET_PRIVADDR); 13138f140aaSMichael Hunter (void) priv_addset(priv_set, PRIV_PROC_AUDIT); 13238f140aaSMichael Hunter (void) priv_addset(priv_set, PRIV_PROC_OWNER); 13338f140aaSMichael Hunter (void) priv_addset(priv_set, PRIV_PROC_SETID); 13438f140aaSMichael Hunter (void) priv_addset(priv_set, PRIV_SYS_CONFIG); 13538f140aaSMichael Hunter (void) priv_addset(priv_set, PRIV_SYS_IP_CONFIG); 13638f140aaSMichael Hunter (void) priv_addset(priv_set, PRIV_SYS_IPC_CONFIG); 13738f140aaSMichael Hunter (void) priv_addset(priv_set, PRIV_SYS_MOUNT); 13838f140aaSMichael Hunter (void) priv_addset(priv_set, PRIV_SYS_NET_CONFIG); 13938f140aaSMichael Hunter (void) priv_addset(priv_set, PRIV_SYS_RES_CONFIG); 14038f140aaSMichael Hunter (void) priv_addset(priv_set, PRIV_SYS_RESOURCE); 14138f140aaSMichael Hunter 14238f140aaSMichael Hunter /* 14338f140aaSMichael Hunter * Since our zone might not have all these privs, 14438f140aaSMichael Hunter * just ask for those that are available. 14538f140aaSMichael Hunter */ 14638f140aaSMichael Hunter priv_intersect(allpriv_set, priv_set); 14738f140aaSMichael Hunter 14838f140aaSMichael Hunter if (setppriv(PRIV_SET, PRIV_INHERITABLE, priv_set) == -1) { 14938f140aaSMichael Hunter priv_freeset(allpriv_set); 15038f140aaSMichael Hunter priv_freeset(priv_set); 15138f140aaSMichael Hunter pfail("setppriv inheritable: %s", strerror(errno)); 15238f140aaSMichael Hunter } 15338f140aaSMichael Hunter /* 15438f140aaSMichael Hunter * Need to ensure permitted set contains all privs so we can 15538f140aaSMichael Hunter * escalate later. 15638f140aaSMichael Hunter */ 15738f140aaSMichael Hunter if (setppriv(PRIV_SET, PRIV_PERMITTED, allpriv_set) == -1) { 15838f140aaSMichael Hunter priv_freeset(allpriv_set); 15938f140aaSMichael Hunter priv_freeset(priv_set); 16038f140aaSMichael Hunter pfail("setppriv permitted: %s", strerror(errno)); 16138f140aaSMichael Hunter } 16238f140aaSMichael Hunter /* 16338f140aaSMichael Hunter * We need to find a smaller set of privs that are important to 16438f140aaSMichael Hunter * us. Otherwise we really are not gaining much by doing this. 16538f140aaSMichael Hunter */ 16638f140aaSMichael Hunter if (setppriv(PRIV_SET, PRIV_EFFECTIVE, priv_set) == -1) { 16738f140aaSMichael Hunter priv_freeset(allpriv_set); 16838f140aaSMichael Hunter priv_freeset(priv_set); 16938f140aaSMichael Hunter pfail("setppriv effective: %s", strerror(errno)); 17038f140aaSMichael Hunter } 171*3773ed2dSAnurag S. Maskey 172*3773ed2dSAnurag S. Maskey priv_freeset(priv_set); 173*3773ed2dSAnurag S. Maskey priv_freeset(allpriv_set); 1746ba597c5SAnurag S. Maskey } 1756ba597c5SAnurag S. Maskey (void) pthread_mutex_unlock(&uid_mutex); 176b00044a2SJames Carlson } 177b00044a2SJames Carlson 178d71dbb73Sjbeck /* 179d71dbb73Sjbeck * 180d71dbb73Sjbeck * This starts a child process determined by command. If command contains a 181d71dbb73Sjbeck * slash then it is assumed to be a full path; otherwise the path is searched 182d71dbb73Sjbeck * for an executable file with the name command. Command is also used as 183d71dbb73Sjbeck * argv[0] of the new process. The rest of the arguments of the function 184d71dbb73Sjbeck * up to the first NULL make up pointers to arguments of the new process. 185d71dbb73Sjbeck * 186d71dbb73Sjbeck * This function returns child exit status on success and -1 on failure. 187d71dbb73Sjbeck * 188d71dbb73Sjbeck * NOTE: original_sigmask must be set before this function is called. 189d71dbb73Sjbeck */ 190d71dbb73Sjbeck int 1916ba597c5SAnurag S. Maskey nwamd_start_childv(const char *command, char const * const *argv) 192d71dbb73Sjbeck { 193d71dbb73Sjbeck posix_spawnattr_t attr; 194d71dbb73Sjbeck sigset_t fullset; 195d71dbb73Sjbeck int i, rc, status, n; 196d71dbb73Sjbeck pid_t pid; 197d71dbb73Sjbeck char vbuf[1024]; 198d71dbb73Sjbeck 199d71dbb73Sjbeck vbuf[0] = 0; 200d71dbb73Sjbeck n = sizeof (vbuf); 201d71dbb73Sjbeck for (i = 1; argv[i] != NULL && n > 2; i++) { 202d71dbb73Sjbeck n -= strlcat(vbuf, " ", n); 203d71dbb73Sjbeck n -= strlcat(vbuf, argv[i], n); 204d71dbb73Sjbeck } 205d71dbb73Sjbeck if (argv[i] != NULL || n < 0) 2066ba597c5SAnurag S. Maskey nlog(LOG_ERR, "nwamd_start_childv can't log full arg vector"); 207d71dbb73Sjbeck 208d71dbb73Sjbeck if ((rc = posix_spawnattr_init(&attr)) != 0) { 2096ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "posix_spawnattr_init %d %s\n", 2106ba597c5SAnurag S. Maskey rc, strerror(rc)); 211d71dbb73Sjbeck return (-1); 212d71dbb73Sjbeck } 213d71dbb73Sjbeck (void) sigfillset(&fullset); 214d71dbb73Sjbeck if ((rc = posix_spawnattr_setsigdefault(&attr, &fullset)) != 0) { 2156ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "setsigdefault %d %s\n", rc, strerror(rc)); 216d71dbb73Sjbeck return (-1); 217d71dbb73Sjbeck } 218d71dbb73Sjbeck if ((rc = posix_spawnattr_setsigmask(&attr, &original_sigmask)) != 0) { 2196ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "setsigmask %d %s\n", rc, strerror(rc)); 220d71dbb73Sjbeck return (-1); 221d71dbb73Sjbeck } 222d71dbb73Sjbeck if ((rc = posix_spawnattr_setflags(&attr, 223d71dbb73Sjbeck POSIX_SPAWN_SETSIGDEF|POSIX_SPAWN_SETSIGMASK)) != 0) { 2246ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "setflags %d %s\n", rc, strerror(rc)); 225d71dbb73Sjbeck return (-1); 226d71dbb73Sjbeck } 227d71dbb73Sjbeck 228d71dbb73Sjbeck if ((rc = posix_spawnp(&pid, command, NULL, &attr, (char * const *)argv, 229d71dbb73Sjbeck environ)) > 0) { 2306ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "posix_spawnp failed errno %d", rc); 231d71dbb73Sjbeck return (-1); 232d71dbb73Sjbeck } 233d71dbb73Sjbeck 234d71dbb73Sjbeck if ((rc = posix_spawnattr_destroy(&attr)) != 0) { 2356ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "posix_spawn_attr_destroy %d %s\n", 2366ba597c5SAnurag S. Maskey rc, strerror(rc)); 237d71dbb73Sjbeck return (-1); 238d71dbb73Sjbeck } 239d71dbb73Sjbeck 240d71dbb73Sjbeck (void) waitpid(pid, &status, 0); 241d71dbb73Sjbeck if (WIFSIGNALED(status) || WIFSTOPPED(status)) { 242d71dbb73Sjbeck i = WIFSIGNALED(status) ? WTERMSIG(status) : WSTOPSIG(status); 2436ba597c5SAnurag S. Maskey nlog(LOG_ERR, "'%s%s' %s with signal %d (%s)", command, vbuf, 244d71dbb73Sjbeck (WIFSIGNALED(status) ? "terminated" : "stopped"), i, 245d71dbb73Sjbeck strsignal(i)); 246d71dbb73Sjbeck return (-2); 247d71dbb73Sjbeck } else { 2486ba597c5SAnurag S. Maskey nlog(LOG_INFO, "'%s%s' completed normally: %d", command, vbuf, 249d71dbb73Sjbeck WEXITSTATUS(status)); 250d71dbb73Sjbeck return (WEXITSTATUS(status)); 251d71dbb73Sjbeck } 252d71dbb73Sjbeck } 253d71dbb73Sjbeck 2546ba597c5SAnurag S. Maskey /* 2556ba597c5SAnurag S. Maskey * For global zone, check if the link is used by a non-global 2566ba597c5SAnurag S. Maskey * zone, note that the non-global zones doesn't need this check, 2576ba597c5SAnurag S. Maskey * because zoneadm has taken care of this when the zone boots. 2586ba597c5SAnurag S. Maskey * In the global zone, we ignore events for local-zone-owned links 2596ba597c5SAnurag S. Maskey * since these are taken care of by the local zone's network 2606ba597c5SAnurag S. Maskey * configuration services. 2616ba597c5SAnurag S. Maskey */ 2626ba597c5SAnurag S. Maskey boolean_t 2636ba597c5SAnurag S. Maskey nwamd_link_belongs_to_this_zone(const char *linkname) 264d71dbb73Sjbeck { 2656ba597c5SAnurag S. Maskey zoneid_t zoneid; 2666ba597c5SAnurag S. Maskey char zonename[ZONENAME_MAX]; 2676ba597c5SAnurag S. Maskey int ret; 2686ba597c5SAnurag S. Maskey 2696ba597c5SAnurag S. Maskey zoneid = getzoneid(); 2706ba597c5SAnurag S. Maskey if (zoneid == GLOBAL_ZONEID) { 2716ba597c5SAnurag S. Maskey datalink_id_t linkid; 2726ba597c5SAnurag S. Maskey dladm_status_t status; 2736ba597c5SAnurag S. Maskey char errstr[DLADM_STRSIZE]; 2746ba597c5SAnurag S. Maskey 2756ba597c5SAnurag S. Maskey if ((status = dladm_name2info(dld_handle, linkname, &linkid, 2766ba597c5SAnurag S. Maskey NULL, NULL, NULL)) != DLADM_STATUS_OK) { 2776ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_link_belongs_to_this_zone: " 2786ba597c5SAnurag S. Maskey "could not get linkid for %s: %s", 2796ba597c5SAnurag S. Maskey linkname, dladm_status2str(status, errstr)); 2806ba597c5SAnurag S. Maskey return (B_FALSE); 2816ba597c5SAnurag S. Maskey } 2826ba597c5SAnurag S. Maskey zoneid = ALL_ZONES; 2836ba597c5SAnurag S. Maskey ret = zone_check_datalink(&zoneid, linkid); 2846ba597c5SAnurag S. Maskey if (ret == 0) { 2856ba597c5SAnurag S. Maskey (void) getzonenamebyid(zoneid, zonename, ZONENAME_MAX); 2866ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_link_belongs_to_this_zone: " 2876ba597c5SAnurag S. Maskey "%s is used by non-global zone: %s", 2886ba597c5SAnurag S. Maskey linkname, zonename); 2896ba597c5SAnurag S. Maskey return (B_FALSE); 290d71dbb73Sjbeck } 2916ba597c5SAnurag S. Maskey } 2926ba597c5SAnurag S. Maskey return (B_TRUE); 2936ba597c5SAnurag S. Maskey } 294d71dbb73Sjbeck 2956ba597c5SAnurag S. Maskey /* 2966ba597c5SAnurag S. Maskey * Inputs: 2976ba597c5SAnurag S. Maskey * res is a pointer to the scf_resources_t to be released. 2986ba597c5SAnurag S. Maskey */ 2996ba597c5SAnurag S. Maskey static void 3006ba597c5SAnurag S. Maskey release_scf_resources(scf_resources_t *res) 3016ba597c5SAnurag S. Maskey { 3026ba597c5SAnurag S. Maskey scf_entry_destroy(res->sr_ent); 3036ba597c5SAnurag S. Maskey scf_transaction_destroy(res->sr_tx); 3046ba597c5SAnurag S. Maskey scf_value_destroy(res->sr_val); 3056ba597c5SAnurag S. Maskey scf_property_destroy(res->sr_prop); 3066ba597c5SAnurag S. Maskey scf_pg_destroy(res->sr_pg); 3076ba597c5SAnurag S. Maskey scf_snapshot_destroy(res->sr_snap); 3086ba597c5SAnurag S. Maskey scf_instance_destroy(res->sr_inst); 3096ba597c5SAnurag S. Maskey (void) scf_handle_unbind(res->sr_handle); 3106ba597c5SAnurag S. Maskey scf_handle_destroy(res->sr_handle); 3116ba597c5SAnurag S. Maskey } 312d71dbb73Sjbeck 313d71dbb73Sjbeck /* 3146ba597c5SAnurag S. Maskey * Inputs: 3156ba597c5SAnurag S. Maskey * fmri is the instance to look up 3166ba597c5SAnurag S. Maskey * Outputs: 3176ba597c5SAnurag S. Maskey * res is a pointer to an scf_resources_t. This is an internal 3186ba597c5SAnurag S. Maskey * structure that holds all the handles needed to get a specific 3196ba597c5SAnurag S. Maskey * property from the running snapshot; on a successful return it 3206ba597c5SAnurag S. Maskey * contains the scf_value_t that should be passed to the desired 3216ba597c5SAnurag S. Maskey * scf_value_get_foo() function, and must be freed after use by 3226ba597c5SAnurag S. Maskey * calling release_scf_resources(). On a failure return, any 3236ba597c5SAnurag S. Maskey * resources that may have been assigned to res are released, so 3246ba597c5SAnurag S. Maskey * the caller does not need to do any cleanup in the failure case. 3256ba597c5SAnurag S. Maskey * Returns: 3266ba597c5SAnurag S. Maskey * 0 on success 3276ba597c5SAnurag S. Maskey * -1 on failure 328d71dbb73Sjbeck */ 3296ba597c5SAnurag S. Maskey 3306ba597c5SAnurag S. Maskey static int 3316ba597c5SAnurag S. Maskey create_scf_resources(const char *fmri, scf_resources_t *res) 3326ba597c5SAnurag S. Maskey { 3336ba597c5SAnurag S. Maskey res->sr_tx = NULL; 3346ba597c5SAnurag S. Maskey res->sr_ent = NULL; 3356ba597c5SAnurag S. Maskey res->sr_inst = NULL; 3366ba597c5SAnurag S. Maskey res->sr_snap = NULL; 3376ba597c5SAnurag S. Maskey res->sr_pg = NULL; 3386ba597c5SAnurag S. Maskey res->sr_prop = NULL; 3396ba597c5SAnurag S. Maskey res->sr_val = NULL; 3406ba597c5SAnurag S. Maskey 3416ba597c5SAnurag S. Maskey if ((res->sr_handle = scf_handle_create(SCF_VERSION)) == NULL) { 3426ba597c5SAnurag S. Maskey return (-1); 3436ba597c5SAnurag S. Maskey } 3446ba597c5SAnurag S. Maskey 3456ba597c5SAnurag S. Maskey if (scf_handle_bind(res->sr_handle) != 0) { 3466ba597c5SAnurag S. Maskey scf_handle_destroy(res->sr_handle); 3476ba597c5SAnurag S. Maskey return (-1); 3486ba597c5SAnurag S. Maskey } 3496ba597c5SAnurag S. Maskey if ((res->sr_inst = scf_instance_create(res->sr_handle)) == NULL) { 3506ba597c5SAnurag S. Maskey goto failure; 3516ba597c5SAnurag S. Maskey } 3526ba597c5SAnurag S. Maskey if (scf_handle_decode_fmri(res->sr_handle, fmri, NULL, NULL, 3536ba597c5SAnurag S. Maskey res->sr_inst, NULL, NULL, SCF_DECODE_FMRI_REQUIRE_INSTANCE) != 0) { 3546ba597c5SAnurag S. Maskey goto failure; 3556ba597c5SAnurag S. Maskey } 3566ba597c5SAnurag S. Maskey if ((res->sr_snap = scf_snapshot_create(res->sr_handle)) == NULL) { 3576ba597c5SAnurag S. Maskey goto failure; 3586ba597c5SAnurag S. Maskey } 3596ba597c5SAnurag S. Maskey if (scf_instance_get_snapshot(res->sr_inst, "running", 3606ba597c5SAnurag S. Maskey res->sr_snap) != 0) { 3616ba597c5SAnurag S. Maskey goto failure; 3626ba597c5SAnurag S. Maskey } 3636ba597c5SAnurag S. Maskey if ((res->sr_pg = scf_pg_create(res->sr_handle)) == NULL) { 3646ba597c5SAnurag S. Maskey goto failure; 3656ba597c5SAnurag S. Maskey } 3666ba597c5SAnurag S. Maskey if ((res->sr_prop = scf_property_create(res->sr_handle)) == NULL) { 3676ba597c5SAnurag S. Maskey goto failure; 3686ba597c5SAnurag S. Maskey } 3696ba597c5SAnurag S. Maskey if ((res->sr_val = scf_value_create(res->sr_handle)) == NULL) { 3706ba597c5SAnurag S. Maskey goto failure; 3716ba597c5SAnurag S. Maskey } 3726ba597c5SAnurag S. Maskey if ((res->sr_tx = scf_transaction_create(res->sr_handle)) == NULL) { 3736ba597c5SAnurag S. Maskey goto failure; 3746ba597c5SAnurag S. Maskey } 3756ba597c5SAnurag S. Maskey if ((res->sr_ent = scf_entry_create(res->sr_handle)) == NULL) { 3766ba597c5SAnurag S. Maskey goto failure; 3776ba597c5SAnurag S. Maskey } 3786ba597c5SAnurag S. Maskey return (0); 3796ba597c5SAnurag S. Maskey 3806ba597c5SAnurag S. Maskey failure: 3816ba597c5SAnurag S. Maskey nlog(LOG_ERR, "create_scf_resources failed: %s", 3826ba597c5SAnurag S. Maskey scf_strerror(scf_error())); 3836ba597c5SAnurag S. Maskey release_scf_resources(res); 3846ba597c5SAnurag S. Maskey return (-1); 3856ba597c5SAnurag S. Maskey } 3866ba597c5SAnurag S. Maskey 3876ba597c5SAnurag S. Maskey /* 3886ba597c5SAnurag S. Maskey * Inputs: 3896ba597c5SAnurag S. Maskey * fmri is the instance to look up 3906ba597c5SAnurag S. Maskey * pg is the property group to look up 3916ba597c5SAnurag S. Maskey * prop is the property within that group to look up 3926ba597c5SAnurag S. Maskey * running specifies if running snapshot is to be used 3936ba597c5SAnurag S. Maskey * Outputs: 3946ba597c5SAnurag S. Maskey * res is a pointer to an scf_resources_t. This is an internal 3956ba597c5SAnurag S. Maskey * structure that holds all the handles needed to get a specific 3966ba597c5SAnurag S. Maskey * property from the running snapshot; on a successful return it 3976ba597c5SAnurag S. Maskey * contains the scf_value_t that should be passed to the desired 3986ba597c5SAnurag S. Maskey * scf_value_get_foo() function, and must be freed after use by 3996ba597c5SAnurag S. Maskey * calling release_scf_resources(). On a failure return, any 4006ba597c5SAnurag S. Maskey * resources that may have been assigned to res are released, so 4016ba597c5SAnurag S. Maskey * the caller does not need to do any cleanup in the failure case. 4026ba597c5SAnurag S. Maskey * Returns: 4036ba597c5SAnurag S. Maskey * 0 on success 4046ba597c5SAnurag S. Maskey * -1 on failure 4056ba597c5SAnurag S. Maskey */ 4066ba597c5SAnurag S. Maskey static int 4076ba597c5SAnurag S. Maskey get_property_value(const char *fmri, const char *pg, const char *prop, 4086ba597c5SAnurag S. Maskey boolean_t running, scf_resources_t *res) 409d71dbb73Sjbeck { 4106ba597c5SAnurag S. Maskey if (create_scf_resources(fmri, res) != 0) 4116ba597c5SAnurag S. Maskey return (-1); 4126ba597c5SAnurag S. Maskey 4136ba597c5SAnurag S. Maskey if (scf_instance_get_pg_composed(res->sr_inst, 4146ba597c5SAnurag S. Maskey running ? res->sr_snap : NULL, pg, res->sr_pg) != 0) { 4156ba597c5SAnurag S. Maskey goto failure; 4166ba597c5SAnurag S. Maskey } 4176ba597c5SAnurag S. Maskey if (scf_pg_get_property(res->sr_pg, prop, res->sr_prop) != 0) { 4186ba597c5SAnurag S. Maskey goto failure; 4196ba597c5SAnurag S. Maskey } 4206ba597c5SAnurag S. Maskey if (scf_property_get_value(res->sr_prop, res->sr_val) != 0) { 4216ba597c5SAnurag S. Maskey goto failure; 4226ba597c5SAnurag S. Maskey } 4236ba597c5SAnurag S. Maskey return (0); 424d71dbb73Sjbeck 4256ba597c5SAnurag S. Maskey failure: 4266ba597c5SAnurag S. Maskey release_scf_resources(res); 4276ba597c5SAnurag S. Maskey return (-1); 428d71dbb73Sjbeck } 429d71dbb73Sjbeck 4306ba597c5SAnurag S. Maskey /* 4316ba597c5SAnurag S. Maskey * Inputs: 4326ba597c5SAnurag S. Maskey * lfmri is the instance fmri to look up 4336ba597c5SAnurag S. Maskey * lpg is the property group to look up 4346ba597c5SAnurag S. Maskey * lprop is the property within that group to look up 4356ba597c5SAnurag S. Maskey * Outputs: 4366ba597c5SAnurag S. Maskey * answer is a pointer to the property value 4376ba597c5SAnurag S. Maskey * Returns: 4386ba597c5SAnurag S. Maskey * 0 on success 4396ba597c5SAnurag S. Maskey * -1 on failure 4406ba597c5SAnurag S. Maskey * If successful, the property value is retured in *answer. 4416ba597c5SAnurag S. Maskey * Otherwise, *answer is undefined, and it is up to the caller to decide 4426ba597c5SAnurag S. Maskey * how to handle that case. 4436ba597c5SAnurag S. Maskey */ 4446ba597c5SAnurag S. Maskey int 4456ba597c5SAnurag S. Maskey nwamd_lookup_boolean_property(const char *lfmri, const char *lpg, 4466ba597c5SAnurag S. Maskey const char *lprop, boolean_t *answer) 4476ba597c5SAnurag S. Maskey { 4486ba597c5SAnurag S. Maskey int result = -1; 4496ba597c5SAnurag S. Maskey scf_resources_t res; 4506ba597c5SAnurag S. Maskey uint8_t prop_val; 4516ba597c5SAnurag S. Maskey 4526ba597c5SAnurag S. Maskey if (get_property_value(lfmri, lpg, lprop, B_TRUE, &res) != 0) { 4536ba597c5SAnurag S. Maskey 4546ba597c5SAnurag S. Maskey /* 4556ba597c5SAnurag S. Maskey * an error was already logged by get_property_value, 4566ba597c5SAnurag S. Maskey * and it released any resources assigned to res before 4576ba597c5SAnurag S. Maskey * returning. 4586ba597c5SAnurag S. Maskey */ 4596ba597c5SAnurag S. Maskey return (result); 4606ba597c5SAnurag S. Maskey } 4616ba597c5SAnurag S. Maskey if (scf_value_get_boolean(res.sr_val, &prop_val) != 0) { 4626ba597c5SAnurag S. Maskey goto cleanup; 4636ba597c5SAnurag S. Maskey } 4646ba597c5SAnurag S. Maskey *answer = (boolean_t)prop_val; 4656ba597c5SAnurag S. Maskey result = 0; 4666ba597c5SAnurag S. Maskey cleanup: 4676ba597c5SAnurag S. Maskey release_scf_resources(&res); 4686ba597c5SAnurag S. Maskey return (result); 4696ba597c5SAnurag S. Maskey } 4706ba597c5SAnurag S. Maskey 4716ba597c5SAnurag S. Maskey /* 4726ba597c5SAnurag S. Maskey * Inputs: 4736ba597c5SAnurag S. Maskey * lfmri is the instance fmri to look up 4746ba597c5SAnurag S. Maskey * lpg is the property group to look up 4756ba597c5SAnurag S. Maskey * lprop is the property within that group to look up 4766ba597c5SAnurag S. Maskey * buf is the place to put the answer 4776ba597c5SAnurag S. Maskey * bufsz is the size of buf 4786ba597c5SAnurag S. Maskey * Outputs: 4796ba597c5SAnurag S. Maskey * 4806ba597c5SAnurag S. Maskey * Returns: 4816ba597c5SAnurag S. Maskey * 0 on success 4826ba597c5SAnurag S. Maskey * -1 on failure 4836ba597c5SAnurag S. Maskey * If successful, the property value is retured in buf. 4846ba597c5SAnurag S. Maskey * Otherwise, buf is undefined, and it is up to the caller to decide 4856ba597c5SAnurag S. Maskey * how to handle that case. 4866ba597c5SAnurag S. Maskey */ 4876ba597c5SAnurag S. Maskey int 4886ba597c5SAnurag S. Maskey nwamd_lookup_string_property(const char *lfmri, const char *lpg, 4896ba597c5SAnurag S. Maskey const char *lprop, char *buf, size_t bufsz) 490d71dbb73Sjbeck { 4916ba597c5SAnurag S. Maskey int result = -1; 4926ba597c5SAnurag S. Maskey scf_resources_t res; 4936ba597c5SAnurag S. Maskey 4946ba597c5SAnurag S. Maskey if (get_property_value(lfmri, lpg, lprop, B_TRUE, &res) != 0) { 4956ba597c5SAnurag S. Maskey /* 4966ba597c5SAnurag S. Maskey * The above function fails when trying to get a 4976ba597c5SAnurag S. Maskey * non-persistent property group from the running snapshot. 4986ba597c5SAnurag S. Maskey * Try going for the non-running snapshot. 4996ba597c5SAnurag S. Maskey */ 5006ba597c5SAnurag S. Maskey if (get_property_value(lfmri, lpg, lprop, B_FALSE, &res) != 0) { 5016ba597c5SAnurag S. Maskey /* 5026ba597c5SAnurag S. Maskey * an error was already logged by get_property_value, 5036ba597c5SAnurag S. Maskey * and it released any resources assigned to res before 5046ba597c5SAnurag S. Maskey * returning. 5056ba597c5SAnurag S. Maskey */ 5066ba597c5SAnurag S. Maskey return (result); 5076ba597c5SAnurag S. Maskey } 5086ba597c5SAnurag S. Maskey } 5096ba597c5SAnurag S. Maskey if (scf_value_get_astring(res.sr_val, buf, bufsz) == 0) 5106ba597c5SAnurag S. Maskey goto cleanup; 5116ba597c5SAnurag S. Maskey 5126ba597c5SAnurag S. Maskey result = 0; 5136ba597c5SAnurag S. Maskey cleanup: 5146ba597c5SAnurag S. Maskey release_scf_resources(&res); 5156ba597c5SAnurag S. Maskey return (result); 5166ba597c5SAnurag S. Maskey } 517d71dbb73Sjbeck 5186ba597c5SAnurag S. Maskey /* 5196ba597c5SAnurag S. Maskey * Inputs: 5206ba597c5SAnurag S. Maskey * lfmri is the instance fmri to look up 5216ba597c5SAnurag S. Maskey * lpg is the property group to look up 5226ba597c5SAnurag S. Maskey * lprop is the property within that group to look up 5236ba597c5SAnurag S. Maskey * Outputs: 5246ba597c5SAnurag S. Maskey * answer is a pointer to the property value 5256ba597c5SAnurag S. Maskey * Returns: 5266ba597c5SAnurag S. Maskey * 0 on success 5276ba597c5SAnurag S. Maskey * -1 on failure 5286ba597c5SAnurag S. Maskey * If successful, the property value is retured in *answer. 5296ba597c5SAnurag S. Maskey * Otherwise, *answer is undefined, and it is up to the caller to decide 5306ba597c5SAnurag S. Maskey * how to handle that case. 5316ba597c5SAnurag S. Maskey */ 5326ba597c5SAnurag S. Maskey int 5336ba597c5SAnurag S. Maskey nwamd_lookup_count_property(const char *lfmri, const char *lpg, 5346ba597c5SAnurag S. Maskey const char *lprop, uint64_t *answer) 5356ba597c5SAnurag S. Maskey { 5366ba597c5SAnurag S. Maskey int result = -1; 5376ba597c5SAnurag S. Maskey scf_resources_t res; 5386ba597c5SAnurag S. Maskey 5396ba597c5SAnurag S. Maskey if (get_property_value(lfmri, lpg, lprop, B_TRUE, &res) != 0) { 5406ba597c5SAnurag S. Maskey 5416ba597c5SAnurag S. Maskey /* 5426ba597c5SAnurag S. Maskey * an error was already logged by get_property_value, 5436ba597c5SAnurag S. Maskey * and it released any resources assigned to res before 5446ba597c5SAnurag S. Maskey * returning. 5456ba597c5SAnurag S. Maskey */ 5466ba597c5SAnurag S. Maskey return (result); 5476ba597c5SAnurag S. Maskey } 5486ba597c5SAnurag S. Maskey if (scf_value_get_count(res.sr_val, answer) != 0) { 5496ba597c5SAnurag S. Maskey goto cleanup; 5506ba597c5SAnurag S. Maskey } 5516ba597c5SAnurag S. Maskey result = 0; 5526ba597c5SAnurag S. Maskey cleanup: 5536ba597c5SAnurag S. Maskey release_scf_resources(&res); 5546ba597c5SAnurag S. Maskey return (result); 5556ba597c5SAnurag S. Maskey } 5566ba597c5SAnurag S. Maskey 5576ba597c5SAnurag S. Maskey static int 5586ba597c5SAnurag S. Maskey set_property_value(scf_resources_t *res, const char *propname, 5596ba597c5SAnurag S. Maskey scf_type_t proptype) 5606ba597c5SAnurag S. Maskey { 5616ba597c5SAnurag S. Maskey int result = -1; 5626ba597c5SAnurag S. Maskey boolean_t new; 5636ba597c5SAnurag S. Maskey 5646ba597c5SAnurag S. Maskey retry: 5656ba597c5SAnurag S. Maskey new = (scf_pg_get_property(res->sr_pg, propname, res->sr_prop) != 0); 5666ba597c5SAnurag S. Maskey 5676ba597c5SAnurag S. Maskey if (scf_transaction_start(res->sr_tx, res->sr_pg) == -1) { 5686ba597c5SAnurag S. Maskey goto failure; 5696ba597c5SAnurag S. Maskey } 5706ba597c5SAnurag S. Maskey if (new) { 5716ba597c5SAnurag S. Maskey if (scf_transaction_property_new(res->sr_tx, res->sr_ent, 5726ba597c5SAnurag S. Maskey propname, proptype) == -1) { 5736ba597c5SAnurag S. Maskey goto failure; 5746ba597c5SAnurag S. Maskey } 5756ba597c5SAnurag S. Maskey } else { 5766ba597c5SAnurag S. Maskey if (scf_transaction_property_change(res->sr_tx, res->sr_ent, 5776ba597c5SAnurag S. Maskey propname, proptype) == -1) { 5786ba597c5SAnurag S. Maskey goto failure; 5796ba597c5SAnurag S. Maskey } 5806ba597c5SAnurag S. Maskey } 5816ba597c5SAnurag S. Maskey 5826ba597c5SAnurag S. Maskey if (scf_entry_add_value(res->sr_ent, res->sr_val) != 0) { 5836ba597c5SAnurag S. Maskey goto failure; 5846ba597c5SAnurag S. Maskey } 5856ba597c5SAnurag S. Maskey 5866ba597c5SAnurag S. Maskey result = scf_transaction_commit(res->sr_tx); 5876ba597c5SAnurag S. Maskey if (result == 0) { 5886ba597c5SAnurag S. Maskey scf_transaction_reset(res->sr_tx); 5896ba597c5SAnurag S. Maskey if (scf_pg_update(res->sr_pg) == -1) { 5906ba597c5SAnurag S. Maskey goto failure; 5916ba597c5SAnurag S. Maskey } 5926ba597c5SAnurag S. Maskey nlog(LOG_INFO, "set_property_value: transaction commit failed " 5936ba597c5SAnurag S. Maskey "for %s; retrying", propname); 5946ba597c5SAnurag S. Maskey goto retry; 5956ba597c5SAnurag S. Maskey } 5966ba597c5SAnurag S. Maskey if (result == -1) 5976ba597c5SAnurag S. Maskey goto failure; 5986ba597c5SAnurag S. Maskey return (0); 5996ba597c5SAnurag S. Maskey 6006ba597c5SAnurag S. Maskey failure: 6016ba597c5SAnurag S. Maskey return (-1); 6026ba597c5SAnurag S. Maskey } 6036ba597c5SAnurag S. Maskey 6046ba597c5SAnurag S. Maskey int 6056ba597c5SAnurag S. Maskey nwamd_set_count_property(const char *fmri, const char *pg, const char *prop, 6066ba597c5SAnurag S. Maskey uint64_t count) 6076ba597c5SAnurag S. Maskey { 6086ba597c5SAnurag S. Maskey scf_resources_t res; 6096ba597c5SAnurag S. Maskey 6106ba597c5SAnurag S. Maskey if (create_scf_resources(fmri, &res) != 0) 6116ba597c5SAnurag S. Maskey return (-1); 6126ba597c5SAnurag S. Maskey 6136ba597c5SAnurag S. Maskey if (scf_instance_add_pg(res.sr_inst, pg, SCF_GROUP_APPLICATION, 6146ba597c5SAnurag S. Maskey SCF_PG_FLAG_NONPERSISTENT, res.sr_pg) != 0) { 6156ba597c5SAnurag S. Maskey if (scf_error() != SCF_ERROR_EXISTS) 6166ba597c5SAnurag S. Maskey goto failure; 6176ba597c5SAnurag S. Maskey if (scf_instance_get_pg_composed(res.sr_inst, NULL, pg, 6186ba597c5SAnurag S. Maskey res.sr_pg) != 0) 6196ba597c5SAnurag S. Maskey goto failure; 6206ba597c5SAnurag S. Maskey } 6216ba597c5SAnurag S. Maskey 6226ba597c5SAnurag S. Maskey scf_value_set_count(res.sr_val, (uint64_t)count); 6236ba597c5SAnurag S. Maskey 6246ba597c5SAnurag S. Maskey if (set_property_value(&res, prop, SCF_TYPE_COUNT) != 0) 6256ba597c5SAnurag S. Maskey goto failure; 6266ba597c5SAnurag S. Maskey 6276ba597c5SAnurag S. Maskey release_scf_resources(&res); 6286ba597c5SAnurag S. Maskey return (0); 6296ba597c5SAnurag S. Maskey 6306ba597c5SAnurag S. Maskey failure: 6316ba597c5SAnurag S. Maskey nlog(LOG_INFO, "nwamd_set_count_property: scf failure %s while " 6326ba597c5SAnurag S. Maskey "setting %s", scf_strerror(scf_error()), prop); 6336ba597c5SAnurag S. Maskey release_scf_resources(&res); 6346ba597c5SAnurag S. Maskey return (-1); 6356ba597c5SAnurag S. Maskey } 6366ba597c5SAnurag S. Maskey 6376ba597c5SAnurag S. Maskey int 6386ba597c5SAnurag S. Maskey nwamd_set_string_property(const char *fmri, const char *pg, const char *prop, 6396ba597c5SAnurag S. Maskey const char *str) 6406ba597c5SAnurag S. Maskey { 6416ba597c5SAnurag S. Maskey scf_resources_t res; 6426ba597c5SAnurag S. Maskey 6436ba597c5SAnurag S. Maskey if (create_scf_resources(fmri, &res) != 0) 6446ba597c5SAnurag S. Maskey return (-1); 6456ba597c5SAnurag S. Maskey 6466ba597c5SAnurag S. Maskey if (scf_instance_add_pg(res.sr_inst, pg, SCF_GROUP_APPLICATION, 6476ba597c5SAnurag S. Maskey SCF_PG_FLAG_NONPERSISTENT, res.sr_pg) != 0) { 6486ba597c5SAnurag S. Maskey if (scf_error() != SCF_ERROR_EXISTS) 6496ba597c5SAnurag S. Maskey goto failure; 6506ba597c5SAnurag S. Maskey if (scf_instance_get_pg_composed(res.sr_inst, NULL, pg, 6516ba597c5SAnurag S. Maskey res.sr_pg) != 0) 6526ba597c5SAnurag S. Maskey goto failure; 6536ba597c5SAnurag S. Maskey } 6546ba597c5SAnurag S. Maskey 6556ba597c5SAnurag S. Maskey if (scf_value_set_astring(res.sr_val, str) != 0) 6566ba597c5SAnurag S. Maskey goto failure; 6576ba597c5SAnurag S. Maskey 6586ba597c5SAnurag S. Maskey if (set_property_value(&res, prop, SCF_TYPE_ASTRING) != 0) 6596ba597c5SAnurag S. Maskey goto failure; 6606ba597c5SAnurag S. Maskey 6616ba597c5SAnurag S. Maskey release_scf_resources(&res); 6626ba597c5SAnurag S. Maskey return (0); 6636ba597c5SAnurag S. Maskey 6646ba597c5SAnurag S. Maskey failure: 6656ba597c5SAnurag S. Maskey nlog(LOG_INFO, "nwamd_set_string_property: scf failure %s while " 6666ba597c5SAnurag S. Maskey "setting %s", scf_strerror(scf_error()), prop); 6676ba597c5SAnurag S. Maskey release_scf_resources(&res); 6686ba597c5SAnurag S. Maskey return (-1); 6696ba597c5SAnurag S. Maskey } 6706ba597c5SAnurag S. Maskey 6716ba597c5SAnurag S. Maskey /* 6726ba597c5SAnurag S. Maskey * Deletes property prop from property group pg in SMF instance fmri. 6736ba597c5SAnurag S. Maskey * Returns 0 on success, -1 on failure. 6746ba597c5SAnurag S. Maskey */ 6756ba597c5SAnurag S. Maskey int 6766ba597c5SAnurag S. Maskey nwamd_delete_scf_property(const char *fmri, const char *pg, const char *prop) 6776ba597c5SAnurag S. Maskey { 6786ba597c5SAnurag S. Maskey scf_resources_t res; 6796ba597c5SAnurag S. Maskey int result = -1; 6806ba597c5SAnurag S. Maskey 6816ba597c5SAnurag S. Maskey if (create_scf_resources(fmri, &res) != 0) 6826ba597c5SAnurag S. Maskey return (-1); 6836ba597c5SAnurag S. Maskey 6846ba597c5SAnurag S. Maskey if (scf_instance_add_pg(res.sr_inst, pg, SCF_GROUP_APPLICATION, 6856ba597c5SAnurag S. Maskey SCF_PG_FLAG_NONPERSISTENT, res.sr_pg) != 0) { 6866ba597c5SAnurag S. Maskey if (scf_error() != SCF_ERROR_EXISTS) 6876ba597c5SAnurag S. Maskey goto failure; 6886ba597c5SAnurag S. Maskey if (scf_instance_get_pg_composed(res.sr_inst, NULL, pg, 6896ba597c5SAnurag S. Maskey res.sr_pg) != 0) 6906ba597c5SAnurag S. Maskey goto failure; 6916ba597c5SAnurag S. Maskey } 6926ba597c5SAnurag S. Maskey 6936ba597c5SAnurag S. Maskey if (scf_pg_get_property(res.sr_pg, prop, res.sr_prop) != 0) 6946ba597c5SAnurag S. Maskey goto failure; 6956ba597c5SAnurag S. Maskey retry: 6966ba597c5SAnurag S. Maskey if (scf_transaction_start(res.sr_tx, res.sr_pg) == -1) 6976ba597c5SAnurag S. Maskey goto failure; 6986ba597c5SAnurag S. Maskey 6996ba597c5SAnurag S. Maskey if (scf_transaction_property_delete(res.sr_tx, res.sr_ent, prop) == -1) 7006ba597c5SAnurag S. Maskey goto failure; 7016ba597c5SAnurag S. Maskey 7026ba597c5SAnurag S. Maskey result = scf_transaction_commit(res.sr_tx); 7036ba597c5SAnurag S. Maskey if (result == 0) { 7046ba597c5SAnurag S. Maskey scf_transaction_reset(res.sr_tx); 7056ba597c5SAnurag S. Maskey if (scf_pg_update(res.sr_pg) == -1) 7066ba597c5SAnurag S. Maskey goto failure; 7076ba597c5SAnurag S. Maskey goto retry; 7086ba597c5SAnurag S. Maskey } 7096ba597c5SAnurag S. Maskey if (result == -1) 7106ba597c5SAnurag S. Maskey goto failure; 7116ba597c5SAnurag S. Maskey 7126ba597c5SAnurag S. Maskey release_scf_resources(&res); 7136ba597c5SAnurag S. Maskey return (0); 7146ba597c5SAnurag S. Maskey failure: 7156ba597c5SAnurag S. Maskey release_scf_resources(&res); 7166ba597c5SAnurag S. Maskey return (-1); 717d71dbb73Sjbeck } 718