17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 53ad28c1eSrm88369 * Common Development and Distribution License (the "License"). 63ad28c1eSrm88369 * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217257d1b4Sraf 227c478bd9Sstevel@tonic-gate /* 23eb1a3463STruong Nguyen * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate #include <librestart.h> 287c478bd9Sstevel@tonic-gate #include <librestart_priv.h> 297c478bd9Sstevel@tonic-gate #include <libscf.h> 307c478bd9Sstevel@tonic-gate #include <libscf_priv.h> 317c478bd9Sstevel@tonic-gate 327c478bd9Sstevel@tonic-gate #include <assert.h> 337c478bd9Sstevel@tonic-gate #include <ctype.h> 347c478bd9Sstevel@tonic-gate #include <dlfcn.h> 357c478bd9Sstevel@tonic-gate #include <errno.h> 367c478bd9Sstevel@tonic-gate #include <exec_attr.h> 377c478bd9Sstevel@tonic-gate #include <grp.h> 387c478bd9Sstevel@tonic-gate #include <libsysevent.h> 397c478bd9Sstevel@tonic-gate #include <libuutil.h> 407c478bd9Sstevel@tonic-gate #include <limits.h> 417c478bd9Sstevel@tonic-gate #include <link.h> 427c478bd9Sstevel@tonic-gate #include <malloc.h> 437c478bd9Sstevel@tonic-gate #include <pool.h> 447c478bd9Sstevel@tonic-gate #include <priv.h> 457c478bd9Sstevel@tonic-gate #include <project.h> 467c478bd9Sstevel@tonic-gate #include <pthread.h> 477c478bd9Sstevel@tonic-gate #include <pwd.h> 487c478bd9Sstevel@tonic-gate #include <secdb.h> 497c478bd9Sstevel@tonic-gate #include <signal.h> 507c478bd9Sstevel@tonic-gate #include <stdlib.h> 517c478bd9Sstevel@tonic-gate #include <string.h> 527c478bd9Sstevel@tonic-gate #include <syslog.h> 537c478bd9Sstevel@tonic-gate #include <sys/corectl.h> 547c478bd9Sstevel@tonic-gate #include <sys/machelf.h> 557c478bd9Sstevel@tonic-gate #include <sys/task.h> 567c478bd9Sstevel@tonic-gate #include <sys/types.h> 577c478bd9Sstevel@tonic-gate #include <time.h> 587c478bd9Sstevel@tonic-gate #include <unistd.h> 597c478bd9Sstevel@tonic-gate #include <ucontext.h> 607c478bd9Sstevel@tonic-gate 617c478bd9Sstevel@tonic-gate #define min(a, b) ((a) > (b) ? (b) : (a)) 627c478bd9Sstevel@tonic-gate 637c478bd9Sstevel@tonic-gate #define MKW_TRUE ":true" 647c478bd9Sstevel@tonic-gate #define MKW_KILL ":kill" 657c478bd9Sstevel@tonic-gate #define MKW_KILL_PROC ":kill_process" 667c478bd9Sstevel@tonic-gate 677c478bd9Sstevel@tonic-gate #define ALLOCFAIL ((char *)"Allocation failure.") 687c478bd9Sstevel@tonic-gate #define RCBROKEN ((char *)"Repository connection broken.") 697c478bd9Sstevel@tonic-gate 702c65c8b0Srm88369 #define MAX_COMMIT_RETRIES 10 717c478bd9Sstevel@tonic-gate #define MAX_COMMIT_RETRY_INT (5 * 1000000) /* 5 seconds */ 727c478bd9Sstevel@tonic-gate #define INITIAL_COMMIT_RETRY_INT (10000) /* 1/100th second */ 737c478bd9Sstevel@tonic-gate 747c478bd9Sstevel@tonic-gate /* 757c478bd9Sstevel@tonic-gate * bad_fail() catches bugs in this and lower layers by reporting supposedly 767c478bd9Sstevel@tonic-gate * impossible function failures. The NDEBUG case keeps the strings out of the 777c478bd9Sstevel@tonic-gate * library but still calls abort() so we can root-cause from the coredump. 787c478bd9Sstevel@tonic-gate */ 797c478bd9Sstevel@tonic-gate #ifndef NDEBUG 807c478bd9Sstevel@tonic-gate #define bad_fail(func, err) { \ 817c478bd9Sstevel@tonic-gate (void) fprintf(stderr, \ 827c478bd9Sstevel@tonic-gate "At %s:%d, %s() failed with unexpected error %d. Aborting.\n", \ 837c478bd9Sstevel@tonic-gate __FILE__, __LINE__, (func), (err)); \ 847c478bd9Sstevel@tonic-gate abort(); \ 857c478bd9Sstevel@tonic-gate } 867c478bd9Sstevel@tonic-gate #else 877c478bd9Sstevel@tonic-gate #define bad_fail(func, err) abort() 887c478bd9Sstevel@tonic-gate #endif 897c478bd9Sstevel@tonic-gate 907c478bd9Sstevel@tonic-gate struct restarter_event_handle { 917c478bd9Sstevel@tonic-gate char *reh_restarter_name; 927c478bd9Sstevel@tonic-gate char *reh_delegate_channel_name; 937c478bd9Sstevel@tonic-gate evchan_t *reh_delegate_channel; 947c478bd9Sstevel@tonic-gate char *reh_delegate_subscriber_id; 957c478bd9Sstevel@tonic-gate char *reh_master_channel_name; 967c478bd9Sstevel@tonic-gate evchan_t *reh_master_channel; 977c478bd9Sstevel@tonic-gate char *reh_master_subscriber_id; 987c478bd9Sstevel@tonic-gate int (*reh_handler)(restarter_event_t *); 997c478bd9Sstevel@tonic-gate }; 1007c478bd9Sstevel@tonic-gate 1017c478bd9Sstevel@tonic-gate struct restarter_event { 1027c478bd9Sstevel@tonic-gate sysevent_t *re_sysevent; 1037c478bd9Sstevel@tonic-gate restarter_event_type_t re_type; 1047c478bd9Sstevel@tonic-gate char *re_instance_name; 1057c478bd9Sstevel@tonic-gate restarter_event_handle_t *re_event_handle; 1067c478bd9Sstevel@tonic-gate restarter_instance_state_t re_state; 1077c478bd9Sstevel@tonic-gate restarter_instance_state_t re_next_state; 1087c478bd9Sstevel@tonic-gate }; 1097c478bd9Sstevel@tonic-gate 110*870ad75aSSean Wilcox /* 111*870ad75aSSean Wilcox * A static no memory error message mc_error_t structure 112*870ad75aSSean Wilcox * to be used in cases when memory errors are to be returned 113*870ad75aSSean Wilcox * This avoids the need to attempt to allocate memory for the 114*870ad75aSSean Wilcox * message, therefore getting into a cycle of no memory failures. 115*870ad75aSSean Wilcox */ 116*870ad75aSSean Wilcox mc_error_t mc_nomem_err = { 117*870ad75aSSean Wilcox 0, ENOMEM, sizeof ("Out of memory") - 1, "Out of memory" 118*870ad75aSSean Wilcox }; 119*870ad75aSSean Wilcox 1207c478bd9Sstevel@tonic-gate static const char * const allocfail = "Allocation failure.\n"; 1217c478bd9Sstevel@tonic-gate static const char * const rcbroken = "Repository connection broken.\n"; 1227c478bd9Sstevel@tonic-gate 1237c478bd9Sstevel@tonic-gate static int method_context_safety = 0; /* Can safely call pools/projects. */ 1247c478bd9Sstevel@tonic-gate 1257c478bd9Sstevel@tonic-gate int ndebug = 1; 1267c478bd9Sstevel@tonic-gate 127*870ad75aSSean Wilcox /* PRINTFLIKE3 */ 128*870ad75aSSean Wilcox static mc_error_t * 129*870ad75aSSean Wilcox mc_error_create(mc_error_t *e, int type, const char *format, ...) 130*870ad75aSSean Wilcox { 131*870ad75aSSean Wilcox mc_error_t *le; 132*870ad75aSSean Wilcox va_list args; 133*870ad75aSSean Wilcox int size; 134*870ad75aSSean Wilcox 135*870ad75aSSean Wilcox /* 136*870ad75aSSean Wilcox * If the type is ENOMEM and format is NULL, then 137*870ad75aSSean Wilcox * go ahead and return the default nomem error. 138*870ad75aSSean Wilcox * Otherwise, attempt to allocate the memory and if 139*870ad75aSSean Wilcox * that fails then there is no reason to continue. 140*870ad75aSSean Wilcox */ 141*870ad75aSSean Wilcox if (type == ENOMEM && format == NULL) 142*870ad75aSSean Wilcox return (&mc_nomem_err); 143*870ad75aSSean Wilcox 144*870ad75aSSean Wilcox if (e == NULL && (le = malloc(sizeof (mc_error_t))) == NULL) 145*870ad75aSSean Wilcox return (&mc_nomem_err); 146*870ad75aSSean Wilcox else 147*870ad75aSSean Wilcox le = e; 148*870ad75aSSean Wilcox 149*870ad75aSSean Wilcox le->type = type; 150*870ad75aSSean Wilcox le->destroy = 1; 151*870ad75aSSean Wilcox va_start(args, format); 152*870ad75aSSean Wilcox size = vsnprintf(NULL, 0, format, args) + 1; 153*870ad75aSSean Wilcox if (size >= RESTARTER_ERRMSGSZ) { 154*870ad75aSSean Wilcox if ((le = realloc(e, sizeof (mc_error_t) + 155*870ad75aSSean Wilcox (size - RESTARTER_ERRMSGSZ))) == NULL) { 156*870ad75aSSean Wilcox size = RESTARTER_ERRMSGSZ - 1; 157*870ad75aSSean Wilcox le = e; 158*870ad75aSSean Wilcox } 159*870ad75aSSean Wilcox } 160*870ad75aSSean Wilcox 161*870ad75aSSean Wilcox le->size = size; 162*870ad75aSSean Wilcox (void) vsnprintf(le->msg, le->size, format, args); 163*870ad75aSSean Wilcox va_end(args); 164*870ad75aSSean Wilcox 165*870ad75aSSean Wilcox return (le); 166*870ad75aSSean Wilcox } 167*870ad75aSSean Wilcox 168*870ad75aSSean Wilcox void 169*870ad75aSSean Wilcox restarter_mc_error_destroy(mc_error_t *mc_err) 170*870ad75aSSean Wilcox { 171*870ad75aSSean Wilcox if (mc_err == NULL) 172*870ad75aSSean Wilcox return; 173*870ad75aSSean Wilcox 174*870ad75aSSean Wilcox /* 175*870ad75aSSean Wilcox * If the error messages was allocated then free. 176*870ad75aSSean Wilcox */ 177*870ad75aSSean Wilcox if (mc_err->destroy) { 178*870ad75aSSean Wilcox free(mc_err); 179*870ad75aSSean Wilcox } 180*870ad75aSSean Wilcox } 181*870ad75aSSean Wilcox 1827c478bd9Sstevel@tonic-gate static void 1837c478bd9Sstevel@tonic-gate free_restarter_event_handle(struct restarter_event_handle *h) 1847c478bd9Sstevel@tonic-gate { 1857c478bd9Sstevel@tonic-gate if (h == NULL) 1867c478bd9Sstevel@tonic-gate return; 1877c478bd9Sstevel@tonic-gate 1887c478bd9Sstevel@tonic-gate /* 1897c478bd9Sstevel@tonic-gate * Just free the memory -- don't unbind the sysevent handle, 1907c478bd9Sstevel@tonic-gate * as otherwise events may be lost if this is just a restarter 1917c478bd9Sstevel@tonic-gate * restart. 1927c478bd9Sstevel@tonic-gate */ 1937c478bd9Sstevel@tonic-gate 1947c478bd9Sstevel@tonic-gate if (h->reh_restarter_name != NULL) 1957c478bd9Sstevel@tonic-gate free(h->reh_restarter_name); 1967c478bd9Sstevel@tonic-gate if (h->reh_delegate_channel_name != NULL) 1977c478bd9Sstevel@tonic-gate free(h->reh_delegate_channel_name); 1987c478bd9Sstevel@tonic-gate if (h->reh_delegate_subscriber_id != NULL) 1997c478bd9Sstevel@tonic-gate free(h->reh_delegate_subscriber_id); 2007c478bd9Sstevel@tonic-gate if (h->reh_master_channel_name != NULL) 2017c478bd9Sstevel@tonic-gate free(h->reh_master_channel_name); 2027c478bd9Sstevel@tonic-gate if (h->reh_master_subscriber_id != NULL) 2037c478bd9Sstevel@tonic-gate free(h->reh_master_subscriber_id); 2047c478bd9Sstevel@tonic-gate 2057c478bd9Sstevel@tonic-gate free(h); 2067c478bd9Sstevel@tonic-gate } 2077c478bd9Sstevel@tonic-gate 2087c478bd9Sstevel@tonic-gate char * 2097c478bd9Sstevel@tonic-gate _restarter_get_channel_name(const char *fmri, int type) 2107c478bd9Sstevel@tonic-gate { 21113d8aaa1SSean Wilcox char *name; 2127c478bd9Sstevel@tonic-gate char *chan_name = malloc(MAX_CHNAME_LEN); 2137c478bd9Sstevel@tonic-gate char prefix_name[3]; 21413d8aaa1SSean Wilcox int i; 2157c478bd9Sstevel@tonic-gate 2167c478bd9Sstevel@tonic-gate if (chan_name == NULL) 2177c478bd9Sstevel@tonic-gate return (NULL); 2187c478bd9Sstevel@tonic-gate 2197c478bd9Sstevel@tonic-gate if (type == RESTARTER_CHANNEL_DELEGATE) 2207c478bd9Sstevel@tonic-gate (void) strcpy(prefix_name, "d_"); 2217c478bd9Sstevel@tonic-gate else if (type == RESTARTER_CHANNEL_MASTER) 2227c478bd9Sstevel@tonic-gate (void) strcpy(prefix_name, "m_"); 2237c478bd9Sstevel@tonic-gate else { 2247c478bd9Sstevel@tonic-gate free(chan_name); 2257c478bd9Sstevel@tonic-gate return (NULL); 2267c478bd9Sstevel@tonic-gate } 2277c478bd9Sstevel@tonic-gate 22813d8aaa1SSean Wilcox /* 22913d8aaa1SSean Wilcox * Create a unique name 23013d8aaa1SSean Wilcox * 23113d8aaa1SSean Wilcox * Use the entire name, using a replacement of the / 23213d8aaa1SSean Wilcox * characters to get a better name. 23313d8aaa1SSean Wilcox * 23413d8aaa1SSean Wilcox * Remove the svc:/ from the beginning as this really 23513d8aaa1SSean Wilcox * isn't going to provide any uniqueness... 23613d8aaa1SSean Wilcox * 23713d8aaa1SSean Wilcox * An fmri name greater than MAX_CHNAME_LEN is going 23813d8aaa1SSean Wilcox * to be rejected as too long for the chan_name below 23913d8aaa1SSean Wilcox * in the snprintf call. 24013d8aaa1SSean Wilcox */ 24113d8aaa1SSean Wilcox if ((name = strdup(strchr(fmri, '/') + 1)) == NULL) { 24213d8aaa1SSean Wilcox free(chan_name); 24313d8aaa1SSean Wilcox return (NULL); 24413d8aaa1SSean Wilcox } 24513d8aaa1SSean Wilcox i = 0; 24613d8aaa1SSean Wilcox while (name[i]) { 24713d8aaa1SSean Wilcox if (name[i] == '/') { 24813d8aaa1SSean Wilcox name[i] = '_'; 24913d8aaa1SSean Wilcox } 25013d8aaa1SSean Wilcox 25113d8aaa1SSean Wilcox i++; 25213d8aaa1SSean Wilcox } 2537c478bd9Sstevel@tonic-gate 2547c478bd9Sstevel@tonic-gate /* 2557c478bd9Sstevel@tonic-gate * Should check for [a-z],[A-Z],[0-9],.,_,-,: 2567c478bd9Sstevel@tonic-gate */ 2577c478bd9Sstevel@tonic-gate 2587c478bd9Sstevel@tonic-gate if (snprintf(chan_name, MAX_CHNAME_LEN, "com.sun:scf:%s%s", 2597c478bd9Sstevel@tonic-gate prefix_name, name) > MAX_CHNAME_LEN) { 2607c478bd9Sstevel@tonic-gate free(chan_name); 26113d8aaa1SSean Wilcox chan_name = NULL; 2627c478bd9Sstevel@tonic-gate } 2637c478bd9Sstevel@tonic-gate 26413d8aaa1SSean Wilcox free(name); 2657c478bd9Sstevel@tonic-gate return (chan_name); 2667c478bd9Sstevel@tonic-gate } 2677c478bd9Sstevel@tonic-gate 2687c478bd9Sstevel@tonic-gate int 2697c478bd9Sstevel@tonic-gate cb(sysevent_t *syse, void *cookie) 2707c478bd9Sstevel@tonic-gate { 2717c478bd9Sstevel@tonic-gate restarter_event_handle_t *h = (restarter_event_handle_t *)cookie; 2727c478bd9Sstevel@tonic-gate restarter_event_t *e; 2737c478bd9Sstevel@tonic-gate nvlist_t *attr_list = NULL; 2747c478bd9Sstevel@tonic-gate int ret = 0; 2757c478bd9Sstevel@tonic-gate 2767c478bd9Sstevel@tonic-gate e = uu_zalloc(sizeof (restarter_event_t)); 2777c478bd9Sstevel@tonic-gate if (e == NULL) 2787c478bd9Sstevel@tonic-gate uu_die(allocfail); 2797c478bd9Sstevel@tonic-gate e->re_event_handle = h; 2807c478bd9Sstevel@tonic-gate e->re_sysevent = syse; 2817c478bd9Sstevel@tonic-gate 2827c478bd9Sstevel@tonic-gate if (sysevent_get_attr_list(syse, &attr_list) != 0) 2837c478bd9Sstevel@tonic-gate uu_die(allocfail); 2847c478bd9Sstevel@tonic-gate 2857c478bd9Sstevel@tonic-gate if ((nvlist_lookup_uint32(attr_list, RESTARTER_NAME_TYPE, 2867c478bd9Sstevel@tonic-gate &(e->re_type)) != 0) || 2877c478bd9Sstevel@tonic-gate (nvlist_lookup_string(attr_list, 2887c478bd9Sstevel@tonic-gate RESTARTER_NAME_INSTANCE, &(e->re_instance_name)) != 0)) { 2897c478bd9Sstevel@tonic-gate uu_warn("%s: Can't decode nvlist for event %p\n", 2907c478bd9Sstevel@tonic-gate h->reh_restarter_name, (void *)syse); 2917c478bd9Sstevel@tonic-gate 2927c478bd9Sstevel@tonic-gate ret = 0; 2937c478bd9Sstevel@tonic-gate } else { 2947c478bd9Sstevel@tonic-gate ret = h->reh_handler(e); 2957c478bd9Sstevel@tonic-gate } 2967c478bd9Sstevel@tonic-gate 2977c478bd9Sstevel@tonic-gate uu_free(e); 2987c478bd9Sstevel@tonic-gate nvlist_free(attr_list); 2997c478bd9Sstevel@tonic-gate return (ret); 3007c478bd9Sstevel@tonic-gate } 3017c478bd9Sstevel@tonic-gate 3027c478bd9Sstevel@tonic-gate /* 3037c478bd9Sstevel@tonic-gate * restarter_bind_handle(uint32_t, char *, int (*)(restarter_event_t *), int, 3047c478bd9Sstevel@tonic-gate * restarter_event_handle_t **) 3057c478bd9Sstevel@tonic-gate * 3067c478bd9Sstevel@tonic-gate * Bind to a delegated restarter event channel. 3077c478bd9Sstevel@tonic-gate * Each delegated restarter gets its own channel for resource management. 3087c478bd9Sstevel@tonic-gate * 3097c478bd9Sstevel@tonic-gate * Returns 0 on success or 3107c478bd9Sstevel@tonic-gate * ENOTSUP version mismatch 3117c478bd9Sstevel@tonic-gate * EINVAL restarter_name or event_handle is NULL 3127c478bd9Sstevel@tonic-gate * ENOMEM out of memory, too many channels, or too many subscriptions 3137c478bd9Sstevel@tonic-gate * EBUSY sysevent_evc_bind() could not establish binding 3147c478bd9Sstevel@tonic-gate * EFAULT internal sysevent_evc_bind()/sysevent_evc_subscribe() error 3157c478bd9Sstevel@tonic-gate * EMFILE out of file descriptors 3167c478bd9Sstevel@tonic-gate * EPERM insufficient privilege for sysevent_evc_bind() 3177c478bd9Sstevel@tonic-gate * EEXIST already subscribed 3187c478bd9Sstevel@tonic-gate */ 3197c478bd9Sstevel@tonic-gate int 3207c478bd9Sstevel@tonic-gate restarter_bind_handle(uint32_t version, const char *restarter_name, 3217c478bd9Sstevel@tonic-gate int (*event_handler)(restarter_event_t *), int flags, 3227c478bd9Sstevel@tonic-gate restarter_event_handle_t **rehp) 3237c478bd9Sstevel@tonic-gate { 3247c478bd9Sstevel@tonic-gate restarter_event_handle_t *h; 3257c478bd9Sstevel@tonic-gate size_t sz; 3267c478bd9Sstevel@tonic-gate int err; 3277c478bd9Sstevel@tonic-gate 3287c478bd9Sstevel@tonic-gate if (version != RESTARTER_EVENT_VERSION) 3297c478bd9Sstevel@tonic-gate return (ENOTSUP); 3307c478bd9Sstevel@tonic-gate 3317c478bd9Sstevel@tonic-gate if (restarter_name == NULL || event_handler == NULL) 3327c478bd9Sstevel@tonic-gate return (EINVAL); 3337c478bd9Sstevel@tonic-gate 3347c478bd9Sstevel@tonic-gate if (flags & RESTARTER_FLAG_DEBUG) 3357c478bd9Sstevel@tonic-gate ndebug++; 3367c478bd9Sstevel@tonic-gate 3377c478bd9Sstevel@tonic-gate if ((h = uu_zalloc(sizeof (restarter_event_handle_t))) == NULL) 3387c478bd9Sstevel@tonic-gate return (ENOMEM); 3397c478bd9Sstevel@tonic-gate 3407c478bd9Sstevel@tonic-gate h->reh_delegate_subscriber_id = malloc(MAX_SUBID_LEN); 3417c478bd9Sstevel@tonic-gate h->reh_master_subscriber_id = malloc(MAX_SUBID_LEN); 3427c478bd9Sstevel@tonic-gate h->reh_restarter_name = strdup(restarter_name); 3437c478bd9Sstevel@tonic-gate if (h->reh_delegate_subscriber_id == NULL || 3447c478bd9Sstevel@tonic-gate h->reh_master_subscriber_id == NULL || 3457c478bd9Sstevel@tonic-gate h->reh_restarter_name == NULL) { 3467c478bd9Sstevel@tonic-gate free_restarter_event_handle(h); 3477c478bd9Sstevel@tonic-gate return (ENOMEM); 3487c478bd9Sstevel@tonic-gate } 3497c478bd9Sstevel@tonic-gate 3507c478bd9Sstevel@tonic-gate sz = strlcpy(h->reh_delegate_subscriber_id, "del", MAX_SUBID_LEN); 3517c478bd9Sstevel@tonic-gate assert(sz < MAX_SUBID_LEN); 3527c478bd9Sstevel@tonic-gate sz = strlcpy(h->reh_master_subscriber_id, "master", MAX_SUBID_LEN); 3537c478bd9Sstevel@tonic-gate assert(sz < MAX_SUBID_LEN); 3547c478bd9Sstevel@tonic-gate 3557c478bd9Sstevel@tonic-gate h->reh_delegate_channel_name = 3567c478bd9Sstevel@tonic-gate _restarter_get_channel_name(restarter_name, 3577c478bd9Sstevel@tonic-gate RESTARTER_CHANNEL_DELEGATE); 3587c478bd9Sstevel@tonic-gate h->reh_master_channel_name = 3597c478bd9Sstevel@tonic-gate _restarter_get_channel_name(restarter_name, 3607c478bd9Sstevel@tonic-gate RESTARTER_CHANNEL_MASTER); 3617c478bd9Sstevel@tonic-gate 3627c478bd9Sstevel@tonic-gate if (h->reh_delegate_channel_name == NULL || 3637c478bd9Sstevel@tonic-gate h->reh_master_channel_name == NULL) { 3647c478bd9Sstevel@tonic-gate free_restarter_event_handle(h); 3657c478bd9Sstevel@tonic-gate return (ENOMEM); 3667c478bd9Sstevel@tonic-gate } 3677c478bd9Sstevel@tonic-gate 3687c478bd9Sstevel@tonic-gate if (sysevent_evc_bind(h->reh_delegate_channel_name, 3697c478bd9Sstevel@tonic-gate &h->reh_delegate_channel, EVCH_CREAT|EVCH_HOLD_PEND) != 0) { 3707c478bd9Sstevel@tonic-gate err = errno; 3717c478bd9Sstevel@tonic-gate assert(err != EINVAL); 3727c478bd9Sstevel@tonic-gate assert(err != ENOENT); 3737c478bd9Sstevel@tonic-gate free_restarter_event_handle(h); 3747c478bd9Sstevel@tonic-gate return (err); 3757c478bd9Sstevel@tonic-gate } 3767c478bd9Sstevel@tonic-gate 3777c478bd9Sstevel@tonic-gate if (sysevent_evc_bind(h->reh_master_channel_name, 3787c478bd9Sstevel@tonic-gate &h->reh_master_channel, EVCH_CREAT|EVCH_HOLD_PEND) != 0) { 3797c478bd9Sstevel@tonic-gate err = errno; 3807c478bd9Sstevel@tonic-gate assert(err != EINVAL); 3817c478bd9Sstevel@tonic-gate assert(err != ENOENT); 3827c478bd9Sstevel@tonic-gate free_restarter_event_handle(h); 3837c478bd9Sstevel@tonic-gate return (err); 3847c478bd9Sstevel@tonic-gate } 3857c478bd9Sstevel@tonic-gate 3867c478bd9Sstevel@tonic-gate h->reh_handler = event_handler; 3877c478bd9Sstevel@tonic-gate 3887c478bd9Sstevel@tonic-gate assert(strlen(restarter_name) <= MAX_CLASS_LEN - 1); 3897c478bd9Sstevel@tonic-gate assert(strlen(h->reh_delegate_subscriber_id) <= MAX_SUBID_LEN - 1); 3907c478bd9Sstevel@tonic-gate assert(strlen(h->reh_master_subscriber_id) <= MAX_SUBID_LEN - 1); 3917c478bd9Sstevel@tonic-gate 3927c478bd9Sstevel@tonic-gate if (sysevent_evc_subscribe(h->reh_delegate_channel, 3937c478bd9Sstevel@tonic-gate h->reh_delegate_subscriber_id, EC_ALL, cb, h, EVCH_SUB_KEEP) != 0) { 3947c478bd9Sstevel@tonic-gate err = errno; 3957c478bd9Sstevel@tonic-gate assert(err != EINVAL); 3967c478bd9Sstevel@tonic-gate free_restarter_event_handle(h); 3977c478bd9Sstevel@tonic-gate return (err); 3987c478bd9Sstevel@tonic-gate } 3997c478bd9Sstevel@tonic-gate 4007c478bd9Sstevel@tonic-gate *rehp = h; 4017c478bd9Sstevel@tonic-gate return (0); 4027c478bd9Sstevel@tonic-gate } 4037c478bd9Sstevel@tonic-gate 4047c478bd9Sstevel@tonic-gate restarter_event_handle_t * 4057c478bd9Sstevel@tonic-gate restarter_event_get_handle(restarter_event_t *e) 4067c478bd9Sstevel@tonic-gate { 4077c478bd9Sstevel@tonic-gate assert(e != NULL && e->re_event_handle != NULL); 4087c478bd9Sstevel@tonic-gate return (e->re_event_handle); 4097c478bd9Sstevel@tonic-gate } 4107c478bd9Sstevel@tonic-gate 4117c478bd9Sstevel@tonic-gate restarter_event_type_t 4127c478bd9Sstevel@tonic-gate restarter_event_get_type(restarter_event_t *e) 4137c478bd9Sstevel@tonic-gate { 4147c478bd9Sstevel@tonic-gate assert(e != NULL); 4157c478bd9Sstevel@tonic-gate return (e->re_type); 4167c478bd9Sstevel@tonic-gate } 4177c478bd9Sstevel@tonic-gate 4187c478bd9Sstevel@tonic-gate ssize_t 4197c478bd9Sstevel@tonic-gate restarter_event_get_instance(restarter_event_t *e, char *inst, size_t sz) 4207c478bd9Sstevel@tonic-gate { 4217c478bd9Sstevel@tonic-gate assert(e != NULL && inst != NULL); 4227c478bd9Sstevel@tonic-gate return ((ssize_t)strlcpy(inst, e->re_instance_name, sz)); 4237c478bd9Sstevel@tonic-gate } 4247c478bd9Sstevel@tonic-gate 4257c478bd9Sstevel@tonic-gate int 4267c478bd9Sstevel@tonic-gate restarter_event_get_current_states(restarter_event_t *e, 4277c478bd9Sstevel@tonic-gate restarter_instance_state_t *state, restarter_instance_state_t *next_state) 4287c478bd9Sstevel@tonic-gate { 4297c478bd9Sstevel@tonic-gate if (e == NULL) 4307c478bd9Sstevel@tonic-gate return (-1); 4317c478bd9Sstevel@tonic-gate *state = e->re_state; 4327c478bd9Sstevel@tonic-gate *next_state = e->re_next_state; 4337c478bd9Sstevel@tonic-gate return (0); 4347c478bd9Sstevel@tonic-gate } 4357c478bd9Sstevel@tonic-gate 4367c478bd9Sstevel@tonic-gate /* 4372c65c8b0Srm88369 * restarter_event_publish_retry() is a wrapper around sysevent_evc_publish(). 4382c65c8b0Srm88369 * In case, the event cannot be sent at the first attempt (sysevent_evc_publish 4392c65c8b0Srm88369 * returned EAGAIN - sysevent queue full), this function retries a few time 4402c65c8b0Srm88369 * and return ENOSPC if it reaches the retry limit. 4412c65c8b0Srm88369 * 4422c65c8b0Srm88369 * The arguments to this function map the arguments of sysevent_evc_publish(). 4432c65c8b0Srm88369 * 4442c65c8b0Srm88369 * On success, return 0. On error, return 4452c65c8b0Srm88369 * 4462c65c8b0Srm88369 * EFAULT - internal sysevent_evc_publish() error 4472c65c8b0Srm88369 * ENOMEM - internal sysevent_evc_publish() error 4482c65c8b0Srm88369 * EBADF - scp is invalid (sysevent_evc_publish() returned EINVAL) 4492c65c8b0Srm88369 * ENOSPC - sysevent queue full (sysevent_evc_publish() returned EAGAIN) 4502c65c8b0Srm88369 */ 4512c65c8b0Srm88369 int 4522c65c8b0Srm88369 restarter_event_publish_retry(evchan_t *scp, const char *class, 4532c65c8b0Srm88369 const char *subclass, const char *vendor, const char *pub_name, 4542c65c8b0Srm88369 nvlist_t *attr_list, uint32_t flags) 4552c65c8b0Srm88369 { 4562c65c8b0Srm88369 int retries, ret; 4572c65c8b0Srm88369 useconds_t retry_int = INITIAL_COMMIT_RETRY_INT; 4582c65c8b0Srm88369 4592c65c8b0Srm88369 for (retries = 0; retries < MAX_COMMIT_RETRIES; retries++) { 4602c65c8b0Srm88369 ret = sysevent_evc_publish(scp, class, subclass, vendor, 4612c65c8b0Srm88369 pub_name, attr_list, flags); 4622c65c8b0Srm88369 if (ret == 0) 4632c65c8b0Srm88369 break; 4642c65c8b0Srm88369 4652c65c8b0Srm88369 switch (ret) { 4662c65c8b0Srm88369 case EAGAIN: 4672c65c8b0Srm88369 /* Queue is full */ 4682c65c8b0Srm88369 (void) usleep(retry_int); 4692c65c8b0Srm88369 4702c65c8b0Srm88369 retry_int = min(retry_int * 2, MAX_COMMIT_RETRY_INT); 4712c65c8b0Srm88369 break; 4722c65c8b0Srm88369 4732c65c8b0Srm88369 case EINVAL: 4742c65c8b0Srm88369 ret = EBADF; 4752c65c8b0Srm88369 /* FALLTHROUGH */ 4762c65c8b0Srm88369 4772c65c8b0Srm88369 case EFAULT: 4782c65c8b0Srm88369 case ENOMEM: 4792c65c8b0Srm88369 return (ret); 4802c65c8b0Srm88369 4812c65c8b0Srm88369 case EOVERFLOW: 4822c65c8b0Srm88369 default: 4832c65c8b0Srm88369 /* internal error - abort */ 4842c65c8b0Srm88369 bad_fail("sysevent_evc_publish", ret); 4852c65c8b0Srm88369 } 4862c65c8b0Srm88369 } 4872c65c8b0Srm88369 4882c65c8b0Srm88369 if (retries == MAX_COMMIT_RETRIES) 4892c65c8b0Srm88369 ret = ENOSPC; 4902c65c8b0Srm88369 4912c65c8b0Srm88369 return (ret); 4922c65c8b0Srm88369 } 4932c65c8b0Srm88369 4942c65c8b0Srm88369 /* 4957c478bd9Sstevel@tonic-gate * Commit the state, next state, and auxiliary state into the repository. 4967c478bd9Sstevel@tonic-gate * Let the graph engine know about the state change and error. On success, 4977c478bd9Sstevel@tonic-gate * return 0. On error, return 4987c478bd9Sstevel@tonic-gate * EINVAL - aux has spaces 4997c478bd9Sstevel@tonic-gate * - inst is invalid or not an instance FMRI 5007c478bd9Sstevel@tonic-gate * EPROTO - librestart compiled against different libscf 5017c478bd9Sstevel@tonic-gate * ENOMEM - out of memory 5027c478bd9Sstevel@tonic-gate * - repository server out of resources 5037c478bd9Sstevel@tonic-gate * ENOTACTIVE - repository server not running 5047c478bd9Sstevel@tonic-gate * ECONNABORTED - repository connection established, but then broken 5057c478bd9Sstevel@tonic-gate * - unknown libscf error 5067c478bd9Sstevel@tonic-gate * ENOENT - inst does not exist in the repository 5077c478bd9Sstevel@tonic-gate * EPERM - insufficient permissions 5087c478bd9Sstevel@tonic-gate * EACCESS - backend access denied 5097c478bd9Sstevel@tonic-gate * EROFS - backend is readonly 5107c478bd9Sstevel@tonic-gate * EFAULT - internal sysevent_evc_publish() error 5117c478bd9Sstevel@tonic-gate * EBADF - h is invalid (sysevent_evc_publish() returned EINVAL) 5122c65c8b0Srm88369 * ENOSPC - sysevent queue full (sysevent_evc_publish() returned EAGAIN) 5137c478bd9Sstevel@tonic-gate */ 5147c478bd9Sstevel@tonic-gate int 5157c478bd9Sstevel@tonic-gate restarter_set_states(restarter_event_handle_t *h, const char *inst, 5167c478bd9Sstevel@tonic-gate restarter_instance_state_t cur_state, 5177c478bd9Sstevel@tonic-gate restarter_instance_state_t new_cur_state, 5187c478bd9Sstevel@tonic-gate restarter_instance_state_t next_state, 5197c478bd9Sstevel@tonic-gate restarter_instance_state_t new_next_state, restarter_error_t e, 5207c478bd9Sstevel@tonic-gate const char *aux) 5217c478bd9Sstevel@tonic-gate { 5227c478bd9Sstevel@tonic-gate nvlist_t *attr; 5237c478bd9Sstevel@tonic-gate scf_handle_t *scf_h; 5247c478bd9Sstevel@tonic-gate instance_data_t id; 5257c478bd9Sstevel@tonic-gate int ret = 0; 5267c478bd9Sstevel@tonic-gate char *p = (char *)aux; 5277c478bd9Sstevel@tonic-gate 5287c478bd9Sstevel@tonic-gate assert(h->reh_master_channel != NULL); 5297c478bd9Sstevel@tonic-gate assert(h->reh_master_channel_name != NULL); 5307c478bd9Sstevel@tonic-gate assert(h->reh_master_subscriber_id != NULL); 5317c478bd9Sstevel@tonic-gate 5327c478bd9Sstevel@tonic-gate /* Validate format of auxiliary state: no spaces allowed */ 533ba91983eSlianep if (p != NULL) { 534ba91983eSlianep while (*p != '\0') { 5357c478bd9Sstevel@tonic-gate if (isspace(*p)) 5367c478bd9Sstevel@tonic-gate return (EINVAL); 5377c478bd9Sstevel@tonic-gate p++; 5387c478bd9Sstevel@tonic-gate } 539ba91983eSlianep } 5407c478bd9Sstevel@tonic-gate 5417c478bd9Sstevel@tonic-gate if ((scf_h = scf_handle_create(SCF_VERSION)) == NULL) { 5427c478bd9Sstevel@tonic-gate switch (scf_error()) { 5437c478bd9Sstevel@tonic-gate case SCF_ERROR_VERSION_MISMATCH: 5447c478bd9Sstevel@tonic-gate return (EPROTO); 5457c478bd9Sstevel@tonic-gate 5467c478bd9Sstevel@tonic-gate case SCF_ERROR_NO_MEMORY: 5477c478bd9Sstevel@tonic-gate return (ENOMEM); 5487c478bd9Sstevel@tonic-gate 5497c478bd9Sstevel@tonic-gate default: 5507c478bd9Sstevel@tonic-gate bad_fail("scf_handle_create", scf_error()); 5517c478bd9Sstevel@tonic-gate } 5527c478bd9Sstevel@tonic-gate } 5537c478bd9Sstevel@tonic-gate 5547c478bd9Sstevel@tonic-gate if (scf_handle_bind(scf_h) == -1) { 5557c478bd9Sstevel@tonic-gate scf_handle_destroy(scf_h); 5567c478bd9Sstevel@tonic-gate switch (scf_error()) { 5577c478bd9Sstevel@tonic-gate case SCF_ERROR_NO_SERVER: 5587c478bd9Sstevel@tonic-gate return (ENOTACTIVE); 5597c478bd9Sstevel@tonic-gate 5607c478bd9Sstevel@tonic-gate case SCF_ERROR_NO_RESOURCES: 5617c478bd9Sstevel@tonic-gate return (ENOMEM); 5627c478bd9Sstevel@tonic-gate 5637c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 5647c478bd9Sstevel@tonic-gate case SCF_ERROR_IN_USE: 5657c478bd9Sstevel@tonic-gate default: 5667c478bd9Sstevel@tonic-gate bad_fail("scf_handle_bind", scf_error()); 5677c478bd9Sstevel@tonic-gate } 5687c478bd9Sstevel@tonic-gate } 5697c478bd9Sstevel@tonic-gate 5707c478bd9Sstevel@tonic-gate if (nvlist_alloc(&attr, NV_UNIQUE_NAME, 0) != 0 || 5717c478bd9Sstevel@tonic-gate nvlist_add_int32(attr, RESTARTER_NAME_STATE, new_cur_state) != 0 || 5727c478bd9Sstevel@tonic-gate nvlist_add_int32(attr, RESTARTER_NAME_NEXT_STATE, new_next_state) 5737c478bd9Sstevel@tonic-gate != 0 || 5747c478bd9Sstevel@tonic-gate nvlist_add_int32(attr, RESTARTER_NAME_ERROR, e) != 0 || 5757c478bd9Sstevel@tonic-gate nvlist_add_string(attr, RESTARTER_NAME_INSTANCE, inst) != 0) { 5767c478bd9Sstevel@tonic-gate ret = ENOMEM; 5772c65c8b0Srm88369 } else { 5787c478bd9Sstevel@tonic-gate id.i_fmri = inst; 5797c478bd9Sstevel@tonic-gate id.i_state = cur_state; 5807c478bd9Sstevel@tonic-gate id.i_next_state = next_state; 5817c478bd9Sstevel@tonic-gate 5827c478bd9Sstevel@tonic-gate ret = _restarter_commit_states(scf_h, &id, new_cur_state, 5837c478bd9Sstevel@tonic-gate new_next_state, aux); 5847c478bd9Sstevel@tonic-gate 5852c65c8b0Srm88369 if (ret == 0) { 5862c65c8b0Srm88369 ret = restarter_event_publish_retry( 5872c65c8b0Srm88369 h->reh_master_channel, "master", "state_change", 5882c65c8b0Srm88369 "com.sun", "librestart", attr, EVCH_NOSLEEP); 5897c478bd9Sstevel@tonic-gate } 5907c478bd9Sstevel@tonic-gate } 5917c478bd9Sstevel@tonic-gate 5927c478bd9Sstevel@tonic-gate nvlist_free(attr); 5937c478bd9Sstevel@tonic-gate (void) scf_handle_unbind(scf_h); 5947c478bd9Sstevel@tonic-gate scf_handle_destroy(scf_h); 5957c478bd9Sstevel@tonic-gate 5967c478bd9Sstevel@tonic-gate return (ret); 5977c478bd9Sstevel@tonic-gate } 5987c478bd9Sstevel@tonic-gate 5997c478bd9Sstevel@tonic-gate restarter_instance_state_t 6007c478bd9Sstevel@tonic-gate restarter_string_to_state(char *string) 6017c478bd9Sstevel@tonic-gate { 6027c478bd9Sstevel@tonic-gate assert(string != NULL); 6037c478bd9Sstevel@tonic-gate 6047c478bd9Sstevel@tonic-gate if (strcmp(string, SCF_STATE_STRING_NONE) == 0) 6057c478bd9Sstevel@tonic-gate return (RESTARTER_STATE_NONE); 6067c478bd9Sstevel@tonic-gate else if (strcmp(string, SCF_STATE_STRING_UNINIT) == 0) 6077c478bd9Sstevel@tonic-gate return (RESTARTER_STATE_UNINIT); 6087c478bd9Sstevel@tonic-gate else if (strcmp(string, SCF_STATE_STRING_MAINT) == 0) 6097c478bd9Sstevel@tonic-gate return (RESTARTER_STATE_MAINT); 6107c478bd9Sstevel@tonic-gate else if (strcmp(string, SCF_STATE_STRING_OFFLINE) == 0) 6117c478bd9Sstevel@tonic-gate return (RESTARTER_STATE_OFFLINE); 6127c478bd9Sstevel@tonic-gate else if (strcmp(string, SCF_STATE_STRING_DISABLED) == 0) 6137c478bd9Sstevel@tonic-gate return (RESTARTER_STATE_DISABLED); 6147c478bd9Sstevel@tonic-gate else if (strcmp(string, SCF_STATE_STRING_ONLINE) == 0) 6157c478bd9Sstevel@tonic-gate return (RESTARTER_STATE_ONLINE); 6167c478bd9Sstevel@tonic-gate else if (strcmp(string, SCF_STATE_STRING_DEGRADED) == 0) 6177c478bd9Sstevel@tonic-gate return (RESTARTER_STATE_DEGRADED); 6187c478bd9Sstevel@tonic-gate else { 6197c478bd9Sstevel@tonic-gate return (RESTARTER_STATE_NONE); 6207c478bd9Sstevel@tonic-gate } 6217c478bd9Sstevel@tonic-gate } 6227c478bd9Sstevel@tonic-gate 6237c478bd9Sstevel@tonic-gate ssize_t 6247c478bd9Sstevel@tonic-gate restarter_state_to_string(restarter_instance_state_t state, char *string, 6257c478bd9Sstevel@tonic-gate size_t len) 6267c478bd9Sstevel@tonic-gate { 6277c478bd9Sstevel@tonic-gate assert(string != NULL); 6287c478bd9Sstevel@tonic-gate 6297c478bd9Sstevel@tonic-gate if (state == RESTARTER_STATE_NONE) 6307c478bd9Sstevel@tonic-gate return ((ssize_t)strlcpy(string, SCF_STATE_STRING_NONE, len)); 6317c478bd9Sstevel@tonic-gate else if (state == RESTARTER_STATE_UNINIT) 6327c478bd9Sstevel@tonic-gate return ((ssize_t)strlcpy(string, SCF_STATE_STRING_UNINIT, len)); 6337c478bd9Sstevel@tonic-gate else if (state == RESTARTER_STATE_MAINT) 6347c478bd9Sstevel@tonic-gate return ((ssize_t)strlcpy(string, SCF_STATE_STRING_MAINT, len)); 6357c478bd9Sstevel@tonic-gate else if (state == RESTARTER_STATE_OFFLINE) 6367c478bd9Sstevel@tonic-gate return ((ssize_t)strlcpy(string, SCF_STATE_STRING_OFFLINE, 6377c478bd9Sstevel@tonic-gate len)); 6387c478bd9Sstevel@tonic-gate else if (state == RESTARTER_STATE_DISABLED) 6397c478bd9Sstevel@tonic-gate return ((ssize_t)strlcpy(string, SCF_STATE_STRING_DISABLED, 6407c478bd9Sstevel@tonic-gate len)); 6417c478bd9Sstevel@tonic-gate else if (state == RESTARTER_STATE_ONLINE) 6427c478bd9Sstevel@tonic-gate return ((ssize_t)strlcpy(string, SCF_STATE_STRING_ONLINE, len)); 6437c478bd9Sstevel@tonic-gate else if (state == RESTARTER_STATE_DEGRADED) 6447c478bd9Sstevel@tonic-gate return ((ssize_t)strlcpy(string, SCF_STATE_STRING_DEGRADED, 6457c478bd9Sstevel@tonic-gate len)); 6467c478bd9Sstevel@tonic-gate else 6477c478bd9Sstevel@tonic-gate return ((ssize_t)strlcpy(string, "unknown", len)); 6487c478bd9Sstevel@tonic-gate } 6497c478bd9Sstevel@tonic-gate 6507c478bd9Sstevel@tonic-gate /* 6517c478bd9Sstevel@tonic-gate * Sets pg to the name property group of s_inst. If it doesn't exist, it is 6527c478bd9Sstevel@tonic-gate * added. 6537c478bd9Sstevel@tonic-gate * 6547c478bd9Sstevel@tonic-gate * Fails with 6557c478bd9Sstevel@tonic-gate * ECONNABORTED - repository disconnection or unknown libscf error 6567c478bd9Sstevel@tonic-gate * EBADF - inst is not set 6577c478bd9Sstevel@tonic-gate * ECANCELED - inst is deleted 6587c478bd9Sstevel@tonic-gate * EPERM - permission is denied 6597c478bd9Sstevel@tonic-gate * EACCES - backend denied access 6607c478bd9Sstevel@tonic-gate * EROFS - backend readonly 6617c478bd9Sstevel@tonic-gate */ 6627c478bd9Sstevel@tonic-gate static int 6637c478bd9Sstevel@tonic-gate instance_get_or_add_pg(scf_instance_t *inst, const char *name, 6647c478bd9Sstevel@tonic-gate const char *type, uint32_t flags, scf_propertygroup_t *pg) 6657c478bd9Sstevel@tonic-gate { 6667c478bd9Sstevel@tonic-gate again: 6677c478bd9Sstevel@tonic-gate if (scf_instance_get_pg(inst, name, pg) == 0) 6687c478bd9Sstevel@tonic-gate return (0); 6697c478bd9Sstevel@tonic-gate 6707c478bd9Sstevel@tonic-gate switch (scf_error()) { 6717c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 6727c478bd9Sstevel@tonic-gate default: 6737c478bd9Sstevel@tonic-gate return (ECONNABORTED); 6747c478bd9Sstevel@tonic-gate 6757c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 6767c478bd9Sstevel@tonic-gate return (EBADF); 6777c478bd9Sstevel@tonic-gate 6787c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 6797c478bd9Sstevel@tonic-gate return (ECANCELED); 6807c478bd9Sstevel@tonic-gate 6817c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 6827c478bd9Sstevel@tonic-gate break; 6837c478bd9Sstevel@tonic-gate 6847c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 6857c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 6867c478bd9Sstevel@tonic-gate bad_fail("scf_instance_get_pg", scf_error()); 6877c478bd9Sstevel@tonic-gate } 6887c478bd9Sstevel@tonic-gate 6897c478bd9Sstevel@tonic-gate if (scf_instance_add_pg(inst, name, type, flags, pg) == 0) 6907c478bd9Sstevel@tonic-gate return (0); 6917c478bd9Sstevel@tonic-gate 6927c478bd9Sstevel@tonic-gate switch (scf_error()) { 6937c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 6947c478bd9Sstevel@tonic-gate default: 6957c478bd9Sstevel@tonic-gate return (ECONNABORTED); 6967c478bd9Sstevel@tonic-gate 6977c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 6987c478bd9Sstevel@tonic-gate return (ECANCELED); 6997c478bd9Sstevel@tonic-gate 7007c478bd9Sstevel@tonic-gate case SCF_ERROR_EXISTS: 7017c478bd9Sstevel@tonic-gate goto again; 7027c478bd9Sstevel@tonic-gate 7037c478bd9Sstevel@tonic-gate case SCF_ERROR_PERMISSION_DENIED: 7047c478bd9Sstevel@tonic-gate return (EPERM); 7057c478bd9Sstevel@tonic-gate 7067c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_ACCESS: 7077c478bd9Sstevel@tonic-gate return (EACCES); 7087c478bd9Sstevel@tonic-gate 7097c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_READONLY: 7107c478bd9Sstevel@tonic-gate return (EROFS); 7117c478bd9Sstevel@tonic-gate 7127c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 7137c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 7147c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: /* should be caught above */ 7157c478bd9Sstevel@tonic-gate bad_fail("scf_instance_add_pg", scf_error()); 7167c478bd9Sstevel@tonic-gate } 7177c478bd9Sstevel@tonic-gate 7187c478bd9Sstevel@tonic-gate return (0); 7197c478bd9Sstevel@tonic-gate } 7207c478bd9Sstevel@tonic-gate 7217c478bd9Sstevel@tonic-gate /* 7227c478bd9Sstevel@tonic-gate * Fails with 7237c478bd9Sstevel@tonic-gate * ECONNABORTED 7247c478bd9Sstevel@tonic-gate * ECANCELED - pg was deleted 7257c478bd9Sstevel@tonic-gate */ 7267c478bd9Sstevel@tonic-gate static int 7277c478bd9Sstevel@tonic-gate tx_set_value(scf_transaction_t *tx, scf_transaction_entry_t *ent, 7287c478bd9Sstevel@tonic-gate const char *pname, scf_type_t ty, scf_value_t *val) 7297c478bd9Sstevel@tonic-gate { 7307c478bd9Sstevel@tonic-gate int r; 7317c478bd9Sstevel@tonic-gate 7327c478bd9Sstevel@tonic-gate for (;;) { 7337c478bd9Sstevel@tonic-gate if (scf_transaction_property_change_type(tx, ent, pname, 7347c478bd9Sstevel@tonic-gate ty) == 0) 7357c478bd9Sstevel@tonic-gate break; 7367c478bd9Sstevel@tonic-gate 7377c478bd9Sstevel@tonic-gate switch (scf_error()) { 7387c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 7397c478bd9Sstevel@tonic-gate default: 7407c478bd9Sstevel@tonic-gate return (ECONNABORTED); 7417c478bd9Sstevel@tonic-gate 7427c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 7437c478bd9Sstevel@tonic-gate return (ECANCELED); 7447c478bd9Sstevel@tonic-gate 7457c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 7467c478bd9Sstevel@tonic-gate break; 7477c478bd9Sstevel@tonic-gate 7487c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 7497c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 7507c478bd9Sstevel@tonic-gate case SCF_ERROR_IN_USE: 7517c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 7527c478bd9Sstevel@tonic-gate bad_fail("scf_transaction_property_change_type", 7537c478bd9Sstevel@tonic-gate scf_error()); 7547c478bd9Sstevel@tonic-gate } 7557c478bd9Sstevel@tonic-gate 7567c478bd9Sstevel@tonic-gate if (scf_transaction_property_new(tx, ent, pname, ty) == 0) 7577c478bd9Sstevel@tonic-gate break; 7587c478bd9Sstevel@tonic-gate 7597c478bd9Sstevel@tonic-gate switch (scf_error()) { 7607c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 7617c478bd9Sstevel@tonic-gate default: 7627c478bd9Sstevel@tonic-gate return (ECONNABORTED); 7637c478bd9Sstevel@tonic-gate 7647c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 7657c478bd9Sstevel@tonic-gate return (ECANCELED); 7667c478bd9Sstevel@tonic-gate 7677c478bd9Sstevel@tonic-gate case SCF_ERROR_EXISTS: 7687c478bd9Sstevel@tonic-gate break; 7697c478bd9Sstevel@tonic-gate 7707c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 7717c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 7727c478bd9Sstevel@tonic-gate case SCF_ERROR_IN_USE: 7737c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 7747c478bd9Sstevel@tonic-gate bad_fail("scf_transaction_property_new", scf_error()); 7757c478bd9Sstevel@tonic-gate } 7767c478bd9Sstevel@tonic-gate } 7777c478bd9Sstevel@tonic-gate 7787c478bd9Sstevel@tonic-gate r = scf_entry_add_value(ent, val); 7797c478bd9Sstevel@tonic-gate assert(r == 0); 7807c478bd9Sstevel@tonic-gate 7817c478bd9Sstevel@tonic-gate return (0); 7827c478bd9Sstevel@tonic-gate } 7837c478bd9Sstevel@tonic-gate 7847c478bd9Sstevel@tonic-gate /* 7857c478bd9Sstevel@tonic-gate * Commit new_state, new_next_state, and aux to the repository for id. If 7867c478bd9Sstevel@tonic-gate * successful, also set id's state and next-state as given, and return 0. 7877c478bd9Sstevel@tonic-gate * Fails with 7887c478bd9Sstevel@tonic-gate * ENOMEM - out of memory 7897c478bd9Sstevel@tonic-gate * ECONNABORTED - repository connection broken 7907c478bd9Sstevel@tonic-gate * - unknown libscf error 7917c478bd9Sstevel@tonic-gate * EINVAL - id->i_fmri is invalid or not an instance FMRI 7927c478bd9Sstevel@tonic-gate * ENOENT - id->i_fmri does not exist 7937c478bd9Sstevel@tonic-gate * EPERM - insufficient permissions 7947c478bd9Sstevel@tonic-gate * EACCES - backend access denied 7957c478bd9Sstevel@tonic-gate * EROFS - backend is readonly 7967c478bd9Sstevel@tonic-gate */ 7977c478bd9Sstevel@tonic-gate int 7987c478bd9Sstevel@tonic-gate _restarter_commit_states(scf_handle_t *h, instance_data_t *id, 7997c478bd9Sstevel@tonic-gate restarter_instance_state_t new_state, 8007c478bd9Sstevel@tonic-gate restarter_instance_state_t new_state_next, const char *aux) 8017c478bd9Sstevel@tonic-gate { 8027c478bd9Sstevel@tonic-gate char str_state[MAX_SCF_STATE_STRING_SZ]; 8037c478bd9Sstevel@tonic-gate char str_new_state[MAX_SCF_STATE_STRING_SZ]; 8047c478bd9Sstevel@tonic-gate char str_state_next[MAX_SCF_STATE_STRING_SZ]; 8057c478bd9Sstevel@tonic-gate char str_new_state_next[MAX_SCF_STATE_STRING_SZ]; 8067c478bd9Sstevel@tonic-gate int ret = 0, r; 8077c478bd9Sstevel@tonic-gate struct timeval now; 8087c478bd9Sstevel@tonic-gate ssize_t sz; 8097c478bd9Sstevel@tonic-gate 8107c478bd9Sstevel@tonic-gate scf_transaction_t *t = NULL; 8117c478bd9Sstevel@tonic-gate scf_transaction_entry_t *t_state = NULL, *t_state_next = NULL; 8127c478bd9Sstevel@tonic-gate scf_transaction_entry_t *t_stime = NULL, *t_aux = NULL; 8137c478bd9Sstevel@tonic-gate scf_value_t *v_state = NULL, *v_state_next = NULL, *v_stime = NULL; 8147c478bd9Sstevel@tonic-gate scf_value_t *v_aux = NULL; 8157c478bd9Sstevel@tonic-gate scf_instance_t *s_inst = NULL; 8167c478bd9Sstevel@tonic-gate scf_propertygroup_t *pg = NULL; 8177c478bd9Sstevel@tonic-gate 8187c478bd9Sstevel@tonic-gate assert(new_state != RESTARTER_STATE_NONE); 8197c478bd9Sstevel@tonic-gate 8207c478bd9Sstevel@tonic-gate if ((s_inst = scf_instance_create(h)) == NULL || 8217c478bd9Sstevel@tonic-gate (pg = scf_pg_create(h)) == NULL || 8227c478bd9Sstevel@tonic-gate (t = scf_transaction_create(h)) == NULL || 8237c478bd9Sstevel@tonic-gate (t_state = scf_entry_create(h)) == NULL || 8247c478bd9Sstevel@tonic-gate (t_state_next = scf_entry_create(h)) == NULL || 8257c478bd9Sstevel@tonic-gate (t_stime = scf_entry_create(h)) == NULL || 8267c478bd9Sstevel@tonic-gate (t_aux = scf_entry_create(h)) == NULL || 8277c478bd9Sstevel@tonic-gate (v_state = scf_value_create(h)) == NULL || 8287c478bd9Sstevel@tonic-gate (v_state_next = scf_value_create(h)) == NULL || 8297c478bd9Sstevel@tonic-gate (v_stime = scf_value_create(h)) == NULL || 8307c478bd9Sstevel@tonic-gate (v_aux = scf_value_create(h)) == NULL) { 8317c478bd9Sstevel@tonic-gate ret = ENOMEM; 8327c478bd9Sstevel@tonic-gate goto out; 8337c478bd9Sstevel@tonic-gate } 8347c478bd9Sstevel@tonic-gate 8357c478bd9Sstevel@tonic-gate sz = restarter_state_to_string(new_state, str_new_state, 8367c478bd9Sstevel@tonic-gate sizeof (str_new_state)); 8377c478bd9Sstevel@tonic-gate assert(sz < sizeof (str_new_state)); 8387c478bd9Sstevel@tonic-gate sz = restarter_state_to_string(new_state_next, str_new_state_next, 8397c478bd9Sstevel@tonic-gate sizeof (str_new_state_next)); 8407c478bd9Sstevel@tonic-gate assert(sz < sizeof (str_new_state_next)); 8417c478bd9Sstevel@tonic-gate sz = restarter_state_to_string(id->i_state, str_state, 8427c478bd9Sstevel@tonic-gate sizeof (str_state)); 8437c478bd9Sstevel@tonic-gate assert(sz < sizeof (str_state)); 8447c478bd9Sstevel@tonic-gate sz = restarter_state_to_string(id->i_next_state, str_state_next, 8457c478bd9Sstevel@tonic-gate sizeof (str_state_next)); 8467c478bd9Sstevel@tonic-gate assert(sz < sizeof (str_state_next)); 8477c478bd9Sstevel@tonic-gate 8487c478bd9Sstevel@tonic-gate ret = gettimeofday(&now, NULL); 8497c478bd9Sstevel@tonic-gate assert(ret != -1); 8507c478bd9Sstevel@tonic-gate 8517c478bd9Sstevel@tonic-gate if (scf_handle_decode_fmri(h, id->i_fmri, NULL, NULL, s_inst, 8527c478bd9Sstevel@tonic-gate NULL, NULL, SCF_DECODE_FMRI_EXACT) == -1) { 8537c478bd9Sstevel@tonic-gate switch (scf_error()) { 8547c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 8557c478bd9Sstevel@tonic-gate default: 8567c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 8577c478bd9Sstevel@tonic-gate break; 8587c478bd9Sstevel@tonic-gate 8597c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 8607c478bd9Sstevel@tonic-gate case SCF_ERROR_CONSTRAINT_VIOLATED: 8617c478bd9Sstevel@tonic-gate ret = EINVAL; 8627c478bd9Sstevel@tonic-gate break; 8637c478bd9Sstevel@tonic-gate 8647c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 8657c478bd9Sstevel@tonic-gate ret = ENOENT; 8667c478bd9Sstevel@tonic-gate break; 8677c478bd9Sstevel@tonic-gate 8687c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 8697c478bd9Sstevel@tonic-gate bad_fail("scf_handle_decode_fmri", scf_error()); 8707c478bd9Sstevel@tonic-gate } 8717c478bd9Sstevel@tonic-gate goto out; 8727c478bd9Sstevel@tonic-gate } 8737c478bd9Sstevel@tonic-gate 8747c478bd9Sstevel@tonic-gate 8757c478bd9Sstevel@tonic-gate if (scf_value_set_astring(v_state, str_new_state) != 0 || 876eb1a3463STruong Nguyen scf_value_set_astring(v_state_next, str_new_state_next) != 0) 8777c478bd9Sstevel@tonic-gate bad_fail("scf_value_set_astring", scf_error()); 8787c478bd9Sstevel@tonic-gate 879eb1a3463STruong Nguyen if (aux) { 880eb1a3463STruong Nguyen if (scf_value_set_astring(v_aux, aux) != 0) 881eb1a3463STruong Nguyen bad_fail("scf_value_set_astring", scf_error()); 882eb1a3463STruong Nguyen } 883eb1a3463STruong Nguyen 8847c478bd9Sstevel@tonic-gate if (scf_value_set_time(v_stime, now.tv_sec, now.tv_usec * 1000) != 0) 8857c478bd9Sstevel@tonic-gate bad_fail("scf_value_set_time", scf_error()); 8867c478bd9Sstevel@tonic-gate 8877c478bd9Sstevel@tonic-gate add_pg: 8887c478bd9Sstevel@tonic-gate switch (r = instance_get_or_add_pg(s_inst, SCF_PG_RESTARTER, 8897c478bd9Sstevel@tonic-gate SCF_PG_RESTARTER_TYPE, SCF_PG_RESTARTER_FLAGS, pg)) { 8907c478bd9Sstevel@tonic-gate case 0: 8917c478bd9Sstevel@tonic-gate break; 8927c478bd9Sstevel@tonic-gate 8937c478bd9Sstevel@tonic-gate case ECONNABORTED: 8947c478bd9Sstevel@tonic-gate case EPERM: 8957c478bd9Sstevel@tonic-gate case EACCES: 8967c478bd9Sstevel@tonic-gate case EROFS: 8977c478bd9Sstevel@tonic-gate ret = r; 8987c478bd9Sstevel@tonic-gate goto out; 8997c478bd9Sstevel@tonic-gate 9007c478bd9Sstevel@tonic-gate case ECANCELED: 9017c478bd9Sstevel@tonic-gate ret = ENOENT; 9027c478bd9Sstevel@tonic-gate goto out; 9037c478bd9Sstevel@tonic-gate 9047c478bd9Sstevel@tonic-gate case EBADF: 9057c478bd9Sstevel@tonic-gate default: 9067c478bd9Sstevel@tonic-gate bad_fail("instance_get_or_add_pg", r); 9077c478bd9Sstevel@tonic-gate } 9087c478bd9Sstevel@tonic-gate 9097c478bd9Sstevel@tonic-gate for (;;) { 9107c478bd9Sstevel@tonic-gate if (scf_transaction_start(t, pg) != 0) { 9117c478bd9Sstevel@tonic-gate switch (scf_error()) { 9127c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 9137c478bd9Sstevel@tonic-gate default: 9147c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 9157c478bd9Sstevel@tonic-gate goto out; 9167c478bd9Sstevel@tonic-gate 9177c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 9187c478bd9Sstevel@tonic-gate goto add_pg; 9197c478bd9Sstevel@tonic-gate 9207c478bd9Sstevel@tonic-gate case SCF_ERROR_PERMISSION_DENIED: 9217c478bd9Sstevel@tonic-gate ret = EPERM; 9227c478bd9Sstevel@tonic-gate goto out; 9237c478bd9Sstevel@tonic-gate 9247c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_ACCESS: 9257c478bd9Sstevel@tonic-gate ret = EACCES; 9267c478bd9Sstevel@tonic-gate goto out; 9277c478bd9Sstevel@tonic-gate 9287c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_READONLY: 9297c478bd9Sstevel@tonic-gate ret = EROFS; 9307c478bd9Sstevel@tonic-gate goto out; 9317c478bd9Sstevel@tonic-gate 9327c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 9337c478bd9Sstevel@tonic-gate case SCF_ERROR_IN_USE: 9347c478bd9Sstevel@tonic-gate bad_fail("scf_transaction_start", scf_error()); 9357c478bd9Sstevel@tonic-gate } 9367c478bd9Sstevel@tonic-gate } 9377c478bd9Sstevel@tonic-gate 9387c478bd9Sstevel@tonic-gate if ((r = tx_set_value(t, t_state, SCF_PROPERTY_STATE, 9397c478bd9Sstevel@tonic-gate SCF_TYPE_ASTRING, v_state)) != 0 || 9407c478bd9Sstevel@tonic-gate (r = tx_set_value(t, t_state_next, SCF_PROPERTY_NEXT_STATE, 9417c478bd9Sstevel@tonic-gate SCF_TYPE_ASTRING, v_state_next)) != 0 || 9427c478bd9Sstevel@tonic-gate (r = tx_set_value(t, t_stime, SCF_PROPERTY_STATE_TIMESTAMP, 9437c478bd9Sstevel@tonic-gate SCF_TYPE_TIME, v_stime)) != 0) { 9447c478bd9Sstevel@tonic-gate switch (r) { 9457c478bd9Sstevel@tonic-gate case ECONNABORTED: 9467c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 9477c478bd9Sstevel@tonic-gate goto out; 9487c478bd9Sstevel@tonic-gate 9497c478bd9Sstevel@tonic-gate case ECANCELED: 9507c478bd9Sstevel@tonic-gate scf_transaction_reset(t); 9517c478bd9Sstevel@tonic-gate goto add_pg; 9527c478bd9Sstevel@tonic-gate 9537c478bd9Sstevel@tonic-gate default: 9547c478bd9Sstevel@tonic-gate bad_fail("tx_set_value", r); 9557c478bd9Sstevel@tonic-gate } 9567c478bd9Sstevel@tonic-gate } 9577c478bd9Sstevel@tonic-gate 958eb1a3463STruong Nguyen if (aux) { 959eb1a3463STruong Nguyen if ((r = tx_set_value(t, t_aux, SCF_PROPERTY_AUX_STATE, 960eb1a3463STruong Nguyen SCF_TYPE_ASTRING, v_aux)) != 0) { 961eb1a3463STruong Nguyen switch (r) { 962eb1a3463STruong Nguyen case ECONNABORTED: 963eb1a3463STruong Nguyen ret = ECONNABORTED; 964eb1a3463STruong Nguyen goto out; 965eb1a3463STruong Nguyen 966eb1a3463STruong Nguyen case ECANCELED: 967eb1a3463STruong Nguyen scf_transaction_reset(t); 968eb1a3463STruong Nguyen goto add_pg; 969eb1a3463STruong Nguyen 970eb1a3463STruong Nguyen default: 971eb1a3463STruong Nguyen bad_fail("tx_set_value", r); 972eb1a3463STruong Nguyen } 973eb1a3463STruong Nguyen } 974eb1a3463STruong Nguyen } 975eb1a3463STruong Nguyen 9767c478bd9Sstevel@tonic-gate ret = scf_transaction_commit(t); 9777c478bd9Sstevel@tonic-gate if (ret == 1) 9787c478bd9Sstevel@tonic-gate break; 9797c478bd9Sstevel@tonic-gate if (ret == -1) { 9807c478bd9Sstevel@tonic-gate switch (scf_error()) { 9817c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 9827c478bd9Sstevel@tonic-gate default: 9837c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 9847c478bd9Sstevel@tonic-gate goto out; 9857c478bd9Sstevel@tonic-gate 9867c478bd9Sstevel@tonic-gate case SCF_ERROR_PERMISSION_DENIED: 9877c478bd9Sstevel@tonic-gate ret = EPERM; 9887c478bd9Sstevel@tonic-gate goto out; 9897c478bd9Sstevel@tonic-gate 9907c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_ACCESS: 9917c478bd9Sstevel@tonic-gate ret = EACCES; 9927c478bd9Sstevel@tonic-gate goto out; 9937c478bd9Sstevel@tonic-gate 9947c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_READONLY: 9957c478bd9Sstevel@tonic-gate ret = EROFS; 9967c478bd9Sstevel@tonic-gate goto out; 9977c478bd9Sstevel@tonic-gate 9987c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 9997c478bd9Sstevel@tonic-gate bad_fail("scf_transaction_commit", scf_error()); 10007c478bd9Sstevel@tonic-gate } 10017c478bd9Sstevel@tonic-gate } 10027c478bd9Sstevel@tonic-gate 10037c478bd9Sstevel@tonic-gate scf_transaction_reset(t); 10047c478bd9Sstevel@tonic-gate if (scf_pg_update(pg) == -1) { 10057c478bd9Sstevel@tonic-gate switch (scf_error()) { 10067c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 10077c478bd9Sstevel@tonic-gate default: 10087c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 10097c478bd9Sstevel@tonic-gate goto out; 10107c478bd9Sstevel@tonic-gate 10117c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 10127c478bd9Sstevel@tonic-gate goto add_pg; 10137c478bd9Sstevel@tonic-gate } 10147c478bd9Sstevel@tonic-gate } 10157c478bd9Sstevel@tonic-gate } 10167c478bd9Sstevel@tonic-gate 10177c478bd9Sstevel@tonic-gate id->i_state = new_state; 10187c478bd9Sstevel@tonic-gate id->i_next_state = new_state_next; 10197c478bd9Sstevel@tonic-gate ret = 0; 10207c478bd9Sstevel@tonic-gate 10217c478bd9Sstevel@tonic-gate out: 10227c478bd9Sstevel@tonic-gate scf_transaction_destroy(t); 10237c478bd9Sstevel@tonic-gate scf_entry_destroy(t_state); 10247c478bd9Sstevel@tonic-gate scf_entry_destroy(t_state_next); 10257c478bd9Sstevel@tonic-gate scf_entry_destroy(t_stime); 10267c478bd9Sstevel@tonic-gate scf_entry_destroy(t_aux); 10277c478bd9Sstevel@tonic-gate scf_value_destroy(v_state); 10287c478bd9Sstevel@tonic-gate scf_value_destroy(v_state_next); 10297c478bd9Sstevel@tonic-gate scf_value_destroy(v_stime); 10307c478bd9Sstevel@tonic-gate scf_value_destroy(v_aux); 10317c478bd9Sstevel@tonic-gate scf_pg_destroy(pg); 10327c478bd9Sstevel@tonic-gate scf_instance_destroy(s_inst); 10337c478bd9Sstevel@tonic-gate 10347c478bd9Sstevel@tonic-gate return (ret); 10357c478bd9Sstevel@tonic-gate } 10367c478bd9Sstevel@tonic-gate 10377c478bd9Sstevel@tonic-gate /* 10387c478bd9Sstevel@tonic-gate * Fails with 10397c478bd9Sstevel@tonic-gate * EINVAL - type is invalid 10407c478bd9Sstevel@tonic-gate * ENOMEM 10417c478bd9Sstevel@tonic-gate * ECONNABORTED - repository connection broken 10427c478bd9Sstevel@tonic-gate * EBADF - s_inst is not set 10437c478bd9Sstevel@tonic-gate * ECANCELED - s_inst is deleted 10447c478bd9Sstevel@tonic-gate * EPERM - permission denied 10457c478bd9Sstevel@tonic-gate * EACCES - backend access denied 10467c478bd9Sstevel@tonic-gate * EROFS - backend readonly 10477c478bd9Sstevel@tonic-gate */ 10487c478bd9Sstevel@tonic-gate int 10497c478bd9Sstevel@tonic-gate restarter_remove_contract(scf_instance_t *s_inst, ctid_t contract_id, 10507c478bd9Sstevel@tonic-gate restarter_contract_type_t type) 10517c478bd9Sstevel@tonic-gate { 10527c478bd9Sstevel@tonic-gate scf_handle_t *h; 10537c478bd9Sstevel@tonic-gate scf_transaction_t *t = NULL; 10547c478bd9Sstevel@tonic-gate scf_transaction_entry_t *t_cid = NULL; 10557c478bd9Sstevel@tonic-gate scf_propertygroup_t *pg = NULL; 10567c478bd9Sstevel@tonic-gate scf_property_t *prop = NULL; 10577c478bd9Sstevel@tonic-gate scf_value_t *val; 10587c478bd9Sstevel@tonic-gate scf_iter_t *iter = NULL; 10597c478bd9Sstevel@tonic-gate const char *pname; 10607c478bd9Sstevel@tonic-gate int ret = 0, primary; 10617c478bd9Sstevel@tonic-gate uint64_t c; 10627c478bd9Sstevel@tonic-gate 10637c478bd9Sstevel@tonic-gate switch (type) { 10647c478bd9Sstevel@tonic-gate case RESTARTER_CONTRACT_PRIMARY: 10657c478bd9Sstevel@tonic-gate primary = 1; 10667c478bd9Sstevel@tonic-gate break; 10677c478bd9Sstevel@tonic-gate case RESTARTER_CONTRACT_TRANSIENT: 10687c478bd9Sstevel@tonic-gate primary = 0; 10697c478bd9Sstevel@tonic-gate break; 10707c478bd9Sstevel@tonic-gate default: 10717c478bd9Sstevel@tonic-gate return (EINVAL); 10727c478bd9Sstevel@tonic-gate } 10737c478bd9Sstevel@tonic-gate 10747c478bd9Sstevel@tonic-gate h = scf_instance_handle(s_inst); 10757c478bd9Sstevel@tonic-gate 10767c478bd9Sstevel@tonic-gate pg = scf_pg_create(h); 10777c478bd9Sstevel@tonic-gate prop = scf_property_create(h); 10787c478bd9Sstevel@tonic-gate iter = scf_iter_create(h); 10797c478bd9Sstevel@tonic-gate t = scf_transaction_create(h); 10807c478bd9Sstevel@tonic-gate 10817c478bd9Sstevel@tonic-gate if (pg == NULL || prop == NULL || iter == NULL || t == NULL) { 10827c478bd9Sstevel@tonic-gate ret = ENOMEM; 10837c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 10847c478bd9Sstevel@tonic-gate } 10857c478bd9Sstevel@tonic-gate 10867c478bd9Sstevel@tonic-gate add: 10877c478bd9Sstevel@tonic-gate scf_transaction_destroy_children(t); 10887c478bd9Sstevel@tonic-gate ret = instance_get_or_add_pg(s_inst, SCF_PG_RESTARTER, 10897c478bd9Sstevel@tonic-gate SCF_PG_RESTARTER_TYPE, SCF_PG_RESTARTER_FLAGS, pg); 10907c478bd9Sstevel@tonic-gate if (ret != 0) 10917c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 10927c478bd9Sstevel@tonic-gate 10937c478bd9Sstevel@tonic-gate pname = primary? SCF_PROPERTY_CONTRACT : 10947c478bd9Sstevel@tonic-gate SCF_PROPERTY_TRANSIENT_CONTRACT; 10957c478bd9Sstevel@tonic-gate 10967c478bd9Sstevel@tonic-gate for (;;) { 10977c478bd9Sstevel@tonic-gate if (scf_transaction_start(t, pg) != 0) { 10987c478bd9Sstevel@tonic-gate switch (scf_error()) { 10997c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 11007c478bd9Sstevel@tonic-gate default: 11017c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 11027c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 11037c478bd9Sstevel@tonic-gate 11047c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 11057c478bd9Sstevel@tonic-gate goto add; 11067c478bd9Sstevel@tonic-gate 11077c478bd9Sstevel@tonic-gate case SCF_ERROR_PERMISSION_DENIED: 11087c478bd9Sstevel@tonic-gate ret = EPERM; 11097c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 11107c478bd9Sstevel@tonic-gate 11117c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_ACCESS: 11127c478bd9Sstevel@tonic-gate ret = EACCES; 11137c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 11147c478bd9Sstevel@tonic-gate 11157c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_READONLY: 11167c478bd9Sstevel@tonic-gate ret = EROFS; 11177c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 11187c478bd9Sstevel@tonic-gate 11197c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 11207c478bd9Sstevel@tonic-gate case SCF_ERROR_IN_USE: 11217c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 11227c478bd9Sstevel@tonic-gate bad_fail("scf_transaction_start", scf_error()); 11237c478bd9Sstevel@tonic-gate } 11247c478bd9Sstevel@tonic-gate } 11257c478bd9Sstevel@tonic-gate 11267c478bd9Sstevel@tonic-gate t_cid = scf_entry_create(h); 11277c478bd9Sstevel@tonic-gate 11287c478bd9Sstevel@tonic-gate if (scf_pg_get_property(pg, pname, prop) == 0) { 11297c478bd9Sstevel@tonic-gate replace: 11307c478bd9Sstevel@tonic-gate if (scf_transaction_property_change_type(t, t_cid, 11317c478bd9Sstevel@tonic-gate pname, SCF_TYPE_COUNT) != 0) { 11327c478bd9Sstevel@tonic-gate switch (scf_error()) { 11337c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 11347c478bd9Sstevel@tonic-gate default: 11357c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 11367c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 11377c478bd9Sstevel@tonic-gate 11387c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 11397c478bd9Sstevel@tonic-gate scf_entry_destroy(t_cid); 11407c478bd9Sstevel@tonic-gate goto add; 11417c478bd9Sstevel@tonic-gate 11427c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 11437c478bd9Sstevel@tonic-gate goto new; 11447c478bd9Sstevel@tonic-gate 11457c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 11467c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 11477c478bd9Sstevel@tonic-gate case SCF_ERROR_IN_USE: 11487c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 11497c478bd9Sstevel@tonic-gate bad_fail( 11507c478bd9Sstevel@tonic-gate "scf_transaction_property_changetype", 11517c478bd9Sstevel@tonic-gate scf_error()); 11527c478bd9Sstevel@tonic-gate } 11537c478bd9Sstevel@tonic-gate } 11547c478bd9Sstevel@tonic-gate 11557c478bd9Sstevel@tonic-gate if (scf_property_is_type(prop, SCF_TYPE_COUNT) == 0) { 11567c478bd9Sstevel@tonic-gate if (scf_iter_property_values(iter, prop) != 0) { 11577c478bd9Sstevel@tonic-gate switch (scf_error()) { 11587c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 11597c478bd9Sstevel@tonic-gate default: 11607c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 11617c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 11627c478bd9Sstevel@tonic-gate 11637c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 11647c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 11657c478bd9Sstevel@tonic-gate bad_fail( 11667c478bd9Sstevel@tonic-gate "scf_iter_property_values", 11677c478bd9Sstevel@tonic-gate scf_error()); 11687c478bd9Sstevel@tonic-gate } 11697c478bd9Sstevel@tonic-gate } 11707c478bd9Sstevel@tonic-gate 11717c478bd9Sstevel@tonic-gate next_val: 11727c478bd9Sstevel@tonic-gate val = scf_value_create(h); 11737c478bd9Sstevel@tonic-gate if (val == NULL) { 11747c478bd9Sstevel@tonic-gate assert(scf_error() == 11757c478bd9Sstevel@tonic-gate SCF_ERROR_NO_MEMORY); 11767c478bd9Sstevel@tonic-gate ret = ENOMEM; 11777c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 11787c478bd9Sstevel@tonic-gate } 11797c478bd9Sstevel@tonic-gate 11807c478bd9Sstevel@tonic-gate ret = scf_iter_next_value(iter, val); 11817c478bd9Sstevel@tonic-gate if (ret == -1) { 11827c478bd9Sstevel@tonic-gate switch (scf_error()) { 11837c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 11847c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 11857c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 11867c478bd9Sstevel@tonic-gate 11877c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 11887c478bd9Sstevel@tonic-gate scf_value_destroy(val); 11897c478bd9Sstevel@tonic-gate goto add; 11907c478bd9Sstevel@tonic-gate 11917c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 11927c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 11933eae19d9Swesolows case SCF_ERROR_PERMISSION_DENIED: 11947c478bd9Sstevel@tonic-gate default: 11957c478bd9Sstevel@tonic-gate bad_fail("scf_iter_next_value", 11967c478bd9Sstevel@tonic-gate scf_error()); 11977c478bd9Sstevel@tonic-gate } 11987c478bd9Sstevel@tonic-gate } 11997c478bd9Sstevel@tonic-gate 12007c478bd9Sstevel@tonic-gate if (ret == 1) { 12017c478bd9Sstevel@tonic-gate ret = scf_value_get_count(val, &c); 12027c478bd9Sstevel@tonic-gate assert(ret == 0); 12037c478bd9Sstevel@tonic-gate 12047c478bd9Sstevel@tonic-gate if (c != contract_id) { 12057c478bd9Sstevel@tonic-gate ret = scf_entry_add_value(t_cid, 12067c478bd9Sstevel@tonic-gate val); 12077c478bd9Sstevel@tonic-gate assert(ret == 0); 12087c478bd9Sstevel@tonic-gate } else { 12097c478bd9Sstevel@tonic-gate scf_value_destroy(val); 12107c478bd9Sstevel@tonic-gate } 12117c478bd9Sstevel@tonic-gate 12127c478bd9Sstevel@tonic-gate goto next_val; 12137c478bd9Sstevel@tonic-gate } 12147c478bd9Sstevel@tonic-gate 12157c478bd9Sstevel@tonic-gate scf_value_destroy(val); 12167c478bd9Sstevel@tonic-gate } else { 12177c478bd9Sstevel@tonic-gate switch (scf_error()) { 12187c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 12197c478bd9Sstevel@tonic-gate default: 12207c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 12217c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 12227c478bd9Sstevel@tonic-gate 12237c478bd9Sstevel@tonic-gate case SCF_ERROR_TYPE_MISMATCH: 12247c478bd9Sstevel@tonic-gate break; 12257c478bd9Sstevel@tonic-gate 12267c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 12277c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 12287c478bd9Sstevel@tonic-gate bad_fail("scf_property_is_type", 12297c478bd9Sstevel@tonic-gate scf_error()); 12307c478bd9Sstevel@tonic-gate } 12317c478bd9Sstevel@tonic-gate } 12327c478bd9Sstevel@tonic-gate } else { 12337c478bd9Sstevel@tonic-gate switch (scf_error()) { 12347c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 12357c478bd9Sstevel@tonic-gate default: 12367c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 12377c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 12387c478bd9Sstevel@tonic-gate 12397c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 12407c478bd9Sstevel@tonic-gate scf_entry_destroy(t_cid); 12417c478bd9Sstevel@tonic-gate goto add; 12427c478bd9Sstevel@tonic-gate 12437c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 12447c478bd9Sstevel@tonic-gate break; 12457c478bd9Sstevel@tonic-gate 12467c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 12477c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 12487c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 12497c478bd9Sstevel@tonic-gate bad_fail("scf_pg_get_property", scf_error()); 12507c478bd9Sstevel@tonic-gate } 12517c478bd9Sstevel@tonic-gate 12527c478bd9Sstevel@tonic-gate new: 12537c478bd9Sstevel@tonic-gate if (scf_transaction_property_new(t, t_cid, pname, 12547c478bd9Sstevel@tonic-gate SCF_TYPE_COUNT) != 0) { 12557c478bd9Sstevel@tonic-gate switch (scf_error()) { 12567c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 12577c478bd9Sstevel@tonic-gate default: 12587c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 12597c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 12607c478bd9Sstevel@tonic-gate 12617c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 12627c478bd9Sstevel@tonic-gate scf_entry_destroy(t_cid); 12637c478bd9Sstevel@tonic-gate goto add; 12647c478bd9Sstevel@tonic-gate 12657c478bd9Sstevel@tonic-gate case SCF_ERROR_EXISTS: 12667c478bd9Sstevel@tonic-gate goto replace; 12677c478bd9Sstevel@tonic-gate 12687c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 12697c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 12707c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 12717c478bd9Sstevel@tonic-gate bad_fail("scf_transaction_property_new", 12727c478bd9Sstevel@tonic-gate scf_error()); 12737c478bd9Sstevel@tonic-gate } 12747c478bd9Sstevel@tonic-gate } 12757c478bd9Sstevel@tonic-gate } 12767c478bd9Sstevel@tonic-gate 12777c478bd9Sstevel@tonic-gate ret = scf_transaction_commit(t); 12787c478bd9Sstevel@tonic-gate if (ret == -1) { 12797c478bd9Sstevel@tonic-gate switch (scf_error()) { 12807c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 12817c478bd9Sstevel@tonic-gate default: 12827c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 12837c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 12847c478bd9Sstevel@tonic-gate 12857c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 12867c478bd9Sstevel@tonic-gate goto add; 12877c478bd9Sstevel@tonic-gate 12887c478bd9Sstevel@tonic-gate case SCF_ERROR_PERMISSION_DENIED: 12897c478bd9Sstevel@tonic-gate ret = EPERM; 12907c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 12917c478bd9Sstevel@tonic-gate 12927c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_ACCESS: 12937c478bd9Sstevel@tonic-gate ret = EACCES; 12947c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 12957c478bd9Sstevel@tonic-gate 12967c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_READONLY: 12977c478bd9Sstevel@tonic-gate ret = EROFS; 12987c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 12997c478bd9Sstevel@tonic-gate 13007c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 13017c478bd9Sstevel@tonic-gate bad_fail("scf_transaction_commit", scf_error()); 13027c478bd9Sstevel@tonic-gate } 13037c478bd9Sstevel@tonic-gate } 13047c478bd9Sstevel@tonic-gate if (ret == 1) { 13057c478bd9Sstevel@tonic-gate ret = 0; 13067c478bd9Sstevel@tonic-gate break; 13077c478bd9Sstevel@tonic-gate } 13087c478bd9Sstevel@tonic-gate 13097c478bd9Sstevel@tonic-gate scf_transaction_destroy_children(t); 13107c478bd9Sstevel@tonic-gate if (scf_pg_update(pg) == -1) { 13117c478bd9Sstevel@tonic-gate switch (scf_error()) { 13127c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 13137c478bd9Sstevel@tonic-gate default: 13147c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 13157c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 13167c478bd9Sstevel@tonic-gate 13177c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 13187c478bd9Sstevel@tonic-gate goto add; 13197c478bd9Sstevel@tonic-gate 13207c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 13217c478bd9Sstevel@tonic-gate bad_fail("scf_pg_update", scf_error()); 13227c478bd9Sstevel@tonic-gate } 13237c478bd9Sstevel@tonic-gate } 13247c478bd9Sstevel@tonic-gate } 13257c478bd9Sstevel@tonic-gate 13267c478bd9Sstevel@tonic-gate remove_contract_cleanup: 13277c478bd9Sstevel@tonic-gate scf_transaction_destroy_children(t); 13287c478bd9Sstevel@tonic-gate scf_transaction_destroy(t); 13297c478bd9Sstevel@tonic-gate scf_iter_destroy(iter); 13307c478bd9Sstevel@tonic-gate scf_property_destroy(prop); 13317c478bd9Sstevel@tonic-gate scf_pg_destroy(pg); 13327c478bd9Sstevel@tonic-gate 13337c478bd9Sstevel@tonic-gate return (ret); 13347c478bd9Sstevel@tonic-gate } 13357c478bd9Sstevel@tonic-gate 13367c478bd9Sstevel@tonic-gate /* 13377c478bd9Sstevel@tonic-gate * Fails with 13387c478bd9Sstevel@tonic-gate * EINVAL - type is invalid 13397c478bd9Sstevel@tonic-gate * ENOMEM 13407c478bd9Sstevel@tonic-gate * ECONNABORTED - repository disconnection 13417c478bd9Sstevel@tonic-gate * EBADF - s_inst is not set 13427c478bd9Sstevel@tonic-gate * ECANCELED - s_inst is deleted 13437c478bd9Sstevel@tonic-gate * EPERM 13447c478bd9Sstevel@tonic-gate * EACCES 13457c478bd9Sstevel@tonic-gate * EROFS 13467c478bd9Sstevel@tonic-gate */ 13477c478bd9Sstevel@tonic-gate int 13487c478bd9Sstevel@tonic-gate restarter_store_contract(scf_instance_t *s_inst, ctid_t contract_id, 13497c478bd9Sstevel@tonic-gate restarter_contract_type_t type) 13507c478bd9Sstevel@tonic-gate { 13517c478bd9Sstevel@tonic-gate scf_handle_t *h; 13527c478bd9Sstevel@tonic-gate scf_transaction_t *t = NULL; 13537c478bd9Sstevel@tonic-gate scf_transaction_entry_t *t_cid = NULL; 13547c478bd9Sstevel@tonic-gate scf_value_t *val; 13557c478bd9Sstevel@tonic-gate scf_propertygroup_t *pg = NULL; 13567c478bd9Sstevel@tonic-gate scf_property_t *prop = NULL; 13577c478bd9Sstevel@tonic-gate scf_iter_t *iter = NULL; 13587c478bd9Sstevel@tonic-gate const char *pname; 13597c478bd9Sstevel@tonic-gate int ret = 0, primary; 13607c478bd9Sstevel@tonic-gate 13617c478bd9Sstevel@tonic-gate if (type == RESTARTER_CONTRACT_PRIMARY) 13627c478bd9Sstevel@tonic-gate primary = 1; 13637c478bd9Sstevel@tonic-gate else if (type == RESTARTER_CONTRACT_TRANSIENT) 13647c478bd9Sstevel@tonic-gate primary = 0; 13657c478bd9Sstevel@tonic-gate else 13667c478bd9Sstevel@tonic-gate return (EINVAL); 13677c478bd9Sstevel@tonic-gate 13687c478bd9Sstevel@tonic-gate h = scf_instance_handle(s_inst); 13697c478bd9Sstevel@tonic-gate 13707c478bd9Sstevel@tonic-gate pg = scf_pg_create(h); 13717c478bd9Sstevel@tonic-gate prop = scf_property_create(h); 13727c478bd9Sstevel@tonic-gate iter = scf_iter_create(h); 13737c478bd9Sstevel@tonic-gate t = scf_transaction_create(h); 13747c478bd9Sstevel@tonic-gate 13757c478bd9Sstevel@tonic-gate if (pg == NULL || prop == NULL || iter == NULL || t == NULL) { 13767c478bd9Sstevel@tonic-gate ret = ENOMEM; 13777c478bd9Sstevel@tonic-gate goto out; 13787c478bd9Sstevel@tonic-gate } 13797c478bd9Sstevel@tonic-gate 13807c478bd9Sstevel@tonic-gate add: 13817c478bd9Sstevel@tonic-gate scf_transaction_destroy_children(t); 13827c478bd9Sstevel@tonic-gate ret = instance_get_or_add_pg(s_inst, SCF_PG_RESTARTER, 13837c478bd9Sstevel@tonic-gate SCF_PG_RESTARTER_TYPE, SCF_PG_RESTARTER_FLAGS, pg); 13847c478bd9Sstevel@tonic-gate if (ret != 0) 13857c478bd9Sstevel@tonic-gate goto out; 13867c478bd9Sstevel@tonic-gate 13877c478bd9Sstevel@tonic-gate pname = primary ? SCF_PROPERTY_CONTRACT : 13887c478bd9Sstevel@tonic-gate SCF_PROPERTY_TRANSIENT_CONTRACT; 13897c478bd9Sstevel@tonic-gate 13907c478bd9Sstevel@tonic-gate for (;;) { 13917c478bd9Sstevel@tonic-gate if (scf_transaction_start(t, pg) != 0) { 13927c478bd9Sstevel@tonic-gate switch (scf_error()) { 13937c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 13947c478bd9Sstevel@tonic-gate default: 13957c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 13967c478bd9Sstevel@tonic-gate goto out; 13977c478bd9Sstevel@tonic-gate 13987c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 13997c478bd9Sstevel@tonic-gate goto add; 14007c478bd9Sstevel@tonic-gate 14017c478bd9Sstevel@tonic-gate case SCF_ERROR_PERMISSION_DENIED: 14027c478bd9Sstevel@tonic-gate ret = EPERM; 14037c478bd9Sstevel@tonic-gate goto out; 14047c478bd9Sstevel@tonic-gate 14057c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_ACCESS: 14067c478bd9Sstevel@tonic-gate ret = EACCES; 14077c478bd9Sstevel@tonic-gate goto out; 14087c478bd9Sstevel@tonic-gate 14097c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_READONLY: 14107c478bd9Sstevel@tonic-gate ret = EROFS; 14117c478bd9Sstevel@tonic-gate goto out; 14127c478bd9Sstevel@tonic-gate 14137c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 14147c478bd9Sstevel@tonic-gate case SCF_ERROR_IN_USE: 14157c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 14167c478bd9Sstevel@tonic-gate bad_fail("scf_transaction_start", scf_error()); 14177c478bd9Sstevel@tonic-gate } 14187c478bd9Sstevel@tonic-gate } 14197c478bd9Sstevel@tonic-gate 14207c478bd9Sstevel@tonic-gate t_cid = scf_entry_create(h); 14217c478bd9Sstevel@tonic-gate if (t_cid == NULL) { 14227c478bd9Sstevel@tonic-gate ret = ENOMEM; 14237c478bd9Sstevel@tonic-gate goto out; 14247c478bd9Sstevel@tonic-gate } 14257c478bd9Sstevel@tonic-gate 14267c478bd9Sstevel@tonic-gate if (scf_pg_get_property(pg, pname, prop) == 0) { 14277c478bd9Sstevel@tonic-gate replace: 14287c478bd9Sstevel@tonic-gate if (scf_transaction_property_change_type(t, t_cid, 14297c478bd9Sstevel@tonic-gate pname, SCF_TYPE_COUNT) != 0) { 14307c478bd9Sstevel@tonic-gate switch (scf_error()) { 14317c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 14327c478bd9Sstevel@tonic-gate default: 14337c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 14347c478bd9Sstevel@tonic-gate goto out; 14357c478bd9Sstevel@tonic-gate 14367c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 14377c478bd9Sstevel@tonic-gate scf_entry_destroy(t_cid); 14387c478bd9Sstevel@tonic-gate goto add; 14397c478bd9Sstevel@tonic-gate 14407c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 14417c478bd9Sstevel@tonic-gate goto new; 14427c478bd9Sstevel@tonic-gate 14437c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 14447c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 14457c478bd9Sstevel@tonic-gate case SCF_ERROR_IN_USE: 14467c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 14477c478bd9Sstevel@tonic-gate bad_fail( 14487c478bd9Sstevel@tonic-gate "scf_transaction_propert_change_type", 14497c478bd9Sstevel@tonic-gate scf_error()); 14507c478bd9Sstevel@tonic-gate } 14517c478bd9Sstevel@tonic-gate } 14527c478bd9Sstevel@tonic-gate 14537c478bd9Sstevel@tonic-gate if (scf_property_is_type(prop, SCF_TYPE_COUNT) == 0) { 14547c478bd9Sstevel@tonic-gate if (scf_iter_property_values(iter, prop) != 0) { 14557c478bd9Sstevel@tonic-gate switch (scf_error()) { 14567c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 14577c478bd9Sstevel@tonic-gate default: 14587c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 14597c478bd9Sstevel@tonic-gate goto out; 14607c478bd9Sstevel@tonic-gate 14617c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 14627c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 14637c478bd9Sstevel@tonic-gate bad_fail( 14647c478bd9Sstevel@tonic-gate "scf_iter_property_values", 14657c478bd9Sstevel@tonic-gate scf_error()); 14667c478bd9Sstevel@tonic-gate } 14677c478bd9Sstevel@tonic-gate } 14687c478bd9Sstevel@tonic-gate 14697c478bd9Sstevel@tonic-gate next_val: 14707c478bd9Sstevel@tonic-gate val = scf_value_create(h); 14717c478bd9Sstevel@tonic-gate if (val == NULL) { 14727c478bd9Sstevel@tonic-gate assert(scf_error() == 14737c478bd9Sstevel@tonic-gate SCF_ERROR_NO_MEMORY); 14747c478bd9Sstevel@tonic-gate ret = ENOMEM; 14757c478bd9Sstevel@tonic-gate goto out; 14767c478bd9Sstevel@tonic-gate } 14777c478bd9Sstevel@tonic-gate 14787c478bd9Sstevel@tonic-gate ret = scf_iter_next_value(iter, val); 14797c478bd9Sstevel@tonic-gate if (ret == -1) { 14807c478bd9Sstevel@tonic-gate switch (scf_error()) { 14817c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 14827c478bd9Sstevel@tonic-gate default: 14837c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 14847c478bd9Sstevel@tonic-gate goto out; 14857c478bd9Sstevel@tonic-gate 14867c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 14877c478bd9Sstevel@tonic-gate scf_value_destroy(val); 14887c478bd9Sstevel@tonic-gate goto add; 14897c478bd9Sstevel@tonic-gate 14907c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 14917c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 14923eae19d9Swesolows case SCF_ERROR_PERMISSION_DENIED: 14937c478bd9Sstevel@tonic-gate bad_fail( 14947c478bd9Sstevel@tonic-gate "scf_iter_next_value", 14957c478bd9Sstevel@tonic-gate scf_error()); 14967c478bd9Sstevel@tonic-gate } 14977c478bd9Sstevel@tonic-gate } 14987c478bd9Sstevel@tonic-gate 14997c478bd9Sstevel@tonic-gate if (ret == 1) { 15007c478bd9Sstevel@tonic-gate ret = scf_entry_add_value(t_cid, val); 15017c478bd9Sstevel@tonic-gate assert(ret == 0); 15027c478bd9Sstevel@tonic-gate 15037c478bd9Sstevel@tonic-gate goto next_val; 15047c478bd9Sstevel@tonic-gate } 15057c478bd9Sstevel@tonic-gate 15067c478bd9Sstevel@tonic-gate scf_value_destroy(val); 15077c478bd9Sstevel@tonic-gate } else { 15087c478bd9Sstevel@tonic-gate switch (scf_error()) { 15097c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 15107c478bd9Sstevel@tonic-gate default: 15117c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 15127c478bd9Sstevel@tonic-gate goto out; 15137c478bd9Sstevel@tonic-gate 15147c478bd9Sstevel@tonic-gate case SCF_ERROR_TYPE_MISMATCH: 15157c478bd9Sstevel@tonic-gate break; 15167c478bd9Sstevel@tonic-gate 15177c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 15187c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 15197c478bd9Sstevel@tonic-gate bad_fail("scf_property_is_type", 15207c478bd9Sstevel@tonic-gate scf_error()); 15217c478bd9Sstevel@tonic-gate } 15227c478bd9Sstevel@tonic-gate } 15237c478bd9Sstevel@tonic-gate } else { 15247c478bd9Sstevel@tonic-gate switch (scf_error()) { 15257c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 15267c478bd9Sstevel@tonic-gate default: 15277c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 15287c478bd9Sstevel@tonic-gate goto out; 15297c478bd9Sstevel@tonic-gate 15307c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 15317c478bd9Sstevel@tonic-gate scf_entry_destroy(t_cid); 15327c478bd9Sstevel@tonic-gate goto add; 15337c478bd9Sstevel@tonic-gate 15347c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 15357c478bd9Sstevel@tonic-gate break; 15367c478bd9Sstevel@tonic-gate 15377c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 15387c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 15397c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 15407c478bd9Sstevel@tonic-gate bad_fail("scf_pg_get_property", scf_error()); 15417c478bd9Sstevel@tonic-gate } 15427c478bd9Sstevel@tonic-gate 15437c478bd9Sstevel@tonic-gate new: 15447c478bd9Sstevel@tonic-gate if (scf_transaction_property_new(t, t_cid, pname, 15457c478bd9Sstevel@tonic-gate SCF_TYPE_COUNT) != 0) { 15467c478bd9Sstevel@tonic-gate switch (scf_error()) { 15477c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 15487c478bd9Sstevel@tonic-gate default: 15497c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 15507c478bd9Sstevel@tonic-gate goto out; 15517c478bd9Sstevel@tonic-gate 15527c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 15537c478bd9Sstevel@tonic-gate scf_entry_destroy(t_cid); 15547c478bd9Sstevel@tonic-gate goto add; 15557c478bd9Sstevel@tonic-gate 15567c478bd9Sstevel@tonic-gate case SCF_ERROR_EXISTS: 15577c478bd9Sstevel@tonic-gate goto replace; 15587c478bd9Sstevel@tonic-gate 15597c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 15607c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 15617c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 15627c478bd9Sstevel@tonic-gate bad_fail("scf_transaction_property_new", 15637c478bd9Sstevel@tonic-gate scf_error()); 15647c478bd9Sstevel@tonic-gate } 15657c478bd9Sstevel@tonic-gate } 15667c478bd9Sstevel@tonic-gate } 15677c478bd9Sstevel@tonic-gate 15687c478bd9Sstevel@tonic-gate val = scf_value_create(h); 15697c478bd9Sstevel@tonic-gate if (val == NULL) { 15707c478bd9Sstevel@tonic-gate assert(scf_error() == SCF_ERROR_NO_MEMORY); 15717c478bd9Sstevel@tonic-gate ret = ENOMEM; 15727c478bd9Sstevel@tonic-gate goto out; 15737c478bd9Sstevel@tonic-gate } 15747c478bd9Sstevel@tonic-gate 15757c478bd9Sstevel@tonic-gate scf_value_set_count(val, contract_id); 15767c478bd9Sstevel@tonic-gate ret = scf_entry_add_value(t_cid, val); 15777c478bd9Sstevel@tonic-gate assert(ret == 0); 15787c478bd9Sstevel@tonic-gate 15797c478bd9Sstevel@tonic-gate ret = scf_transaction_commit(t); 15807c478bd9Sstevel@tonic-gate if (ret == -1) { 15817c478bd9Sstevel@tonic-gate switch (scf_error()) { 15827c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 15837c478bd9Sstevel@tonic-gate default: 15847c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 15857c478bd9Sstevel@tonic-gate goto out; 15867c478bd9Sstevel@tonic-gate 15877c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 15887c478bd9Sstevel@tonic-gate goto add; 15897c478bd9Sstevel@tonic-gate 15907c478bd9Sstevel@tonic-gate case SCF_ERROR_PERMISSION_DENIED: 15917c478bd9Sstevel@tonic-gate ret = EPERM; 15927c478bd9Sstevel@tonic-gate goto out; 15937c478bd9Sstevel@tonic-gate 15947c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_ACCESS: 15957c478bd9Sstevel@tonic-gate ret = EACCES; 15967c478bd9Sstevel@tonic-gate goto out; 15977c478bd9Sstevel@tonic-gate 15987c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_READONLY: 15997c478bd9Sstevel@tonic-gate ret = EROFS; 16007c478bd9Sstevel@tonic-gate goto out; 16017c478bd9Sstevel@tonic-gate 16027c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 16037c478bd9Sstevel@tonic-gate bad_fail("scf_transaction_commit", scf_error()); 16047c478bd9Sstevel@tonic-gate } 16057c478bd9Sstevel@tonic-gate } 16067c478bd9Sstevel@tonic-gate if (ret == 1) { 16077c478bd9Sstevel@tonic-gate ret = 0; 16087c478bd9Sstevel@tonic-gate break; 16097c478bd9Sstevel@tonic-gate } 16107c478bd9Sstevel@tonic-gate 16117c478bd9Sstevel@tonic-gate scf_transaction_destroy_children(t); 16127c478bd9Sstevel@tonic-gate if (scf_pg_update(pg) == -1) { 16137c478bd9Sstevel@tonic-gate switch (scf_error()) { 16147c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 16157c478bd9Sstevel@tonic-gate default: 16167c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 16177c478bd9Sstevel@tonic-gate goto out; 16187c478bd9Sstevel@tonic-gate 16197c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 16207c478bd9Sstevel@tonic-gate goto add; 16217c478bd9Sstevel@tonic-gate 16227c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 16237c478bd9Sstevel@tonic-gate bad_fail("scf_pg_update", scf_error()); 16247c478bd9Sstevel@tonic-gate } 16257c478bd9Sstevel@tonic-gate } 16267c478bd9Sstevel@tonic-gate } 16277c478bd9Sstevel@tonic-gate 16287c478bd9Sstevel@tonic-gate out: 16297c478bd9Sstevel@tonic-gate scf_transaction_destroy_children(t); 16307c478bd9Sstevel@tonic-gate scf_transaction_destroy(t); 16317c478bd9Sstevel@tonic-gate scf_iter_destroy(iter); 16327c478bd9Sstevel@tonic-gate scf_property_destroy(prop); 16337c478bd9Sstevel@tonic-gate scf_pg_destroy(pg); 16347c478bd9Sstevel@tonic-gate 16357c478bd9Sstevel@tonic-gate return (ret); 16367c478bd9Sstevel@tonic-gate } 16377c478bd9Sstevel@tonic-gate 16387c478bd9Sstevel@tonic-gate int 16397c478bd9Sstevel@tonic-gate restarter_rm_libs_loadable() 16407c478bd9Sstevel@tonic-gate { 16417c478bd9Sstevel@tonic-gate void *libhndl; 16427c478bd9Sstevel@tonic-gate 16437c478bd9Sstevel@tonic-gate if (method_context_safety) 16447c478bd9Sstevel@tonic-gate return (1); 16457c478bd9Sstevel@tonic-gate 16467c478bd9Sstevel@tonic-gate if ((libhndl = dlopen("libpool.so", RTLD_LAZY | RTLD_LOCAL)) == NULL) 16477c478bd9Sstevel@tonic-gate return (0); 16487c478bd9Sstevel@tonic-gate 16497c478bd9Sstevel@tonic-gate (void) dlclose(libhndl); 16507c478bd9Sstevel@tonic-gate 16517c478bd9Sstevel@tonic-gate if ((libhndl = dlopen("libproject.so", RTLD_LAZY | RTLD_LOCAL)) == NULL) 16527c478bd9Sstevel@tonic-gate return (0); 16537c478bd9Sstevel@tonic-gate 16547c478bd9Sstevel@tonic-gate (void) dlclose(libhndl); 16557c478bd9Sstevel@tonic-gate 16567c478bd9Sstevel@tonic-gate method_context_safety = 1; 16577c478bd9Sstevel@tonic-gate 16587c478bd9Sstevel@tonic-gate return (1); 16597c478bd9Sstevel@tonic-gate } 16607c478bd9Sstevel@tonic-gate 16617c478bd9Sstevel@tonic-gate static int 16627c478bd9Sstevel@tonic-gate get_astring_val(scf_propertygroup_t *pg, const char *name, char *buf, 16637c478bd9Sstevel@tonic-gate size_t bufsz, scf_property_t *prop, scf_value_t *val) 16647c478bd9Sstevel@tonic-gate { 16657c478bd9Sstevel@tonic-gate ssize_t szret; 16667c478bd9Sstevel@tonic-gate 166713d8aaa1SSean Wilcox if (pg == NULL) 166813d8aaa1SSean Wilcox return (-1); 166913d8aaa1SSean Wilcox 16707c478bd9Sstevel@tonic-gate if (scf_pg_get_property(pg, name, prop) != SCF_SUCCESS) { 16717c478bd9Sstevel@tonic-gate if (scf_error() == SCF_ERROR_CONNECTION_BROKEN) 16727c478bd9Sstevel@tonic-gate uu_die(rcbroken); 16737c478bd9Sstevel@tonic-gate return (-1); 16747c478bd9Sstevel@tonic-gate } 16757c478bd9Sstevel@tonic-gate 16767c478bd9Sstevel@tonic-gate if (scf_property_get_value(prop, val) != SCF_SUCCESS) { 16777c478bd9Sstevel@tonic-gate if (scf_error() == SCF_ERROR_CONNECTION_BROKEN) 16787c478bd9Sstevel@tonic-gate uu_die(rcbroken); 16797c478bd9Sstevel@tonic-gate return (-1); 16807c478bd9Sstevel@tonic-gate } 16817c478bd9Sstevel@tonic-gate 16827c478bd9Sstevel@tonic-gate szret = scf_value_get_astring(val, buf, bufsz); 16837c478bd9Sstevel@tonic-gate 16847c478bd9Sstevel@tonic-gate return (szret >= 0 ? 0 : -1); 16857c478bd9Sstevel@tonic-gate } 16867c478bd9Sstevel@tonic-gate 1687eb1a3463STruong Nguyen static int 1688eb1a3463STruong Nguyen get_boolean_val(scf_propertygroup_t *pg, const char *name, uint8_t *b, 1689eb1a3463STruong Nguyen scf_property_t *prop, scf_value_t *val) 1690eb1a3463STruong Nguyen { 1691eb1a3463STruong Nguyen if (scf_pg_get_property(pg, name, prop) != SCF_SUCCESS) { 1692eb1a3463STruong Nguyen if (scf_error() == SCF_ERROR_CONNECTION_BROKEN) 1693eb1a3463STruong Nguyen uu_die(rcbroken); 1694eb1a3463STruong Nguyen return (-1); 1695eb1a3463STruong Nguyen } 1696eb1a3463STruong Nguyen 1697eb1a3463STruong Nguyen if (scf_property_get_value(prop, val) != SCF_SUCCESS) { 1698eb1a3463STruong Nguyen if (scf_error() == SCF_ERROR_CONNECTION_BROKEN) 1699eb1a3463STruong Nguyen uu_die(rcbroken); 1700eb1a3463STruong Nguyen return (-1); 1701eb1a3463STruong Nguyen } 1702eb1a3463STruong Nguyen 1703eb1a3463STruong Nguyen if (scf_value_get_boolean(val, b)) 1704eb1a3463STruong Nguyen return (-1); 1705eb1a3463STruong Nguyen 1706eb1a3463STruong Nguyen return (0); 1707eb1a3463STruong Nguyen } 1708eb1a3463STruong Nguyen 17097c478bd9Sstevel@tonic-gate /* 17107c478bd9Sstevel@tonic-gate * Try to load mcp->pwd, if it isn't already. 17117c478bd9Sstevel@tonic-gate * Fails with 17127c478bd9Sstevel@tonic-gate * ENOMEM - malloc() failed 17137c478bd9Sstevel@tonic-gate * ENOENT - no entry found 17147c478bd9Sstevel@tonic-gate * EIO - I/O error 17157c478bd9Sstevel@tonic-gate * EMFILE - process out of file descriptors 17167c478bd9Sstevel@tonic-gate * ENFILE - system out of file handles 17177c478bd9Sstevel@tonic-gate */ 17187c478bd9Sstevel@tonic-gate static int 17197c478bd9Sstevel@tonic-gate lookup_pwd(struct method_context *mcp) 17207c478bd9Sstevel@tonic-gate { 17217c478bd9Sstevel@tonic-gate struct passwd *pwdp; 17227c478bd9Sstevel@tonic-gate 17237c478bd9Sstevel@tonic-gate if (mcp->pwbuf != NULL && mcp->pwd.pw_uid == mcp->uid) 17247c478bd9Sstevel@tonic-gate return (0); 17257c478bd9Sstevel@tonic-gate 17267c478bd9Sstevel@tonic-gate if (mcp->pwbuf == NULL) { 17277c478bd9Sstevel@tonic-gate mcp->pwbufsz = sysconf(_SC_GETPW_R_SIZE_MAX); 17287c478bd9Sstevel@tonic-gate assert(mcp->pwbufsz >= 0); 17297c478bd9Sstevel@tonic-gate mcp->pwbuf = malloc(mcp->pwbufsz); 17307c478bd9Sstevel@tonic-gate if (mcp->pwbuf == NULL) 17317c478bd9Sstevel@tonic-gate return (ENOMEM); 17327c478bd9Sstevel@tonic-gate } 17337c478bd9Sstevel@tonic-gate 17347c478bd9Sstevel@tonic-gate do { 17357c478bd9Sstevel@tonic-gate errno = 0; 17367c478bd9Sstevel@tonic-gate pwdp = getpwuid_r(mcp->uid, &mcp->pwd, mcp->pwbuf, 17377c478bd9Sstevel@tonic-gate mcp->pwbufsz); 17387c478bd9Sstevel@tonic-gate } while (pwdp == NULL && errno == EINTR); 17397c478bd9Sstevel@tonic-gate if (pwdp != NULL) 17407c478bd9Sstevel@tonic-gate return (0); 17417c478bd9Sstevel@tonic-gate 17427c478bd9Sstevel@tonic-gate free(mcp->pwbuf); 17437c478bd9Sstevel@tonic-gate mcp->pwbuf = NULL; 17447c478bd9Sstevel@tonic-gate 17457c478bd9Sstevel@tonic-gate switch (errno) { 17467c478bd9Sstevel@tonic-gate case 0: 17477c478bd9Sstevel@tonic-gate default: 17487c478bd9Sstevel@tonic-gate /* 17497c478bd9Sstevel@tonic-gate * Until bug 5065780 is fixed, getpwuid_r() can fail with 17507c478bd9Sstevel@tonic-gate * ENOENT, particularly on the miniroot. Since the 17517c478bd9Sstevel@tonic-gate * documentation is inaccurate, we'll return ENOENT for unknown 17527c478bd9Sstevel@tonic-gate * errors. 17537c478bd9Sstevel@tonic-gate */ 17547c478bd9Sstevel@tonic-gate return (ENOENT); 17557c478bd9Sstevel@tonic-gate 17567c478bd9Sstevel@tonic-gate case EIO: 17577c478bd9Sstevel@tonic-gate case EMFILE: 17587c478bd9Sstevel@tonic-gate case ENFILE: 17597c478bd9Sstevel@tonic-gate return (errno); 17607c478bd9Sstevel@tonic-gate 17617c478bd9Sstevel@tonic-gate case ERANGE: 17627c478bd9Sstevel@tonic-gate bad_fail("getpwuid_r", errno); 17637c478bd9Sstevel@tonic-gate /* NOTREACHED */ 17647c478bd9Sstevel@tonic-gate } 17657c478bd9Sstevel@tonic-gate } 17667c478bd9Sstevel@tonic-gate 17677c478bd9Sstevel@tonic-gate /* 17687c478bd9Sstevel@tonic-gate * Get the user id for str. Returns 0 on success or 17697c478bd9Sstevel@tonic-gate * ERANGE the uid is too big 17707c478bd9Sstevel@tonic-gate * EINVAL the string starts with a digit, but is not a valid uid 17717c478bd9Sstevel@tonic-gate * ENOMEM out of memory 17727c478bd9Sstevel@tonic-gate * ENOENT no passwd entry for str 17737c478bd9Sstevel@tonic-gate * EIO an I/O error has occurred 17747c478bd9Sstevel@tonic-gate * EMFILE/ENFILE out of file descriptors 17757c478bd9Sstevel@tonic-gate */ 17767c478bd9Sstevel@tonic-gate int 17777c478bd9Sstevel@tonic-gate get_uid(const char *str, struct method_context *ci, uid_t *uidp) 17787c478bd9Sstevel@tonic-gate { 17797c478bd9Sstevel@tonic-gate if (isdigit(str[0])) { 17807c478bd9Sstevel@tonic-gate uid_t uid; 17817c478bd9Sstevel@tonic-gate char *cp; 17827c478bd9Sstevel@tonic-gate 17837c478bd9Sstevel@tonic-gate errno = 0; 17847c478bd9Sstevel@tonic-gate uid = strtol(str, &cp, 10); 17857c478bd9Sstevel@tonic-gate 17867c478bd9Sstevel@tonic-gate if (uid == 0 && errno != 0) { 17877c478bd9Sstevel@tonic-gate assert(errno != EINVAL); 17887c478bd9Sstevel@tonic-gate return (errno); 17897c478bd9Sstevel@tonic-gate } 17907c478bd9Sstevel@tonic-gate 17917c478bd9Sstevel@tonic-gate for (; *cp != '\0'; ++cp) 17927c478bd9Sstevel@tonic-gate if (*cp != ' ' || *cp != '\t') 17937c478bd9Sstevel@tonic-gate return (EINVAL); 17947c478bd9Sstevel@tonic-gate 17957c478bd9Sstevel@tonic-gate if (uid > UID_MAX) 17967c478bd9Sstevel@tonic-gate return (EINVAL); 17977c478bd9Sstevel@tonic-gate 17987c478bd9Sstevel@tonic-gate *uidp = uid; 17997c478bd9Sstevel@tonic-gate return (0); 18007c478bd9Sstevel@tonic-gate } else { 18017c478bd9Sstevel@tonic-gate struct passwd *pwdp; 18027c478bd9Sstevel@tonic-gate 18037c478bd9Sstevel@tonic-gate if (ci->pwbuf == NULL) { 18047c478bd9Sstevel@tonic-gate ci->pwbufsz = sysconf(_SC_GETPW_R_SIZE_MAX); 18057c478bd9Sstevel@tonic-gate ci->pwbuf = malloc(ci->pwbufsz); 18067c478bd9Sstevel@tonic-gate if (ci->pwbuf == NULL) 18077c478bd9Sstevel@tonic-gate return (ENOMEM); 18087c478bd9Sstevel@tonic-gate } 18097c478bd9Sstevel@tonic-gate 18107c478bd9Sstevel@tonic-gate do { 18117c478bd9Sstevel@tonic-gate errno = 0; 18127c478bd9Sstevel@tonic-gate pwdp = 18137c478bd9Sstevel@tonic-gate getpwnam_r(str, &ci->pwd, ci->pwbuf, ci->pwbufsz); 18147c478bd9Sstevel@tonic-gate } while (pwdp == NULL && errno == EINTR); 18157c478bd9Sstevel@tonic-gate 18167c478bd9Sstevel@tonic-gate if (pwdp != NULL) { 18177c478bd9Sstevel@tonic-gate *uidp = ci->pwd.pw_uid; 18187c478bd9Sstevel@tonic-gate return (0); 18197c478bd9Sstevel@tonic-gate } else { 18207c478bd9Sstevel@tonic-gate free(ci->pwbuf); 18217c478bd9Sstevel@tonic-gate ci->pwbuf = NULL; 18227c478bd9Sstevel@tonic-gate switch (errno) { 18237c478bd9Sstevel@tonic-gate case 0: 18247c478bd9Sstevel@tonic-gate return (ENOENT); 18257c478bd9Sstevel@tonic-gate 18267c478bd9Sstevel@tonic-gate case ENOENT: 18277c478bd9Sstevel@tonic-gate case EIO: 18287c478bd9Sstevel@tonic-gate case EMFILE: 18297c478bd9Sstevel@tonic-gate case ENFILE: 18307c478bd9Sstevel@tonic-gate return (errno); 18317c478bd9Sstevel@tonic-gate 18327c478bd9Sstevel@tonic-gate case ERANGE: 18337c478bd9Sstevel@tonic-gate default: 18347c478bd9Sstevel@tonic-gate bad_fail("getpwnam_r", errno); 18357c478bd9Sstevel@tonic-gate /* NOTREACHED */ 18367c478bd9Sstevel@tonic-gate } 18377c478bd9Sstevel@tonic-gate } 18387c478bd9Sstevel@tonic-gate } 18397c478bd9Sstevel@tonic-gate } 18407c478bd9Sstevel@tonic-gate 18417c478bd9Sstevel@tonic-gate gid_t 18427c478bd9Sstevel@tonic-gate get_gid(const char *str) 18437c478bd9Sstevel@tonic-gate { 18447c478bd9Sstevel@tonic-gate if (isdigit(str[0])) { 18457c478bd9Sstevel@tonic-gate gid_t gid; 18467c478bd9Sstevel@tonic-gate char *cp; 18477c478bd9Sstevel@tonic-gate 18487c478bd9Sstevel@tonic-gate errno = 0; 18497c478bd9Sstevel@tonic-gate gid = strtol(str, &cp, 10); 18507c478bd9Sstevel@tonic-gate 18517c478bd9Sstevel@tonic-gate if (gid == 0 && errno != 0) 1852f48205beScasper return ((gid_t)-1); 18537c478bd9Sstevel@tonic-gate 18547c478bd9Sstevel@tonic-gate for (; *cp != '\0'; ++cp) 18557c478bd9Sstevel@tonic-gate if (*cp != ' ' || *cp != '\t') 1856f48205beScasper return ((gid_t)-1); 18577c478bd9Sstevel@tonic-gate 18587c478bd9Sstevel@tonic-gate return (gid); 18597c478bd9Sstevel@tonic-gate } else { 18607c478bd9Sstevel@tonic-gate struct group grp, *ret; 18617c478bd9Sstevel@tonic-gate char *buffer; 18627c478bd9Sstevel@tonic-gate size_t buflen; 18637c478bd9Sstevel@tonic-gate 18647c478bd9Sstevel@tonic-gate buflen = sysconf(_SC_GETGR_R_SIZE_MAX); 18657c478bd9Sstevel@tonic-gate buffer = malloc(buflen); 18667c478bd9Sstevel@tonic-gate if (buffer == NULL) 18677c478bd9Sstevel@tonic-gate uu_die(allocfail); 18687c478bd9Sstevel@tonic-gate 18697c478bd9Sstevel@tonic-gate errno = 0; 18707c478bd9Sstevel@tonic-gate ret = getgrnam_r(str, &grp, buffer, buflen); 18717c478bd9Sstevel@tonic-gate free(buffer); 18727c478bd9Sstevel@tonic-gate 1873f48205beScasper return (ret == NULL ? (gid_t)-1 : grp.gr_gid); 18747c478bd9Sstevel@tonic-gate } 18757c478bd9Sstevel@tonic-gate } 18767c478bd9Sstevel@tonic-gate 18777c478bd9Sstevel@tonic-gate /* 18787c478bd9Sstevel@tonic-gate * Fails with 18797c478bd9Sstevel@tonic-gate * ENOMEM - out of memory 18807c478bd9Sstevel@tonic-gate * ENOENT - no passwd entry 18817c478bd9Sstevel@tonic-gate * no project entry 18827c478bd9Sstevel@tonic-gate * EIO - an I/O error occurred 18837c478bd9Sstevel@tonic-gate * EMFILE - the process is out of file descriptors 18847c478bd9Sstevel@tonic-gate * ENFILE - the system is out of file handles 18857c478bd9Sstevel@tonic-gate * ERANGE - the project id is out of range 18867c478bd9Sstevel@tonic-gate * EINVAL - str is invalid 18877c478bd9Sstevel@tonic-gate * E2BIG - the project entry was too big 18887c478bd9Sstevel@tonic-gate * -1 - the name service switch is misconfigured 18897c478bd9Sstevel@tonic-gate */ 18907c478bd9Sstevel@tonic-gate int 18917c478bd9Sstevel@tonic-gate get_projid(const char *str, struct method_context *cip) 18927c478bd9Sstevel@tonic-gate { 18937c478bd9Sstevel@tonic-gate int ret; 18947c478bd9Sstevel@tonic-gate void *buf; 18957c478bd9Sstevel@tonic-gate const size_t bufsz = PROJECT_BUFSZ; 18967c478bd9Sstevel@tonic-gate struct project proj, *pp; 18977c478bd9Sstevel@tonic-gate 18987c478bd9Sstevel@tonic-gate if (strcmp(str, ":default") == 0) { 18997c478bd9Sstevel@tonic-gate if (cip->uid == 0) { 19007c478bd9Sstevel@tonic-gate /* Don't change project for root services */ 19017c478bd9Sstevel@tonic-gate cip->project = NULL; 19027c478bd9Sstevel@tonic-gate return (0); 19037c478bd9Sstevel@tonic-gate } 19047c478bd9Sstevel@tonic-gate 19057c478bd9Sstevel@tonic-gate switch (ret = lookup_pwd(cip)) { 19067c478bd9Sstevel@tonic-gate case 0: 19077c478bd9Sstevel@tonic-gate break; 19087c478bd9Sstevel@tonic-gate 19097c478bd9Sstevel@tonic-gate case ENOMEM: 19107c478bd9Sstevel@tonic-gate case ENOENT: 19117c478bd9Sstevel@tonic-gate case EIO: 19127c478bd9Sstevel@tonic-gate case EMFILE: 19137c478bd9Sstevel@tonic-gate case ENFILE: 19147c478bd9Sstevel@tonic-gate return (ret); 19157c478bd9Sstevel@tonic-gate 19167c478bd9Sstevel@tonic-gate default: 19177c478bd9Sstevel@tonic-gate bad_fail("lookup_pwd", ret); 19187c478bd9Sstevel@tonic-gate } 19197c478bd9Sstevel@tonic-gate 19207c478bd9Sstevel@tonic-gate buf = malloc(bufsz); 19217c478bd9Sstevel@tonic-gate if (buf == NULL) 19227c478bd9Sstevel@tonic-gate return (ENOMEM); 19237c478bd9Sstevel@tonic-gate 19247c478bd9Sstevel@tonic-gate do { 19257c478bd9Sstevel@tonic-gate errno = 0; 19267c478bd9Sstevel@tonic-gate pp = getdefaultproj(cip->pwd.pw_name, &proj, buf, 19277c478bd9Sstevel@tonic-gate bufsz); 19287c478bd9Sstevel@tonic-gate } while (pp == NULL && errno == EINTR); 19297c478bd9Sstevel@tonic-gate 19307c478bd9Sstevel@tonic-gate /* to be continued ... */ 19317c478bd9Sstevel@tonic-gate } else { 19327c478bd9Sstevel@tonic-gate projid_t projid; 19337c478bd9Sstevel@tonic-gate char *cp; 19347c478bd9Sstevel@tonic-gate 19357c478bd9Sstevel@tonic-gate if (!isdigit(str[0])) { 19367c478bd9Sstevel@tonic-gate cip->project = strdup(str); 19377c478bd9Sstevel@tonic-gate return (cip->project != NULL ? 0 : ENOMEM); 19387c478bd9Sstevel@tonic-gate } 19397c478bd9Sstevel@tonic-gate 19407c478bd9Sstevel@tonic-gate errno = 0; 19417c478bd9Sstevel@tonic-gate projid = strtol(str, &cp, 10); 19427c478bd9Sstevel@tonic-gate 19437c478bd9Sstevel@tonic-gate if (projid == 0 && errno != 0) { 19447c478bd9Sstevel@tonic-gate assert(errno == ERANGE); 19457c478bd9Sstevel@tonic-gate return (errno); 19467c478bd9Sstevel@tonic-gate } 19477c478bd9Sstevel@tonic-gate 19487c478bd9Sstevel@tonic-gate for (; *cp != '\0'; ++cp) 19497c478bd9Sstevel@tonic-gate if (*cp != ' ' || *cp != '\t') 19507c478bd9Sstevel@tonic-gate return (EINVAL); 19517c478bd9Sstevel@tonic-gate 19527c478bd9Sstevel@tonic-gate if (projid > MAXPROJID) 19537c478bd9Sstevel@tonic-gate return (ERANGE); 19547c478bd9Sstevel@tonic-gate 19557c478bd9Sstevel@tonic-gate buf = malloc(bufsz); 19567c478bd9Sstevel@tonic-gate if (buf == NULL) 19577c478bd9Sstevel@tonic-gate return (ENOMEM); 19587c478bd9Sstevel@tonic-gate 19597c478bd9Sstevel@tonic-gate do { 19607c478bd9Sstevel@tonic-gate errno = 0; 19617c478bd9Sstevel@tonic-gate pp = getprojbyid(projid, &proj, buf, bufsz); 19627c478bd9Sstevel@tonic-gate } while (pp == NULL && errno == EINTR); 19637c478bd9Sstevel@tonic-gate } 19647c478bd9Sstevel@tonic-gate 19657c478bd9Sstevel@tonic-gate if (pp) { 19667c478bd9Sstevel@tonic-gate cip->project = strdup(pp->pj_name); 19677c478bd9Sstevel@tonic-gate free(buf); 19687c478bd9Sstevel@tonic-gate return (cip->project != NULL ? 0 : ENOMEM); 19697c478bd9Sstevel@tonic-gate } 19707c478bd9Sstevel@tonic-gate 19717c478bd9Sstevel@tonic-gate free(buf); 19727c478bd9Sstevel@tonic-gate 19737c478bd9Sstevel@tonic-gate switch (errno) { 19747c478bd9Sstevel@tonic-gate case 0: 19757c478bd9Sstevel@tonic-gate return (ENOENT); 19767c478bd9Sstevel@tonic-gate 19777c478bd9Sstevel@tonic-gate case EIO: 19787c478bd9Sstevel@tonic-gate case EMFILE: 19797c478bd9Sstevel@tonic-gate case ENFILE: 19807c478bd9Sstevel@tonic-gate return (errno); 19817c478bd9Sstevel@tonic-gate 19827c478bd9Sstevel@tonic-gate case ERANGE: 19837c478bd9Sstevel@tonic-gate return (E2BIG); 19847c478bd9Sstevel@tonic-gate 19857c478bd9Sstevel@tonic-gate default: 19867c478bd9Sstevel@tonic-gate return (-1); 19877c478bd9Sstevel@tonic-gate } 19887c478bd9Sstevel@tonic-gate } 19897c478bd9Sstevel@tonic-gate 19907c478bd9Sstevel@tonic-gate /* 19917c478bd9Sstevel@tonic-gate * Parse the supp_groups property value and populate ci->groups. Returns 19927c478bd9Sstevel@tonic-gate * EINVAL (get_gid() failed for one of the components), E2BIG (the property has 19937c478bd9Sstevel@tonic-gate * more than NGROUPS_MAX-1 groups), or 0 on success. 19947c478bd9Sstevel@tonic-gate */ 19957c478bd9Sstevel@tonic-gate int 19967c478bd9Sstevel@tonic-gate get_groups(char *str, struct method_context *ci) 19977c478bd9Sstevel@tonic-gate { 19987c478bd9Sstevel@tonic-gate char *cp, *end, *next; 19997c478bd9Sstevel@tonic-gate uint_t i; 20007c478bd9Sstevel@tonic-gate 20017c478bd9Sstevel@tonic-gate const char * const whitespace = " \t"; 20027c478bd9Sstevel@tonic-gate const char * const illegal = ", \t"; 20037c478bd9Sstevel@tonic-gate 20047c478bd9Sstevel@tonic-gate if (str[0] == '\0') { 20057c478bd9Sstevel@tonic-gate ci->ngroups = 0; 20067c478bd9Sstevel@tonic-gate return (0); 20077c478bd9Sstevel@tonic-gate } 20087c478bd9Sstevel@tonic-gate 20097c478bd9Sstevel@tonic-gate for (cp = str, i = 0; *cp != '\0'; ) { 20107c478bd9Sstevel@tonic-gate /* skip whitespace */ 20117c478bd9Sstevel@tonic-gate cp += strspn(cp, whitespace); 20127c478bd9Sstevel@tonic-gate 20137c478bd9Sstevel@tonic-gate /* find the end */ 20147c478bd9Sstevel@tonic-gate end = cp + strcspn(cp, illegal); 20157c478bd9Sstevel@tonic-gate 20167c478bd9Sstevel@tonic-gate /* skip whitespace after end */ 20177c478bd9Sstevel@tonic-gate next = end + strspn(end, whitespace); 20187c478bd9Sstevel@tonic-gate 20197c478bd9Sstevel@tonic-gate /* if there's a comma, it separates the fields */ 20207c478bd9Sstevel@tonic-gate if (*next == ',') 20217c478bd9Sstevel@tonic-gate ++next; 20227c478bd9Sstevel@tonic-gate 20237c478bd9Sstevel@tonic-gate *end = '\0'; 20247c478bd9Sstevel@tonic-gate 2025f48205beScasper if ((ci->groups[i] = get_gid(cp)) == (gid_t)-1) { 20267c478bd9Sstevel@tonic-gate ci->ngroups = 0; 20277c478bd9Sstevel@tonic-gate return (EINVAL); 20287c478bd9Sstevel@tonic-gate } 20297c478bd9Sstevel@tonic-gate 20307c478bd9Sstevel@tonic-gate ++i; 20317c478bd9Sstevel@tonic-gate if (i > NGROUPS_MAX - 1) { 20327c478bd9Sstevel@tonic-gate ci->ngroups = 0; 20337c478bd9Sstevel@tonic-gate return (E2BIG); 20347c478bd9Sstevel@tonic-gate } 20357c478bd9Sstevel@tonic-gate 20367c478bd9Sstevel@tonic-gate cp = next; 20377c478bd9Sstevel@tonic-gate } 20387c478bd9Sstevel@tonic-gate 20397c478bd9Sstevel@tonic-gate ci->ngroups = i; 20407c478bd9Sstevel@tonic-gate return (0); 20417c478bd9Sstevel@tonic-gate } 20427c478bd9Sstevel@tonic-gate 2043*870ad75aSSean Wilcox 20447c478bd9Sstevel@tonic-gate /* 2045*870ad75aSSean Wilcox * Return an error message structure containing the error message 2046*870ad75aSSean Wilcox * with context, and the error so the caller can make a decision 2047*870ad75aSSean Wilcox * on what to do next. 2048*870ad75aSSean Wilcox * 2049*870ad75aSSean Wilcox * Because get_ids uses the mc_error_create() function which can 2050*870ad75aSSean Wilcox * reallocate the merr, this function must return the merr pointer 2051*870ad75aSSean Wilcox * in case it was reallocated. 20527c478bd9Sstevel@tonic-gate */ 2053*870ad75aSSean Wilcox static mc_error_t * 205413d8aaa1SSean Wilcox get_profile(scf_propertygroup_t *methpg, scf_propertygroup_t *instpg, 205513d8aaa1SSean Wilcox scf_property_t *prop, scf_value_t *val, const char *cmdline, 2056*870ad75aSSean Wilcox struct method_context *ci, mc_error_t *merr) 20577c478bd9Sstevel@tonic-gate { 20587c478bd9Sstevel@tonic-gate char *buf = ci->vbuf; 20597c478bd9Sstevel@tonic-gate ssize_t buf_sz = ci->vbuf_sz; 20607c478bd9Sstevel@tonic-gate char cmd[PATH_MAX]; 20617c478bd9Sstevel@tonic-gate char *cp, *value; 20627c478bd9Sstevel@tonic-gate const char *cmdp; 20637c478bd9Sstevel@tonic-gate execattr_t *eap; 2064*870ad75aSSean Wilcox mc_error_t *err = merr; 2065*870ad75aSSean Wilcox int r; 20667c478bd9Sstevel@tonic-gate 206713d8aaa1SSean Wilcox if (!(get_astring_val(methpg, SCF_PROPERTY_PROFILE, buf, buf_sz, prop, 206813d8aaa1SSean Wilcox val) == 0 || get_astring_val(instpg, SCF_PROPERTY_PROFILE, buf, 206913d8aaa1SSean Wilcox buf_sz, prop, val) == 0)) 2070*870ad75aSSean Wilcox return (mc_error_create(merr, scf_error(), 2071*870ad75aSSean Wilcox "Method context requires a profile, but the \"%s\" " 2072*870ad75aSSean Wilcox "property could not be read. scf_error is %s", 2073*870ad75aSSean Wilcox SCF_PROPERTY_PROFILE, scf_strerror(scf_error()))); 20747c478bd9Sstevel@tonic-gate 20757c478bd9Sstevel@tonic-gate /* Extract the command from the command line. */ 20767c478bd9Sstevel@tonic-gate cp = strpbrk(cmdline, " \t"); 20777c478bd9Sstevel@tonic-gate 20787c478bd9Sstevel@tonic-gate if (cp == NULL) { 20797c478bd9Sstevel@tonic-gate cmdp = cmdline; 20807c478bd9Sstevel@tonic-gate } else { 20817c478bd9Sstevel@tonic-gate (void) strncpy(cmd, cmdline, cp - cmdline); 20827c478bd9Sstevel@tonic-gate cmd[cp - cmdline] = '\0'; 20837c478bd9Sstevel@tonic-gate cmdp = cmd; 20847c478bd9Sstevel@tonic-gate } 20857c478bd9Sstevel@tonic-gate 20867c478bd9Sstevel@tonic-gate /* Require that cmdp[0] == '/'? */ 20877c478bd9Sstevel@tonic-gate 20887c478bd9Sstevel@tonic-gate eap = getexecprof(buf, KV_COMMAND, cmdp, GET_ONE); 20897c478bd9Sstevel@tonic-gate if (eap == NULL) 2090*870ad75aSSean Wilcox return (mc_error_create(merr, ENOENT, 2091*870ad75aSSean Wilcox "Could not find the execution profile \"%s\", " 2092*870ad75aSSean Wilcox "command %s.", buf, cmdp)); 20937c478bd9Sstevel@tonic-gate 20947c478bd9Sstevel@tonic-gate /* Based on pfexec.c */ 20957c478bd9Sstevel@tonic-gate 20967c478bd9Sstevel@tonic-gate /* Get the euid first so we don't override ci->pwd for the uid. */ 20977c478bd9Sstevel@tonic-gate if ((value = kva_match(eap->attr, EXECATTR_EUID_KW)) != NULL) { 2098*870ad75aSSean Wilcox if ((r = get_uid(value, ci, &ci->euid)) != 0) { 2099f48205beScasper ci->euid = (uid_t)-1; 2100*870ad75aSSean Wilcox err = mc_error_create(merr, r, 2101*870ad75aSSean Wilcox "Could not interpret profile euid value \"%s\", " 2102*870ad75aSSean Wilcox "from the execution profile \"%s\", error %d.", 2103*870ad75aSSean Wilcox value, buf, r); 21047c478bd9Sstevel@tonic-gate goto out; 21057c478bd9Sstevel@tonic-gate } 21067c478bd9Sstevel@tonic-gate } 21077c478bd9Sstevel@tonic-gate 21087c478bd9Sstevel@tonic-gate if ((value = kva_match(eap->attr, EXECATTR_UID_KW)) != NULL) { 2109*870ad75aSSean Wilcox if ((r = get_uid(value, ci, &ci->uid)) != 0) { 2110f48205beScasper ci->euid = ci->uid = (uid_t)-1; 2111*870ad75aSSean Wilcox err = mc_error_create(merr, r, 2112*870ad75aSSean Wilcox "Could not interpret profile uid value \"%s\", " 2113*870ad75aSSean Wilcox "from the execution profile \"%s\", error %d.", 2114*870ad75aSSean Wilcox value, buf, r); 21157c478bd9Sstevel@tonic-gate goto out; 21167c478bd9Sstevel@tonic-gate } 21177c478bd9Sstevel@tonic-gate ci->euid = ci->uid; 21187c478bd9Sstevel@tonic-gate } 21197c478bd9Sstevel@tonic-gate 21207c478bd9Sstevel@tonic-gate if ((value = kva_match(eap->attr, EXECATTR_GID_KW)) != NULL) { 21217c478bd9Sstevel@tonic-gate ci->egid = ci->gid = get_gid(value); 2122f48205beScasper if (ci->gid == (gid_t)-1) { 2123*870ad75aSSean Wilcox err = mc_error_create(merr, EINVAL, 2124*870ad75aSSean Wilcox "Could not interpret profile gid value \"%s\", " 2125*870ad75aSSean Wilcox "from the execution profile \"%s\".", value, buf); 21267c478bd9Sstevel@tonic-gate goto out; 21277c478bd9Sstevel@tonic-gate } 21287c478bd9Sstevel@tonic-gate } 21297c478bd9Sstevel@tonic-gate 21307c478bd9Sstevel@tonic-gate if ((value = kva_match(eap->attr, EXECATTR_EGID_KW)) != NULL) { 21317c478bd9Sstevel@tonic-gate ci->egid = get_gid(value); 2132f48205beScasper if (ci->egid == (gid_t)-1) { 2133*870ad75aSSean Wilcox err = mc_error_create(merr, EINVAL, 2134*870ad75aSSean Wilcox "Could not interpret profile egid value \"%s\", " 2135*870ad75aSSean Wilcox "from the execution profile \"%s\".", value, buf); 21367c478bd9Sstevel@tonic-gate goto out; 21377c478bd9Sstevel@tonic-gate } 21387c478bd9Sstevel@tonic-gate } 21397c478bd9Sstevel@tonic-gate 21407c478bd9Sstevel@tonic-gate if ((value = kva_match(eap->attr, EXECATTR_LPRIV_KW)) != NULL) { 21417c478bd9Sstevel@tonic-gate ci->lpriv_set = priv_str_to_set(value, ",", NULL); 21427c478bd9Sstevel@tonic-gate if (ci->lpriv_set == NULL) { 21437c478bd9Sstevel@tonic-gate if (errno != EINVAL) 2144*870ad75aSSean Wilcox err = mc_error_create(merr, ENOMEM, 2145*870ad75aSSean Wilcox ALLOCFAIL); 21467c478bd9Sstevel@tonic-gate else 2147*870ad75aSSean Wilcox err = mc_error_create(merr, EINVAL, 2148*870ad75aSSean Wilcox "Could not interpret profile " 2149*870ad75aSSean Wilcox "limitprivs value \"%s\", from " 2150*870ad75aSSean Wilcox "the execution profile \"%s\".", 2151*870ad75aSSean Wilcox value, buf); 21527c478bd9Sstevel@tonic-gate goto out; 21537c478bd9Sstevel@tonic-gate } 21547c478bd9Sstevel@tonic-gate } 21557c478bd9Sstevel@tonic-gate 21567c478bd9Sstevel@tonic-gate if ((value = kva_match(eap->attr, EXECATTR_IPRIV_KW)) != NULL) { 21577c478bd9Sstevel@tonic-gate ci->priv_set = priv_str_to_set(value, ",", NULL); 21587c478bd9Sstevel@tonic-gate if (ci->priv_set == NULL) { 21597c478bd9Sstevel@tonic-gate if (errno != EINVAL) 2160*870ad75aSSean Wilcox err = mc_error_create(merr, ENOMEM, 2161*870ad75aSSean Wilcox ALLOCFAIL); 21627c478bd9Sstevel@tonic-gate else 2163*870ad75aSSean Wilcox err = mc_error_create(merr, EINVAL, 2164*870ad75aSSean Wilcox "Could not interpret profile privs value " 2165*870ad75aSSean Wilcox "\"%s\", from the execution profile " 2166*870ad75aSSean Wilcox "\"%s\".", value, buf); 21677c478bd9Sstevel@tonic-gate goto out; 21687c478bd9Sstevel@tonic-gate } 21697c478bd9Sstevel@tonic-gate } 21707c478bd9Sstevel@tonic-gate 21717c478bd9Sstevel@tonic-gate out: 21727c478bd9Sstevel@tonic-gate free_execattr(eap); 21737c478bd9Sstevel@tonic-gate 2174*870ad75aSSean Wilcox return (err); 21757c478bd9Sstevel@tonic-gate } 21767c478bd9Sstevel@tonic-gate 21777c478bd9Sstevel@tonic-gate /* 2178*870ad75aSSean Wilcox * Return an error message structure containing the error message 2179*870ad75aSSean Wilcox * with context, and the error so the caller can make a decision 2180*870ad75aSSean Wilcox * on what to do next. 2181*870ad75aSSean Wilcox * 2182*870ad75aSSean Wilcox * Because get_ids uses the mc_error_create() function which can 2183*870ad75aSSean Wilcox * reallocate the merr, this function must return the merr pointer 2184*870ad75aSSean Wilcox * in case it was reallocated. 21857c478bd9Sstevel@tonic-gate */ 2186*870ad75aSSean Wilcox static mc_error_t * 218713d8aaa1SSean Wilcox get_ids(scf_propertygroup_t *methpg, scf_propertygroup_t *instpg, 2188*870ad75aSSean Wilcox scf_property_t *prop, scf_value_t *val, struct method_context *ci, 2189*870ad75aSSean Wilcox mc_error_t *merr) 21907c478bd9Sstevel@tonic-gate { 21917c478bd9Sstevel@tonic-gate char *vbuf = ci->vbuf; 21927c478bd9Sstevel@tonic-gate ssize_t vbuf_sz = ci->vbuf_sz; 21937c478bd9Sstevel@tonic-gate int r; 21947c478bd9Sstevel@tonic-gate 219513d8aaa1SSean Wilcox /* 219613d8aaa1SSean Wilcox * This should never happen because the caller should fall through 219713d8aaa1SSean Wilcox * another path of just setting the ids to defaults, instead of 219813d8aaa1SSean Wilcox * attempting to get the ids here. 219913d8aaa1SSean Wilcox */ 2200*870ad75aSSean Wilcox if (methpg == NULL && instpg == NULL) 2201*870ad75aSSean Wilcox return (mc_error_create(merr, ENOENT, 2202*870ad75aSSean Wilcox "No property groups to get ids from.")); 220313d8aaa1SSean Wilcox 220413d8aaa1SSean Wilcox if (!(get_astring_val(methpg, SCF_PROPERTY_USER, 220513d8aaa1SSean Wilcox vbuf, vbuf_sz, prop, val) == 0 || get_astring_val(instpg, 220613d8aaa1SSean Wilcox SCF_PROPERTY_USER, vbuf, vbuf_sz, prop, 2207*870ad75aSSean Wilcox val) == 0)) 2208*870ad75aSSean Wilcox return (mc_error_create(merr, ENOENT, 2209*870ad75aSSean Wilcox "Could not get \"%s\" property.", SCF_PROPERTY_USER)); 22107c478bd9Sstevel@tonic-gate 2211*870ad75aSSean Wilcox if ((r = get_uid(vbuf, ci, &ci->uid)) != 0) { 2212f48205beScasper ci->uid = (uid_t)-1; 2213*870ad75aSSean Wilcox return (mc_error_create(merr, r, 2214*870ad75aSSean Wilcox "Could not interpret \"%s\" property value \"%s\", " 2215*870ad75aSSean Wilcox "error %d.", SCF_PROPERTY_USER, vbuf, r)); 22167c478bd9Sstevel@tonic-gate } 22177c478bd9Sstevel@tonic-gate 221813d8aaa1SSean Wilcox if (!(get_astring_val(methpg, SCF_PROPERTY_GROUP, vbuf, vbuf_sz, prop, 221913d8aaa1SSean Wilcox val) == 0 || get_astring_val(instpg, SCF_PROPERTY_GROUP, vbuf, 222013d8aaa1SSean Wilcox vbuf_sz, prop, val) == 0)) { 222113d8aaa1SSean Wilcox if (scf_error() == SCF_ERROR_NOT_FOUND) { 222213d8aaa1SSean Wilcox (void) strcpy(vbuf, ":default"); 222313d8aaa1SSean Wilcox } else { 2224*870ad75aSSean Wilcox return (mc_error_create(merr, ENOENT, 2225*870ad75aSSean Wilcox "Could not get \"%s\" property.", 2226*870ad75aSSean Wilcox SCF_PROPERTY_GROUP)); 22277c478bd9Sstevel@tonic-gate } 222813d8aaa1SSean Wilcox } 22297c478bd9Sstevel@tonic-gate 22307c478bd9Sstevel@tonic-gate if (strcmp(vbuf, ":default") != 0) { 22317c478bd9Sstevel@tonic-gate ci->gid = get_gid(vbuf); 2232f48205beScasper if (ci->gid == (gid_t)-1) { 2233*870ad75aSSean Wilcox return (mc_error_create(merr, ENOENT, 2234*870ad75aSSean Wilcox "Could not interpret \"%s\" property value \"%s\".", 2235*870ad75aSSean Wilcox SCF_PROPERTY_GROUP, vbuf)); 22367c478bd9Sstevel@tonic-gate } 22377c478bd9Sstevel@tonic-gate } else { 22387c478bd9Sstevel@tonic-gate switch (r = lookup_pwd(ci)) { 22397c478bd9Sstevel@tonic-gate case 0: 22407c478bd9Sstevel@tonic-gate ci->gid = ci->pwd.pw_gid; 22417c478bd9Sstevel@tonic-gate break; 22427c478bd9Sstevel@tonic-gate 22437c478bd9Sstevel@tonic-gate case ENOENT: 2244f48205beScasper ci->gid = (gid_t)-1; 2245*870ad75aSSean Wilcox return (mc_error_create(merr, ENOENT, 2246*870ad75aSSean Wilcox "No passwd entry for uid \"%d\".", ci->uid)); 22477c478bd9Sstevel@tonic-gate 22487c478bd9Sstevel@tonic-gate case ENOMEM: 2249*870ad75aSSean Wilcox return (mc_error_create(merr, ENOMEM, 2250*870ad75aSSean Wilcox "Out of memory.")); 22517c478bd9Sstevel@tonic-gate 22527c478bd9Sstevel@tonic-gate case EIO: 22537c478bd9Sstevel@tonic-gate case EMFILE: 22547c478bd9Sstevel@tonic-gate case ENFILE: 2255*870ad75aSSean Wilcox return (mc_error_create(merr, ENFILE, 2256*870ad75aSSean Wilcox "getpwuid_r() failed, error %d.", r)); 22577c478bd9Sstevel@tonic-gate 22587c478bd9Sstevel@tonic-gate default: 22597c478bd9Sstevel@tonic-gate bad_fail("lookup_pwd", r); 22607c478bd9Sstevel@tonic-gate } 22617c478bd9Sstevel@tonic-gate } 22627c478bd9Sstevel@tonic-gate 226313d8aaa1SSean Wilcox if (!(get_astring_val(methpg, SCF_PROPERTY_SUPP_GROUPS, vbuf, vbuf_sz, 226413d8aaa1SSean Wilcox prop, val) == 0 || get_astring_val(instpg, 226513d8aaa1SSean Wilcox SCF_PROPERTY_SUPP_GROUPS, vbuf, vbuf_sz, prop, val) == 0)) { 226613d8aaa1SSean Wilcox if (scf_error() == SCF_ERROR_NOT_FOUND) { 226713d8aaa1SSean Wilcox (void) strcpy(vbuf, ":default"); 226813d8aaa1SSean Wilcox } else { 2269*870ad75aSSean Wilcox return (mc_error_create(merr, ENOENT, 2270*870ad75aSSean Wilcox "Could not get supplemental groups (\"%s\") " 2271*870ad75aSSean Wilcox "property.", SCF_PROPERTY_SUPP_GROUPS)); 22727c478bd9Sstevel@tonic-gate } 227313d8aaa1SSean Wilcox } 22747c478bd9Sstevel@tonic-gate 22757c478bd9Sstevel@tonic-gate if (strcmp(vbuf, ":default") != 0) { 22767c478bd9Sstevel@tonic-gate switch (r = get_groups(vbuf, ci)) { 22777c478bd9Sstevel@tonic-gate case 0: 22787c478bd9Sstevel@tonic-gate break; 22797c478bd9Sstevel@tonic-gate 22807c478bd9Sstevel@tonic-gate case EINVAL: 2281*870ad75aSSean Wilcox return (mc_error_create(merr, EINVAL, 2282*870ad75aSSean Wilcox "Could not interpret supplemental groups (\"%s\") " 2283*870ad75aSSean Wilcox "property value \"%s\".", SCF_PROPERTY_SUPP_GROUPS, 2284*870ad75aSSean Wilcox vbuf)); 22857c478bd9Sstevel@tonic-gate 22867c478bd9Sstevel@tonic-gate case E2BIG: 2287*870ad75aSSean Wilcox return (mc_error_create(merr, E2BIG, 2288*870ad75aSSean Wilcox "Too many supplemental groups values in \"%s\".", 2289*870ad75aSSean Wilcox vbuf)); 22907c478bd9Sstevel@tonic-gate 22917c478bd9Sstevel@tonic-gate default: 22927c478bd9Sstevel@tonic-gate bad_fail("get_groups", r); 22937c478bd9Sstevel@tonic-gate } 22947c478bd9Sstevel@tonic-gate } else { 22957c478bd9Sstevel@tonic-gate ci->ngroups = -1; 22967c478bd9Sstevel@tonic-gate } 22977c478bd9Sstevel@tonic-gate 229813d8aaa1SSean Wilcox if (!(get_astring_val(methpg, SCF_PROPERTY_PRIVILEGES, vbuf, vbuf_sz, 229913d8aaa1SSean Wilcox prop, val) == 0 || get_astring_val(instpg, SCF_PROPERTY_PRIVILEGES, 230013d8aaa1SSean Wilcox vbuf, vbuf_sz, prop, val) == 0)) { 230113d8aaa1SSean Wilcox if (scf_error() == SCF_ERROR_NOT_FOUND) { 230213d8aaa1SSean Wilcox (void) strcpy(vbuf, ":default"); 230313d8aaa1SSean Wilcox } else { 2304*870ad75aSSean Wilcox return (mc_error_create(merr, ENOENT, 2305*870ad75aSSean Wilcox "Could not get \"%s\" property.", 2306*870ad75aSSean Wilcox SCF_PROPERTY_PRIVILEGES)); 23077c478bd9Sstevel@tonic-gate } 230813d8aaa1SSean Wilcox } 23097c478bd9Sstevel@tonic-gate 23107c478bd9Sstevel@tonic-gate /* 23117c478bd9Sstevel@tonic-gate * For default privs, we need to keep priv_set == NULL, as 23127c478bd9Sstevel@tonic-gate * we use this test elsewhere. 23137c478bd9Sstevel@tonic-gate */ 23147c478bd9Sstevel@tonic-gate if (strcmp(vbuf, ":default") != 0) { 23157c478bd9Sstevel@tonic-gate ci->priv_set = priv_str_to_set(vbuf, ",", NULL); 23167c478bd9Sstevel@tonic-gate if (ci->priv_set == NULL) { 23177c478bd9Sstevel@tonic-gate if (errno != EINVAL) { 2318*870ad75aSSean Wilcox return (mc_error_create(merr, ENOMEM, 2319*870ad75aSSean Wilcox ALLOCFAIL)); 23207c478bd9Sstevel@tonic-gate } else { 2321*870ad75aSSean Wilcox return (mc_error_create(merr, EINVAL, 2322*870ad75aSSean Wilcox "Could not interpret \"%s\" " 2323*870ad75aSSean Wilcox "property value \"%s\".", 2324*870ad75aSSean Wilcox SCF_PROPERTY_PRIVILEGES, vbuf)); 23257c478bd9Sstevel@tonic-gate } 23267c478bd9Sstevel@tonic-gate } 23277c478bd9Sstevel@tonic-gate } 23287c478bd9Sstevel@tonic-gate 232913d8aaa1SSean Wilcox if (!(get_astring_val(methpg, SCF_PROPERTY_LIMIT_PRIVILEGES, vbuf, 233013d8aaa1SSean Wilcox vbuf_sz, prop, val) == 0 || get_astring_val(instpg, 233113d8aaa1SSean Wilcox SCF_PROPERTY_LIMIT_PRIVILEGES, vbuf, vbuf_sz, prop, val) == 0)) { 233213d8aaa1SSean Wilcox if (scf_error() == SCF_ERROR_NOT_FOUND) { 233313d8aaa1SSean Wilcox (void) strcpy(vbuf, ":default"); 233413d8aaa1SSean Wilcox } else { 2335*870ad75aSSean Wilcox return (mc_error_create(merr, ENOENT, 2336*870ad75aSSean Wilcox "Could not get \"%s\" property.", 2337*870ad75aSSean Wilcox SCF_PROPERTY_LIMIT_PRIVILEGES)); 23387c478bd9Sstevel@tonic-gate } 233913d8aaa1SSean Wilcox } 23407c478bd9Sstevel@tonic-gate 23417c478bd9Sstevel@tonic-gate if (strcmp(vbuf, ":default") == 0) 23427c478bd9Sstevel@tonic-gate /* 23437c478bd9Sstevel@tonic-gate * L must default to all privileges so root NPA services see 23447c478bd9Sstevel@tonic-gate * iE = all. "zone" is all privileges available in the current 23457c478bd9Sstevel@tonic-gate * zone, equivalent to "all" in the global zone. 23467c478bd9Sstevel@tonic-gate */ 23477c478bd9Sstevel@tonic-gate (void) strcpy(vbuf, "zone"); 23487c478bd9Sstevel@tonic-gate 23497c478bd9Sstevel@tonic-gate ci->lpriv_set = priv_str_to_set(vbuf, ",", NULL); 23507c478bd9Sstevel@tonic-gate if (ci->lpriv_set == NULL) { 2351*870ad75aSSean Wilcox if (errno != EINVAL) { 2352*870ad75aSSean Wilcox return (mc_error_create(merr, ENOMEM, ALLOCFAIL)); 2353*870ad75aSSean Wilcox } else { 2354*870ad75aSSean Wilcox return (mc_error_create(merr, EINVAL, 2355*870ad75aSSean Wilcox "Could not interpret \"%s\" property value \"%s\".", 2356*870ad75aSSean Wilcox SCF_PROPERTY_LIMIT_PRIVILEGES, vbuf)); 23577c478bd9Sstevel@tonic-gate } 23587c478bd9Sstevel@tonic-gate } 23597c478bd9Sstevel@tonic-gate 2360*870ad75aSSean Wilcox return (merr); 23617c478bd9Sstevel@tonic-gate } 23627c478bd9Sstevel@tonic-gate 23637c478bd9Sstevel@tonic-gate static int 23647c478bd9Sstevel@tonic-gate get_environment(scf_handle_t *h, scf_propertygroup_t *pg, 23657c478bd9Sstevel@tonic-gate struct method_context *mcp, scf_property_t *prop, scf_value_t *val) 23667c478bd9Sstevel@tonic-gate { 23677c478bd9Sstevel@tonic-gate scf_iter_t *iter; 23687c478bd9Sstevel@tonic-gate scf_type_t type; 23697c478bd9Sstevel@tonic-gate size_t i = 0; 23707c478bd9Sstevel@tonic-gate int ret; 23717c478bd9Sstevel@tonic-gate 23727c478bd9Sstevel@tonic-gate if (scf_pg_get_property(pg, SCF_PROPERTY_ENVIRONMENT, prop) != 0) { 23737c478bd9Sstevel@tonic-gate if (scf_error() == SCF_ERROR_NOT_FOUND) 23747c478bd9Sstevel@tonic-gate return (ENOENT); 23757c478bd9Sstevel@tonic-gate return (scf_error()); 23767c478bd9Sstevel@tonic-gate } 23777c478bd9Sstevel@tonic-gate if (scf_property_type(prop, &type) != 0) 23787c478bd9Sstevel@tonic-gate return (scf_error()); 23797c478bd9Sstevel@tonic-gate if (type != SCF_TYPE_ASTRING) 23807c478bd9Sstevel@tonic-gate return (EINVAL); 23817c478bd9Sstevel@tonic-gate if ((iter = scf_iter_create(h)) == NULL) 23827c478bd9Sstevel@tonic-gate return (scf_error()); 23837c478bd9Sstevel@tonic-gate 23847c478bd9Sstevel@tonic-gate if (scf_iter_property_values(iter, prop) != 0) { 23857c478bd9Sstevel@tonic-gate ret = scf_error(); 23867c478bd9Sstevel@tonic-gate scf_iter_destroy(iter); 23877c478bd9Sstevel@tonic-gate return (ret); 23887c478bd9Sstevel@tonic-gate } 23897c478bd9Sstevel@tonic-gate 23907c478bd9Sstevel@tonic-gate mcp->env_sz = 10; 23917c478bd9Sstevel@tonic-gate 23927c478bd9Sstevel@tonic-gate if ((mcp->env = uu_zalloc(sizeof (*mcp->env) * mcp->env_sz)) == NULL) { 23937c478bd9Sstevel@tonic-gate ret = ENOMEM; 23947c478bd9Sstevel@tonic-gate goto out; 23957c478bd9Sstevel@tonic-gate } 23967c478bd9Sstevel@tonic-gate 23977c478bd9Sstevel@tonic-gate while ((ret = scf_iter_next_value(iter, val)) == 1) { 23987c478bd9Sstevel@tonic-gate ret = scf_value_get_as_string(val, mcp->vbuf, mcp->vbuf_sz); 23997c478bd9Sstevel@tonic-gate if (ret == -1) { 24007c478bd9Sstevel@tonic-gate ret = scf_error(); 24017c478bd9Sstevel@tonic-gate goto out; 24027c478bd9Sstevel@tonic-gate } 24037c478bd9Sstevel@tonic-gate 24047c478bd9Sstevel@tonic-gate if ((mcp->env[i] = strdup(mcp->vbuf)) == NULL) { 24057c478bd9Sstevel@tonic-gate ret = ENOMEM; 24067c478bd9Sstevel@tonic-gate goto out; 24077c478bd9Sstevel@tonic-gate } 24087c478bd9Sstevel@tonic-gate 24097c478bd9Sstevel@tonic-gate if (++i == mcp->env_sz) { 24107c478bd9Sstevel@tonic-gate char **env; 24117c478bd9Sstevel@tonic-gate mcp->env_sz *= 2; 24127c478bd9Sstevel@tonic-gate env = uu_zalloc(sizeof (*mcp->env) * mcp->env_sz); 24137c478bd9Sstevel@tonic-gate if (env == NULL) { 24147c478bd9Sstevel@tonic-gate ret = ENOMEM; 24157c478bd9Sstevel@tonic-gate goto out; 24167c478bd9Sstevel@tonic-gate } 24177c478bd9Sstevel@tonic-gate (void) memcpy(env, mcp->env, 24187c478bd9Sstevel@tonic-gate sizeof (*mcp->env) * (mcp->env_sz / 2)); 24197c478bd9Sstevel@tonic-gate free(mcp->env); 24207c478bd9Sstevel@tonic-gate mcp->env = env; 24217c478bd9Sstevel@tonic-gate } 24227c478bd9Sstevel@tonic-gate } 24237c478bd9Sstevel@tonic-gate 24247c478bd9Sstevel@tonic-gate if (ret == -1) 24257c478bd9Sstevel@tonic-gate ret = scf_error(); 24267c478bd9Sstevel@tonic-gate 24277c478bd9Sstevel@tonic-gate out: 24287c478bd9Sstevel@tonic-gate scf_iter_destroy(iter); 24297c478bd9Sstevel@tonic-gate return (ret); 24307c478bd9Sstevel@tonic-gate } 24317c478bd9Sstevel@tonic-gate 24327c478bd9Sstevel@tonic-gate /* 24337c478bd9Sstevel@tonic-gate * Fetch method context information from the repository, allocate and fill 2434*870ad75aSSean Wilcox * a method_context structure, return it in *mcpp, and return NULL. 24357c478bd9Sstevel@tonic-gate * 243613d8aaa1SSean Wilcox * If no method_context is defined, original init context is provided, where 243713d8aaa1SSean Wilcox * the working directory is '/', and uid/gid are 0/0. But if a method_context 243813d8aaa1SSean Wilcox * is defined at any level the smf_method(5) method_context defaults are used. 243913d8aaa1SSean Wilcox * 2440*870ad75aSSean Wilcox * Return an error message structure containing the error message 2441*870ad75aSSean Wilcox * with context, and the error so the caller can make a decision 2442*870ad75aSSean Wilcox * on what to do next. 2443*870ad75aSSean Wilcox * 2444*870ad75aSSean Wilcox * Error Types : 2445*870ad75aSSean Wilcox * E2BIG Too many values or entry is too big 2446*870ad75aSSean Wilcox * EINVAL Invalid value 2447*870ad75aSSean Wilcox * EIO an I/O error has occured 2448*870ad75aSSean Wilcox * ENOENT no entry for value 2449*870ad75aSSean Wilcox * ENOMEM out of memory 2450*870ad75aSSean Wilcox * ENOTSUP Version mismatch 2451*870ad75aSSean Wilcox * ERANGE value is out of range 2452*870ad75aSSean Wilcox * EMFILE/ENFILE out of file descriptors 2453*870ad75aSSean Wilcox * 2454*870ad75aSSean Wilcox * SCF_ERROR_BACKEND_ACCESS 2455*870ad75aSSean Wilcox * SCF_ERROR_CONNECTION_BROKEN 2456*870ad75aSSean Wilcox * SCF_ERROR_DELETED 2457*870ad75aSSean Wilcox * SCF_ERROR_CONSTRAINT_VIOLATED 2458*870ad75aSSean Wilcox * SCF_ERROR_HANDLE_DESTROYED 2459*870ad75aSSean Wilcox * SCF_ERROR_INTERNAL 2460*870ad75aSSean Wilcox * SCF_ERROR_INVALID_ARGUMENT 2461*870ad75aSSean Wilcox * SCF_ERROR_NO_MEMORY 2462*870ad75aSSean Wilcox * SCF_ERROR_NO_RESOURCES 2463*870ad75aSSean Wilcox * SCF_ERROR_NOT_BOUND 2464*870ad75aSSean Wilcox * SCF_ERROR_NOT_FOUND 2465*870ad75aSSean Wilcox * SCF_ERROR_NOT_SET 2466*870ad75aSSean Wilcox * SCF_ERROR_TYPE_MISMATCH 2467*870ad75aSSean Wilcox * 24687c478bd9Sstevel@tonic-gate */ 2469*870ad75aSSean Wilcox mc_error_t * 24707c478bd9Sstevel@tonic-gate restarter_get_method_context(uint_t version, scf_instance_t *inst, 24717c478bd9Sstevel@tonic-gate scf_snapshot_t *snap, const char *mname, const char *cmdline, 24727c478bd9Sstevel@tonic-gate struct method_context **mcpp) 24737c478bd9Sstevel@tonic-gate { 24747c478bd9Sstevel@tonic-gate scf_handle_t *h; 24757c478bd9Sstevel@tonic-gate scf_propertygroup_t *methpg = NULL; 24767c478bd9Sstevel@tonic-gate scf_propertygroup_t *instpg = NULL; 24777c478bd9Sstevel@tonic-gate scf_propertygroup_t *pg = NULL; 24787c478bd9Sstevel@tonic-gate scf_property_t *prop = NULL; 24797c478bd9Sstevel@tonic-gate scf_value_t *val = NULL; 24807c478bd9Sstevel@tonic-gate scf_type_t ty; 24817c478bd9Sstevel@tonic-gate uint8_t use_profile; 2482*870ad75aSSean Wilcox int ret = 0; 248313d8aaa1SSean Wilcox int mc_used = 0; 2484*870ad75aSSean Wilcox mc_error_t *err = NULL; 24857c478bd9Sstevel@tonic-gate struct method_context *cip; 24867c478bd9Sstevel@tonic-gate 2487*870ad75aSSean Wilcox if ((err = malloc(sizeof (mc_error_t))) == NULL) 2488*870ad75aSSean Wilcox return (mc_error_create(NULL, ENOMEM, NULL)); 2489*870ad75aSSean Wilcox 2490*870ad75aSSean Wilcox /* Set the type to zero to track if an error occured. */ 2491*870ad75aSSean Wilcox err->type = 0; 2492*870ad75aSSean Wilcox 24937c478bd9Sstevel@tonic-gate if (version != RESTARTER_METHOD_CONTEXT_VERSION) 2494*870ad75aSSean Wilcox return (mc_error_create(err, ENOTSUP, 2495*870ad75aSSean Wilcox "Invalid client version %d. (Expected %d)", 2496*870ad75aSSean Wilcox version, RESTARTER_METHOD_CONTEXT_VERSION)); 24977c478bd9Sstevel@tonic-gate 24987c478bd9Sstevel@tonic-gate /* Get the handle before we allocate anything. */ 24997c478bd9Sstevel@tonic-gate h = scf_instance_handle(inst); 25007c478bd9Sstevel@tonic-gate if (h == NULL) 2501*870ad75aSSean Wilcox return (mc_error_create(err, scf_error(), 2502*870ad75aSSean Wilcox scf_strerror(scf_error()))); 25037c478bd9Sstevel@tonic-gate 25047c478bd9Sstevel@tonic-gate cip = malloc(sizeof (*cip)); 25057c478bd9Sstevel@tonic-gate if (cip == NULL) 2506*870ad75aSSean Wilcox return (mc_error_create(err, ENOMEM, ALLOCFAIL)); 25077c478bd9Sstevel@tonic-gate 25087c478bd9Sstevel@tonic-gate (void) memset(cip, 0, sizeof (*cip)); 2509f48205beScasper cip->uid = (uid_t)-1; 2510f48205beScasper cip->euid = (uid_t)-1; 2511f48205beScasper cip->gid = (gid_t)-1; 2512f48205beScasper cip->egid = (gid_t)-1; 25137c478bd9Sstevel@tonic-gate 25147c478bd9Sstevel@tonic-gate cip->vbuf_sz = scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH); 25157c478bd9Sstevel@tonic-gate assert(cip->vbuf_sz >= 0); 25167c478bd9Sstevel@tonic-gate cip->vbuf = malloc(cip->vbuf_sz); 25177c478bd9Sstevel@tonic-gate if (cip->vbuf == NULL) { 25187c478bd9Sstevel@tonic-gate free(cip); 2519*870ad75aSSean Wilcox return (mc_error_create(err, ENOMEM, ALLOCFAIL)); 25207c478bd9Sstevel@tonic-gate } 25217c478bd9Sstevel@tonic-gate 25227c478bd9Sstevel@tonic-gate if ((instpg = scf_pg_create(h)) == NULL || 25237c478bd9Sstevel@tonic-gate (methpg = scf_pg_create(h)) == NULL || 25247c478bd9Sstevel@tonic-gate (prop = scf_property_create(h)) == NULL || 25257c478bd9Sstevel@tonic-gate (val = scf_value_create(h)) == NULL) { 2526*870ad75aSSean Wilcox err = mc_error_create(err, scf_error(), 2527*870ad75aSSean Wilcox "Failed to create repository object: %s\n", 2528*870ad75aSSean Wilcox scf_strerror(scf_error())); 25297c478bd9Sstevel@tonic-gate goto out; 25307c478bd9Sstevel@tonic-gate } 25317c478bd9Sstevel@tonic-gate 25327c478bd9Sstevel@tonic-gate /* 25337c478bd9Sstevel@tonic-gate * The method environment, and the credentials/profile data, 25347c478bd9Sstevel@tonic-gate * may be found either in the pg for the method (methpg), 25357c478bd9Sstevel@tonic-gate * or in the instance/service SCF_PG_METHOD_CONTEXT pg (named 25367c478bd9Sstevel@tonic-gate * instpg below). 25377c478bd9Sstevel@tonic-gate */ 25387c478bd9Sstevel@tonic-gate 25397c478bd9Sstevel@tonic-gate if (scf_instance_get_pg_composed(inst, snap, mname, methpg) != 25407c478bd9Sstevel@tonic-gate SCF_SUCCESS) { 2541*870ad75aSSean Wilcox err = mc_error_create(err, scf_error(), "Unable to get the " 2542*870ad75aSSean Wilcox "\"%s\" method, %s", mname, scf_strerror(scf_error())); 25437c478bd9Sstevel@tonic-gate goto out; 25447c478bd9Sstevel@tonic-gate } 25457c478bd9Sstevel@tonic-gate 25467c478bd9Sstevel@tonic-gate if (scf_instance_get_pg_composed(inst, snap, SCF_PG_METHOD_CONTEXT, 25477c478bd9Sstevel@tonic-gate instpg) != SCF_SUCCESS) { 25487c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_NOT_FOUND) { 2549*870ad75aSSean Wilcox err = mc_error_create(err, scf_error(), 2550*870ad75aSSean Wilcox "Unable to retrieve the \"%s\" property group, %s", 2551*870ad75aSSean Wilcox SCF_PG_METHOD_CONTEXT, scf_strerror(scf_error())); 25527c478bd9Sstevel@tonic-gate goto out; 25537c478bd9Sstevel@tonic-gate } 25547c478bd9Sstevel@tonic-gate scf_pg_destroy(instpg); 25557c478bd9Sstevel@tonic-gate instpg = NULL; 255613d8aaa1SSean Wilcox } else { 255713d8aaa1SSean Wilcox mc_used++; 25587c478bd9Sstevel@tonic-gate } 25597c478bd9Sstevel@tonic-gate 25607c478bd9Sstevel@tonic-gate ret = get_environment(h, methpg, cip, prop, val); 25617c478bd9Sstevel@tonic-gate if (ret == ENOENT && instpg != NULL) { 25627c478bd9Sstevel@tonic-gate ret = get_environment(h, instpg, cip, prop, val); 25637c478bd9Sstevel@tonic-gate } 25647c478bd9Sstevel@tonic-gate 25657c478bd9Sstevel@tonic-gate switch (ret) { 25667c478bd9Sstevel@tonic-gate case 0: 256713d8aaa1SSean Wilcox mc_used++; 256813d8aaa1SSean Wilcox break; 25697c478bd9Sstevel@tonic-gate case ENOENT: 25707c478bd9Sstevel@tonic-gate break; 25717c478bd9Sstevel@tonic-gate case ENOMEM: 2572*870ad75aSSean Wilcox err = mc_error_create(err, ret, "Out of memory."); 25737c478bd9Sstevel@tonic-gate goto out; 25747c478bd9Sstevel@tonic-gate case EINVAL: 2575*870ad75aSSean Wilcox err = mc_error_create(err, ret, "Invalid method environment."); 25767c478bd9Sstevel@tonic-gate goto out; 25777c478bd9Sstevel@tonic-gate default: 2578*870ad75aSSean Wilcox err = mc_error_create(err, ret, 2579*870ad75aSSean Wilcox "Get method environment failed : %s\n", scf_strerror(ret)); 25807c478bd9Sstevel@tonic-gate goto out; 25817c478bd9Sstevel@tonic-gate } 25827c478bd9Sstevel@tonic-gate 25837c478bd9Sstevel@tonic-gate pg = methpg; 25847c478bd9Sstevel@tonic-gate 25857c478bd9Sstevel@tonic-gate ret = scf_pg_get_property(pg, SCF_PROPERTY_USE_PROFILE, prop); 25867c478bd9Sstevel@tonic-gate if (ret && scf_error() == SCF_ERROR_NOT_FOUND && instpg != NULL) { 258713d8aaa1SSean Wilcox pg = NULL; 258813d8aaa1SSean Wilcox ret = scf_pg_get_property(instpg, SCF_PROPERTY_USE_PROFILE, 258913d8aaa1SSean Wilcox prop); 25907c478bd9Sstevel@tonic-gate } 25917c478bd9Sstevel@tonic-gate 25927c478bd9Sstevel@tonic-gate if (ret) { 25937c478bd9Sstevel@tonic-gate switch (scf_error()) { 25947c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 259513d8aaa1SSean Wilcox /* No profile context: use default credentials */ 25967c478bd9Sstevel@tonic-gate cip->uid = 0; 25977c478bd9Sstevel@tonic-gate cip->gid = 0; 259813d8aaa1SSean Wilcox break; 25997c478bd9Sstevel@tonic-gate 26007c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 2601*870ad75aSSean Wilcox err = mc_error_create(err, SCF_ERROR_CONNECTION_BROKEN, 2602*870ad75aSSean Wilcox RCBROKEN); 26037c478bd9Sstevel@tonic-gate goto out; 26047c478bd9Sstevel@tonic-gate 26057c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 2606*870ad75aSSean Wilcox err = mc_error_create(err, SCF_ERROR_NOT_FOUND, 2607*870ad75aSSean Wilcox "Could not find property group \"%s\"", 2608*870ad75aSSean Wilcox pg == NULL ? SCF_PG_METHOD_CONTEXT : mname); 26097c478bd9Sstevel@tonic-gate goto out; 26107c478bd9Sstevel@tonic-gate 26117c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 26127c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 26137c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 26147c478bd9Sstevel@tonic-gate default: 26157c478bd9Sstevel@tonic-gate bad_fail("scf_pg_get_property", scf_error()); 26167c478bd9Sstevel@tonic-gate } 261713d8aaa1SSean Wilcox } else { 26187c478bd9Sstevel@tonic-gate if (scf_property_type(prop, &ty) != SCF_SUCCESS) { 2619*870ad75aSSean Wilcox ret = scf_error(); 2620*870ad75aSSean Wilcox switch (ret) { 26217c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 2622*870ad75aSSean Wilcox err = mc_error_create(err, 2623*870ad75aSSean Wilcox SCF_ERROR_CONNECTION_BROKEN, RCBROKEN); 26247c478bd9Sstevel@tonic-gate break; 26257c478bd9Sstevel@tonic-gate 26267c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 2627*870ad75aSSean Wilcox err = mc_error_create(err, 2628*870ad75aSSean Wilcox SCF_ERROR_NOT_FOUND, 2629*870ad75aSSean Wilcox "Could not find property group \"%s\"", 2630*870ad75aSSean Wilcox pg == NULL ? SCF_PG_METHOD_CONTEXT : mname); 26317c478bd9Sstevel@tonic-gate break; 26327c478bd9Sstevel@tonic-gate 26337c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 26347c478bd9Sstevel@tonic-gate default: 2635*870ad75aSSean Wilcox bad_fail("scf_property_type", ret); 26367c478bd9Sstevel@tonic-gate } 26377c478bd9Sstevel@tonic-gate 26387c478bd9Sstevel@tonic-gate goto out; 26397c478bd9Sstevel@tonic-gate } 26407c478bd9Sstevel@tonic-gate 26417c478bd9Sstevel@tonic-gate if (ty != SCF_TYPE_BOOLEAN) { 2642*870ad75aSSean Wilcox err = mc_error_create(err, 2643*870ad75aSSean Wilcox SCF_ERROR_TYPE_MISMATCH, 2644*870ad75aSSean Wilcox "\"%s\" property is not boolean in property group " 2645*870ad75aSSean Wilcox "\"%s\".", SCF_PROPERTY_USE_PROFILE, 2646*870ad75aSSean Wilcox pg == NULL ? SCF_PG_METHOD_CONTEXT : mname); 26477c478bd9Sstevel@tonic-gate goto out; 26487c478bd9Sstevel@tonic-gate } 26497c478bd9Sstevel@tonic-gate 26507c478bd9Sstevel@tonic-gate if (scf_property_get_value(prop, val) != SCF_SUCCESS) { 2651*870ad75aSSean Wilcox ret = scf_error(); 2652*870ad75aSSean Wilcox switch (ret) { 26537c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 2654*870ad75aSSean Wilcox err = mc_error_create(err, 2655*870ad75aSSean Wilcox SCF_ERROR_CONNECTION_BROKEN, RCBROKEN); 26567c478bd9Sstevel@tonic-gate break; 26577c478bd9Sstevel@tonic-gate 26587c478bd9Sstevel@tonic-gate case SCF_ERROR_CONSTRAINT_VIOLATED: 2659*870ad75aSSean Wilcox err = mc_error_create(err, 2660*870ad75aSSean Wilcox SCF_ERROR_CONSTRAINT_VIOLATED, 2661*870ad75aSSean Wilcox "\"%s\" property has multiple values.", 2662*870ad75aSSean Wilcox SCF_PROPERTY_USE_PROFILE); 26637c478bd9Sstevel@tonic-gate break; 26647c478bd9Sstevel@tonic-gate 26657c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 2666*870ad75aSSean Wilcox err = mc_error_create(err, 2667*870ad75aSSean Wilcox SCF_ERROR_NOT_FOUND, 2668*870ad75aSSean Wilcox "\"%s\" property has no values.", 2669*870ad75aSSean Wilcox SCF_PROPERTY_USE_PROFILE); 26707c478bd9Sstevel@tonic-gate break; 26717c478bd9Sstevel@tonic-gate default: 2672*870ad75aSSean Wilcox bad_fail("scf_property_get_value", ret); 26737c478bd9Sstevel@tonic-gate } 26747c478bd9Sstevel@tonic-gate 26757c478bd9Sstevel@tonic-gate goto out; 26767c478bd9Sstevel@tonic-gate } 26777c478bd9Sstevel@tonic-gate 267813d8aaa1SSean Wilcox mc_used++; 26797c478bd9Sstevel@tonic-gate ret = scf_value_get_boolean(val, &use_profile); 26807c478bd9Sstevel@tonic-gate assert(ret == SCF_SUCCESS); 26817c478bd9Sstevel@tonic-gate 26827c478bd9Sstevel@tonic-gate /* get ids & privileges */ 26837c478bd9Sstevel@tonic-gate if (use_profile) 2684*870ad75aSSean Wilcox err = get_profile(pg, instpg, prop, val, cmdline, 2685*870ad75aSSean Wilcox cip, err); 26867c478bd9Sstevel@tonic-gate else 2687*870ad75aSSean Wilcox err = get_ids(pg, instpg, prop, val, cip, err); 268813d8aaa1SSean Wilcox 2689*870ad75aSSean Wilcox if (err->type != 0) 26907c478bd9Sstevel@tonic-gate goto out; 269113d8aaa1SSean Wilcox } 26927c478bd9Sstevel@tonic-gate 26937c478bd9Sstevel@tonic-gate /* get working directory */ 269413d8aaa1SSean Wilcox if ((methpg != NULL && scf_pg_get_property(methpg, 269513d8aaa1SSean Wilcox SCF_PROPERTY_WORKING_DIRECTORY, prop) == SCF_SUCCESS) || 269613d8aaa1SSean Wilcox (instpg != NULL && scf_pg_get_property(instpg, 269713d8aaa1SSean Wilcox SCF_PROPERTY_WORKING_DIRECTORY, prop) == SCF_SUCCESS)) { 269813d8aaa1SSean Wilcox if (scf_property_get_value(prop, val) != SCF_SUCCESS) { 2699*870ad75aSSean Wilcox ret = scf_error(); 2700*870ad75aSSean Wilcox switch (ret) { 270113d8aaa1SSean Wilcox case SCF_ERROR_CONNECTION_BROKEN: 2702*870ad75aSSean Wilcox err = mc_error_create(err, ret, RCBROKEN); 270313d8aaa1SSean Wilcox break; 270413d8aaa1SSean Wilcox 270513d8aaa1SSean Wilcox case SCF_ERROR_CONSTRAINT_VIOLATED: 2706*870ad75aSSean Wilcox err = mc_error_create(err, ret, 2707*870ad75aSSean Wilcox "\"%s\" property has multiple values.", 2708*870ad75aSSean Wilcox SCF_PROPERTY_WORKING_DIRECTORY); 270913d8aaa1SSean Wilcox break; 271013d8aaa1SSean Wilcox 271113d8aaa1SSean Wilcox case SCF_ERROR_NOT_FOUND: 2712*870ad75aSSean Wilcox err = mc_error_create(err, ret, 2713*870ad75aSSean Wilcox "\"%s\" property has no values.", 2714*870ad75aSSean Wilcox SCF_PROPERTY_WORKING_DIRECTORY); 271513d8aaa1SSean Wilcox break; 271613d8aaa1SSean Wilcox 271713d8aaa1SSean Wilcox default: 2718*870ad75aSSean Wilcox bad_fail("scf_property_get_value", ret); 271913d8aaa1SSean Wilcox } 272013d8aaa1SSean Wilcox 27217c478bd9Sstevel@tonic-gate goto out; 27227c478bd9Sstevel@tonic-gate } 27237c478bd9Sstevel@tonic-gate 272413d8aaa1SSean Wilcox mc_used++; 272513d8aaa1SSean Wilcox ret = scf_value_get_astring(val, cip->vbuf, cip->vbuf_sz); 272613d8aaa1SSean Wilcox assert(ret != -1); 272713d8aaa1SSean Wilcox } else { 2728*870ad75aSSean Wilcox ret = scf_error(); 2729*870ad75aSSean Wilcox switch (ret) { 273013d8aaa1SSean Wilcox case SCF_ERROR_NOT_FOUND: 273113d8aaa1SSean Wilcox /* okay if missing. */ 273213d8aaa1SSean Wilcox (void) strcpy(cip->vbuf, ":default"); 273313d8aaa1SSean Wilcox break; 273413d8aaa1SSean Wilcox 273513d8aaa1SSean Wilcox case SCF_ERROR_CONNECTION_BROKEN: 2736*870ad75aSSean Wilcox err = mc_error_create(err, ret, RCBROKEN); 273713d8aaa1SSean Wilcox goto out; 273813d8aaa1SSean Wilcox 273913d8aaa1SSean Wilcox case SCF_ERROR_DELETED: 2740*870ad75aSSean Wilcox err = mc_error_create(err, ret, 2741*870ad75aSSean Wilcox "Property group could not be found"); 274213d8aaa1SSean Wilcox goto out; 274313d8aaa1SSean Wilcox 274413d8aaa1SSean Wilcox case SCF_ERROR_HANDLE_MISMATCH: 274513d8aaa1SSean Wilcox case SCF_ERROR_INVALID_ARGUMENT: 274613d8aaa1SSean Wilcox case SCF_ERROR_NOT_SET: 274713d8aaa1SSean Wilcox default: 2748*870ad75aSSean Wilcox bad_fail("scf_pg_get_property", ret); 274913d8aaa1SSean Wilcox } 275013d8aaa1SSean Wilcox } 275113d8aaa1SSean Wilcox 27527c478bd9Sstevel@tonic-gate if (strcmp(cip->vbuf, ":default") == 0 || 27537c478bd9Sstevel@tonic-gate strcmp(cip->vbuf, ":home") == 0) { 27547c478bd9Sstevel@tonic-gate switch (ret = lookup_pwd(cip)) { 27557c478bd9Sstevel@tonic-gate case 0: 27567c478bd9Sstevel@tonic-gate break; 27577c478bd9Sstevel@tonic-gate 27587c478bd9Sstevel@tonic-gate case ENOMEM: 2759*870ad75aSSean Wilcox err = mc_error_create(err, ret, "Out of memory."); 27607c478bd9Sstevel@tonic-gate goto out; 27617c478bd9Sstevel@tonic-gate 27627c478bd9Sstevel@tonic-gate case ENOENT: 27637c478bd9Sstevel@tonic-gate case EIO: 27647c478bd9Sstevel@tonic-gate case EMFILE: 27657c478bd9Sstevel@tonic-gate case ENFILE: 2766*870ad75aSSean Wilcox err = mc_error_create(err, ret, 2767*870ad75aSSean Wilcox "Could not get passwd entry."); 27687c478bd9Sstevel@tonic-gate goto out; 27697c478bd9Sstevel@tonic-gate 27707c478bd9Sstevel@tonic-gate default: 27717c478bd9Sstevel@tonic-gate bad_fail("lookup_pwd", ret); 27727c478bd9Sstevel@tonic-gate } 27737c478bd9Sstevel@tonic-gate 27747c478bd9Sstevel@tonic-gate cip->working_dir = strdup(cip->pwd.pw_dir); 27757c478bd9Sstevel@tonic-gate if (cip->working_dir == NULL) { 2776*870ad75aSSean Wilcox err = mc_error_create(err, ENOMEM, ALLOCFAIL); 27777c478bd9Sstevel@tonic-gate goto out; 27787c478bd9Sstevel@tonic-gate } 27797c478bd9Sstevel@tonic-gate } else { 27807c478bd9Sstevel@tonic-gate cip->working_dir = strdup(cip->vbuf); 27817c478bd9Sstevel@tonic-gate if (cip->working_dir == NULL) { 2782*870ad75aSSean Wilcox err = mc_error_create(err, ENOMEM, ALLOCFAIL); 27837c478bd9Sstevel@tonic-gate goto out; 27847c478bd9Sstevel@tonic-gate } 27857c478bd9Sstevel@tonic-gate } 27867c478bd9Sstevel@tonic-gate 27877c478bd9Sstevel@tonic-gate /* get (optional) corefile pattern */ 278813d8aaa1SSean Wilcox if ((methpg != NULL && scf_pg_get_property(methpg, 278913d8aaa1SSean Wilcox SCF_PROPERTY_COREFILE_PATTERN, prop) == SCF_SUCCESS) || 279013d8aaa1SSean Wilcox (instpg != NULL && scf_pg_get_property(instpg, 279113d8aaa1SSean Wilcox SCF_PROPERTY_COREFILE_PATTERN, prop) == SCF_SUCCESS)) { 279213d8aaa1SSean Wilcox if (scf_property_get_value(prop, val) != SCF_SUCCESS) { 2793*870ad75aSSean Wilcox ret = scf_error(); 2794*870ad75aSSean Wilcox switch (ret) { 279513d8aaa1SSean Wilcox case SCF_ERROR_CONNECTION_BROKEN: 2796*870ad75aSSean Wilcox err = mc_error_create(err, ret, RCBROKEN); 279713d8aaa1SSean Wilcox break; 279813d8aaa1SSean Wilcox 279913d8aaa1SSean Wilcox case SCF_ERROR_CONSTRAINT_VIOLATED: 2800*870ad75aSSean Wilcox err = mc_error_create(err, ret, 2801*870ad75aSSean Wilcox "\"%s\" property has multiple values.", 2802*870ad75aSSean Wilcox SCF_PROPERTY_COREFILE_PATTERN); 280313d8aaa1SSean Wilcox break; 280413d8aaa1SSean Wilcox 280513d8aaa1SSean Wilcox case SCF_ERROR_NOT_FOUND: 2806*870ad75aSSean Wilcox err = mc_error_create(err, ret, 2807*870ad75aSSean Wilcox "\"%s\" property has no values.", 2808*870ad75aSSean Wilcox SCF_PROPERTY_COREFILE_PATTERN); 280913d8aaa1SSean Wilcox break; 281013d8aaa1SSean Wilcox 281113d8aaa1SSean Wilcox default: 2812*870ad75aSSean Wilcox bad_fail("scf_property_get_value", ret); 28137c478bd9Sstevel@tonic-gate } 28147c478bd9Sstevel@tonic-gate 281513d8aaa1SSean Wilcox } else { 281613d8aaa1SSean Wilcox 281713d8aaa1SSean Wilcox ret = scf_value_get_astring(val, cip->vbuf, 281813d8aaa1SSean Wilcox cip->vbuf_sz); 281913d8aaa1SSean Wilcox assert(ret != -1); 282013d8aaa1SSean Wilcox 28217c478bd9Sstevel@tonic-gate cip->corefile_pattern = strdup(cip->vbuf); 28227c478bd9Sstevel@tonic-gate if (cip->corefile_pattern == NULL) { 2823*870ad75aSSean Wilcox err = mc_error_create(err, ENOMEM, ALLOCFAIL); 28247c478bd9Sstevel@tonic-gate goto out; 28257c478bd9Sstevel@tonic-gate } 282613d8aaa1SSean Wilcox } 282713d8aaa1SSean Wilcox 282813d8aaa1SSean Wilcox mc_used++; 28297c478bd9Sstevel@tonic-gate } else { 2830*870ad75aSSean Wilcox ret = scf_error(); 2831*870ad75aSSean Wilcox switch (ret) { 28327c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 28337c478bd9Sstevel@tonic-gate /* okay if missing. */ 28347c478bd9Sstevel@tonic-gate break; 28357c478bd9Sstevel@tonic-gate 28367c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 2837*870ad75aSSean Wilcox err = mc_error_create(err, ret, RCBROKEN); 28387c478bd9Sstevel@tonic-gate goto out; 28397c478bd9Sstevel@tonic-gate 28407c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 2841*870ad75aSSean Wilcox err = mc_error_create(err, ret, 2842*870ad75aSSean Wilcox "Property group could not be found"); 28437c478bd9Sstevel@tonic-gate goto out; 28447c478bd9Sstevel@tonic-gate 28457c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 28467c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 28477c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 28487c478bd9Sstevel@tonic-gate default: 2849*870ad75aSSean Wilcox bad_fail("scf_pg_get_property", ret); 28507c478bd9Sstevel@tonic-gate } 28517c478bd9Sstevel@tonic-gate } 28527c478bd9Sstevel@tonic-gate 28537c478bd9Sstevel@tonic-gate if (restarter_rm_libs_loadable()) { 28547c478bd9Sstevel@tonic-gate /* get project */ 285513d8aaa1SSean Wilcox if ((methpg != NULL && scf_pg_get_property(methpg, 285613d8aaa1SSean Wilcox SCF_PROPERTY_PROJECT, prop) == SCF_SUCCESS) || 285713d8aaa1SSean Wilcox (instpg != NULL && scf_pg_get_property(instpg, 285813d8aaa1SSean Wilcox SCF_PROPERTY_PROJECT, prop) == SCF_SUCCESS)) { 285913d8aaa1SSean Wilcox if (scf_property_get_value(prop, val) != SCF_SUCCESS) { 2860*870ad75aSSean Wilcox ret = scf_error(); 2861*870ad75aSSean Wilcox switch (ret) { 286213d8aaa1SSean Wilcox case SCF_ERROR_CONNECTION_BROKEN: 2863*870ad75aSSean Wilcox err = mc_error_create(err, ret, 2864*870ad75aSSean Wilcox RCBROKEN); 286513d8aaa1SSean Wilcox break; 286613d8aaa1SSean Wilcox 286713d8aaa1SSean Wilcox case SCF_ERROR_CONSTRAINT_VIOLATED: 2868*870ad75aSSean Wilcox err = mc_error_create(err, ret, 2869*870ad75aSSean Wilcox "\"%s\" property has multiple " 2870*870ad75aSSean Wilcox "values.", SCF_PROPERTY_PROJECT); 287113d8aaa1SSean Wilcox break; 287213d8aaa1SSean Wilcox 287313d8aaa1SSean Wilcox case SCF_ERROR_NOT_FOUND: 2874*870ad75aSSean Wilcox err = mc_error_create(err, ret, 2875*870ad75aSSean Wilcox "\"%s\" property has no values.", 2876*870ad75aSSean Wilcox SCF_PROPERTY_PROJECT); 287713d8aaa1SSean Wilcox break; 287813d8aaa1SSean Wilcox 287913d8aaa1SSean Wilcox default: 2880*870ad75aSSean Wilcox bad_fail("scf_property_get_value", ret); 288113d8aaa1SSean Wilcox } 288213d8aaa1SSean Wilcox 288313d8aaa1SSean Wilcox (void) strcpy(cip->vbuf, ":default"); 288413d8aaa1SSean Wilcox } else { 288513d8aaa1SSean Wilcox ret = scf_value_get_astring(val, cip->vbuf, 288613d8aaa1SSean Wilcox cip->vbuf_sz); 288713d8aaa1SSean Wilcox assert(ret != -1); 288813d8aaa1SSean Wilcox } 288913d8aaa1SSean Wilcox 289013d8aaa1SSean Wilcox mc_used++; 289113d8aaa1SSean Wilcox } else { 289213d8aaa1SSean Wilcox (void) strcpy(cip->vbuf, ":default"); 28937c478bd9Sstevel@tonic-gate } 28947c478bd9Sstevel@tonic-gate 28957c478bd9Sstevel@tonic-gate switch (ret = get_projid(cip->vbuf, cip)) { 28967c478bd9Sstevel@tonic-gate case 0: 28977c478bd9Sstevel@tonic-gate break; 28987c478bd9Sstevel@tonic-gate 28997c478bd9Sstevel@tonic-gate case ENOMEM: 2900*870ad75aSSean Wilcox err = mc_error_create(err, ret, "Out of memory."); 29017c478bd9Sstevel@tonic-gate goto out; 29027c478bd9Sstevel@tonic-gate 29037c478bd9Sstevel@tonic-gate case ENOENT: 2904*870ad75aSSean Wilcox err = mc_error_create(err, ret, 2905*870ad75aSSean Wilcox "Missing passwd or project entry for \"%s\".", 2906*870ad75aSSean Wilcox cip->vbuf); 29077c478bd9Sstevel@tonic-gate goto out; 29087c478bd9Sstevel@tonic-gate 29097c478bd9Sstevel@tonic-gate case EIO: 2910*870ad75aSSean Wilcox err = mc_error_create(err, ret, "I/O error."); 29117c478bd9Sstevel@tonic-gate goto out; 29127c478bd9Sstevel@tonic-gate 29137c478bd9Sstevel@tonic-gate case EMFILE: 29147c478bd9Sstevel@tonic-gate case ENFILE: 2915*870ad75aSSean Wilcox err = mc_error_create(err, ret, 2916*870ad75aSSean Wilcox "Out of file descriptors."); 29177c478bd9Sstevel@tonic-gate goto out; 29187c478bd9Sstevel@tonic-gate 29197c478bd9Sstevel@tonic-gate case -1: 2920*870ad75aSSean Wilcox err = mc_error_create(err, ret, 2921*870ad75aSSean Wilcox "Name service switch is misconfigured."); 29227c478bd9Sstevel@tonic-gate goto out; 29237c478bd9Sstevel@tonic-gate 29247c478bd9Sstevel@tonic-gate case ERANGE: 2925*870ad75aSSean Wilcox case E2BIG: 2926*870ad75aSSean Wilcox err = mc_error_create(err, ret, 2927*870ad75aSSean Wilcox "Project ID \"%s\" too big.", cip->vbuf); 29287c478bd9Sstevel@tonic-gate goto out; 29297c478bd9Sstevel@tonic-gate 29307c478bd9Sstevel@tonic-gate case EINVAL: 2931*870ad75aSSean Wilcox err = mc_error_create(err, ret, 2932*870ad75aSSean Wilcox "Project ID \"%s\" is invalid.", cip->vbuf); 29337c478bd9Sstevel@tonic-gate goto out; 29347c478bd9Sstevel@tonic-gate 29357c478bd9Sstevel@tonic-gate default: 29367c478bd9Sstevel@tonic-gate bad_fail("get_projid", ret); 29377c478bd9Sstevel@tonic-gate } 29387c478bd9Sstevel@tonic-gate 29397c478bd9Sstevel@tonic-gate /* get resource pool */ 294013d8aaa1SSean Wilcox if ((methpg != NULL && scf_pg_get_property(methpg, 294113d8aaa1SSean Wilcox SCF_PROPERTY_RESOURCE_POOL, prop) == SCF_SUCCESS) || 294213d8aaa1SSean Wilcox (instpg != NULL && scf_pg_get_property(instpg, 294313d8aaa1SSean Wilcox SCF_PROPERTY_RESOURCE_POOL, prop) == SCF_SUCCESS)) { 294413d8aaa1SSean Wilcox if (scf_property_get_value(prop, val) != SCF_SUCCESS) { 2945*870ad75aSSean Wilcox ret = scf_error(); 2946*870ad75aSSean Wilcox switch (ret) { 294713d8aaa1SSean Wilcox case SCF_ERROR_CONNECTION_BROKEN: 2948*870ad75aSSean Wilcox err = mc_error_create(err, ret, 2949*870ad75aSSean Wilcox RCBROKEN); 295013d8aaa1SSean Wilcox break; 295113d8aaa1SSean Wilcox 295213d8aaa1SSean Wilcox case SCF_ERROR_CONSTRAINT_VIOLATED: 2953*870ad75aSSean Wilcox err = mc_error_create(err, ret, 2954*870ad75aSSean Wilcox "\"%s\" property has multiple " 2955*870ad75aSSean Wilcox "values.", 2956*870ad75aSSean Wilcox SCF_PROPERTY_RESOURCE_POOL); 295713d8aaa1SSean Wilcox break; 295813d8aaa1SSean Wilcox 295913d8aaa1SSean Wilcox case SCF_ERROR_NOT_FOUND: 2960*870ad75aSSean Wilcox err = mc_error_create(err, ret, 2961*870ad75aSSean Wilcox "\"%s\" property has no " 2962*870ad75aSSean Wilcox "values.", 2963*870ad75aSSean Wilcox SCF_PROPERTY_RESOURCE_POOL); 296413d8aaa1SSean Wilcox break; 296513d8aaa1SSean Wilcox 296613d8aaa1SSean Wilcox default: 2967*870ad75aSSean Wilcox bad_fail("scf_property_get_value", ret); 296813d8aaa1SSean Wilcox } 296913d8aaa1SSean Wilcox 297013d8aaa1SSean Wilcox (void) strcpy(cip->vbuf, ":default"); 297113d8aaa1SSean Wilcox } else { 297213d8aaa1SSean Wilcox ret = scf_value_get_astring(val, cip->vbuf, 297313d8aaa1SSean Wilcox cip->vbuf_sz); 297413d8aaa1SSean Wilcox assert(ret != -1); 297513d8aaa1SSean Wilcox } 297613d8aaa1SSean Wilcox 297713d8aaa1SSean Wilcox mc_used++; 297813d8aaa1SSean Wilcox } else { 2979*870ad75aSSean Wilcox ret = scf_error(); 2980*870ad75aSSean Wilcox switch (ret) { 298113d8aaa1SSean Wilcox case SCF_ERROR_NOT_FOUND: 298213d8aaa1SSean Wilcox /* okay if missing. */ 298313d8aaa1SSean Wilcox (void) strcpy(cip->vbuf, ":default"); 298413d8aaa1SSean Wilcox break; 298513d8aaa1SSean Wilcox 298613d8aaa1SSean Wilcox case SCF_ERROR_CONNECTION_BROKEN: 2987*870ad75aSSean Wilcox err = mc_error_create(err, ret, RCBROKEN); 29887c478bd9Sstevel@tonic-gate goto out; 298913d8aaa1SSean Wilcox 299013d8aaa1SSean Wilcox case SCF_ERROR_DELETED: 2991*870ad75aSSean Wilcox err = mc_error_create(err, ret, 2992*870ad75aSSean Wilcox "property group could not be found."); 299313d8aaa1SSean Wilcox goto out; 299413d8aaa1SSean Wilcox 299513d8aaa1SSean Wilcox case SCF_ERROR_HANDLE_MISMATCH: 299613d8aaa1SSean Wilcox case SCF_ERROR_INVALID_ARGUMENT: 299713d8aaa1SSean Wilcox case SCF_ERROR_NOT_SET: 299813d8aaa1SSean Wilcox default: 2999*870ad75aSSean Wilcox bad_fail("scf_pg_get_property", ret); 300013d8aaa1SSean Wilcox } 30017c478bd9Sstevel@tonic-gate } 30027c478bd9Sstevel@tonic-gate 30037c478bd9Sstevel@tonic-gate if (strcmp(cip->vbuf, ":default") != 0) { 30047c478bd9Sstevel@tonic-gate cip->resource_pool = strdup(cip->vbuf); 30057c478bd9Sstevel@tonic-gate if (cip->resource_pool == NULL) { 3006*870ad75aSSean Wilcox err = mc_error_create(err, ENOMEM, ALLOCFAIL); 30077c478bd9Sstevel@tonic-gate goto out; 30087c478bd9Sstevel@tonic-gate } 30097c478bd9Sstevel@tonic-gate } 30107c478bd9Sstevel@tonic-gate } 30117c478bd9Sstevel@tonic-gate 301213d8aaa1SSean Wilcox /* 301313d8aaa1SSean Wilcox * A method_context was not used for any configurable 301413d8aaa1SSean Wilcox * elements or attributes, so reset and use the simple 301513d8aaa1SSean Wilcox * defaults that provide historic init behavior. 301613d8aaa1SSean Wilcox */ 301713d8aaa1SSean Wilcox if (mc_used == 0) { 301813d8aaa1SSean Wilcox (void) memset(cip, 0, sizeof (*cip)); 301913d8aaa1SSean Wilcox cip->uid = 0; 302013d8aaa1SSean Wilcox cip->gid = 0; 302113d8aaa1SSean Wilcox cip->euid = (uid_t)-1; 302213d8aaa1SSean Wilcox cip->egid = (gid_t)-1; 302313d8aaa1SSean Wilcox } 302413d8aaa1SSean Wilcox 30257c478bd9Sstevel@tonic-gate *mcpp = cip; 30267c478bd9Sstevel@tonic-gate 30277c478bd9Sstevel@tonic-gate out: 30287c478bd9Sstevel@tonic-gate (void) scf_value_destroy(val); 30297c478bd9Sstevel@tonic-gate scf_property_destroy(prop); 30307c478bd9Sstevel@tonic-gate scf_pg_destroy(instpg); 30317c478bd9Sstevel@tonic-gate scf_pg_destroy(methpg); 30327c478bd9Sstevel@tonic-gate 30337c478bd9Sstevel@tonic-gate if (cip->pwbuf != NULL) 30347c478bd9Sstevel@tonic-gate free(cip->pwbuf); 30357c478bd9Sstevel@tonic-gate free(cip->vbuf); 30367c478bd9Sstevel@tonic-gate 3037*870ad75aSSean Wilcox if (err->type != 0) { 30387c478bd9Sstevel@tonic-gate restarter_free_method_context(cip); 3039*870ad75aSSean Wilcox } else { 3040*870ad75aSSean Wilcox restarter_mc_error_destroy(err); 3041*870ad75aSSean Wilcox err = NULL; 3042*870ad75aSSean Wilcox } 30437c478bd9Sstevel@tonic-gate 3044*870ad75aSSean Wilcox return (err); 30457c478bd9Sstevel@tonic-gate } 30467c478bd9Sstevel@tonic-gate 30477c478bd9Sstevel@tonic-gate /* 30487c478bd9Sstevel@tonic-gate * Modify the current process per the given method_context. On success, returns 30497c478bd9Sstevel@tonic-gate * 0. Note that the environment is not modified by this function to include the 30507c478bd9Sstevel@tonic-gate * environment variables in cip->env. 30517c478bd9Sstevel@tonic-gate * 30527c478bd9Sstevel@tonic-gate * On failure, sets *fp to NULL or the name of the function which failed, 30537c478bd9Sstevel@tonic-gate * and returns one of the following error codes. The words in parentheses are 30547c478bd9Sstevel@tonic-gate * the values to which *fp may be set for the error case. 30557c478bd9Sstevel@tonic-gate * ENOMEM - malloc() failed 30567c478bd9Sstevel@tonic-gate * EIO - an I/O error occurred (getpwuid_r, chdir) 30577c478bd9Sstevel@tonic-gate * EMFILE - process is out of file descriptors (getpwuid_r) 30587c478bd9Sstevel@tonic-gate * ENFILE - system is out of file handles (getpwuid_r) 30597c478bd9Sstevel@tonic-gate * EINVAL - gid or egid is out of range (setregid) 30607c478bd9Sstevel@tonic-gate * ngroups is too big (setgroups) 30617c478bd9Sstevel@tonic-gate * project's project id is bad (setproject) 30627c478bd9Sstevel@tonic-gate * uid or euid is out of range (setreuid) 30633ad28c1eSrm88369 * poolname is invalid (pool_set_binding) 30647c478bd9Sstevel@tonic-gate * EPERM - insufficient privilege (setregid, initgroups, setgroups, setppriv, 30657c478bd9Sstevel@tonic-gate * setproject, setreuid, settaskid) 30667c478bd9Sstevel@tonic-gate * ENOENT - uid has a passwd entry but no shadow entry 30677c478bd9Sstevel@tonic-gate * working_dir does not exist (chdir) 30687c478bd9Sstevel@tonic-gate * uid has no passwd entry 30697c478bd9Sstevel@tonic-gate * the pool could not be found (pool_set_binding) 30707c478bd9Sstevel@tonic-gate * EFAULT - lpriv_set or priv_set has a bad address (setppriv) 30717c478bd9Sstevel@tonic-gate * working_dir has a bad address (chdir) 30727c478bd9Sstevel@tonic-gate * EACCES - could not access working_dir (chdir) 30737c478bd9Sstevel@tonic-gate * in a TASK_FINAL task (setproject, settaskid) 30747c478bd9Sstevel@tonic-gate * no resource pool accepting default binding exists (setproject) 30757c478bd9Sstevel@tonic-gate * ELOOP - too many symbolic links in working_dir (chdir) 30767c478bd9Sstevel@tonic-gate * ENAMETOOLONG - working_dir is too long (chdir) 30777c478bd9Sstevel@tonic-gate * ENOLINK - working_dir is on an inaccessible remote machine (chdir) 30787c478bd9Sstevel@tonic-gate * ENOTDIR - working_dir is not a directory (chdir) 30797c478bd9Sstevel@tonic-gate * ESRCH - uid is not a user of project (setproject) 30807c478bd9Sstevel@tonic-gate * project is invalid (setproject) 30817c478bd9Sstevel@tonic-gate * the resource pool specified for project is unknown (setproject) 30827c478bd9Sstevel@tonic-gate * EBADF - the configuration for the pool is invalid (pool_set_binding) 30837c478bd9Sstevel@tonic-gate * -1 - core_set_process_path() failed (core_set_process_path) 30847c478bd9Sstevel@tonic-gate * a resource control assignment failed (setproject) 30857c478bd9Sstevel@tonic-gate * a system error occurred during pool_set_binding (pool_set_binding) 30867c478bd9Sstevel@tonic-gate */ 30877c478bd9Sstevel@tonic-gate int 30887c478bd9Sstevel@tonic-gate restarter_set_method_context(struct method_context *cip, const char **fp) 30897c478bd9Sstevel@tonic-gate { 30907c478bd9Sstevel@tonic-gate pid_t mypid = -1; 30917c478bd9Sstevel@tonic-gate int r, ret; 30927c478bd9Sstevel@tonic-gate 30937c478bd9Sstevel@tonic-gate cip->pwbuf = NULL; 30947c478bd9Sstevel@tonic-gate *fp = NULL; 30957c478bd9Sstevel@tonic-gate 3096f48205beScasper if (cip->gid != (gid_t)-1) { 30977c478bd9Sstevel@tonic-gate if (setregid(cip->gid, 3098f48205beScasper cip->egid != (gid_t)-1 ? cip->egid : cip->gid) != 0) { 30997c478bd9Sstevel@tonic-gate *fp = "setregid"; 31007c478bd9Sstevel@tonic-gate 31017c478bd9Sstevel@tonic-gate ret = errno; 31027c478bd9Sstevel@tonic-gate assert(ret == EINVAL || ret == EPERM); 31037c478bd9Sstevel@tonic-gate goto out; 31047c478bd9Sstevel@tonic-gate } 31057c478bd9Sstevel@tonic-gate } else { 31067c478bd9Sstevel@tonic-gate if (cip->pwbuf == NULL) { 31077c478bd9Sstevel@tonic-gate switch (ret = lookup_pwd(cip)) { 31087c478bd9Sstevel@tonic-gate case 0: 31097c478bd9Sstevel@tonic-gate break; 31107c478bd9Sstevel@tonic-gate 31117c478bd9Sstevel@tonic-gate case ENOMEM: 31127c478bd9Sstevel@tonic-gate case ENOENT: 31137c478bd9Sstevel@tonic-gate *fp = NULL; 31147c478bd9Sstevel@tonic-gate goto out; 31157c478bd9Sstevel@tonic-gate 31167c478bd9Sstevel@tonic-gate case EIO: 31177c478bd9Sstevel@tonic-gate case EMFILE: 31187c478bd9Sstevel@tonic-gate case ENFILE: 31197c478bd9Sstevel@tonic-gate *fp = "getpwuid_r"; 31207c478bd9Sstevel@tonic-gate goto out; 31217c478bd9Sstevel@tonic-gate 31227c478bd9Sstevel@tonic-gate default: 31237c478bd9Sstevel@tonic-gate bad_fail("lookup_pwd", ret); 31247c478bd9Sstevel@tonic-gate } 31257c478bd9Sstevel@tonic-gate } 31267c478bd9Sstevel@tonic-gate 31277c478bd9Sstevel@tonic-gate if (setregid(cip->pwd.pw_gid, 3128f48205beScasper cip->egid != (gid_t)-1 ? 3129f48205beScasper cip->egid : cip->pwd.pw_gid) != 0) { 31307c478bd9Sstevel@tonic-gate *fp = "setregid"; 31317c478bd9Sstevel@tonic-gate 31327c478bd9Sstevel@tonic-gate ret = errno; 31337c478bd9Sstevel@tonic-gate assert(ret == EINVAL || ret == EPERM); 31347c478bd9Sstevel@tonic-gate goto out; 31357c478bd9Sstevel@tonic-gate } 31367c478bd9Sstevel@tonic-gate } 31377c478bd9Sstevel@tonic-gate 31387c478bd9Sstevel@tonic-gate if (cip->ngroups == -1) { 31397c478bd9Sstevel@tonic-gate if (cip->pwbuf == NULL) { 31407c478bd9Sstevel@tonic-gate switch (ret = lookup_pwd(cip)) { 31417c478bd9Sstevel@tonic-gate case 0: 31427c478bd9Sstevel@tonic-gate break; 31437c478bd9Sstevel@tonic-gate 31447c478bd9Sstevel@tonic-gate case ENOMEM: 31457c478bd9Sstevel@tonic-gate case ENOENT: 31467c478bd9Sstevel@tonic-gate *fp = NULL; 31477c478bd9Sstevel@tonic-gate goto out; 31487c478bd9Sstevel@tonic-gate 31497c478bd9Sstevel@tonic-gate case EIO: 31507c478bd9Sstevel@tonic-gate case EMFILE: 31517c478bd9Sstevel@tonic-gate case ENFILE: 31527c478bd9Sstevel@tonic-gate *fp = "getpwuid_r"; 31537c478bd9Sstevel@tonic-gate goto out; 31547c478bd9Sstevel@tonic-gate 31557c478bd9Sstevel@tonic-gate default: 31567c478bd9Sstevel@tonic-gate bad_fail("lookup_pwd", ret); 31577c478bd9Sstevel@tonic-gate } 31587c478bd9Sstevel@tonic-gate } 31597c478bd9Sstevel@tonic-gate 31607c478bd9Sstevel@tonic-gate /* Ok if cip->gid == -1 */ 31617c478bd9Sstevel@tonic-gate if (initgroups(cip->pwd.pw_name, cip->gid) != 0) { 31627c478bd9Sstevel@tonic-gate *fp = "initgroups"; 31637c478bd9Sstevel@tonic-gate ret = errno; 31647c478bd9Sstevel@tonic-gate assert(ret == EPERM); 31657c478bd9Sstevel@tonic-gate goto out; 31667c478bd9Sstevel@tonic-gate } 31677c478bd9Sstevel@tonic-gate } else if (cip->ngroups > 0 && 31687c478bd9Sstevel@tonic-gate setgroups(cip->ngroups, cip->groups) != 0) { 31697c478bd9Sstevel@tonic-gate *fp = "setgroups"; 31707c478bd9Sstevel@tonic-gate 31717c478bd9Sstevel@tonic-gate ret = errno; 31727c478bd9Sstevel@tonic-gate assert(ret == EINVAL || ret == EPERM); 31737c478bd9Sstevel@tonic-gate goto out; 31747c478bd9Sstevel@tonic-gate } 31757c478bd9Sstevel@tonic-gate 31767c478bd9Sstevel@tonic-gate if (cip->corefile_pattern != NULL) { 31777c478bd9Sstevel@tonic-gate mypid = getpid(); 31787c478bd9Sstevel@tonic-gate 31797c478bd9Sstevel@tonic-gate if (core_set_process_path(cip->corefile_pattern, 31807c478bd9Sstevel@tonic-gate strlen(cip->corefile_pattern) + 1, mypid) != 0) { 31817c478bd9Sstevel@tonic-gate *fp = "core_set_process_path"; 31827c478bd9Sstevel@tonic-gate ret = -1; 31837c478bd9Sstevel@tonic-gate goto out; 31847c478bd9Sstevel@tonic-gate } 31857c478bd9Sstevel@tonic-gate } 31867c478bd9Sstevel@tonic-gate 31877c478bd9Sstevel@tonic-gate if (restarter_rm_libs_loadable()) { 31887c478bd9Sstevel@tonic-gate if (cip->project == NULL) { 31897c478bd9Sstevel@tonic-gate if (settaskid(getprojid(), TASK_NORMAL) == -1) { 31907c478bd9Sstevel@tonic-gate switch (errno) { 31917c478bd9Sstevel@tonic-gate case EACCES: 31927c478bd9Sstevel@tonic-gate case EPERM: 31937c478bd9Sstevel@tonic-gate *fp = "settaskid"; 31947c478bd9Sstevel@tonic-gate ret = errno; 31957c478bd9Sstevel@tonic-gate goto out; 31967c478bd9Sstevel@tonic-gate 31977c478bd9Sstevel@tonic-gate case EINVAL: 31987c478bd9Sstevel@tonic-gate default: 31997c478bd9Sstevel@tonic-gate bad_fail("settaskid", errno); 32007c478bd9Sstevel@tonic-gate } 32017c478bd9Sstevel@tonic-gate } 32027c478bd9Sstevel@tonic-gate } else { 32037c478bd9Sstevel@tonic-gate switch (ret = lookup_pwd(cip)) { 32047c478bd9Sstevel@tonic-gate case 0: 32057c478bd9Sstevel@tonic-gate break; 32067c478bd9Sstevel@tonic-gate 32077c478bd9Sstevel@tonic-gate case ENOMEM: 32087c478bd9Sstevel@tonic-gate case ENOENT: 32097c478bd9Sstevel@tonic-gate *fp = NULL; 32107c478bd9Sstevel@tonic-gate goto out; 32117c478bd9Sstevel@tonic-gate 32127c478bd9Sstevel@tonic-gate case EIO: 32137c478bd9Sstevel@tonic-gate case EMFILE: 32147c478bd9Sstevel@tonic-gate case ENFILE: 32157c478bd9Sstevel@tonic-gate *fp = "getpwuid_r"; 32167c478bd9Sstevel@tonic-gate goto out; 32177c478bd9Sstevel@tonic-gate 32187c478bd9Sstevel@tonic-gate default: 32197c478bd9Sstevel@tonic-gate bad_fail("lookup_pwd", ret); 32207c478bd9Sstevel@tonic-gate } 32217c478bd9Sstevel@tonic-gate 32227c478bd9Sstevel@tonic-gate *fp = "setproject"; 32237c478bd9Sstevel@tonic-gate 32247c478bd9Sstevel@tonic-gate switch (setproject(cip->project, cip->pwd.pw_name, 32257c478bd9Sstevel@tonic-gate TASK_NORMAL)) { 32267c478bd9Sstevel@tonic-gate case 0: 32277c478bd9Sstevel@tonic-gate break; 32287c478bd9Sstevel@tonic-gate 32297c478bd9Sstevel@tonic-gate case SETPROJ_ERR_TASK: 32307c478bd9Sstevel@tonic-gate case SETPROJ_ERR_POOL: 32317c478bd9Sstevel@tonic-gate ret = errno; 32327c478bd9Sstevel@tonic-gate goto out; 32337c478bd9Sstevel@tonic-gate 32347c478bd9Sstevel@tonic-gate default: 32357c478bd9Sstevel@tonic-gate ret = -1; 32367c478bd9Sstevel@tonic-gate goto out; 32377c478bd9Sstevel@tonic-gate } 32387c478bd9Sstevel@tonic-gate } 32397c478bd9Sstevel@tonic-gate 32407c478bd9Sstevel@tonic-gate if (cip->resource_pool != NULL) { 32417c478bd9Sstevel@tonic-gate if (mypid == -1) 32427c478bd9Sstevel@tonic-gate mypid = getpid(); 32437c478bd9Sstevel@tonic-gate 32447c478bd9Sstevel@tonic-gate *fp = "pool_set_binding"; 32457c478bd9Sstevel@tonic-gate 32467c478bd9Sstevel@tonic-gate if (pool_set_binding(cip->resource_pool, P_PID, 32477c478bd9Sstevel@tonic-gate mypid) != PO_SUCCESS) { 32487c478bd9Sstevel@tonic-gate switch (pool_error()) { 32493ad28c1eSrm88369 case POE_INVALID_SEARCH: 32507c478bd9Sstevel@tonic-gate ret = ENOENT; 32517c478bd9Sstevel@tonic-gate break; 32527c478bd9Sstevel@tonic-gate 32533ad28c1eSrm88369 case POE_BADPARAM: 32543ad28c1eSrm88369 ret = EINVAL; 32553ad28c1eSrm88369 break; 32563ad28c1eSrm88369 32577c478bd9Sstevel@tonic-gate case POE_INVALID_CONF: 32587c478bd9Sstevel@tonic-gate ret = EBADF; 32597c478bd9Sstevel@tonic-gate break; 32607c478bd9Sstevel@tonic-gate 32617c478bd9Sstevel@tonic-gate case POE_SYSTEM: 32627c478bd9Sstevel@tonic-gate ret = -1; 32637c478bd9Sstevel@tonic-gate break; 32647c478bd9Sstevel@tonic-gate 32657c478bd9Sstevel@tonic-gate default: 32667c478bd9Sstevel@tonic-gate bad_fail("pool_set_binding", 32677c478bd9Sstevel@tonic-gate pool_error()); 32687c478bd9Sstevel@tonic-gate } 32697c478bd9Sstevel@tonic-gate 32707c478bd9Sstevel@tonic-gate goto out; 32717c478bd9Sstevel@tonic-gate } 32727c478bd9Sstevel@tonic-gate } 32737c478bd9Sstevel@tonic-gate } 32747c478bd9Sstevel@tonic-gate 32757c478bd9Sstevel@tonic-gate /* 32762a3221a4Svp157776 * Now, we have to assume our ID. If the UID is 0, we want it to be 32772a3221a4Svp157776 * privilege-aware, otherwise the limit set gets used instead of E/P. 32787c478bd9Sstevel@tonic-gate * We can do this by setting P as well, which keeps 32797c478bd9Sstevel@tonic-gate * PA status (see priv_can_clear_PA()). 32807c478bd9Sstevel@tonic-gate */ 32817c478bd9Sstevel@tonic-gate 328213d8aaa1SSean Wilcox *fp = "setppriv"; 328313d8aaa1SSean Wilcox 328413d8aaa1SSean Wilcox if (cip->lpriv_set != NULL) { 328513d8aaa1SSean Wilcox if (setppriv(PRIV_SET, PRIV_LIMIT, cip->lpriv_set) != 0) { 328613d8aaa1SSean Wilcox ret = errno; 328713d8aaa1SSean Wilcox assert(ret == EFAULT || ret == EPERM); 328813d8aaa1SSean Wilcox goto out; 328913d8aaa1SSean Wilcox } 329013d8aaa1SSean Wilcox } 329113d8aaa1SSean Wilcox if (cip->priv_set != NULL) { 329213d8aaa1SSean Wilcox if (setppriv(PRIV_SET, PRIV_INHERITABLE, cip->priv_set) != 0) { 329313d8aaa1SSean Wilcox ret = errno; 329413d8aaa1SSean Wilcox assert(ret == EFAULT || ret == EPERM); 329513d8aaa1SSean Wilcox goto out; 329613d8aaa1SSean Wilcox } 329713d8aaa1SSean Wilcox } 329813d8aaa1SSean Wilcox 329913d8aaa1SSean Wilcox /* 330013d8aaa1SSean Wilcox * If the limit privset is already set, then must be privilege 330113d8aaa1SSean Wilcox * aware. Otherwise, don't assume anything, and force privilege 330213d8aaa1SSean Wilcox * aware status. 330313d8aaa1SSean Wilcox */ 330413d8aaa1SSean Wilcox 330513d8aaa1SSean Wilcox if (cip->lpriv_set == NULL && cip->priv_set != NULL) { 330613d8aaa1SSean Wilcox ret = setpflags(PRIV_AWARE, 1); 330713d8aaa1SSean Wilcox assert(ret == 0); 330813d8aaa1SSean Wilcox } 330913d8aaa1SSean Wilcox 33107c478bd9Sstevel@tonic-gate *fp = "setreuid"; 3311f48205beScasper if (setreuid(cip->uid, 3312f48205beScasper cip->euid != (uid_t)-1 ? cip->euid : cip->uid) != 0) { 33137c478bd9Sstevel@tonic-gate ret = errno; 33147c478bd9Sstevel@tonic-gate assert(ret == EINVAL || ret == EPERM); 33157c478bd9Sstevel@tonic-gate goto out; 33167c478bd9Sstevel@tonic-gate } 33177c478bd9Sstevel@tonic-gate 33187c478bd9Sstevel@tonic-gate *fp = "setppriv"; 33197c478bd9Sstevel@tonic-gate if (cip->priv_set != NULL) { 33207c478bd9Sstevel@tonic-gate if (setppriv(PRIV_SET, PRIV_PERMITTED, cip->priv_set) != 0) { 33217c478bd9Sstevel@tonic-gate ret = errno; 33227c478bd9Sstevel@tonic-gate assert(ret == EFAULT || ret == EPERM); 33237c478bd9Sstevel@tonic-gate goto out; 33247c478bd9Sstevel@tonic-gate } 33257c478bd9Sstevel@tonic-gate } 33267c478bd9Sstevel@tonic-gate 33272a3221a4Svp157776 /* 33282a3221a4Svp157776 * The last thing to do is chdir to the specified working directory. 33292a3221a4Svp157776 * This should come after the uid switching as only the user might 33302a3221a4Svp157776 * have access to the specified directory. 33312a3221a4Svp157776 */ 33322a3221a4Svp157776 if (cip->working_dir != NULL) { 33333eae19d9Swesolows do { 33342a3221a4Svp157776 r = chdir(cip->working_dir); 33353eae19d9Swesolows } while (r != 0 && errno == EINTR); 33362a3221a4Svp157776 if (r != 0) { 33372a3221a4Svp157776 *fp = "chdir"; 33382a3221a4Svp157776 ret = errno; 33392a3221a4Svp157776 goto out; 33402a3221a4Svp157776 } 33412a3221a4Svp157776 } 33422a3221a4Svp157776 33437c478bd9Sstevel@tonic-gate ret = 0; 33447c478bd9Sstevel@tonic-gate out: 33457c478bd9Sstevel@tonic-gate free(cip->pwbuf); 33467c478bd9Sstevel@tonic-gate cip->pwbuf = NULL; 33477c478bd9Sstevel@tonic-gate return (ret); 33487c478bd9Sstevel@tonic-gate } 33497c478bd9Sstevel@tonic-gate 33507c478bd9Sstevel@tonic-gate void 33517c478bd9Sstevel@tonic-gate restarter_free_method_context(struct method_context *mcp) 33527c478bd9Sstevel@tonic-gate { 33537c478bd9Sstevel@tonic-gate size_t i; 33547c478bd9Sstevel@tonic-gate 33557c478bd9Sstevel@tonic-gate if (mcp->lpriv_set != NULL) 33567c478bd9Sstevel@tonic-gate priv_freeset(mcp->lpriv_set); 33577c478bd9Sstevel@tonic-gate if (mcp->priv_set != NULL) 33587c478bd9Sstevel@tonic-gate priv_freeset(mcp->priv_set); 33597c478bd9Sstevel@tonic-gate 33607c478bd9Sstevel@tonic-gate if (mcp->env != NULL) { 33617c478bd9Sstevel@tonic-gate for (i = 0; i < mcp->env_sz; i++) 33627c478bd9Sstevel@tonic-gate free(mcp->env[i]); 33637c478bd9Sstevel@tonic-gate free(mcp->env); 33647c478bd9Sstevel@tonic-gate } 33657c478bd9Sstevel@tonic-gate 33667c478bd9Sstevel@tonic-gate free(mcp->working_dir); 33677c478bd9Sstevel@tonic-gate free(mcp->corefile_pattern); 33687c478bd9Sstevel@tonic-gate free(mcp->project); 33697c478bd9Sstevel@tonic-gate free(mcp->resource_pool); 33707c478bd9Sstevel@tonic-gate free(mcp); 33717c478bd9Sstevel@tonic-gate } 33727c478bd9Sstevel@tonic-gate 33737c478bd9Sstevel@tonic-gate /* 33747c478bd9Sstevel@tonic-gate * Method keyword functions 33757c478bd9Sstevel@tonic-gate */ 33767c478bd9Sstevel@tonic-gate 33777c478bd9Sstevel@tonic-gate int 33787c478bd9Sstevel@tonic-gate restarter_is_null_method(const char *meth) 33797c478bd9Sstevel@tonic-gate { 33807c478bd9Sstevel@tonic-gate return (strcmp(meth, MKW_TRUE) == 0); 33817c478bd9Sstevel@tonic-gate } 33827c478bd9Sstevel@tonic-gate 33837c478bd9Sstevel@tonic-gate static int 33847c478bd9Sstevel@tonic-gate is_kill_method(const char *method, const char *kill_str, 33857c478bd9Sstevel@tonic-gate size_t kill_str_len) 33867c478bd9Sstevel@tonic-gate { 33877c478bd9Sstevel@tonic-gate const char *cp; 33887c478bd9Sstevel@tonic-gate int sig; 33897c478bd9Sstevel@tonic-gate 33907c478bd9Sstevel@tonic-gate if (strncmp(method, kill_str, kill_str_len) != 0 || 33917c478bd9Sstevel@tonic-gate (method[kill_str_len] != '\0' && 33927c478bd9Sstevel@tonic-gate !isspace(method[kill_str_len]))) 33937c478bd9Sstevel@tonic-gate return (-1); 33947c478bd9Sstevel@tonic-gate 33957c478bd9Sstevel@tonic-gate cp = method + kill_str_len; 33967c478bd9Sstevel@tonic-gate while (*cp != '\0' && isspace(*cp)) 33977c478bd9Sstevel@tonic-gate ++cp; 33987c478bd9Sstevel@tonic-gate 33997c478bd9Sstevel@tonic-gate if (*cp == '\0') 34007c478bd9Sstevel@tonic-gate return (SIGTERM); 34017c478bd9Sstevel@tonic-gate 34027c478bd9Sstevel@tonic-gate if (*cp != '-') 34037c478bd9Sstevel@tonic-gate return (-1); 34047c478bd9Sstevel@tonic-gate 34057c478bd9Sstevel@tonic-gate return (str2sig(cp + 1, &sig) == 0 ? sig : -1); 34067c478bd9Sstevel@tonic-gate } 34077c478bd9Sstevel@tonic-gate 34087c478bd9Sstevel@tonic-gate int 34097c478bd9Sstevel@tonic-gate restarter_is_kill_proc_method(const char *method) 34107c478bd9Sstevel@tonic-gate { 34117c478bd9Sstevel@tonic-gate return (is_kill_method(method, MKW_KILL_PROC, 34127c478bd9Sstevel@tonic-gate sizeof (MKW_KILL_PROC) - 1)); 34137c478bd9Sstevel@tonic-gate } 34147c478bd9Sstevel@tonic-gate 34157c478bd9Sstevel@tonic-gate int 34167c478bd9Sstevel@tonic-gate restarter_is_kill_method(const char *method) 34177c478bd9Sstevel@tonic-gate { 34187c478bd9Sstevel@tonic-gate return (is_kill_method(method, MKW_KILL, sizeof (MKW_KILL) - 1)); 34197c478bd9Sstevel@tonic-gate } 34207c478bd9Sstevel@tonic-gate 34217c478bd9Sstevel@tonic-gate /* 34227c478bd9Sstevel@tonic-gate * Stubs for now. 34237c478bd9Sstevel@tonic-gate */ 34247c478bd9Sstevel@tonic-gate 34257c478bd9Sstevel@tonic-gate /* ARGSUSED */ 34267c478bd9Sstevel@tonic-gate int 34277c478bd9Sstevel@tonic-gate restarter_event_get_enabled(restarter_event_t *e) 34287c478bd9Sstevel@tonic-gate { 34297c478bd9Sstevel@tonic-gate return (-1); 34307c478bd9Sstevel@tonic-gate } 34317c478bd9Sstevel@tonic-gate 34327c478bd9Sstevel@tonic-gate /* ARGSUSED */ 34337c478bd9Sstevel@tonic-gate uint64_t 34347c478bd9Sstevel@tonic-gate restarter_event_get_seq(restarter_event_t *e) 34357c478bd9Sstevel@tonic-gate { 34367c478bd9Sstevel@tonic-gate return (-1); 34377c478bd9Sstevel@tonic-gate } 34387c478bd9Sstevel@tonic-gate 34397c478bd9Sstevel@tonic-gate /* ARGSUSED */ 34407c478bd9Sstevel@tonic-gate void 34417c478bd9Sstevel@tonic-gate restarter_event_get_time(restarter_event_t *e, hrtime_t *time) 34427c478bd9Sstevel@tonic-gate { 34437c478bd9Sstevel@tonic-gate } 3444eb1a3463STruong Nguyen 3445eb1a3463STruong Nguyen /* 3446eb1a3463STruong Nguyen * Check for and validate fmri specified in restarter_actions/auxiliary_fmri 3447eb1a3463STruong Nguyen * 0 - Success 3448eb1a3463STruong Nguyen * 1 - Failure 3449eb1a3463STruong Nguyen */ 3450eb1a3463STruong Nguyen int 3451eb1a3463STruong Nguyen restarter_inst_validate_ractions_aux_fmri(scf_instance_t *inst) 3452eb1a3463STruong Nguyen { 3453eb1a3463STruong Nguyen scf_handle_t *h; 3454eb1a3463STruong Nguyen scf_propertygroup_t *pg; 3455eb1a3463STruong Nguyen scf_property_t *prop; 3456eb1a3463STruong Nguyen scf_value_t *val; 3457eb1a3463STruong Nguyen char *aux_fmri; 3458eb1a3463STruong Nguyen size_t size = scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH); 3459eb1a3463STruong Nguyen int ret = 1; 3460eb1a3463STruong Nguyen 3461eb1a3463STruong Nguyen if ((aux_fmri = malloc(size)) == NULL) 3462eb1a3463STruong Nguyen return (1); 3463eb1a3463STruong Nguyen 3464eb1a3463STruong Nguyen h = scf_instance_handle(inst); 3465eb1a3463STruong Nguyen 3466eb1a3463STruong Nguyen pg = scf_pg_create(h); 3467eb1a3463STruong Nguyen prop = scf_property_create(h); 3468eb1a3463STruong Nguyen val = scf_value_create(h); 3469eb1a3463STruong Nguyen if (pg == NULL || prop == NULL || val == NULL) 3470eb1a3463STruong Nguyen goto out; 3471eb1a3463STruong Nguyen 3472eb1a3463STruong Nguyen if (instance_get_or_add_pg(inst, SCF_PG_RESTARTER_ACTIONS, 3473eb1a3463STruong Nguyen SCF_PG_RESTARTER_ACTIONS_TYPE, SCF_PG_RESTARTER_ACTIONS_FLAGS, 3474eb1a3463STruong Nguyen pg) != SCF_SUCCESS) 3475eb1a3463STruong Nguyen goto out; 3476eb1a3463STruong Nguyen 3477eb1a3463STruong Nguyen if (get_astring_val(pg, SCF_PROPERTY_AUX_FMRI, aux_fmri, size, 3478eb1a3463STruong Nguyen prop, val) != SCF_SUCCESS) 3479eb1a3463STruong Nguyen goto out; 3480eb1a3463STruong Nguyen 3481eb1a3463STruong Nguyen if (scf_parse_fmri(aux_fmri, NULL, NULL, NULL, NULL, NULL, 3482eb1a3463STruong Nguyen NULL) != SCF_SUCCESS) 3483eb1a3463STruong Nguyen goto out; 3484eb1a3463STruong Nguyen 3485eb1a3463STruong Nguyen ret = 0; 3486eb1a3463STruong Nguyen 3487eb1a3463STruong Nguyen out: 3488eb1a3463STruong Nguyen free(aux_fmri); 3489eb1a3463STruong Nguyen scf_value_destroy(val); 3490eb1a3463STruong Nguyen scf_property_destroy(prop); 3491eb1a3463STruong Nguyen scf_pg_destroy(pg); 3492eb1a3463STruong Nguyen return (ret); 3493eb1a3463STruong Nguyen } 3494eb1a3463STruong Nguyen 3495eb1a3463STruong Nguyen /* 3496eb1a3463STruong Nguyen * Get instance's boolean value in restarter_actions/auxiliary_tty 3497eb1a3463STruong Nguyen * Return -1 on failure 3498eb1a3463STruong Nguyen */ 3499eb1a3463STruong Nguyen int 3500eb1a3463STruong Nguyen restarter_inst_ractions_from_tty(scf_instance_t *inst) 3501eb1a3463STruong Nguyen { 3502eb1a3463STruong Nguyen scf_handle_t *h; 3503eb1a3463STruong Nguyen scf_propertygroup_t *pg; 3504eb1a3463STruong Nguyen scf_property_t *prop; 3505eb1a3463STruong Nguyen scf_value_t *val; 3506eb1a3463STruong Nguyen uint8_t has_tty; 3507eb1a3463STruong Nguyen int ret = -1; 3508eb1a3463STruong Nguyen 3509eb1a3463STruong Nguyen h = scf_instance_handle(inst); 3510eb1a3463STruong Nguyen pg = scf_pg_create(h); 3511eb1a3463STruong Nguyen prop = scf_property_create(h); 3512eb1a3463STruong Nguyen val = scf_value_create(h); 3513eb1a3463STruong Nguyen if (pg == NULL || prop == NULL || val == NULL) 3514eb1a3463STruong Nguyen goto out; 3515eb1a3463STruong Nguyen 3516eb1a3463STruong Nguyen if (instance_get_or_add_pg(inst, SCF_PG_RESTARTER_ACTIONS, 3517eb1a3463STruong Nguyen SCF_PG_RESTARTER_ACTIONS_TYPE, SCF_PG_RESTARTER_ACTIONS_FLAGS, 3518eb1a3463STruong Nguyen pg) != SCF_SUCCESS) 3519eb1a3463STruong Nguyen goto out; 3520eb1a3463STruong Nguyen 3521eb1a3463STruong Nguyen if (get_boolean_val(pg, SCF_PROPERTY_AUX_TTY, &has_tty, prop, 3522eb1a3463STruong Nguyen val) != SCF_SUCCESS) 3523eb1a3463STruong Nguyen goto out; 3524eb1a3463STruong Nguyen 3525eb1a3463STruong Nguyen ret = has_tty; 3526eb1a3463STruong Nguyen 3527eb1a3463STruong Nguyen out: 3528eb1a3463STruong Nguyen scf_value_destroy(val); 3529eb1a3463STruong Nguyen scf_property_destroy(prop); 3530eb1a3463STruong Nguyen scf_pg_destroy(pg); 3531eb1a3463STruong Nguyen return (ret); 3532eb1a3463STruong Nguyen } 3533eb1a3463STruong Nguyen 3534eb1a3463STruong Nguyen static int 3535eb1a3463STruong Nguyen restarter_inst_set_astring_prop(scf_instance_t *inst, const char *pgname, 3536eb1a3463STruong Nguyen const char *pgtype, uint32_t pgflags, const char *pname, const char *str) 3537eb1a3463STruong Nguyen { 3538eb1a3463STruong Nguyen scf_handle_t *h; 3539eb1a3463STruong Nguyen scf_propertygroup_t *pg; 3540eb1a3463STruong Nguyen scf_transaction_t *t; 3541eb1a3463STruong Nguyen scf_transaction_entry_t *e; 3542eb1a3463STruong Nguyen scf_value_t *v; 3543eb1a3463STruong Nguyen int ret = 1, r; 3544eb1a3463STruong Nguyen 3545eb1a3463STruong Nguyen h = scf_instance_handle(inst); 3546eb1a3463STruong Nguyen 3547eb1a3463STruong Nguyen pg = scf_pg_create(h); 3548eb1a3463STruong Nguyen t = scf_transaction_create(h); 3549eb1a3463STruong Nguyen e = scf_entry_create(h); 3550eb1a3463STruong Nguyen v = scf_value_create(h); 3551eb1a3463STruong Nguyen if (pg == NULL || t == NULL || e == NULL || v == NULL) 3552eb1a3463STruong Nguyen goto out; 3553eb1a3463STruong Nguyen 3554eb1a3463STruong Nguyen if (instance_get_or_add_pg(inst, pgname, pgtype, pgflags, pg)) 3555eb1a3463STruong Nguyen goto out; 3556eb1a3463STruong Nguyen 3557eb1a3463STruong Nguyen if (scf_value_set_astring(v, str) != SCF_SUCCESS) 3558eb1a3463STruong Nguyen goto out; 3559eb1a3463STruong Nguyen 3560eb1a3463STruong Nguyen for (;;) { 3561eb1a3463STruong Nguyen if (scf_transaction_start(t, pg) != 0) 3562eb1a3463STruong Nguyen goto out; 3563eb1a3463STruong Nguyen 3564eb1a3463STruong Nguyen if (tx_set_value(t, e, pname, SCF_TYPE_ASTRING, v) != 0) 3565eb1a3463STruong Nguyen goto out; 3566eb1a3463STruong Nguyen 3567eb1a3463STruong Nguyen if ((r = scf_transaction_commit(t)) == 1) 3568eb1a3463STruong Nguyen break; 3569eb1a3463STruong Nguyen 3570eb1a3463STruong Nguyen if (r == -1) 3571eb1a3463STruong Nguyen goto out; 3572eb1a3463STruong Nguyen 3573eb1a3463STruong Nguyen scf_transaction_reset(t); 3574eb1a3463STruong Nguyen if (scf_pg_update(pg) == -1) 3575eb1a3463STruong Nguyen goto out; 3576eb1a3463STruong Nguyen } 3577eb1a3463STruong Nguyen ret = 0; 3578eb1a3463STruong Nguyen 3579eb1a3463STruong Nguyen out: 3580eb1a3463STruong Nguyen scf_transaction_destroy(t); 3581eb1a3463STruong Nguyen scf_entry_destroy(e); 3582eb1a3463STruong Nguyen scf_value_destroy(v); 3583eb1a3463STruong Nguyen scf_pg_destroy(pg); 3584eb1a3463STruong Nguyen 3585eb1a3463STruong Nguyen return (ret); 3586eb1a3463STruong Nguyen } 3587eb1a3463STruong Nguyen 3588eb1a3463STruong Nguyen int 3589eb1a3463STruong Nguyen restarter_inst_set_aux_fmri(scf_instance_t *inst) 3590eb1a3463STruong Nguyen { 3591eb1a3463STruong Nguyen scf_handle_t *h; 3592eb1a3463STruong Nguyen scf_propertygroup_t *pg; 3593eb1a3463STruong Nguyen scf_property_t *prop; 3594eb1a3463STruong Nguyen scf_value_t *val; 3595eb1a3463STruong Nguyen char *aux_fmri; 3596eb1a3463STruong Nguyen size_t size = scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH); 3597eb1a3463STruong Nguyen int ret = 1; 3598eb1a3463STruong Nguyen 3599eb1a3463STruong Nguyen if ((aux_fmri = malloc(size)) == NULL) 3600eb1a3463STruong Nguyen return (1); 3601eb1a3463STruong Nguyen 3602eb1a3463STruong Nguyen h = scf_instance_handle(inst); 3603eb1a3463STruong Nguyen 3604eb1a3463STruong Nguyen pg = scf_pg_create(h); 3605eb1a3463STruong Nguyen prop = scf_property_create(h); 3606eb1a3463STruong Nguyen val = scf_value_create(h); 3607eb1a3463STruong Nguyen if (pg == NULL || prop == NULL || val == NULL) 3608eb1a3463STruong Nguyen goto out; 3609eb1a3463STruong Nguyen 3610eb1a3463STruong Nguyen /* 3611eb1a3463STruong Nguyen * Get auxiliary_fmri value from restarter_actions pg 3612eb1a3463STruong Nguyen */ 3613eb1a3463STruong Nguyen if (instance_get_or_add_pg(inst, SCF_PG_RESTARTER_ACTIONS, 3614eb1a3463STruong Nguyen SCF_PG_RESTARTER_ACTIONS_TYPE, SCF_PG_RESTARTER_ACTIONS_FLAGS, 3615eb1a3463STruong Nguyen pg) != SCF_SUCCESS) 3616eb1a3463STruong Nguyen goto out; 3617eb1a3463STruong Nguyen 3618eb1a3463STruong Nguyen if (get_astring_val(pg, SCF_PROPERTY_AUX_FMRI, aux_fmri, size, 3619eb1a3463STruong Nguyen prop, val) != SCF_SUCCESS) 3620eb1a3463STruong Nguyen goto out; 3621eb1a3463STruong Nguyen 3622eb1a3463STruong Nguyen /* 3623eb1a3463STruong Nguyen * Populate restarter/auxiliary_fmri with the obtained fmri. 3624eb1a3463STruong Nguyen */ 3625eb1a3463STruong Nguyen ret = restarter_inst_set_astring_prop(inst, SCF_PG_RESTARTER, 3626eb1a3463STruong Nguyen SCF_PG_RESTARTER_TYPE, SCF_PG_RESTARTER_FLAGS, 3627eb1a3463STruong Nguyen SCF_PROPERTY_AUX_FMRI, aux_fmri); 3628eb1a3463STruong Nguyen 3629eb1a3463STruong Nguyen out: 3630eb1a3463STruong Nguyen free(aux_fmri); 3631eb1a3463STruong Nguyen scf_value_destroy(val); 3632eb1a3463STruong Nguyen scf_property_destroy(prop); 3633eb1a3463STruong Nguyen scf_pg_destroy(pg); 3634eb1a3463STruong Nguyen return (ret); 3635eb1a3463STruong Nguyen } 3636eb1a3463STruong Nguyen 3637eb1a3463STruong Nguyen int 3638eb1a3463STruong Nguyen restarter_inst_reset_aux_fmri(scf_instance_t *inst) 3639eb1a3463STruong Nguyen { 3640eb1a3463STruong Nguyen return (scf_instance_delete_prop(inst, 3641eb1a3463STruong Nguyen SCF_PG_RESTARTER, SCF_PROPERTY_AUX_FMRI)); 3642eb1a3463STruong Nguyen } 3643eb1a3463STruong Nguyen 3644eb1a3463STruong Nguyen int 3645eb1a3463STruong Nguyen restarter_inst_reset_ractions_aux_fmri(scf_instance_t *inst) 3646eb1a3463STruong Nguyen { 3647eb1a3463STruong Nguyen return (scf_instance_delete_prop(inst, 3648eb1a3463STruong Nguyen SCF_PG_RESTARTER_ACTIONS, SCF_PROPERTY_AUX_FMRI)); 3649eb1a3463STruong Nguyen } 3650