1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate /* 30*7c478bd9Sstevel@tonic-gate * This is the client layer for svc.configd. All direct protocol interactions 31*7c478bd9Sstevel@tonic-gate * are handled here. 32*7c478bd9Sstevel@tonic-gate * 33*7c478bd9Sstevel@tonic-gate * Essentially, the job of this layer is to turn the idempotent protocol 34*7c478bd9Sstevel@tonic-gate * into a series of non-idempotent calls into the object layer, while 35*7c478bd9Sstevel@tonic-gate * also handling the necessary locking. 36*7c478bd9Sstevel@tonic-gate */ 37*7c478bd9Sstevel@tonic-gate 38*7c478bd9Sstevel@tonic-gate #include <alloca.h> 39*7c478bd9Sstevel@tonic-gate #include <assert.h> 40*7c478bd9Sstevel@tonic-gate #include <door.h> 41*7c478bd9Sstevel@tonic-gate #include <errno.h> 42*7c478bd9Sstevel@tonic-gate #include <limits.h> 43*7c478bd9Sstevel@tonic-gate #include <pthread.h> 44*7c478bd9Sstevel@tonic-gate #include <stdio.h> 45*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 46*7c478bd9Sstevel@tonic-gate #include <string.h> 47*7c478bd9Sstevel@tonic-gate #include <unistd.h> 48*7c478bd9Sstevel@tonic-gate 49*7c478bd9Sstevel@tonic-gate #include <libuutil.h> 50*7c478bd9Sstevel@tonic-gate 51*7c478bd9Sstevel@tonic-gate #include "configd.h" 52*7c478bd9Sstevel@tonic-gate #include "repcache_protocol.h" 53*7c478bd9Sstevel@tonic-gate 54*7c478bd9Sstevel@tonic-gate #define INVALID_CHANGEID (0) 55*7c478bd9Sstevel@tonic-gate #define INVALID_DOORID ((door_id_t)-1) 56*7c478bd9Sstevel@tonic-gate #define INVALID_RESULT ((rep_protocol_responseid_t)INT_MIN) 57*7c478bd9Sstevel@tonic-gate 58*7c478bd9Sstevel@tonic-gate /* 59*7c478bd9Sstevel@tonic-gate * lint doesn't like constant assertions 60*7c478bd9Sstevel@tonic-gate */ 61*7c478bd9Sstevel@tonic-gate #ifdef lint 62*7c478bd9Sstevel@tonic-gate #define assert_nolint(x) (void)0 63*7c478bd9Sstevel@tonic-gate #else 64*7c478bd9Sstevel@tonic-gate #define assert_nolint(x) assert(x) 65*7c478bd9Sstevel@tonic-gate #endif 66*7c478bd9Sstevel@tonic-gate 67*7c478bd9Sstevel@tonic-gate /* 68*7c478bd9Sstevel@tonic-gate * Protects client linkage and the freelist 69*7c478bd9Sstevel@tonic-gate */ 70*7c478bd9Sstevel@tonic-gate #define CLIENT_HASH_SIZE 64 71*7c478bd9Sstevel@tonic-gate 72*7c478bd9Sstevel@tonic-gate #pragma align 64(client_hash) 73*7c478bd9Sstevel@tonic-gate static client_bucket_t client_hash[CLIENT_HASH_SIZE]; 74*7c478bd9Sstevel@tonic-gate 75*7c478bd9Sstevel@tonic-gate static uu_list_pool_t *entity_pool; 76*7c478bd9Sstevel@tonic-gate static uu_list_pool_t *iter_pool; 77*7c478bd9Sstevel@tonic-gate static uu_list_pool_t *client_pool; 78*7c478bd9Sstevel@tonic-gate 79*7c478bd9Sstevel@tonic-gate #define CLIENT_HASH(id) (&client_hash[((id) & (CLIENT_HASH_SIZE - 1))]) 80*7c478bd9Sstevel@tonic-gate 81*7c478bd9Sstevel@tonic-gate uint_t request_log_size = 1024; /* tunable, before we start */ 82*7c478bd9Sstevel@tonic-gate 83*7c478bd9Sstevel@tonic-gate static pthread_mutex_t request_log_lock = PTHREAD_MUTEX_INITIALIZER; 84*7c478bd9Sstevel@tonic-gate static uint_t request_log_cur; 85*7c478bd9Sstevel@tonic-gate request_log_entry_t *request_log; 86*7c478bd9Sstevel@tonic-gate 87*7c478bd9Sstevel@tonic-gate static uint32_t client_maxid; 88*7c478bd9Sstevel@tonic-gate static pthread_mutex_t client_lock; /* protects client_maxid */ 89*7c478bd9Sstevel@tonic-gate 90*7c478bd9Sstevel@tonic-gate static request_log_entry_t * 91*7c478bd9Sstevel@tonic-gate get_log(void) 92*7c478bd9Sstevel@tonic-gate { 93*7c478bd9Sstevel@tonic-gate thread_info_t *ti = thread_self(); 94*7c478bd9Sstevel@tonic-gate return (&ti->ti_log); 95*7c478bd9Sstevel@tonic-gate } 96*7c478bd9Sstevel@tonic-gate 97*7c478bd9Sstevel@tonic-gate void 98*7c478bd9Sstevel@tonic-gate log_enter(request_log_entry_t *rlp) 99*7c478bd9Sstevel@tonic-gate { 100*7c478bd9Sstevel@tonic-gate if (rlp->rl_start != 0 && request_log != NULL) { 101*7c478bd9Sstevel@tonic-gate request_log_entry_t *logrlp; 102*7c478bd9Sstevel@tonic-gate 103*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&request_log_lock); 104*7c478bd9Sstevel@tonic-gate assert(request_log_cur < request_log_size); 105*7c478bd9Sstevel@tonic-gate logrlp = &request_log[request_log_cur++]; 106*7c478bd9Sstevel@tonic-gate if (request_log_cur == request_log_size) 107*7c478bd9Sstevel@tonic-gate request_log_cur = 0; 108*7c478bd9Sstevel@tonic-gate (void) memcpy(logrlp, rlp, sizeof (*rlp)); 109*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&request_log_lock); 110*7c478bd9Sstevel@tonic-gate } 111*7c478bd9Sstevel@tonic-gate } 112*7c478bd9Sstevel@tonic-gate 113*7c478bd9Sstevel@tonic-gate /* 114*7c478bd9Sstevel@tonic-gate * Note that the svc.configd dmod will join all of the per-thread log entries 115*7c478bd9Sstevel@tonic-gate * with the main log, so that even if the log is disabled, there is some 116*7c478bd9Sstevel@tonic-gate * information available. 117*7c478bd9Sstevel@tonic-gate */ 118*7c478bd9Sstevel@tonic-gate static request_log_entry_t * 119*7c478bd9Sstevel@tonic-gate start_log(uint32_t clientid) 120*7c478bd9Sstevel@tonic-gate { 121*7c478bd9Sstevel@tonic-gate request_log_entry_t *rlp = get_log(); 122*7c478bd9Sstevel@tonic-gate 123*7c478bd9Sstevel@tonic-gate log_enter(rlp); 124*7c478bd9Sstevel@tonic-gate 125*7c478bd9Sstevel@tonic-gate (void) memset(rlp, 0, sizeof (*rlp)); 126*7c478bd9Sstevel@tonic-gate rlp->rl_start = gethrtime(); 127*7c478bd9Sstevel@tonic-gate rlp->rl_tid = pthread_self(); 128*7c478bd9Sstevel@tonic-gate rlp->rl_clientid = clientid; 129*7c478bd9Sstevel@tonic-gate 130*7c478bd9Sstevel@tonic-gate return (rlp); 131*7c478bd9Sstevel@tonic-gate } 132*7c478bd9Sstevel@tonic-gate 133*7c478bd9Sstevel@tonic-gate void 134*7c478bd9Sstevel@tonic-gate end_log(void) 135*7c478bd9Sstevel@tonic-gate { 136*7c478bd9Sstevel@tonic-gate request_log_entry_t *rlp = get_log(); 137*7c478bd9Sstevel@tonic-gate 138*7c478bd9Sstevel@tonic-gate rlp->rl_end = gethrtime(); 139*7c478bd9Sstevel@tonic-gate } 140*7c478bd9Sstevel@tonic-gate 141*7c478bd9Sstevel@tonic-gate static void 142*7c478bd9Sstevel@tonic-gate add_log_ptr(request_log_entry_t *rlp, enum rc_ptr_type type, uint32_t id, 143*7c478bd9Sstevel@tonic-gate void *ptr) 144*7c478bd9Sstevel@tonic-gate { 145*7c478bd9Sstevel@tonic-gate request_log_ptr_t *rpp; 146*7c478bd9Sstevel@tonic-gate 147*7c478bd9Sstevel@tonic-gate if (rlp == NULL) 148*7c478bd9Sstevel@tonic-gate return; 149*7c478bd9Sstevel@tonic-gate 150*7c478bd9Sstevel@tonic-gate if (rlp->rl_num_ptrs >= MAX_PTRS) 151*7c478bd9Sstevel@tonic-gate return; 152*7c478bd9Sstevel@tonic-gate 153*7c478bd9Sstevel@tonic-gate rpp = &rlp->rl_ptrs[rlp->rl_num_ptrs++]; 154*7c478bd9Sstevel@tonic-gate rpp->rlp_type = type; 155*7c478bd9Sstevel@tonic-gate rpp->rlp_id = id; 156*7c478bd9Sstevel@tonic-gate rpp->rlp_ptr = ptr; 157*7c478bd9Sstevel@tonic-gate 158*7c478bd9Sstevel@tonic-gate /* 159*7c478bd9Sstevel@tonic-gate * For entities, it's useful to have the node pointer at the start 160*7c478bd9Sstevel@tonic-gate * of the request. 161*7c478bd9Sstevel@tonic-gate */ 162*7c478bd9Sstevel@tonic-gate if (type == RC_PTR_TYPE_ENTITY && ptr != NULL) 163*7c478bd9Sstevel@tonic-gate rpp->rlp_data = ((repcache_entity_t *)ptr)->re_node.rnp_node; 164*7c478bd9Sstevel@tonic-gate } 165*7c478bd9Sstevel@tonic-gate 166*7c478bd9Sstevel@tonic-gate int 167*7c478bd9Sstevel@tonic-gate client_is_privileged(void) 168*7c478bd9Sstevel@tonic-gate { 169*7c478bd9Sstevel@tonic-gate thread_info_t *ti = thread_self(); 170*7c478bd9Sstevel@tonic-gate 171*7c478bd9Sstevel@tonic-gate ucred_t *uc; 172*7c478bd9Sstevel@tonic-gate 173*7c478bd9Sstevel@tonic-gate if (ti->ti_active_client != NULL && 174*7c478bd9Sstevel@tonic-gate ti->ti_active_client->rc_all_auths) 175*7c478bd9Sstevel@tonic-gate return (1); 176*7c478bd9Sstevel@tonic-gate 177*7c478bd9Sstevel@tonic-gate if ((uc = get_ucred()) == NULL) 178*7c478bd9Sstevel@tonic-gate return (0); 179*7c478bd9Sstevel@tonic-gate 180*7c478bd9Sstevel@tonic-gate return (ucred_is_privileged(uc)); 181*7c478bd9Sstevel@tonic-gate } 182*7c478bd9Sstevel@tonic-gate 183*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 184*7c478bd9Sstevel@tonic-gate static int 185*7c478bd9Sstevel@tonic-gate client_compare(const void *lc_arg, const void *rc_arg, void *private) 186*7c478bd9Sstevel@tonic-gate { 187*7c478bd9Sstevel@tonic-gate uint32_t l_id = ((const repcache_client_t *)lc_arg)->rc_id; 188*7c478bd9Sstevel@tonic-gate uint32_t r_id = ((const repcache_client_t *)rc_arg)->rc_id; 189*7c478bd9Sstevel@tonic-gate 190*7c478bd9Sstevel@tonic-gate if (l_id > r_id) 191*7c478bd9Sstevel@tonic-gate return (1); 192*7c478bd9Sstevel@tonic-gate if (l_id < r_id) 193*7c478bd9Sstevel@tonic-gate return (-1); 194*7c478bd9Sstevel@tonic-gate return (0); 195*7c478bd9Sstevel@tonic-gate } 196*7c478bd9Sstevel@tonic-gate 197*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 198*7c478bd9Sstevel@tonic-gate static int 199*7c478bd9Sstevel@tonic-gate entity_compare(const void *lc_arg, const void *rc_arg, void *private) 200*7c478bd9Sstevel@tonic-gate { 201*7c478bd9Sstevel@tonic-gate uint32_t l_id = ((const repcache_entity_t *)lc_arg)->re_id; 202*7c478bd9Sstevel@tonic-gate uint32_t r_id = ((const repcache_entity_t *)rc_arg)->re_id; 203*7c478bd9Sstevel@tonic-gate 204*7c478bd9Sstevel@tonic-gate if (l_id > r_id) 205*7c478bd9Sstevel@tonic-gate return (1); 206*7c478bd9Sstevel@tonic-gate if (l_id < r_id) 207*7c478bd9Sstevel@tonic-gate return (-1); 208*7c478bd9Sstevel@tonic-gate return (0); 209*7c478bd9Sstevel@tonic-gate } 210*7c478bd9Sstevel@tonic-gate 211*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 212*7c478bd9Sstevel@tonic-gate static int 213*7c478bd9Sstevel@tonic-gate iter_compare(const void *lc_arg, const void *rc_arg, void *private) 214*7c478bd9Sstevel@tonic-gate { 215*7c478bd9Sstevel@tonic-gate uint32_t l_id = ((const repcache_iter_t *)lc_arg)->ri_id; 216*7c478bd9Sstevel@tonic-gate uint32_t r_id = ((const repcache_iter_t *)rc_arg)->ri_id; 217*7c478bd9Sstevel@tonic-gate 218*7c478bd9Sstevel@tonic-gate if (l_id > r_id) 219*7c478bd9Sstevel@tonic-gate return (1); 220*7c478bd9Sstevel@tonic-gate if (l_id < r_id) 221*7c478bd9Sstevel@tonic-gate return (-1); 222*7c478bd9Sstevel@tonic-gate return (0); 223*7c478bd9Sstevel@tonic-gate } 224*7c478bd9Sstevel@tonic-gate 225*7c478bd9Sstevel@tonic-gate static int 226*7c478bd9Sstevel@tonic-gate client_hash_init(void) 227*7c478bd9Sstevel@tonic-gate { 228*7c478bd9Sstevel@tonic-gate int x; 229*7c478bd9Sstevel@tonic-gate 230*7c478bd9Sstevel@tonic-gate assert_nolint(offsetof(repcache_entity_t, re_id) == 0); 231*7c478bd9Sstevel@tonic-gate entity_pool = uu_list_pool_create("repcache_entitys", 232*7c478bd9Sstevel@tonic-gate sizeof (repcache_entity_t), offsetof(repcache_entity_t, re_link), 233*7c478bd9Sstevel@tonic-gate entity_compare, UU_LIST_POOL_DEBUG); 234*7c478bd9Sstevel@tonic-gate 235*7c478bd9Sstevel@tonic-gate assert_nolint(offsetof(repcache_iter_t, ri_id) == 0); 236*7c478bd9Sstevel@tonic-gate iter_pool = uu_list_pool_create("repcache_iters", 237*7c478bd9Sstevel@tonic-gate sizeof (repcache_iter_t), offsetof(repcache_iter_t, ri_link), 238*7c478bd9Sstevel@tonic-gate iter_compare, UU_LIST_POOL_DEBUG); 239*7c478bd9Sstevel@tonic-gate 240*7c478bd9Sstevel@tonic-gate assert_nolint(offsetof(repcache_client_t, rc_id) == 0); 241*7c478bd9Sstevel@tonic-gate client_pool = uu_list_pool_create("repcache_clients", 242*7c478bd9Sstevel@tonic-gate sizeof (repcache_client_t), offsetof(repcache_client_t, rc_link), 243*7c478bd9Sstevel@tonic-gate client_compare, UU_LIST_POOL_DEBUG); 244*7c478bd9Sstevel@tonic-gate 245*7c478bd9Sstevel@tonic-gate if (entity_pool == NULL || iter_pool == NULL || client_pool == NULL) 246*7c478bd9Sstevel@tonic-gate return (0); 247*7c478bd9Sstevel@tonic-gate 248*7c478bd9Sstevel@tonic-gate for (x = 0; x < CLIENT_HASH_SIZE; x++) { 249*7c478bd9Sstevel@tonic-gate uu_list_t *lp = uu_list_create(client_pool, &client_hash[x], 250*7c478bd9Sstevel@tonic-gate UU_LIST_SORTED); 251*7c478bd9Sstevel@tonic-gate if (lp == NULL) 252*7c478bd9Sstevel@tonic-gate return (0); 253*7c478bd9Sstevel@tonic-gate 254*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_init(&client_hash[x].cb_lock, NULL); 255*7c478bd9Sstevel@tonic-gate client_hash[x].cb_list = lp; 256*7c478bd9Sstevel@tonic-gate } 257*7c478bd9Sstevel@tonic-gate 258*7c478bd9Sstevel@tonic-gate return (1); 259*7c478bd9Sstevel@tonic-gate } 260*7c478bd9Sstevel@tonic-gate 261*7c478bd9Sstevel@tonic-gate static repcache_client_t * 262*7c478bd9Sstevel@tonic-gate client_alloc(void) 263*7c478bd9Sstevel@tonic-gate { 264*7c478bd9Sstevel@tonic-gate repcache_client_t *cp; 265*7c478bd9Sstevel@tonic-gate cp = uu_zalloc(sizeof (*cp)); 266*7c478bd9Sstevel@tonic-gate if (cp == NULL) 267*7c478bd9Sstevel@tonic-gate return (NULL); 268*7c478bd9Sstevel@tonic-gate 269*7c478bd9Sstevel@tonic-gate cp->rc_entity_list = uu_list_create(entity_pool, cp, UU_LIST_SORTED); 270*7c478bd9Sstevel@tonic-gate if (cp->rc_entity_list == NULL) 271*7c478bd9Sstevel@tonic-gate goto fail; 272*7c478bd9Sstevel@tonic-gate 273*7c478bd9Sstevel@tonic-gate cp->rc_iter_list = uu_list_create(iter_pool, cp, UU_LIST_SORTED); 274*7c478bd9Sstevel@tonic-gate if (cp->rc_iter_list == NULL) 275*7c478bd9Sstevel@tonic-gate goto fail; 276*7c478bd9Sstevel@tonic-gate 277*7c478bd9Sstevel@tonic-gate uu_list_node_init(cp, &cp->rc_link, client_pool); 278*7c478bd9Sstevel@tonic-gate 279*7c478bd9Sstevel@tonic-gate cp->rc_doorfd = -1; 280*7c478bd9Sstevel@tonic-gate cp->rc_doorid = INVALID_DOORID; 281*7c478bd9Sstevel@tonic-gate 282*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_init(&cp->rc_lock, NULL); 283*7c478bd9Sstevel@tonic-gate 284*7c478bd9Sstevel@tonic-gate rc_node_ptr_init(&cp->rc_notify_ptr); 285*7c478bd9Sstevel@tonic-gate 286*7c478bd9Sstevel@tonic-gate return (cp); 287*7c478bd9Sstevel@tonic-gate 288*7c478bd9Sstevel@tonic-gate fail: 289*7c478bd9Sstevel@tonic-gate if (cp->rc_iter_list != NULL) 290*7c478bd9Sstevel@tonic-gate uu_list_destroy(cp->rc_iter_list); 291*7c478bd9Sstevel@tonic-gate if (cp->rc_entity_list != NULL) 292*7c478bd9Sstevel@tonic-gate uu_list_destroy(cp->rc_entity_list); 293*7c478bd9Sstevel@tonic-gate uu_free(cp); 294*7c478bd9Sstevel@tonic-gate return (NULL); 295*7c478bd9Sstevel@tonic-gate } 296*7c478bd9Sstevel@tonic-gate 297*7c478bd9Sstevel@tonic-gate static void 298*7c478bd9Sstevel@tonic-gate client_free(repcache_client_t *cp) 299*7c478bd9Sstevel@tonic-gate { 300*7c478bd9Sstevel@tonic-gate assert(cp->rc_insert_thr == 0); 301*7c478bd9Sstevel@tonic-gate assert(cp->rc_refcnt == 0); 302*7c478bd9Sstevel@tonic-gate assert(cp->rc_doorfd == -1); 303*7c478bd9Sstevel@tonic-gate assert(cp->rc_doorid == INVALID_DOORID); 304*7c478bd9Sstevel@tonic-gate assert(uu_list_first(cp->rc_entity_list) == NULL); 305*7c478bd9Sstevel@tonic-gate assert(uu_list_first(cp->rc_iter_list) == NULL); 306*7c478bd9Sstevel@tonic-gate uu_list_destroy(cp->rc_entity_list); 307*7c478bd9Sstevel@tonic-gate uu_list_destroy(cp->rc_iter_list); 308*7c478bd9Sstevel@tonic-gate uu_list_node_fini(cp, &cp->rc_link, client_pool); 309*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_destroy(&cp->rc_lock); 310*7c478bd9Sstevel@tonic-gate uu_free(cp); 311*7c478bd9Sstevel@tonic-gate } 312*7c478bd9Sstevel@tonic-gate 313*7c478bd9Sstevel@tonic-gate static void 314*7c478bd9Sstevel@tonic-gate client_insert(repcache_client_t *cp) 315*7c478bd9Sstevel@tonic-gate { 316*7c478bd9Sstevel@tonic-gate client_bucket_t *bp = CLIENT_HASH(cp->rc_id); 317*7c478bd9Sstevel@tonic-gate uu_list_index_t idx; 318*7c478bd9Sstevel@tonic-gate 319*7c478bd9Sstevel@tonic-gate assert(cp->rc_id > 0); 320*7c478bd9Sstevel@tonic-gate 321*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&bp->cb_lock); 322*7c478bd9Sstevel@tonic-gate /* 323*7c478bd9Sstevel@tonic-gate * We assume it does not already exist 324*7c478bd9Sstevel@tonic-gate */ 325*7c478bd9Sstevel@tonic-gate (void) uu_list_find(bp->cb_list, cp, NULL, &idx); 326*7c478bd9Sstevel@tonic-gate uu_list_insert(bp->cb_list, cp, idx); 327*7c478bd9Sstevel@tonic-gate 328*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&bp->cb_lock); 329*7c478bd9Sstevel@tonic-gate } 330*7c478bd9Sstevel@tonic-gate 331*7c478bd9Sstevel@tonic-gate static repcache_client_t * 332*7c478bd9Sstevel@tonic-gate client_lookup(uint32_t id) 333*7c478bd9Sstevel@tonic-gate { 334*7c478bd9Sstevel@tonic-gate client_bucket_t *bp = CLIENT_HASH(id); 335*7c478bd9Sstevel@tonic-gate repcache_client_t *cp; 336*7c478bd9Sstevel@tonic-gate 337*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&bp->cb_lock); 338*7c478bd9Sstevel@tonic-gate 339*7c478bd9Sstevel@tonic-gate cp = uu_list_find(bp->cb_list, &id, NULL, NULL); 340*7c478bd9Sstevel@tonic-gate 341*7c478bd9Sstevel@tonic-gate /* 342*7c478bd9Sstevel@tonic-gate * Bump the reference count 343*7c478bd9Sstevel@tonic-gate */ 344*7c478bd9Sstevel@tonic-gate if (cp != NULL) { 345*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&cp->rc_lock); 346*7c478bd9Sstevel@tonic-gate assert(!(cp->rc_flags & RC_CLIENT_DEAD)); 347*7c478bd9Sstevel@tonic-gate cp->rc_refcnt++; 348*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&cp->rc_lock); 349*7c478bd9Sstevel@tonic-gate } 350*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&bp->cb_lock); 351*7c478bd9Sstevel@tonic-gate 352*7c478bd9Sstevel@tonic-gate return (cp); 353*7c478bd9Sstevel@tonic-gate } 354*7c478bd9Sstevel@tonic-gate 355*7c478bd9Sstevel@tonic-gate static void 356*7c478bd9Sstevel@tonic-gate client_release(repcache_client_t *cp) 357*7c478bd9Sstevel@tonic-gate { 358*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&cp->rc_lock); 359*7c478bd9Sstevel@tonic-gate assert(cp->rc_refcnt > 0); 360*7c478bd9Sstevel@tonic-gate assert(cp->rc_insert_thr != pthread_self()); 361*7c478bd9Sstevel@tonic-gate 362*7c478bd9Sstevel@tonic-gate --cp->rc_refcnt; 363*7c478bd9Sstevel@tonic-gate (void) pthread_cond_broadcast(&cp->rc_cv); 364*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&cp->rc_lock); 365*7c478bd9Sstevel@tonic-gate } 366*7c478bd9Sstevel@tonic-gate 367*7c478bd9Sstevel@tonic-gate /* 368*7c478bd9Sstevel@tonic-gate * We only allow one thread to be inserting at a time, to prevent 369*7c478bd9Sstevel@tonic-gate * insert/insert races. 370*7c478bd9Sstevel@tonic-gate */ 371*7c478bd9Sstevel@tonic-gate static void 372*7c478bd9Sstevel@tonic-gate client_start_insert(repcache_client_t *cp) 373*7c478bd9Sstevel@tonic-gate { 374*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&cp->rc_lock); 375*7c478bd9Sstevel@tonic-gate assert(cp->rc_refcnt > 0); 376*7c478bd9Sstevel@tonic-gate 377*7c478bd9Sstevel@tonic-gate while (cp->rc_insert_thr != 0) { 378*7c478bd9Sstevel@tonic-gate assert(cp->rc_insert_thr != pthread_self()); 379*7c478bd9Sstevel@tonic-gate (void) pthread_cond_wait(&cp->rc_cv, &cp->rc_lock); 380*7c478bd9Sstevel@tonic-gate } 381*7c478bd9Sstevel@tonic-gate cp->rc_insert_thr = pthread_self(); 382*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&cp->rc_lock); 383*7c478bd9Sstevel@tonic-gate } 384*7c478bd9Sstevel@tonic-gate 385*7c478bd9Sstevel@tonic-gate static void 386*7c478bd9Sstevel@tonic-gate client_end_insert(repcache_client_t *cp) 387*7c478bd9Sstevel@tonic-gate { 388*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&cp->rc_lock); 389*7c478bd9Sstevel@tonic-gate assert(cp->rc_insert_thr == pthread_self()); 390*7c478bd9Sstevel@tonic-gate cp->rc_insert_thr = 0; 391*7c478bd9Sstevel@tonic-gate (void) pthread_cond_broadcast(&cp->rc_cv); 392*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&cp->rc_lock); 393*7c478bd9Sstevel@tonic-gate } 394*7c478bd9Sstevel@tonic-gate 395*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 396*7c478bd9Sstevel@tonic-gate static repcache_entity_t * 397*7c478bd9Sstevel@tonic-gate entity_alloc(repcache_client_t *cp) 398*7c478bd9Sstevel@tonic-gate { 399*7c478bd9Sstevel@tonic-gate repcache_entity_t *ep = uu_zalloc(sizeof (repcache_entity_t)); 400*7c478bd9Sstevel@tonic-gate if (ep != NULL) { 401*7c478bd9Sstevel@tonic-gate uu_list_node_init(ep, &ep->re_link, entity_pool); 402*7c478bd9Sstevel@tonic-gate } 403*7c478bd9Sstevel@tonic-gate return (ep); 404*7c478bd9Sstevel@tonic-gate } 405*7c478bd9Sstevel@tonic-gate 406*7c478bd9Sstevel@tonic-gate static void 407*7c478bd9Sstevel@tonic-gate entity_add(repcache_client_t *cp, repcache_entity_t *ep) 408*7c478bd9Sstevel@tonic-gate { 409*7c478bd9Sstevel@tonic-gate uu_list_index_t idx; 410*7c478bd9Sstevel@tonic-gate 411*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&cp->rc_lock); 412*7c478bd9Sstevel@tonic-gate assert(cp->rc_insert_thr == pthread_self()); 413*7c478bd9Sstevel@tonic-gate 414*7c478bd9Sstevel@tonic-gate (void) uu_list_find(cp->rc_entity_list, ep, NULL, &idx); 415*7c478bd9Sstevel@tonic-gate uu_list_insert(cp->rc_entity_list, ep, idx); 416*7c478bd9Sstevel@tonic-gate 417*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&cp->rc_lock); 418*7c478bd9Sstevel@tonic-gate } 419*7c478bd9Sstevel@tonic-gate 420*7c478bd9Sstevel@tonic-gate static repcache_entity_t * 421*7c478bd9Sstevel@tonic-gate entity_find(repcache_client_t *cp, uint32_t id) 422*7c478bd9Sstevel@tonic-gate { 423*7c478bd9Sstevel@tonic-gate repcache_entity_t *ep; 424*7c478bd9Sstevel@tonic-gate 425*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&cp->rc_lock); 426*7c478bd9Sstevel@tonic-gate ep = uu_list_find(cp->rc_entity_list, &id, NULL, NULL); 427*7c478bd9Sstevel@tonic-gate if (ep != NULL) { 428*7c478bd9Sstevel@tonic-gate add_log_ptr(get_log(), RC_PTR_TYPE_ENTITY, id, ep); 429*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&ep->re_lock); 430*7c478bd9Sstevel@tonic-gate } 431*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&cp->rc_lock); 432*7c478bd9Sstevel@tonic-gate 433*7c478bd9Sstevel@tonic-gate return (ep); 434*7c478bd9Sstevel@tonic-gate } 435*7c478bd9Sstevel@tonic-gate 436*7c478bd9Sstevel@tonic-gate /* 437*7c478bd9Sstevel@tonic-gate * Fails with 438*7c478bd9Sstevel@tonic-gate * _DUPLICATE_ID - the ids are equal 439*7c478bd9Sstevel@tonic-gate * _UNKNOWN_ID - an id does not designate an active register 440*7c478bd9Sstevel@tonic-gate */ 441*7c478bd9Sstevel@tonic-gate static int 442*7c478bd9Sstevel@tonic-gate entity_find2(repcache_client_t *cp, uint32_t id1, repcache_entity_t **out1, 443*7c478bd9Sstevel@tonic-gate uint32_t id2, repcache_entity_t **out2) 444*7c478bd9Sstevel@tonic-gate { 445*7c478bd9Sstevel@tonic-gate repcache_entity_t *e1, *e2; 446*7c478bd9Sstevel@tonic-gate request_log_entry_t *rlp; 447*7c478bd9Sstevel@tonic-gate 448*7c478bd9Sstevel@tonic-gate if (id1 == id2) 449*7c478bd9Sstevel@tonic-gate return (REP_PROTOCOL_FAIL_DUPLICATE_ID); 450*7c478bd9Sstevel@tonic-gate 451*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&cp->rc_lock); 452*7c478bd9Sstevel@tonic-gate e1 = uu_list_find(cp->rc_entity_list, &id1, NULL, NULL); 453*7c478bd9Sstevel@tonic-gate e2 = uu_list_find(cp->rc_entity_list, &id2, NULL, NULL); 454*7c478bd9Sstevel@tonic-gate if (e1 == NULL || e2 == NULL) { 455*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&cp->rc_lock); 456*7c478bd9Sstevel@tonic-gate return (REP_PROTOCOL_FAIL_UNKNOWN_ID); 457*7c478bd9Sstevel@tonic-gate } 458*7c478bd9Sstevel@tonic-gate 459*7c478bd9Sstevel@tonic-gate assert(e1 != e2); 460*7c478bd9Sstevel@tonic-gate 461*7c478bd9Sstevel@tonic-gate /* 462*7c478bd9Sstevel@tonic-gate * locks are ordered by id number 463*7c478bd9Sstevel@tonic-gate */ 464*7c478bd9Sstevel@tonic-gate if (id1 < id2) { 465*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&e1->re_lock); 466*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&e2->re_lock); 467*7c478bd9Sstevel@tonic-gate } else { 468*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&e2->re_lock); 469*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&e1->re_lock); 470*7c478bd9Sstevel@tonic-gate } 471*7c478bd9Sstevel@tonic-gate *out1 = e1; 472*7c478bd9Sstevel@tonic-gate *out2 = e2; 473*7c478bd9Sstevel@tonic-gate 474*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&cp->rc_lock); 475*7c478bd9Sstevel@tonic-gate 476*7c478bd9Sstevel@tonic-gate if ((rlp = get_log()) != NULL) { 477*7c478bd9Sstevel@tonic-gate add_log_ptr(rlp, RC_PTR_TYPE_ENTITY, id1, e1); 478*7c478bd9Sstevel@tonic-gate add_log_ptr(rlp, RC_PTR_TYPE_ENTITY, id2, e2); 479*7c478bd9Sstevel@tonic-gate } 480*7c478bd9Sstevel@tonic-gate 481*7c478bd9Sstevel@tonic-gate return (REP_PROTOCOL_SUCCESS); 482*7c478bd9Sstevel@tonic-gate } 483*7c478bd9Sstevel@tonic-gate 484*7c478bd9Sstevel@tonic-gate static void 485*7c478bd9Sstevel@tonic-gate entity_release(repcache_entity_t *ep) 486*7c478bd9Sstevel@tonic-gate { 487*7c478bd9Sstevel@tonic-gate assert(ep->re_node.rnp_node == NULL || 488*7c478bd9Sstevel@tonic-gate !MUTEX_HELD(&ep->re_node.rnp_node->rn_lock)); 489*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&ep->re_lock); 490*7c478bd9Sstevel@tonic-gate } 491*7c478bd9Sstevel@tonic-gate 492*7c478bd9Sstevel@tonic-gate static void 493*7c478bd9Sstevel@tonic-gate entity_destroy(repcache_entity_t *entity) 494*7c478bd9Sstevel@tonic-gate { 495*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&entity->re_lock); 496*7c478bd9Sstevel@tonic-gate rc_node_clear(&entity->re_node, 0); 497*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&entity->re_lock); 498*7c478bd9Sstevel@tonic-gate 499*7c478bd9Sstevel@tonic-gate uu_list_node_fini(entity, &entity->re_link, entity_pool); 500*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_destroy(&entity->re_lock); 501*7c478bd9Sstevel@tonic-gate uu_free(entity); 502*7c478bd9Sstevel@tonic-gate } 503*7c478bd9Sstevel@tonic-gate 504*7c478bd9Sstevel@tonic-gate static void 505*7c478bd9Sstevel@tonic-gate entity_remove(repcache_client_t *cp, uint32_t id) 506*7c478bd9Sstevel@tonic-gate { 507*7c478bd9Sstevel@tonic-gate repcache_entity_t *entity; 508*7c478bd9Sstevel@tonic-gate 509*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&cp->rc_lock); 510*7c478bd9Sstevel@tonic-gate entity = uu_list_find(cp->rc_entity_list, &id, NULL, NULL); 511*7c478bd9Sstevel@tonic-gate if (entity != NULL) 512*7c478bd9Sstevel@tonic-gate uu_list_remove(cp->rc_entity_list, entity); 513*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&cp->rc_lock); 514*7c478bd9Sstevel@tonic-gate 515*7c478bd9Sstevel@tonic-gate if (entity != NULL) 516*7c478bd9Sstevel@tonic-gate entity_destroy(entity); 517*7c478bd9Sstevel@tonic-gate } 518*7c478bd9Sstevel@tonic-gate 519*7c478bd9Sstevel@tonic-gate static void 520*7c478bd9Sstevel@tonic-gate entity_cleanup(repcache_client_t *cp) 521*7c478bd9Sstevel@tonic-gate { 522*7c478bd9Sstevel@tonic-gate repcache_entity_t *ep; 523*7c478bd9Sstevel@tonic-gate void *cookie = NULL; 524*7c478bd9Sstevel@tonic-gate 525*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&cp->rc_lock); 526*7c478bd9Sstevel@tonic-gate while ((ep = uu_list_teardown(cp->rc_entity_list, &cookie)) != NULL) { 527*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&cp->rc_lock); 528*7c478bd9Sstevel@tonic-gate entity_destroy(ep); 529*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&cp->rc_lock); 530*7c478bd9Sstevel@tonic-gate } 531*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&cp->rc_lock); 532*7c478bd9Sstevel@tonic-gate } 533*7c478bd9Sstevel@tonic-gate 534*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 535*7c478bd9Sstevel@tonic-gate static repcache_iter_t * 536*7c478bd9Sstevel@tonic-gate iter_alloc(repcache_client_t *cp) 537*7c478bd9Sstevel@tonic-gate { 538*7c478bd9Sstevel@tonic-gate repcache_iter_t *iter; 539*7c478bd9Sstevel@tonic-gate iter = uu_zalloc(sizeof (repcache_iter_t)); 540*7c478bd9Sstevel@tonic-gate if (iter != NULL) 541*7c478bd9Sstevel@tonic-gate uu_list_node_init(iter, &iter->ri_link, iter_pool); 542*7c478bd9Sstevel@tonic-gate return (iter); 543*7c478bd9Sstevel@tonic-gate } 544*7c478bd9Sstevel@tonic-gate 545*7c478bd9Sstevel@tonic-gate static void 546*7c478bd9Sstevel@tonic-gate iter_add(repcache_client_t *cp, repcache_iter_t *iter) 547*7c478bd9Sstevel@tonic-gate { 548*7c478bd9Sstevel@tonic-gate uu_list_index_t idx; 549*7c478bd9Sstevel@tonic-gate 550*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&cp->rc_lock); 551*7c478bd9Sstevel@tonic-gate assert(cp->rc_insert_thr == pthread_self()); 552*7c478bd9Sstevel@tonic-gate 553*7c478bd9Sstevel@tonic-gate (void) uu_list_find(cp->rc_iter_list, iter, NULL, &idx); 554*7c478bd9Sstevel@tonic-gate uu_list_insert(cp->rc_iter_list, iter, idx); 555*7c478bd9Sstevel@tonic-gate 556*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&cp->rc_lock); 557*7c478bd9Sstevel@tonic-gate } 558*7c478bd9Sstevel@tonic-gate 559*7c478bd9Sstevel@tonic-gate static repcache_iter_t * 560*7c478bd9Sstevel@tonic-gate iter_find(repcache_client_t *cp, uint32_t id) 561*7c478bd9Sstevel@tonic-gate { 562*7c478bd9Sstevel@tonic-gate repcache_iter_t *iter; 563*7c478bd9Sstevel@tonic-gate 564*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&cp->rc_lock); 565*7c478bd9Sstevel@tonic-gate 566*7c478bd9Sstevel@tonic-gate iter = uu_list_find(cp->rc_iter_list, &id, NULL, NULL); 567*7c478bd9Sstevel@tonic-gate if (iter != NULL) { 568*7c478bd9Sstevel@tonic-gate add_log_ptr(get_log(), RC_PTR_TYPE_ITER, id, iter); 569*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&iter->ri_lock); 570*7c478bd9Sstevel@tonic-gate } 571*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&cp->rc_lock); 572*7c478bd9Sstevel@tonic-gate 573*7c478bd9Sstevel@tonic-gate return (iter); 574*7c478bd9Sstevel@tonic-gate } 575*7c478bd9Sstevel@tonic-gate 576*7c478bd9Sstevel@tonic-gate /* 577*7c478bd9Sstevel@tonic-gate * Fails with 578*7c478bd9Sstevel@tonic-gate * _UNKNOWN_ID - iter_id or entity_id does not designate an active register 579*7c478bd9Sstevel@tonic-gate */ 580*7c478bd9Sstevel@tonic-gate static int 581*7c478bd9Sstevel@tonic-gate iter_find_w_entity(repcache_client_t *cp, uint32_t iter_id, 582*7c478bd9Sstevel@tonic-gate repcache_iter_t **iterp, uint32_t entity_id, repcache_entity_t **epp) 583*7c478bd9Sstevel@tonic-gate { 584*7c478bd9Sstevel@tonic-gate repcache_iter_t *iter; 585*7c478bd9Sstevel@tonic-gate repcache_entity_t *ep; 586*7c478bd9Sstevel@tonic-gate request_log_entry_t *rlp; 587*7c478bd9Sstevel@tonic-gate 588*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&cp->rc_lock); 589*7c478bd9Sstevel@tonic-gate iter = uu_list_find(cp->rc_iter_list, &iter_id, NULL, NULL); 590*7c478bd9Sstevel@tonic-gate ep = uu_list_find(cp->rc_entity_list, &entity_id, NULL, NULL); 591*7c478bd9Sstevel@tonic-gate 592*7c478bd9Sstevel@tonic-gate assert(iter == NULL || !MUTEX_HELD(&iter->ri_lock)); 593*7c478bd9Sstevel@tonic-gate assert(ep == NULL || !MUTEX_HELD(&ep->re_lock)); 594*7c478bd9Sstevel@tonic-gate 595*7c478bd9Sstevel@tonic-gate if (iter == NULL || ep == NULL) { 596*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&cp->rc_lock); 597*7c478bd9Sstevel@tonic-gate return (REP_PROTOCOL_FAIL_UNKNOWN_ID); 598*7c478bd9Sstevel@tonic-gate } 599*7c478bd9Sstevel@tonic-gate 600*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&iter->ri_lock); 601*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&ep->re_lock); 602*7c478bd9Sstevel@tonic-gate 603*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&cp->rc_lock); 604*7c478bd9Sstevel@tonic-gate 605*7c478bd9Sstevel@tonic-gate *iterp = iter; 606*7c478bd9Sstevel@tonic-gate *epp = ep; 607*7c478bd9Sstevel@tonic-gate 608*7c478bd9Sstevel@tonic-gate if ((rlp = get_log()) != NULL) { 609*7c478bd9Sstevel@tonic-gate add_log_ptr(rlp, RC_PTR_TYPE_ENTITY, entity_id, ep); 610*7c478bd9Sstevel@tonic-gate add_log_ptr(rlp, RC_PTR_TYPE_ITER, iter_id, iter); 611*7c478bd9Sstevel@tonic-gate } 612*7c478bd9Sstevel@tonic-gate 613*7c478bd9Sstevel@tonic-gate return (REP_PROTOCOL_SUCCESS); 614*7c478bd9Sstevel@tonic-gate } 615*7c478bd9Sstevel@tonic-gate 616*7c478bd9Sstevel@tonic-gate static void 617*7c478bd9Sstevel@tonic-gate iter_release(repcache_iter_t *iter) 618*7c478bd9Sstevel@tonic-gate { 619*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&iter->ri_lock); 620*7c478bd9Sstevel@tonic-gate } 621*7c478bd9Sstevel@tonic-gate 622*7c478bd9Sstevel@tonic-gate static void 623*7c478bd9Sstevel@tonic-gate iter_destroy(repcache_iter_t *iter) 624*7c478bd9Sstevel@tonic-gate { 625*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&iter->ri_lock); 626*7c478bd9Sstevel@tonic-gate rc_iter_destroy(&iter->ri_iter); 627*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&iter->ri_lock); 628*7c478bd9Sstevel@tonic-gate 629*7c478bd9Sstevel@tonic-gate uu_list_node_fini(iter, &iter->ri_link, iter_pool); 630*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_destroy(&iter->ri_lock); 631*7c478bd9Sstevel@tonic-gate uu_free(iter); 632*7c478bd9Sstevel@tonic-gate } 633*7c478bd9Sstevel@tonic-gate 634*7c478bd9Sstevel@tonic-gate static void 635*7c478bd9Sstevel@tonic-gate iter_remove(repcache_client_t *cp, uint32_t id) 636*7c478bd9Sstevel@tonic-gate { 637*7c478bd9Sstevel@tonic-gate repcache_iter_t *iter; 638*7c478bd9Sstevel@tonic-gate 639*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&cp->rc_lock); 640*7c478bd9Sstevel@tonic-gate iter = uu_list_find(cp->rc_iter_list, &id, NULL, NULL); 641*7c478bd9Sstevel@tonic-gate if (iter != NULL) 642*7c478bd9Sstevel@tonic-gate uu_list_remove(cp->rc_iter_list, iter); 643*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&cp->rc_lock); 644*7c478bd9Sstevel@tonic-gate 645*7c478bd9Sstevel@tonic-gate if (iter != NULL) 646*7c478bd9Sstevel@tonic-gate iter_destroy(iter); 647*7c478bd9Sstevel@tonic-gate } 648*7c478bd9Sstevel@tonic-gate 649*7c478bd9Sstevel@tonic-gate static void 650*7c478bd9Sstevel@tonic-gate iter_cleanup(repcache_client_t *cp) 651*7c478bd9Sstevel@tonic-gate { 652*7c478bd9Sstevel@tonic-gate repcache_iter_t *iter; 653*7c478bd9Sstevel@tonic-gate void *cookie = NULL; 654*7c478bd9Sstevel@tonic-gate 655*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&cp->rc_lock); 656*7c478bd9Sstevel@tonic-gate while ((iter = uu_list_teardown(cp->rc_iter_list, &cookie)) != NULL) { 657*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&cp->rc_lock); 658*7c478bd9Sstevel@tonic-gate iter_destroy(iter); 659*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&cp->rc_lock); 660*7c478bd9Sstevel@tonic-gate } 661*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&cp->rc_lock); 662*7c478bd9Sstevel@tonic-gate } 663*7c478bd9Sstevel@tonic-gate 664*7c478bd9Sstevel@tonic-gate /* 665*7c478bd9Sstevel@tonic-gate * Ensure that the passed client id is no longer usable, wait for any 666*7c478bd9Sstevel@tonic-gate * outstanding invocations to complete, then destroy the client 667*7c478bd9Sstevel@tonic-gate * structure. 668*7c478bd9Sstevel@tonic-gate */ 669*7c478bd9Sstevel@tonic-gate static void 670*7c478bd9Sstevel@tonic-gate client_destroy(uint32_t id) 671*7c478bd9Sstevel@tonic-gate { 672*7c478bd9Sstevel@tonic-gate client_bucket_t *bp = CLIENT_HASH(id); 673*7c478bd9Sstevel@tonic-gate repcache_client_t *cp; 674*7c478bd9Sstevel@tonic-gate 675*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&bp->cb_lock); 676*7c478bd9Sstevel@tonic-gate 677*7c478bd9Sstevel@tonic-gate cp = uu_list_find(bp->cb_list, &id, NULL, NULL); 678*7c478bd9Sstevel@tonic-gate 679*7c478bd9Sstevel@tonic-gate if (cp == NULL) { 680*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&bp->cb_lock); 681*7c478bd9Sstevel@tonic-gate return; 682*7c478bd9Sstevel@tonic-gate } 683*7c478bd9Sstevel@tonic-gate 684*7c478bd9Sstevel@tonic-gate uu_list_remove(bp->cb_list, cp); 685*7c478bd9Sstevel@tonic-gate 686*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&bp->cb_lock); 687*7c478bd9Sstevel@tonic-gate 688*7c478bd9Sstevel@tonic-gate /* kick the waiters out */ 689*7c478bd9Sstevel@tonic-gate rc_notify_info_fini(&cp->rc_notify_info); 690*7c478bd9Sstevel@tonic-gate 691*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&cp->rc_lock); 692*7c478bd9Sstevel@tonic-gate assert(!(cp->rc_flags & RC_CLIENT_DEAD)); 693*7c478bd9Sstevel@tonic-gate cp->rc_flags |= RC_CLIENT_DEAD; 694*7c478bd9Sstevel@tonic-gate 695*7c478bd9Sstevel@tonic-gate if (cp->rc_doorfd != -1) { 696*7c478bd9Sstevel@tonic-gate if (door_revoke(cp->rc_doorfd) < 0) 697*7c478bd9Sstevel@tonic-gate perror("door_revoke"); 698*7c478bd9Sstevel@tonic-gate cp->rc_doorfd = -1; 699*7c478bd9Sstevel@tonic-gate cp->rc_doorid = INVALID_DOORID; 700*7c478bd9Sstevel@tonic-gate } 701*7c478bd9Sstevel@tonic-gate 702*7c478bd9Sstevel@tonic-gate while (cp->rc_refcnt > 0) 703*7c478bd9Sstevel@tonic-gate (void) pthread_cond_wait(&cp->rc_cv, &cp->rc_lock); 704*7c478bd9Sstevel@tonic-gate 705*7c478bd9Sstevel@tonic-gate assert(cp->rc_insert_thr == 0 && cp->rc_notify_thr == 0); 706*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&cp->rc_lock); 707*7c478bd9Sstevel@tonic-gate 708*7c478bd9Sstevel@tonic-gate /* 709*7c478bd9Sstevel@tonic-gate * destroy outstanding objects 710*7c478bd9Sstevel@tonic-gate */ 711*7c478bd9Sstevel@tonic-gate entity_cleanup(cp); 712*7c478bd9Sstevel@tonic-gate iter_cleanup(cp); 713*7c478bd9Sstevel@tonic-gate 714*7c478bd9Sstevel@tonic-gate /* 715*7c478bd9Sstevel@tonic-gate * clean up notifications 716*7c478bd9Sstevel@tonic-gate */ 717*7c478bd9Sstevel@tonic-gate rc_pg_notify_fini(&cp->rc_pg_notify); 718*7c478bd9Sstevel@tonic-gate 719*7c478bd9Sstevel@tonic-gate client_free(cp); 720*7c478bd9Sstevel@tonic-gate } 721*7c478bd9Sstevel@tonic-gate 722*7c478bd9Sstevel@tonic-gate /* 723*7c478bd9Sstevel@tonic-gate * Fails with 724*7c478bd9Sstevel@tonic-gate * _TYPE_MISMATCH - the entity is already set up with a different type 725*7c478bd9Sstevel@tonic-gate * _NO_RESOURCES - out of memory 726*7c478bd9Sstevel@tonic-gate */ 727*7c478bd9Sstevel@tonic-gate static int 728*7c478bd9Sstevel@tonic-gate entity_setup(repcache_client_t *cp, struct rep_protocol_entity_setup *rpr) 729*7c478bd9Sstevel@tonic-gate { 730*7c478bd9Sstevel@tonic-gate repcache_entity_t *ep; 731*7c478bd9Sstevel@tonic-gate uint32_t type; 732*7c478bd9Sstevel@tonic-gate 733*7c478bd9Sstevel@tonic-gate client_start_insert(cp); 734*7c478bd9Sstevel@tonic-gate 735*7c478bd9Sstevel@tonic-gate if ((ep = entity_find(cp, rpr->rpr_entityid)) != NULL) { 736*7c478bd9Sstevel@tonic-gate type = ep->re_type; 737*7c478bd9Sstevel@tonic-gate entity_release(ep); 738*7c478bd9Sstevel@tonic-gate 739*7c478bd9Sstevel@tonic-gate client_end_insert(cp); 740*7c478bd9Sstevel@tonic-gate 741*7c478bd9Sstevel@tonic-gate if (type != rpr->rpr_entitytype) 742*7c478bd9Sstevel@tonic-gate return (REP_PROTOCOL_FAIL_TYPE_MISMATCH); 743*7c478bd9Sstevel@tonic-gate return (REP_PROTOCOL_SUCCESS); 744*7c478bd9Sstevel@tonic-gate } 745*7c478bd9Sstevel@tonic-gate 746*7c478bd9Sstevel@tonic-gate switch (type = rpr->rpr_entitytype) { 747*7c478bd9Sstevel@tonic-gate case REP_PROTOCOL_ENTITY_SCOPE: 748*7c478bd9Sstevel@tonic-gate case REP_PROTOCOL_ENTITY_SERVICE: 749*7c478bd9Sstevel@tonic-gate case REP_PROTOCOL_ENTITY_INSTANCE: 750*7c478bd9Sstevel@tonic-gate case REP_PROTOCOL_ENTITY_SNAPSHOT: 751*7c478bd9Sstevel@tonic-gate case REP_PROTOCOL_ENTITY_SNAPLEVEL: 752*7c478bd9Sstevel@tonic-gate case REP_PROTOCOL_ENTITY_PROPERTYGRP: 753*7c478bd9Sstevel@tonic-gate case REP_PROTOCOL_ENTITY_PROPERTY: 754*7c478bd9Sstevel@tonic-gate break; 755*7c478bd9Sstevel@tonic-gate default: 756*7c478bd9Sstevel@tonic-gate return (REP_PROTOCOL_FAIL_BAD_REQUEST); 757*7c478bd9Sstevel@tonic-gate } 758*7c478bd9Sstevel@tonic-gate 759*7c478bd9Sstevel@tonic-gate ep = entity_alloc(cp); 760*7c478bd9Sstevel@tonic-gate if (ep == NULL) { 761*7c478bd9Sstevel@tonic-gate client_end_insert(cp); 762*7c478bd9Sstevel@tonic-gate return (REP_PROTOCOL_FAIL_NO_RESOURCES); 763*7c478bd9Sstevel@tonic-gate } 764*7c478bd9Sstevel@tonic-gate 765*7c478bd9Sstevel@tonic-gate ep->re_id = rpr->rpr_entityid; 766*7c478bd9Sstevel@tonic-gate ep->re_changeid = INVALID_CHANGEID; 767*7c478bd9Sstevel@tonic-gate 768*7c478bd9Sstevel@tonic-gate ep->re_type = type; 769*7c478bd9Sstevel@tonic-gate rc_node_ptr_init(&ep->re_node); 770*7c478bd9Sstevel@tonic-gate 771*7c478bd9Sstevel@tonic-gate entity_add(cp, ep); 772*7c478bd9Sstevel@tonic-gate client_end_insert(cp); 773*7c478bd9Sstevel@tonic-gate return (REP_PROTOCOL_SUCCESS); 774*7c478bd9Sstevel@tonic-gate } 775*7c478bd9Sstevel@tonic-gate 776*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 777*7c478bd9Sstevel@tonic-gate static void 778*7c478bd9Sstevel@tonic-gate entity_name(repcache_client_t *cp, const void *in, size_t insz, void *out_arg, 779*7c478bd9Sstevel@tonic-gate size_t *outsz, void *arg) 780*7c478bd9Sstevel@tonic-gate { 781*7c478bd9Sstevel@tonic-gate const struct rep_protocol_entity_name *rpr = in; 782*7c478bd9Sstevel@tonic-gate struct rep_protocol_name_response *out = out_arg; 783*7c478bd9Sstevel@tonic-gate repcache_entity_t *ep; 784*7c478bd9Sstevel@tonic-gate size_t sz = sizeof (out->rpr_name); 785*7c478bd9Sstevel@tonic-gate 786*7c478bd9Sstevel@tonic-gate assert(*outsz == sizeof (*out)); 787*7c478bd9Sstevel@tonic-gate 788*7c478bd9Sstevel@tonic-gate ep = entity_find(cp, rpr->rpr_entityid); 789*7c478bd9Sstevel@tonic-gate 790*7c478bd9Sstevel@tonic-gate if (ep == NULL) { 791*7c478bd9Sstevel@tonic-gate out->rpr_response = REP_PROTOCOL_FAIL_UNKNOWN_ID; 792*7c478bd9Sstevel@tonic-gate *outsz = sizeof (out->rpr_response); 793*7c478bd9Sstevel@tonic-gate return; 794*7c478bd9Sstevel@tonic-gate } 795*7c478bd9Sstevel@tonic-gate out->rpr_response = rc_node_name(&ep->re_node, out->rpr_name, 796*7c478bd9Sstevel@tonic-gate sz, rpr->rpr_answertype, &sz); 797*7c478bd9Sstevel@tonic-gate entity_release(ep); 798*7c478bd9Sstevel@tonic-gate 799*7c478bd9Sstevel@tonic-gate /* 800*7c478bd9Sstevel@tonic-gate * If we fail, we only return the response code. 801*7c478bd9Sstevel@tonic-gate * If we succeed, we don't return anything after the '\0' in rpr_name. 802*7c478bd9Sstevel@tonic-gate */ 803*7c478bd9Sstevel@tonic-gate if (out->rpr_response != REP_PROTOCOL_SUCCESS) 804*7c478bd9Sstevel@tonic-gate *outsz = sizeof (out->rpr_response); 805*7c478bd9Sstevel@tonic-gate else 806*7c478bd9Sstevel@tonic-gate *outsz = offsetof(struct rep_protocol_name_response, 807*7c478bd9Sstevel@tonic-gate rpr_name[sz + 1]); 808*7c478bd9Sstevel@tonic-gate } 809*7c478bd9Sstevel@tonic-gate 810*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 811*7c478bd9Sstevel@tonic-gate static void 812*7c478bd9Sstevel@tonic-gate entity_parent_type(repcache_client_t *cp, const void *in, size_t insz, 813*7c478bd9Sstevel@tonic-gate void *out_arg, size_t *outsz, void *arg) 814*7c478bd9Sstevel@tonic-gate { 815*7c478bd9Sstevel@tonic-gate const struct rep_protocol_entity_name *rpr = in; 816*7c478bd9Sstevel@tonic-gate struct rep_protocol_integer_response *out = out_arg; 817*7c478bd9Sstevel@tonic-gate repcache_entity_t *ep; 818*7c478bd9Sstevel@tonic-gate 819*7c478bd9Sstevel@tonic-gate assert(*outsz == sizeof (*out)); 820*7c478bd9Sstevel@tonic-gate 821*7c478bd9Sstevel@tonic-gate ep = entity_find(cp, rpr->rpr_entityid); 822*7c478bd9Sstevel@tonic-gate 823*7c478bd9Sstevel@tonic-gate if (ep == NULL) { 824*7c478bd9Sstevel@tonic-gate out->rpr_response = REP_PROTOCOL_FAIL_UNKNOWN_ID; 825*7c478bd9Sstevel@tonic-gate *outsz = sizeof (out->rpr_response); 826*7c478bd9Sstevel@tonic-gate return; 827*7c478bd9Sstevel@tonic-gate } 828*7c478bd9Sstevel@tonic-gate 829*7c478bd9Sstevel@tonic-gate out->rpr_response = rc_node_parent_type(&ep->re_node, &out->rpr_value); 830*7c478bd9Sstevel@tonic-gate entity_release(ep); 831*7c478bd9Sstevel@tonic-gate 832*7c478bd9Sstevel@tonic-gate if (out->rpr_response != REP_PROTOCOL_SUCCESS) 833*7c478bd9Sstevel@tonic-gate *outsz = sizeof (out->rpr_response); 834*7c478bd9Sstevel@tonic-gate } 835*7c478bd9Sstevel@tonic-gate 836*7c478bd9Sstevel@tonic-gate /* 837*7c478bd9Sstevel@tonic-gate * Fails with 838*7c478bd9Sstevel@tonic-gate * _DUPLICATE_ID - the ids are equal 839*7c478bd9Sstevel@tonic-gate * _UNKNOWN_ID - an id does not designate an active register 840*7c478bd9Sstevel@tonic-gate * _INVALID_TYPE - type is invalid 841*7c478bd9Sstevel@tonic-gate * _TYPE_MISMATCH - np doesn't carry children of type type 842*7c478bd9Sstevel@tonic-gate * _DELETED - np has been deleted 843*7c478bd9Sstevel@tonic-gate * _NOT_FOUND - no child with that name/type combo found 844*7c478bd9Sstevel@tonic-gate * _NO_RESOURCES 845*7c478bd9Sstevel@tonic-gate * _BACKEND_ACCESS 846*7c478bd9Sstevel@tonic-gate */ 847*7c478bd9Sstevel@tonic-gate static int 848*7c478bd9Sstevel@tonic-gate entity_get_child(repcache_client_t *cp, 849*7c478bd9Sstevel@tonic-gate struct rep_protocol_entity_get_child *rpr) 850*7c478bd9Sstevel@tonic-gate { 851*7c478bd9Sstevel@tonic-gate repcache_entity_t *parent, *child; 852*7c478bd9Sstevel@tonic-gate int result; 853*7c478bd9Sstevel@tonic-gate 854*7c478bd9Sstevel@tonic-gate uint32_t parentid = rpr->rpr_entityid; 855*7c478bd9Sstevel@tonic-gate uint32_t childid = rpr->rpr_childid; 856*7c478bd9Sstevel@tonic-gate 857*7c478bd9Sstevel@tonic-gate result = entity_find2(cp, childid, &child, parentid, &parent); 858*7c478bd9Sstevel@tonic-gate if (result != REP_PROTOCOL_SUCCESS) 859*7c478bd9Sstevel@tonic-gate return (result); 860*7c478bd9Sstevel@tonic-gate 861*7c478bd9Sstevel@tonic-gate rpr->rpr_name[sizeof (rpr->rpr_name) - 1] = 0; 862*7c478bd9Sstevel@tonic-gate 863*7c478bd9Sstevel@tonic-gate result = rc_node_get_child(&parent->re_node, rpr->rpr_name, 864*7c478bd9Sstevel@tonic-gate child->re_type, &child->re_node); 865*7c478bd9Sstevel@tonic-gate 866*7c478bd9Sstevel@tonic-gate entity_release(child); 867*7c478bd9Sstevel@tonic-gate entity_release(parent); 868*7c478bd9Sstevel@tonic-gate 869*7c478bd9Sstevel@tonic-gate return (result); 870*7c478bd9Sstevel@tonic-gate } 871*7c478bd9Sstevel@tonic-gate 872*7c478bd9Sstevel@tonic-gate /* 873*7c478bd9Sstevel@tonic-gate * Returns _FAIL_DUPLICATE_ID, _FAIL_UNKNOWN_ID, _FAIL_NOT_SET, _FAIL_DELETED, 874*7c478bd9Sstevel@tonic-gate * _FAIL_TYPE_MISMATCH, _FAIL_NOT_FOUND (scope has no parent), or _SUCCESS. 875*7c478bd9Sstevel@tonic-gate * Fails with 876*7c478bd9Sstevel@tonic-gate * _DUPLICATE_ID - the ids are equal 877*7c478bd9Sstevel@tonic-gate * _UNKNOWN_ID - an id does not designate an active register 878*7c478bd9Sstevel@tonic-gate * _NOT_SET - child is not set 879*7c478bd9Sstevel@tonic-gate * _DELETED - child has been deleted 880*7c478bd9Sstevel@tonic-gate * _TYPE_MISMATCH - child's parent does not match that of the parent register 881*7c478bd9Sstevel@tonic-gate * _NOT_FOUND - child has no parent (and is a scope) 882*7c478bd9Sstevel@tonic-gate */ 883*7c478bd9Sstevel@tonic-gate static int 884*7c478bd9Sstevel@tonic-gate entity_get_parent(repcache_client_t *cp, struct rep_protocol_entity_parent *rpr) 885*7c478bd9Sstevel@tonic-gate { 886*7c478bd9Sstevel@tonic-gate repcache_entity_t *child, *parent; 887*7c478bd9Sstevel@tonic-gate int result; 888*7c478bd9Sstevel@tonic-gate 889*7c478bd9Sstevel@tonic-gate uint32_t childid = rpr->rpr_entityid; 890*7c478bd9Sstevel@tonic-gate uint32_t outid = rpr->rpr_outid; 891*7c478bd9Sstevel@tonic-gate 892*7c478bd9Sstevel@tonic-gate result = entity_find2(cp, childid, &child, outid, &parent); 893*7c478bd9Sstevel@tonic-gate if (result != REP_PROTOCOL_SUCCESS) 894*7c478bd9Sstevel@tonic-gate return (result); 895*7c478bd9Sstevel@tonic-gate 896*7c478bd9Sstevel@tonic-gate result = rc_node_get_parent(&child->re_node, parent->re_type, 897*7c478bd9Sstevel@tonic-gate &parent->re_node); 898*7c478bd9Sstevel@tonic-gate 899*7c478bd9Sstevel@tonic-gate entity_release(child); 900*7c478bd9Sstevel@tonic-gate entity_release(parent); 901*7c478bd9Sstevel@tonic-gate 902*7c478bd9Sstevel@tonic-gate return (result); 903*7c478bd9Sstevel@tonic-gate } 904*7c478bd9Sstevel@tonic-gate 905*7c478bd9Sstevel@tonic-gate static int 906*7c478bd9Sstevel@tonic-gate entity_get(repcache_client_t *cp, struct rep_protocol_entity_get *rpr) 907*7c478bd9Sstevel@tonic-gate { 908*7c478bd9Sstevel@tonic-gate repcache_entity_t *ep; 909*7c478bd9Sstevel@tonic-gate int result; 910*7c478bd9Sstevel@tonic-gate 911*7c478bd9Sstevel@tonic-gate ep = entity_find(cp, rpr->rpr_entityid); 912*7c478bd9Sstevel@tonic-gate 913*7c478bd9Sstevel@tonic-gate if (ep == NULL) 914*7c478bd9Sstevel@tonic-gate return (REP_PROTOCOL_FAIL_UNKNOWN_ID); 915*7c478bd9Sstevel@tonic-gate 916*7c478bd9Sstevel@tonic-gate switch (rpr->rpr_object) { 917*7c478bd9Sstevel@tonic-gate case RP_ENTITY_GET_INVALIDATE: 918*7c478bd9Sstevel@tonic-gate rc_node_clear(&ep->re_node, 0); 919*7c478bd9Sstevel@tonic-gate result = REP_PROTOCOL_SUCCESS; 920*7c478bd9Sstevel@tonic-gate break; 921*7c478bd9Sstevel@tonic-gate case RP_ENTITY_GET_MOST_LOCAL_SCOPE: 922*7c478bd9Sstevel@tonic-gate result = rc_local_scope(ep->re_type, &ep->re_node); 923*7c478bd9Sstevel@tonic-gate break; 924*7c478bd9Sstevel@tonic-gate default: 925*7c478bd9Sstevel@tonic-gate result = REP_PROTOCOL_FAIL_BAD_REQUEST; 926*7c478bd9Sstevel@tonic-gate break; 927*7c478bd9Sstevel@tonic-gate } 928*7c478bd9Sstevel@tonic-gate 929*7c478bd9Sstevel@tonic-gate entity_release(ep); 930*7c478bd9Sstevel@tonic-gate 931*7c478bd9Sstevel@tonic-gate return (result); 932*7c478bd9Sstevel@tonic-gate } 933*7c478bd9Sstevel@tonic-gate 934*7c478bd9Sstevel@tonic-gate static int 935*7c478bd9Sstevel@tonic-gate entity_update(repcache_client_t *cp, struct rep_protocol_entity_update *rpr) 936*7c478bd9Sstevel@tonic-gate { 937*7c478bd9Sstevel@tonic-gate repcache_entity_t *ep; 938*7c478bd9Sstevel@tonic-gate int result; 939*7c478bd9Sstevel@tonic-gate 940*7c478bd9Sstevel@tonic-gate if (rpr->rpr_changeid == INVALID_CHANGEID) 941*7c478bd9Sstevel@tonic-gate return (REP_PROTOCOL_FAIL_BAD_REQUEST); 942*7c478bd9Sstevel@tonic-gate 943*7c478bd9Sstevel@tonic-gate ep = entity_find(cp, rpr->rpr_entityid); 944*7c478bd9Sstevel@tonic-gate 945*7c478bd9Sstevel@tonic-gate if (ep == NULL) 946*7c478bd9Sstevel@tonic-gate return (REP_PROTOCOL_FAIL_UNKNOWN_ID); 947*7c478bd9Sstevel@tonic-gate 948*7c478bd9Sstevel@tonic-gate if (ep->re_changeid == rpr->rpr_changeid) { 949*7c478bd9Sstevel@tonic-gate result = REP_PROTOCOL_DONE; 950*7c478bd9Sstevel@tonic-gate } else { 951*7c478bd9Sstevel@tonic-gate result = rc_node_update(&ep->re_node); 952*7c478bd9Sstevel@tonic-gate if (result == REP_PROTOCOL_DONE) 953*7c478bd9Sstevel@tonic-gate ep->re_changeid = rpr->rpr_changeid; 954*7c478bd9Sstevel@tonic-gate } 955*7c478bd9Sstevel@tonic-gate 956*7c478bd9Sstevel@tonic-gate entity_release(ep); 957*7c478bd9Sstevel@tonic-gate 958*7c478bd9Sstevel@tonic-gate return (result); 959*7c478bd9Sstevel@tonic-gate } 960*7c478bd9Sstevel@tonic-gate 961*7c478bd9Sstevel@tonic-gate static int 962*7c478bd9Sstevel@tonic-gate entity_reset(repcache_client_t *cp, struct rep_protocol_entity_reset *rpr) 963*7c478bd9Sstevel@tonic-gate { 964*7c478bd9Sstevel@tonic-gate repcache_entity_t *ep; 965*7c478bd9Sstevel@tonic-gate 966*7c478bd9Sstevel@tonic-gate ep = entity_find(cp, rpr->rpr_entityid); 967*7c478bd9Sstevel@tonic-gate if (ep == NULL) 968*7c478bd9Sstevel@tonic-gate return (REP_PROTOCOL_FAIL_UNKNOWN_ID); 969*7c478bd9Sstevel@tonic-gate 970*7c478bd9Sstevel@tonic-gate rc_node_clear(&ep->re_node, 0); 971*7c478bd9Sstevel@tonic-gate ep->re_txstate = REPCACHE_TX_INIT; 972*7c478bd9Sstevel@tonic-gate 973*7c478bd9Sstevel@tonic-gate entity_release(ep); 974*7c478bd9Sstevel@tonic-gate return (REP_PROTOCOL_SUCCESS); 975*7c478bd9Sstevel@tonic-gate } 976*7c478bd9Sstevel@tonic-gate 977*7c478bd9Sstevel@tonic-gate /* 978*7c478bd9Sstevel@tonic-gate * Fails with 979*7c478bd9Sstevel@tonic-gate * _BAD_REQUEST - request has invalid changeid 980*7c478bd9Sstevel@tonic-gate * rpr_name is invalid 981*7c478bd9Sstevel@tonic-gate * cannot create children for parent's type of node 982*7c478bd9Sstevel@tonic-gate * _DUPLICATE_ID - request has duplicate ids 983*7c478bd9Sstevel@tonic-gate * _UNKNOWN_ID - request has unknown id 984*7c478bd9Sstevel@tonic-gate * _DELETED - parent has been deleted 985*7c478bd9Sstevel@tonic-gate * _NOT_SET - parent is reset 986*7c478bd9Sstevel@tonic-gate * _NOT_APPLICABLE - rpr_childtype is _PROPERTYGRP 987*7c478bd9Sstevel@tonic-gate * _INVALID_TYPE - parent is corrupt or rpr_childtype is invalid 988*7c478bd9Sstevel@tonic-gate * _TYPE_MISMATCH - parent cannot have children of type rpr_childtype 989*7c478bd9Sstevel@tonic-gate * _NO_RESOURCES 990*7c478bd9Sstevel@tonic-gate * _PERMISSION_DENIED 991*7c478bd9Sstevel@tonic-gate * _BACKEND_ACCESS 992*7c478bd9Sstevel@tonic-gate * _BACKEND_READONLY 993*7c478bd9Sstevel@tonic-gate * _EXISTS - child already exists 994*7c478bd9Sstevel@tonic-gate * _NOT_FOUND - could not allocate new id 995*7c478bd9Sstevel@tonic-gate */ 996*7c478bd9Sstevel@tonic-gate static int 997*7c478bd9Sstevel@tonic-gate entity_create_child(repcache_client_t *cp, 998*7c478bd9Sstevel@tonic-gate struct rep_protocol_entity_create_child *rpr) 999*7c478bd9Sstevel@tonic-gate { 1000*7c478bd9Sstevel@tonic-gate repcache_entity_t *parent; 1001*7c478bd9Sstevel@tonic-gate repcache_entity_t *child; 1002*7c478bd9Sstevel@tonic-gate 1003*7c478bd9Sstevel@tonic-gate uint32_t parentid = rpr->rpr_entityid; 1004*7c478bd9Sstevel@tonic-gate uint32_t childid = rpr->rpr_childid; 1005*7c478bd9Sstevel@tonic-gate 1006*7c478bd9Sstevel@tonic-gate int result; 1007*7c478bd9Sstevel@tonic-gate 1008*7c478bd9Sstevel@tonic-gate if (rpr->rpr_changeid == INVALID_CHANGEID) 1009*7c478bd9Sstevel@tonic-gate return (REP_PROTOCOL_FAIL_BAD_REQUEST); 1010*7c478bd9Sstevel@tonic-gate 1011*7c478bd9Sstevel@tonic-gate result = entity_find2(cp, parentid, &parent, childid, &child); 1012*7c478bd9Sstevel@tonic-gate if (result != REP_PROTOCOL_SUCCESS) 1013*7c478bd9Sstevel@tonic-gate return (result); 1014*7c478bd9Sstevel@tonic-gate 1015*7c478bd9Sstevel@tonic-gate rpr->rpr_name[sizeof (rpr->rpr_name) - 1] = 0; 1016*7c478bd9Sstevel@tonic-gate 1017*7c478bd9Sstevel@tonic-gate if (child->re_changeid == rpr->rpr_changeid) { 1018*7c478bd9Sstevel@tonic-gate result = REP_PROTOCOL_SUCCESS; 1019*7c478bd9Sstevel@tonic-gate } else { 1020*7c478bd9Sstevel@tonic-gate result = rc_node_create_child(&parent->re_node, 1021*7c478bd9Sstevel@tonic-gate rpr->rpr_childtype, rpr->rpr_name, &child->re_node); 1022*7c478bd9Sstevel@tonic-gate if (result == REP_PROTOCOL_SUCCESS) 1023*7c478bd9Sstevel@tonic-gate child->re_changeid = rpr->rpr_changeid; 1024*7c478bd9Sstevel@tonic-gate } 1025*7c478bd9Sstevel@tonic-gate 1026*7c478bd9Sstevel@tonic-gate entity_release(parent); 1027*7c478bd9Sstevel@tonic-gate entity_release(child); 1028*7c478bd9Sstevel@tonic-gate 1029*7c478bd9Sstevel@tonic-gate return (result); 1030*7c478bd9Sstevel@tonic-gate } 1031*7c478bd9Sstevel@tonic-gate 1032*7c478bd9Sstevel@tonic-gate static int 1033*7c478bd9Sstevel@tonic-gate entity_create_pg(repcache_client_t *cp, 1034*7c478bd9Sstevel@tonic-gate struct rep_protocol_entity_create_pg *rpr) 1035*7c478bd9Sstevel@tonic-gate { 1036*7c478bd9Sstevel@tonic-gate repcache_entity_t *parent; 1037*7c478bd9Sstevel@tonic-gate repcache_entity_t *child; 1038*7c478bd9Sstevel@tonic-gate 1039*7c478bd9Sstevel@tonic-gate uint32_t parentid = rpr->rpr_entityid; 1040*7c478bd9Sstevel@tonic-gate uint32_t childid = rpr->rpr_childid; 1041*7c478bd9Sstevel@tonic-gate 1042*7c478bd9Sstevel@tonic-gate int result; 1043*7c478bd9Sstevel@tonic-gate 1044*7c478bd9Sstevel@tonic-gate if (rpr->rpr_changeid == INVALID_CHANGEID) 1045*7c478bd9Sstevel@tonic-gate return (REP_PROTOCOL_FAIL_BAD_REQUEST); 1046*7c478bd9Sstevel@tonic-gate 1047*7c478bd9Sstevel@tonic-gate result = entity_find2(cp, parentid, &parent, childid, &child); 1048*7c478bd9Sstevel@tonic-gate if (result != REP_PROTOCOL_SUCCESS) 1049*7c478bd9Sstevel@tonic-gate return (result); 1050*7c478bd9Sstevel@tonic-gate 1051*7c478bd9Sstevel@tonic-gate rpr->rpr_name[sizeof (rpr->rpr_name) - 1] = 0; 1052*7c478bd9Sstevel@tonic-gate rpr->rpr_type[sizeof (rpr->rpr_type) - 1] = 0; 1053*7c478bd9Sstevel@tonic-gate 1054*7c478bd9Sstevel@tonic-gate if (child->re_changeid == rpr->rpr_changeid) { 1055*7c478bd9Sstevel@tonic-gate result = REP_PROTOCOL_SUCCESS; 1056*7c478bd9Sstevel@tonic-gate } else { 1057*7c478bd9Sstevel@tonic-gate result = rc_node_create_child_pg(&parent->re_node, 1058*7c478bd9Sstevel@tonic-gate child->re_type, rpr->rpr_name, rpr->rpr_type, 1059*7c478bd9Sstevel@tonic-gate rpr->rpr_flags, &child->re_node); 1060*7c478bd9Sstevel@tonic-gate if (result == REP_PROTOCOL_SUCCESS) 1061*7c478bd9Sstevel@tonic-gate child->re_changeid = rpr->rpr_changeid; 1062*7c478bd9Sstevel@tonic-gate } 1063*7c478bd9Sstevel@tonic-gate 1064*7c478bd9Sstevel@tonic-gate entity_release(parent); 1065*7c478bd9Sstevel@tonic-gate entity_release(child); 1066*7c478bd9Sstevel@tonic-gate 1067*7c478bd9Sstevel@tonic-gate return (result); 1068*7c478bd9Sstevel@tonic-gate } 1069*7c478bd9Sstevel@tonic-gate 1070*7c478bd9Sstevel@tonic-gate static int 1071*7c478bd9Sstevel@tonic-gate entity_delete(repcache_client_t *cp, 1072*7c478bd9Sstevel@tonic-gate struct rep_protocol_entity_delete *rpr) 1073*7c478bd9Sstevel@tonic-gate { 1074*7c478bd9Sstevel@tonic-gate repcache_entity_t *entity; 1075*7c478bd9Sstevel@tonic-gate 1076*7c478bd9Sstevel@tonic-gate uint32_t entityid = rpr->rpr_entityid; 1077*7c478bd9Sstevel@tonic-gate 1078*7c478bd9Sstevel@tonic-gate int result; 1079*7c478bd9Sstevel@tonic-gate 1080*7c478bd9Sstevel@tonic-gate if (rpr->rpr_changeid == INVALID_CHANGEID) 1081*7c478bd9Sstevel@tonic-gate return (REP_PROTOCOL_FAIL_BAD_REQUEST); 1082*7c478bd9Sstevel@tonic-gate 1083*7c478bd9Sstevel@tonic-gate entity = entity_find(cp, entityid); 1084*7c478bd9Sstevel@tonic-gate 1085*7c478bd9Sstevel@tonic-gate if (entity == NULL) 1086*7c478bd9Sstevel@tonic-gate return (REP_PROTOCOL_FAIL_UNKNOWN_ID); 1087*7c478bd9Sstevel@tonic-gate 1088*7c478bd9Sstevel@tonic-gate if (entity->re_changeid == rpr->rpr_changeid) { 1089*7c478bd9Sstevel@tonic-gate result = REP_PROTOCOL_SUCCESS; 1090*7c478bd9Sstevel@tonic-gate } else { 1091*7c478bd9Sstevel@tonic-gate result = rc_node_delete(&entity->re_node); 1092*7c478bd9Sstevel@tonic-gate if (result == REP_PROTOCOL_SUCCESS) 1093*7c478bd9Sstevel@tonic-gate entity->re_changeid = rpr->rpr_changeid; 1094*7c478bd9Sstevel@tonic-gate } 1095*7c478bd9Sstevel@tonic-gate 1096*7c478bd9Sstevel@tonic-gate entity_release(entity); 1097*7c478bd9Sstevel@tonic-gate 1098*7c478bd9Sstevel@tonic-gate return (result); 1099*7c478bd9Sstevel@tonic-gate } 1100*7c478bd9Sstevel@tonic-gate 1101*7c478bd9Sstevel@tonic-gate static rep_protocol_responseid_t 1102*7c478bd9Sstevel@tonic-gate entity_teardown(repcache_client_t *cp, struct rep_protocol_entity_teardown *rpr) 1103*7c478bd9Sstevel@tonic-gate { 1104*7c478bd9Sstevel@tonic-gate entity_remove(cp, rpr->rpr_entityid); 1105*7c478bd9Sstevel@tonic-gate 1106*7c478bd9Sstevel@tonic-gate return (REP_PROTOCOL_SUCCESS); 1107*7c478bd9Sstevel@tonic-gate } 1108*7c478bd9Sstevel@tonic-gate 1109*7c478bd9Sstevel@tonic-gate /* 1110*7c478bd9Sstevel@tonic-gate * Fails with 1111*7c478bd9Sstevel@tonic-gate * _MISORDERED - the iterator exists and is not reset 1112*7c478bd9Sstevel@tonic-gate * _NO_RESOURCES - out of memory 1113*7c478bd9Sstevel@tonic-gate */ 1114*7c478bd9Sstevel@tonic-gate static int 1115*7c478bd9Sstevel@tonic-gate iter_setup(repcache_client_t *cp, struct rep_protocol_iter_request *rpr) 1116*7c478bd9Sstevel@tonic-gate { 1117*7c478bd9Sstevel@tonic-gate repcache_iter_t *iter; 1118*7c478bd9Sstevel@tonic-gate uint32_t sequence; 1119*7c478bd9Sstevel@tonic-gate 1120*7c478bd9Sstevel@tonic-gate client_start_insert(cp); 1121*7c478bd9Sstevel@tonic-gate /* 1122*7c478bd9Sstevel@tonic-gate * If the iter already exists, and hasn't been read from, 1123*7c478bd9Sstevel@tonic-gate * we assume the previous call succeeded. 1124*7c478bd9Sstevel@tonic-gate */ 1125*7c478bd9Sstevel@tonic-gate if ((iter = iter_find(cp, rpr->rpr_iterid)) != NULL) { 1126*7c478bd9Sstevel@tonic-gate sequence = iter->ri_sequence; 1127*7c478bd9Sstevel@tonic-gate iter_release(iter); 1128*7c478bd9Sstevel@tonic-gate 1129*7c478bd9Sstevel@tonic-gate client_end_insert(cp); 1130*7c478bd9Sstevel@tonic-gate 1131*7c478bd9Sstevel@tonic-gate if (sequence != 0) 1132*7c478bd9Sstevel@tonic-gate return (REP_PROTOCOL_FAIL_MISORDERED); 1133*7c478bd9Sstevel@tonic-gate return (REP_PROTOCOL_SUCCESS); 1134*7c478bd9Sstevel@tonic-gate } 1135*7c478bd9Sstevel@tonic-gate 1136*7c478bd9Sstevel@tonic-gate iter = iter_alloc(cp); 1137*7c478bd9Sstevel@tonic-gate if (iter == NULL) { 1138*7c478bd9Sstevel@tonic-gate client_end_insert(cp); 1139*7c478bd9Sstevel@tonic-gate return (REP_PROTOCOL_FAIL_NO_RESOURCES); 1140*7c478bd9Sstevel@tonic-gate } 1141*7c478bd9Sstevel@tonic-gate 1142*7c478bd9Sstevel@tonic-gate iter->ri_id = rpr->rpr_iterid; 1143*7c478bd9Sstevel@tonic-gate iter->ri_type = REP_PROTOCOL_TYPE_INVALID; 1144*7c478bd9Sstevel@tonic-gate iter->ri_sequence = 0; 1145*7c478bd9Sstevel@tonic-gate iter_add(cp, iter); 1146*7c478bd9Sstevel@tonic-gate 1147*7c478bd9Sstevel@tonic-gate client_end_insert(cp); 1148*7c478bd9Sstevel@tonic-gate return (REP_PROTOCOL_SUCCESS); 1149*7c478bd9Sstevel@tonic-gate } 1150*7c478bd9Sstevel@tonic-gate 1151*7c478bd9Sstevel@tonic-gate /* 1152*7c478bd9Sstevel@tonic-gate * Fails with 1153*7c478bd9Sstevel@tonic-gate * _UNKNOWN_ID 1154*7c478bd9Sstevel@tonic-gate * _MISORDERED - iterator has already been started 1155*7c478bd9Sstevel@tonic-gate * _NOT_SET 1156*7c478bd9Sstevel@tonic-gate * _DELETED 1157*7c478bd9Sstevel@tonic-gate * _TYPE_MISMATCH - entity cannot have type children 1158*7c478bd9Sstevel@tonic-gate * _BAD_REQUEST - rpr_flags is invalid 1159*7c478bd9Sstevel@tonic-gate * rpr_pattern is invalid 1160*7c478bd9Sstevel@tonic-gate * _NO_RESOURCES 1161*7c478bd9Sstevel@tonic-gate * _INVALID_TYPE 1162*7c478bd9Sstevel@tonic-gate * _BACKEND_ACCESS 1163*7c478bd9Sstevel@tonic-gate */ 1164*7c478bd9Sstevel@tonic-gate static int 1165*7c478bd9Sstevel@tonic-gate iter_start(repcache_client_t *cp, struct rep_protocol_iter_start *rpr) 1166*7c478bd9Sstevel@tonic-gate { 1167*7c478bd9Sstevel@tonic-gate int result; 1168*7c478bd9Sstevel@tonic-gate repcache_iter_t *iter; 1169*7c478bd9Sstevel@tonic-gate repcache_entity_t *ep; 1170*7c478bd9Sstevel@tonic-gate 1171*7c478bd9Sstevel@tonic-gate result = iter_find_w_entity(cp, rpr->rpr_iterid, &iter, 1172*7c478bd9Sstevel@tonic-gate rpr->rpr_entity, &ep); 1173*7c478bd9Sstevel@tonic-gate 1174*7c478bd9Sstevel@tonic-gate if (result != REP_PROTOCOL_SUCCESS) 1175*7c478bd9Sstevel@tonic-gate return (REP_PROTOCOL_FAIL_UNKNOWN_ID); 1176*7c478bd9Sstevel@tonic-gate 1177*7c478bd9Sstevel@tonic-gate if (iter->ri_sequence > 1) { 1178*7c478bd9Sstevel@tonic-gate result = REP_PROTOCOL_FAIL_MISORDERED; 1179*7c478bd9Sstevel@tonic-gate goto end; 1180*7c478bd9Sstevel@tonic-gate } 1181*7c478bd9Sstevel@tonic-gate 1182*7c478bd9Sstevel@tonic-gate if (iter->ri_sequence == 1) { 1183*7c478bd9Sstevel@tonic-gate result = REP_PROTOCOL_SUCCESS; 1184*7c478bd9Sstevel@tonic-gate goto end; 1185*7c478bd9Sstevel@tonic-gate } 1186*7c478bd9Sstevel@tonic-gate 1187*7c478bd9Sstevel@tonic-gate rpr->rpr_pattern[sizeof (rpr->rpr_pattern) - 1] = 0; 1188*7c478bd9Sstevel@tonic-gate 1189*7c478bd9Sstevel@tonic-gate result = rc_node_setup_iter(&ep->re_node, &iter->ri_iter, 1190*7c478bd9Sstevel@tonic-gate rpr->rpr_itertype, rpr->rpr_flags, rpr->rpr_pattern); 1191*7c478bd9Sstevel@tonic-gate 1192*7c478bd9Sstevel@tonic-gate if (result == REP_PROTOCOL_SUCCESS) 1193*7c478bd9Sstevel@tonic-gate iter->ri_sequence++; 1194*7c478bd9Sstevel@tonic-gate 1195*7c478bd9Sstevel@tonic-gate end: 1196*7c478bd9Sstevel@tonic-gate iter_release(iter); 1197*7c478bd9Sstevel@tonic-gate entity_release(ep); 1198*7c478bd9Sstevel@tonic-gate return (result); 1199*7c478bd9Sstevel@tonic-gate } 1200*7c478bd9Sstevel@tonic-gate 1201*7c478bd9Sstevel@tonic-gate /* 1202*7c478bd9Sstevel@tonic-gate * Returns 1203*7c478bd9Sstevel@tonic-gate * _UNKNOWN_ID 1204*7c478bd9Sstevel@tonic-gate * _NOT_SET - iter has not been started 1205*7c478bd9Sstevel@tonic-gate * _MISORDERED 1206*7c478bd9Sstevel@tonic-gate * _BAD_REQUEST - iter walks values 1207*7c478bd9Sstevel@tonic-gate * _TYPE_MISMATCH - iter does not walk type entities 1208*7c478bd9Sstevel@tonic-gate * _DELETED - parent was deleted 1209*7c478bd9Sstevel@tonic-gate * _NO_RESOURCES 1210*7c478bd9Sstevel@tonic-gate * _INVALID_TYPE - type is invalid 1211*7c478bd9Sstevel@tonic-gate * _DONE 1212*7c478bd9Sstevel@tonic-gate * _SUCCESS 1213*7c478bd9Sstevel@tonic-gate * 1214*7c478bd9Sstevel@tonic-gate * For composed property group iterators, can also return 1215*7c478bd9Sstevel@tonic-gate * _TYPE_MISMATCH - parent cannot have type children 1216*7c478bd9Sstevel@tonic-gate * _BACKEND_ACCESS 1217*7c478bd9Sstevel@tonic-gate */ 1218*7c478bd9Sstevel@tonic-gate static rep_protocol_responseid_t 1219*7c478bd9Sstevel@tonic-gate iter_read(repcache_client_t *cp, struct rep_protocol_iter_read *rpr) 1220*7c478bd9Sstevel@tonic-gate { 1221*7c478bd9Sstevel@tonic-gate rep_protocol_responseid_t result; 1222*7c478bd9Sstevel@tonic-gate repcache_iter_t *iter; 1223*7c478bd9Sstevel@tonic-gate repcache_entity_t *ep; 1224*7c478bd9Sstevel@tonic-gate uint32_t sequence; 1225*7c478bd9Sstevel@tonic-gate 1226*7c478bd9Sstevel@tonic-gate result = iter_find_w_entity(cp, rpr->rpr_iterid, &iter, 1227*7c478bd9Sstevel@tonic-gate rpr->rpr_entityid, &ep); 1228*7c478bd9Sstevel@tonic-gate 1229*7c478bd9Sstevel@tonic-gate if (result != REP_PROTOCOL_SUCCESS) 1230*7c478bd9Sstevel@tonic-gate return (result); 1231*7c478bd9Sstevel@tonic-gate 1232*7c478bd9Sstevel@tonic-gate sequence = rpr->rpr_sequence; 1233*7c478bd9Sstevel@tonic-gate 1234*7c478bd9Sstevel@tonic-gate if (iter->ri_sequence == 0) { 1235*7c478bd9Sstevel@tonic-gate iter_release(iter); 1236*7c478bd9Sstevel@tonic-gate entity_release(ep); 1237*7c478bd9Sstevel@tonic-gate return (REP_PROTOCOL_FAIL_NOT_SET); 1238*7c478bd9Sstevel@tonic-gate } 1239*7c478bd9Sstevel@tonic-gate 1240*7c478bd9Sstevel@tonic-gate if (sequence == 1) { 1241*7c478bd9Sstevel@tonic-gate iter_release(iter); 1242*7c478bd9Sstevel@tonic-gate entity_release(ep); 1243*7c478bd9Sstevel@tonic-gate return (REP_PROTOCOL_FAIL_MISORDERED); 1244*7c478bd9Sstevel@tonic-gate } 1245*7c478bd9Sstevel@tonic-gate 1246*7c478bd9Sstevel@tonic-gate if (sequence == iter->ri_sequence) { 1247*7c478bd9Sstevel@tonic-gate iter_release(iter); 1248*7c478bd9Sstevel@tonic-gate entity_release(ep); 1249*7c478bd9Sstevel@tonic-gate return (REP_PROTOCOL_SUCCESS); 1250*7c478bd9Sstevel@tonic-gate } 1251*7c478bd9Sstevel@tonic-gate 1252*7c478bd9Sstevel@tonic-gate if (sequence == iter->ri_sequence + 1) { 1253*7c478bd9Sstevel@tonic-gate result = rc_iter_next(iter->ri_iter, &ep->re_node, 1254*7c478bd9Sstevel@tonic-gate ep->re_type); 1255*7c478bd9Sstevel@tonic-gate 1256*7c478bd9Sstevel@tonic-gate if (result == REP_PROTOCOL_SUCCESS) 1257*7c478bd9Sstevel@tonic-gate iter->ri_sequence++; 1258*7c478bd9Sstevel@tonic-gate 1259*7c478bd9Sstevel@tonic-gate iter_release(iter); 1260*7c478bd9Sstevel@tonic-gate entity_release(ep); 1261*7c478bd9Sstevel@tonic-gate 1262*7c478bd9Sstevel@tonic-gate return (result); 1263*7c478bd9Sstevel@tonic-gate } 1264*7c478bd9Sstevel@tonic-gate 1265*7c478bd9Sstevel@tonic-gate iter_release(iter); 1266*7c478bd9Sstevel@tonic-gate entity_release(ep); 1267*7c478bd9Sstevel@tonic-gate return (REP_PROTOCOL_FAIL_MISORDERED); 1268*7c478bd9Sstevel@tonic-gate } 1269*7c478bd9Sstevel@tonic-gate 1270*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 1271*7c478bd9Sstevel@tonic-gate static void 1272*7c478bd9Sstevel@tonic-gate iter_read_value(repcache_client_t *cp, const void *in, size_t insz, 1273*7c478bd9Sstevel@tonic-gate void *out_arg, size_t *outsz, void *arg) 1274*7c478bd9Sstevel@tonic-gate { 1275*7c478bd9Sstevel@tonic-gate const struct rep_protocol_iter_read_value *rpr = in; 1276*7c478bd9Sstevel@tonic-gate struct rep_protocol_value_response *out = out_arg; 1277*7c478bd9Sstevel@tonic-gate rep_protocol_responseid_t result; 1278*7c478bd9Sstevel@tonic-gate 1279*7c478bd9Sstevel@tonic-gate repcache_iter_t *iter; 1280*7c478bd9Sstevel@tonic-gate uint32_t sequence; 1281*7c478bd9Sstevel@tonic-gate int repeat; 1282*7c478bd9Sstevel@tonic-gate 1283*7c478bd9Sstevel@tonic-gate assert(*outsz == sizeof (*out)); 1284*7c478bd9Sstevel@tonic-gate 1285*7c478bd9Sstevel@tonic-gate iter = iter_find(cp, rpr->rpr_iterid); 1286*7c478bd9Sstevel@tonic-gate 1287*7c478bd9Sstevel@tonic-gate if (iter == NULL) { 1288*7c478bd9Sstevel@tonic-gate result = REP_PROTOCOL_FAIL_UNKNOWN_ID; 1289*7c478bd9Sstevel@tonic-gate goto out; 1290*7c478bd9Sstevel@tonic-gate } 1291*7c478bd9Sstevel@tonic-gate 1292*7c478bd9Sstevel@tonic-gate sequence = rpr->rpr_sequence; 1293*7c478bd9Sstevel@tonic-gate 1294*7c478bd9Sstevel@tonic-gate if (iter->ri_sequence == 0) { 1295*7c478bd9Sstevel@tonic-gate iter_release(iter); 1296*7c478bd9Sstevel@tonic-gate result = REP_PROTOCOL_FAIL_NOT_SET; 1297*7c478bd9Sstevel@tonic-gate goto out; 1298*7c478bd9Sstevel@tonic-gate } 1299*7c478bd9Sstevel@tonic-gate 1300*7c478bd9Sstevel@tonic-gate repeat = (sequence == iter->ri_sequence); 1301*7c478bd9Sstevel@tonic-gate 1302*7c478bd9Sstevel@tonic-gate if (sequence == 1 || (!repeat && sequence != iter->ri_sequence + 1)) { 1303*7c478bd9Sstevel@tonic-gate iter_release(iter); 1304*7c478bd9Sstevel@tonic-gate result = REP_PROTOCOL_FAIL_MISORDERED; 1305*7c478bd9Sstevel@tonic-gate goto out; 1306*7c478bd9Sstevel@tonic-gate } 1307*7c478bd9Sstevel@tonic-gate 1308*7c478bd9Sstevel@tonic-gate result = rc_iter_next_value(iter->ri_iter, out, outsz, repeat); 1309*7c478bd9Sstevel@tonic-gate 1310*7c478bd9Sstevel@tonic-gate if (!repeat && result == REP_PROTOCOL_SUCCESS) 1311*7c478bd9Sstevel@tonic-gate iter->ri_sequence++; 1312*7c478bd9Sstevel@tonic-gate 1313*7c478bd9Sstevel@tonic-gate iter_release(iter); 1314*7c478bd9Sstevel@tonic-gate 1315*7c478bd9Sstevel@tonic-gate out: 1316*7c478bd9Sstevel@tonic-gate /* 1317*7c478bd9Sstevel@tonic-gate * If we fail, we only return the response code. 1318*7c478bd9Sstevel@tonic-gate * If we succeed, rc_iter_next_value has shortened *outsz 1319*7c478bd9Sstevel@tonic-gate * to only include the value bytes needed. 1320*7c478bd9Sstevel@tonic-gate */ 1321*7c478bd9Sstevel@tonic-gate if (result != REP_PROTOCOL_SUCCESS && result != REP_PROTOCOL_DONE) 1322*7c478bd9Sstevel@tonic-gate *outsz = sizeof (out->rpr_response); 1323*7c478bd9Sstevel@tonic-gate 1324*7c478bd9Sstevel@tonic-gate out->rpr_response = result; 1325*7c478bd9Sstevel@tonic-gate } 1326*7c478bd9Sstevel@tonic-gate 1327*7c478bd9Sstevel@tonic-gate static int 1328*7c478bd9Sstevel@tonic-gate iter_reset(repcache_client_t *cp, struct rep_protocol_iter_request *rpr) 1329*7c478bd9Sstevel@tonic-gate { 1330*7c478bd9Sstevel@tonic-gate repcache_iter_t *iter = iter_find(cp, rpr->rpr_iterid); 1331*7c478bd9Sstevel@tonic-gate 1332*7c478bd9Sstevel@tonic-gate if (iter == NULL) 1333*7c478bd9Sstevel@tonic-gate return (REP_PROTOCOL_FAIL_UNKNOWN_ID); 1334*7c478bd9Sstevel@tonic-gate 1335*7c478bd9Sstevel@tonic-gate if (iter->ri_sequence != 0) { 1336*7c478bd9Sstevel@tonic-gate iter->ri_sequence = 0; 1337*7c478bd9Sstevel@tonic-gate rc_iter_destroy(&iter->ri_iter); 1338*7c478bd9Sstevel@tonic-gate } 1339*7c478bd9Sstevel@tonic-gate iter_release(iter); 1340*7c478bd9Sstevel@tonic-gate return (REP_PROTOCOL_SUCCESS); 1341*7c478bd9Sstevel@tonic-gate } 1342*7c478bd9Sstevel@tonic-gate 1343*7c478bd9Sstevel@tonic-gate static rep_protocol_responseid_t 1344*7c478bd9Sstevel@tonic-gate iter_teardown(repcache_client_t *cp, struct rep_protocol_iter_request *rpr) 1345*7c478bd9Sstevel@tonic-gate { 1346*7c478bd9Sstevel@tonic-gate iter_remove(cp, rpr->rpr_iterid); 1347*7c478bd9Sstevel@tonic-gate 1348*7c478bd9Sstevel@tonic-gate return (REP_PROTOCOL_SUCCESS); 1349*7c478bd9Sstevel@tonic-gate } 1350*7c478bd9Sstevel@tonic-gate 1351*7c478bd9Sstevel@tonic-gate static rep_protocol_responseid_t 1352*7c478bd9Sstevel@tonic-gate tx_start(repcache_client_t *cp, struct rep_protocol_transaction_start *rpr) 1353*7c478bd9Sstevel@tonic-gate { 1354*7c478bd9Sstevel@tonic-gate repcache_entity_t *tx; 1355*7c478bd9Sstevel@tonic-gate repcache_entity_t *ep; 1356*7c478bd9Sstevel@tonic-gate rep_protocol_responseid_t result; 1357*7c478bd9Sstevel@tonic-gate 1358*7c478bd9Sstevel@tonic-gate uint32_t txid = rpr->rpr_entityid_tx; 1359*7c478bd9Sstevel@tonic-gate uint32_t epid = rpr->rpr_entityid; 1360*7c478bd9Sstevel@tonic-gate 1361*7c478bd9Sstevel@tonic-gate result = entity_find2(cp, txid, &tx, epid, &ep); 1362*7c478bd9Sstevel@tonic-gate if (result != REP_PROTOCOL_SUCCESS) 1363*7c478bd9Sstevel@tonic-gate return (result); 1364*7c478bd9Sstevel@tonic-gate 1365*7c478bd9Sstevel@tonic-gate if (tx->re_txstate == REPCACHE_TX_SETUP) { 1366*7c478bd9Sstevel@tonic-gate result = REP_PROTOCOL_SUCCESS; 1367*7c478bd9Sstevel@tonic-gate goto end; 1368*7c478bd9Sstevel@tonic-gate } 1369*7c478bd9Sstevel@tonic-gate if (tx->re_txstate != REPCACHE_TX_INIT) { 1370*7c478bd9Sstevel@tonic-gate result = REP_PROTOCOL_FAIL_MISORDERED; 1371*7c478bd9Sstevel@tonic-gate goto end; 1372*7c478bd9Sstevel@tonic-gate } 1373*7c478bd9Sstevel@tonic-gate 1374*7c478bd9Sstevel@tonic-gate result = rc_node_setup_tx(&ep->re_node, &tx->re_node); 1375*7c478bd9Sstevel@tonic-gate 1376*7c478bd9Sstevel@tonic-gate end: 1377*7c478bd9Sstevel@tonic-gate if (result == REP_PROTOCOL_SUCCESS) 1378*7c478bd9Sstevel@tonic-gate tx->re_txstate = REPCACHE_TX_SETUP; 1379*7c478bd9Sstevel@tonic-gate else 1380*7c478bd9Sstevel@tonic-gate rc_node_clear(&tx->re_node, 0); 1381*7c478bd9Sstevel@tonic-gate 1382*7c478bd9Sstevel@tonic-gate entity_release(ep); 1383*7c478bd9Sstevel@tonic-gate entity_release(tx); 1384*7c478bd9Sstevel@tonic-gate return (result); 1385*7c478bd9Sstevel@tonic-gate } 1386*7c478bd9Sstevel@tonic-gate 1387*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 1388*7c478bd9Sstevel@tonic-gate static void 1389*7c478bd9Sstevel@tonic-gate tx_commit(repcache_client_t *cp, const void *in, size_t insz, 1390*7c478bd9Sstevel@tonic-gate void *out_arg, size_t *outsz, void *arg) 1391*7c478bd9Sstevel@tonic-gate { 1392*7c478bd9Sstevel@tonic-gate struct rep_protocol_response *out = out_arg; 1393*7c478bd9Sstevel@tonic-gate const struct rep_protocol_transaction_commit *rpr = in; 1394*7c478bd9Sstevel@tonic-gate repcache_entity_t *tx; 1395*7c478bd9Sstevel@tonic-gate 1396*7c478bd9Sstevel@tonic-gate assert(*outsz == sizeof (*out)); 1397*7c478bd9Sstevel@tonic-gate assert(insz >= REP_PROTOCOL_TRANSACTION_COMMIT_MIN_SIZE); 1398*7c478bd9Sstevel@tonic-gate 1399*7c478bd9Sstevel@tonic-gate if (rpr->rpr_size != insz) { 1400*7c478bd9Sstevel@tonic-gate out->rpr_response = REP_PROTOCOL_FAIL_BAD_REQUEST; 1401*7c478bd9Sstevel@tonic-gate return; 1402*7c478bd9Sstevel@tonic-gate } 1403*7c478bd9Sstevel@tonic-gate 1404*7c478bd9Sstevel@tonic-gate tx = entity_find(cp, rpr->rpr_entityid); 1405*7c478bd9Sstevel@tonic-gate 1406*7c478bd9Sstevel@tonic-gate if (tx == NULL) { 1407*7c478bd9Sstevel@tonic-gate out->rpr_response = REP_PROTOCOL_FAIL_UNKNOWN_ID; 1408*7c478bd9Sstevel@tonic-gate return; 1409*7c478bd9Sstevel@tonic-gate } 1410*7c478bd9Sstevel@tonic-gate 1411*7c478bd9Sstevel@tonic-gate switch (tx->re_txstate) { 1412*7c478bd9Sstevel@tonic-gate case REPCACHE_TX_INIT: 1413*7c478bd9Sstevel@tonic-gate out->rpr_response = REP_PROTOCOL_FAIL_MISORDERED; 1414*7c478bd9Sstevel@tonic-gate break; 1415*7c478bd9Sstevel@tonic-gate 1416*7c478bd9Sstevel@tonic-gate case REPCACHE_TX_SETUP: 1417*7c478bd9Sstevel@tonic-gate out->rpr_response = rc_tx_commit(&tx->re_node, rpr->rpr_cmd, 1418*7c478bd9Sstevel@tonic-gate insz - REP_PROTOCOL_TRANSACTION_COMMIT_MIN_SIZE); 1419*7c478bd9Sstevel@tonic-gate 1420*7c478bd9Sstevel@tonic-gate if (out->rpr_response == REP_PROTOCOL_SUCCESS) { 1421*7c478bd9Sstevel@tonic-gate tx->re_txstate = REPCACHE_TX_COMMITTED; 1422*7c478bd9Sstevel@tonic-gate rc_node_clear(&tx->re_node, 0); 1423*7c478bd9Sstevel@tonic-gate } 1424*7c478bd9Sstevel@tonic-gate 1425*7c478bd9Sstevel@tonic-gate break; 1426*7c478bd9Sstevel@tonic-gate case REPCACHE_TX_COMMITTED: 1427*7c478bd9Sstevel@tonic-gate out->rpr_response = REP_PROTOCOL_SUCCESS; 1428*7c478bd9Sstevel@tonic-gate break; 1429*7c478bd9Sstevel@tonic-gate default: 1430*7c478bd9Sstevel@tonic-gate assert(0); /* CAN'T HAPPEN */ 1431*7c478bd9Sstevel@tonic-gate break; 1432*7c478bd9Sstevel@tonic-gate } 1433*7c478bd9Sstevel@tonic-gate 1434*7c478bd9Sstevel@tonic-gate entity_release(tx); 1435*7c478bd9Sstevel@tonic-gate } 1436*7c478bd9Sstevel@tonic-gate 1437*7c478bd9Sstevel@tonic-gate static rep_protocol_responseid_t 1438*7c478bd9Sstevel@tonic-gate next_snaplevel(repcache_client_t *cp, struct rep_protocol_entity_pair *rpr) 1439*7c478bd9Sstevel@tonic-gate { 1440*7c478bd9Sstevel@tonic-gate repcache_entity_t *src; 1441*7c478bd9Sstevel@tonic-gate repcache_entity_t *dest; 1442*7c478bd9Sstevel@tonic-gate 1443*7c478bd9Sstevel@tonic-gate uint32_t srcid = rpr->rpr_entity_src; 1444*7c478bd9Sstevel@tonic-gate uint32_t destid = rpr->rpr_entity_dst; 1445*7c478bd9Sstevel@tonic-gate 1446*7c478bd9Sstevel@tonic-gate int result; 1447*7c478bd9Sstevel@tonic-gate 1448*7c478bd9Sstevel@tonic-gate result = entity_find2(cp, srcid, &src, destid, &dest); 1449*7c478bd9Sstevel@tonic-gate if (result != REP_PROTOCOL_SUCCESS) 1450*7c478bd9Sstevel@tonic-gate return (result); 1451*7c478bd9Sstevel@tonic-gate 1452*7c478bd9Sstevel@tonic-gate result = rc_node_next_snaplevel(&src->re_node, &dest->re_node); 1453*7c478bd9Sstevel@tonic-gate 1454*7c478bd9Sstevel@tonic-gate entity_release(src); 1455*7c478bd9Sstevel@tonic-gate entity_release(dest); 1456*7c478bd9Sstevel@tonic-gate 1457*7c478bd9Sstevel@tonic-gate return (result); 1458*7c478bd9Sstevel@tonic-gate } 1459*7c478bd9Sstevel@tonic-gate 1460*7c478bd9Sstevel@tonic-gate static rep_protocol_responseid_t 1461*7c478bd9Sstevel@tonic-gate snapshot_take(repcache_client_t *cp, struct rep_protocol_snapshot_take *rpr) 1462*7c478bd9Sstevel@tonic-gate { 1463*7c478bd9Sstevel@tonic-gate repcache_entity_t *src; 1464*7c478bd9Sstevel@tonic-gate uint32_t srcid = rpr->rpr_entityid_src; 1465*7c478bd9Sstevel@tonic-gate repcache_entity_t *dest; 1466*7c478bd9Sstevel@tonic-gate uint32_t destid = rpr->rpr_entityid_dest; 1467*7c478bd9Sstevel@tonic-gate 1468*7c478bd9Sstevel@tonic-gate int result; 1469*7c478bd9Sstevel@tonic-gate 1470*7c478bd9Sstevel@tonic-gate result = entity_find2(cp, srcid, &src, destid, &dest); 1471*7c478bd9Sstevel@tonic-gate if (result != REP_PROTOCOL_SUCCESS) 1472*7c478bd9Sstevel@tonic-gate return (result); 1473*7c478bd9Sstevel@tonic-gate 1474*7c478bd9Sstevel@tonic-gate if (dest->re_type != REP_PROTOCOL_ENTITY_SNAPSHOT) { 1475*7c478bd9Sstevel@tonic-gate result = REP_PROTOCOL_FAIL_TYPE_MISMATCH; 1476*7c478bd9Sstevel@tonic-gate } else { 1477*7c478bd9Sstevel@tonic-gate rpr->rpr_name[sizeof (rpr->rpr_name) - 1] = 0; 1478*7c478bd9Sstevel@tonic-gate 1479*7c478bd9Sstevel@tonic-gate if (rpr->rpr_flags == REP_SNAPSHOT_NEW) 1480*7c478bd9Sstevel@tonic-gate result = rc_snapshot_take_new(&src->re_node, NULL, 1481*7c478bd9Sstevel@tonic-gate NULL, rpr->rpr_name, &dest->re_node); 1482*7c478bd9Sstevel@tonic-gate else if (rpr->rpr_flags == REP_SNAPSHOT_ATTACH && 1483*7c478bd9Sstevel@tonic-gate rpr->rpr_name[0] == 0) 1484*7c478bd9Sstevel@tonic-gate result = rc_snapshot_take_attach(&src->re_node, 1485*7c478bd9Sstevel@tonic-gate &dest->re_node); 1486*7c478bd9Sstevel@tonic-gate else 1487*7c478bd9Sstevel@tonic-gate result = REP_PROTOCOL_FAIL_BAD_REQUEST; 1488*7c478bd9Sstevel@tonic-gate } 1489*7c478bd9Sstevel@tonic-gate entity_release(src); 1490*7c478bd9Sstevel@tonic-gate entity_release(dest); 1491*7c478bd9Sstevel@tonic-gate 1492*7c478bd9Sstevel@tonic-gate return (result); 1493*7c478bd9Sstevel@tonic-gate } 1494*7c478bd9Sstevel@tonic-gate 1495*7c478bd9Sstevel@tonic-gate static rep_protocol_responseid_t 1496*7c478bd9Sstevel@tonic-gate snapshot_take_named(repcache_client_t *cp, 1497*7c478bd9Sstevel@tonic-gate struct rep_protocol_snapshot_take_named *rpr) 1498*7c478bd9Sstevel@tonic-gate { 1499*7c478bd9Sstevel@tonic-gate repcache_entity_t *src; 1500*7c478bd9Sstevel@tonic-gate uint32_t srcid = rpr->rpr_entityid_src; 1501*7c478bd9Sstevel@tonic-gate repcache_entity_t *dest; 1502*7c478bd9Sstevel@tonic-gate uint32_t destid = rpr->rpr_entityid_dest; 1503*7c478bd9Sstevel@tonic-gate 1504*7c478bd9Sstevel@tonic-gate int result; 1505*7c478bd9Sstevel@tonic-gate 1506*7c478bd9Sstevel@tonic-gate result = entity_find2(cp, srcid, &src, destid, &dest); 1507*7c478bd9Sstevel@tonic-gate if (result != REP_PROTOCOL_SUCCESS) 1508*7c478bd9Sstevel@tonic-gate return (result); 1509*7c478bd9Sstevel@tonic-gate 1510*7c478bd9Sstevel@tonic-gate if (dest->re_type != REP_PROTOCOL_ENTITY_SNAPSHOT) { 1511*7c478bd9Sstevel@tonic-gate result = REP_PROTOCOL_FAIL_TYPE_MISMATCH; 1512*7c478bd9Sstevel@tonic-gate } else { 1513*7c478bd9Sstevel@tonic-gate rpr->rpr_svcname[sizeof (rpr->rpr_svcname) - 1] = 0; 1514*7c478bd9Sstevel@tonic-gate rpr->rpr_instname[sizeof (rpr->rpr_instname) - 1] = 0; 1515*7c478bd9Sstevel@tonic-gate rpr->rpr_name[sizeof (rpr->rpr_name) - 1] = 0; 1516*7c478bd9Sstevel@tonic-gate 1517*7c478bd9Sstevel@tonic-gate result = rc_snapshot_take_new(&src->re_node, rpr->rpr_svcname, 1518*7c478bd9Sstevel@tonic-gate rpr->rpr_instname, rpr->rpr_name, &dest->re_node); 1519*7c478bd9Sstevel@tonic-gate } 1520*7c478bd9Sstevel@tonic-gate entity_release(src); 1521*7c478bd9Sstevel@tonic-gate entity_release(dest); 1522*7c478bd9Sstevel@tonic-gate 1523*7c478bd9Sstevel@tonic-gate return (result); 1524*7c478bd9Sstevel@tonic-gate } 1525*7c478bd9Sstevel@tonic-gate 1526*7c478bd9Sstevel@tonic-gate static rep_protocol_responseid_t 1527*7c478bd9Sstevel@tonic-gate snapshot_attach(repcache_client_t *cp, struct rep_protocol_snapshot_attach *rpr) 1528*7c478bd9Sstevel@tonic-gate { 1529*7c478bd9Sstevel@tonic-gate repcache_entity_t *src; 1530*7c478bd9Sstevel@tonic-gate uint32_t srcid = rpr->rpr_entityid_src; 1531*7c478bd9Sstevel@tonic-gate repcache_entity_t *dest; 1532*7c478bd9Sstevel@tonic-gate uint32_t destid = rpr->rpr_entityid_dest; 1533*7c478bd9Sstevel@tonic-gate 1534*7c478bd9Sstevel@tonic-gate int result; 1535*7c478bd9Sstevel@tonic-gate 1536*7c478bd9Sstevel@tonic-gate result = entity_find2(cp, srcid, &src, destid, &dest); 1537*7c478bd9Sstevel@tonic-gate if (result != REP_PROTOCOL_SUCCESS) 1538*7c478bd9Sstevel@tonic-gate return (result); 1539*7c478bd9Sstevel@tonic-gate 1540*7c478bd9Sstevel@tonic-gate result = rc_snapshot_attach(&src->re_node, &dest->re_node); 1541*7c478bd9Sstevel@tonic-gate 1542*7c478bd9Sstevel@tonic-gate entity_release(src); 1543*7c478bd9Sstevel@tonic-gate entity_release(dest); 1544*7c478bd9Sstevel@tonic-gate 1545*7c478bd9Sstevel@tonic-gate return (result); 1546*7c478bd9Sstevel@tonic-gate } 1547*7c478bd9Sstevel@tonic-gate 1548*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 1549*7c478bd9Sstevel@tonic-gate static void 1550*7c478bd9Sstevel@tonic-gate property_get_type(repcache_client_t *cp, const void *in, size_t insz, 1551*7c478bd9Sstevel@tonic-gate void *out_arg, size_t *outsz, void *arg) 1552*7c478bd9Sstevel@tonic-gate { 1553*7c478bd9Sstevel@tonic-gate const struct rep_protocol_property_request *rpr = in; 1554*7c478bd9Sstevel@tonic-gate struct rep_protocol_integer_response *out = out_arg; 1555*7c478bd9Sstevel@tonic-gate repcache_entity_t *ep; 1556*7c478bd9Sstevel@tonic-gate rep_protocol_value_type_t t = 0; 1557*7c478bd9Sstevel@tonic-gate 1558*7c478bd9Sstevel@tonic-gate assert(*outsz == sizeof (*out)); 1559*7c478bd9Sstevel@tonic-gate 1560*7c478bd9Sstevel@tonic-gate ep = entity_find(cp, rpr->rpr_entityid); 1561*7c478bd9Sstevel@tonic-gate 1562*7c478bd9Sstevel@tonic-gate if (ep == NULL) { 1563*7c478bd9Sstevel@tonic-gate out->rpr_response = REP_PROTOCOL_FAIL_UNKNOWN_ID; 1564*7c478bd9Sstevel@tonic-gate *outsz = sizeof (out->rpr_response); 1565*7c478bd9Sstevel@tonic-gate return; 1566*7c478bd9Sstevel@tonic-gate } 1567*7c478bd9Sstevel@tonic-gate 1568*7c478bd9Sstevel@tonic-gate out->rpr_response = rc_node_get_property_type(&ep->re_node, &t); 1569*7c478bd9Sstevel@tonic-gate 1570*7c478bd9Sstevel@tonic-gate entity_release(ep); 1571*7c478bd9Sstevel@tonic-gate 1572*7c478bd9Sstevel@tonic-gate if (out->rpr_response != REP_PROTOCOL_SUCCESS) 1573*7c478bd9Sstevel@tonic-gate *outsz = sizeof (out->rpr_response); 1574*7c478bd9Sstevel@tonic-gate else 1575*7c478bd9Sstevel@tonic-gate out->rpr_value = t; 1576*7c478bd9Sstevel@tonic-gate } 1577*7c478bd9Sstevel@tonic-gate 1578*7c478bd9Sstevel@tonic-gate /* 1579*7c478bd9Sstevel@tonic-gate * Fails with: 1580*7c478bd9Sstevel@tonic-gate * _UNKNOWN_ID - an id does not designate an active register 1581*7c478bd9Sstevel@tonic-gate * _NOT_SET - The property is not set 1582*7c478bd9Sstevel@tonic-gate * _DELETED - The property has been deleted 1583*7c478bd9Sstevel@tonic-gate * _TYPE_MISMATCH - The object is not a property 1584*7c478bd9Sstevel@tonic-gate * _NOT_FOUND - The property has no values. 1585*7c478bd9Sstevel@tonic-gate * 1586*7c478bd9Sstevel@tonic-gate * Succeeds with: 1587*7c478bd9Sstevel@tonic-gate * _SUCCESS - The property has 1 value. 1588*7c478bd9Sstevel@tonic-gate * _TRUNCATED - The property has >1 value. 1589*7c478bd9Sstevel@tonic-gate */ 1590*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 1591*7c478bd9Sstevel@tonic-gate static void 1592*7c478bd9Sstevel@tonic-gate property_get_value(repcache_client_t *cp, const void *in, size_t insz, 1593*7c478bd9Sstevel@tonic-gate void *out_arg, size_t *outsz, void *arg) 1594*7c478bd9Sstevel@tonic-gate { 1595*7c478bd9Sstevel@tonic-gate const struct rep_protocol_property_request *rpr = in; 1596*7c478bd9Sstevel@tonic-gate struct rep_protocol_value_response *out = out_arg; 1597*7c478bd9Sstevel@tonic-gate repcache_entity_t *ep; 1598*7c478bd9Sstevel@tonic-gate 1599*7c478bd9Sstevel@tonic-gate assert(*outsz == sizeof (*out)); 1600*7c478bd9Sstevel@tonic-gate 1601*7c478bd9Sstevel@tonic-gate ep = entity_find(cp, rpr->rpr_entityid); 1602*7c478bd9Sstevel@tonic-gate if (ep == NULL) { 1603*7c478bd9Sstevel@tonic-gate out->rpr_response = REP_PROTOCOL_FAIL_UNKNOWN_ID; 1604*7c478bd9Sstevel@tonic-gate *outsz = sizeof (out->rpr_response); 1605*7c478bd9Sstevel@tonic-gate return; 1606*7c478bd9Sstevel@tonic-gate } 1607*7c478bd9Sstevel@tonic-gate 1608*7c478bd9Sstevel@tonic-gate out->rpr_response = rc_node_get_property_value(&ep->re_node, out, 1609*7c478bd9Sstevel@tonic-gate outsz); 1610*7c478bd9Sstevel@tonic-gate 1611*7c478bd9Sstevel@tonic-gate entity_release(ep); 1612*7c478bd9Sstevel@tonic-gate 1613*7c478bd9Sstevel@tonic-gate /* 1614*7c478bd9Sstevel@tonic-gate * If we fail, we only return the response code. 1615*7c478bd9Sstevel@tonic-gate * If we succeed, rc_node_get_property_value has shortened *outsz 1616*7c478bd9Sstevel@tonic-gate * to only include the value bytes needed. 1617*7c478bd9Sstevel@tonic-gate */ 1618*7c478bd9Sstevel@tonic-gate if (out->rpr_response != REP_PROTOCOL_SUCCESS && 1619*7c478bd9Sstevel@tonic-gate out->rpr_response != REP_PROTOCOL_FAIL_TRUNCATED) 1620*7c478bd9Sstevel@tonic-gate *outsz = sizeof (out->rpr_response); 1621*7c478bd9Sstevel@tonic-gate } 1622*7c478bd9Sstevel@tonic-gate 1623*7c478bd9Sstevel@tonic-gate static rep_protocol_responseid_t 1624*7c478bd9Sstevel@tonic-gate propertygrp_notify(repcache_client_t *cp, 1625*7c478bd9Sstevel@tonic-gate struct rep_protocol_propertygrp_request *rpr, int *out_fd) 1626*7c478bd9Sstevel@tonic-gate { 1627*7c478bd9Sstevel@tonic-gate int fds[2]; 1628*7c478bd9Sstevel@tonic-gate int ours, theirs; 1629*7c478bd9Sstevel@tonic-gate 1630*7c478bd9Sstevel@tonic-gate rep_protocol_responseid_t result; 1631*7c478bd9Sstevel@tonic-gate repcache_entity_t *ep; 1632*7c478bd9Sstevel@tonic-gate 1633*7c478bd9Sstevel@tonic-gate if (pipe(fds) < 0) 1634*7c478bd9Sstevel@tonic-gate return (REP_PROTOCOL_FAIL_NO_RESOURCES); 1635*7c478bd9Sstevel@tonic-gate 1636*7c478bd9Sstevel@tonic-gate ours = fds[0]; 1637*7c478bd9Sstevel@tonic-gate theirs = fds[1]; 1638*7c478bd9Sstevel@tonic-gate 1639*7c478bd9Sstevel@tonic-gate if ((ep = entity_find(cp, rpr->rpr_entityid)) == NULL) { 1640*7c478bd9Sstevel@tonic-gate result = REP_PROTOCOL_FAIL_UNKNOWN_ID; 1641*7c478bd9Sstevel@tonic-gate goto fail; 1642*7c478bd9Sstevel@tonic-gate } 1643*7c478bd9Sstevel@tonic-gate 1644*7c478bd9Sstevel@tonic-gate /* 1645*7c478bd9Sstevel@tonic-gate * While the following can race with other threads setting up a 1646*7c478bd9Sstevel@tonic-gate * notification, the worst that can happen is that our fd has 1647*7c478bd9Sstevel@tonic-gate * already been closed before we return. 1648*7c478bd9Sstevel@tonic-gate */ 1649*7c478bd9Sstevel@tonic-gate result = rc_pg_notify_setup(&cp->rc_pg_notify, &ep->re_node, 1650*7c478bd9Sstevel@tonic-gate ours); 1651*7c478bd9Sstevel@tonic-gate 1652*7c478bd9Sstevel@tonic-gate entity_release(ep); 1653*7c478bd9Sstevel@tonic-gate 1654*7c478bd9Sstevel@tonic-gate if (result != REP_PROTOCOL_SUCCESS) 1655*7c478bd9Sstevel@tonic-gate goto fail; 1656*7c478bd9Sstevel@tonic-gate 1657*7c478bd9Sstevel@tonic-gate *out_fd = theirs; 1658*7c478bd9Sstevel@tonic-gate return (REP_PROTOCOL_SUCCESS); 1659*7c478bd9Sstevel@tonic-gate 1660*7c478bd9Sstevel@tonic-gate fail: 1661*7c478bd9Sstevel@tonic-gate (void) close(ours); 1662*7c478bd9Sstevel@tonic-gate (void) close(theirs); 1663*7c478bd9Sstevel@tonic-gate 1664*7c478bd9Sstevel@tonic-gate return (result); 1665*7c478bd9Sstevel@tonic-gate } 1666*7c478bd9Sstevel@tonic-gate 1667*7c478bd9Sstevel@tonic-gate static rep_protocol_responseid_t 1668*7c478bd9Sstevel@tonic-gate client_add_notify(repcache_client_t *cp, 1669*7c478bd9Sstevel@tonic-gate struct rep_protocol_notify_request *rpr) 1670*7c478bd9Sstevel@tonic-gate { 1671*7c478bd9Sstevel@tonic-gate rpr->rpr_pattern[sizeof (rpr->rpr_pattern) - 1] = 0; 1672*7c478bd9Sstevel@tonic-gate 1673*7c478bd9Sstevel@tonic-gate switch (rpr->rpr_type) { 1674*7c478bd9Sstevel@tonic-gate case REP_PROTOCOL_NOTIFY_PGNAME: 1675*7c478bd9Sstevel@tonic-gate return (rc_notify_info_add_name(&cp->rc_notify_info, 1676*7c478bd9Sstevel@tonic-gate rpr->rpr_pattern)); 1677*7c478bd9Sstevel@tonic-gate 1678*7c478bd9Sstevel@tonic-gate case REP_PROTOCOL_NOTIFY_PGTYPE: 1679*7c478bd9Sstevel@tonic-gate return (rc_notify_info_add_type(&cp->rc_notify_info, 1680*7c478bd9Sstevel@tonic-gate rpr->rpr_pattern)); 1681*7c478bd9Sstevel@tonic-gate 1682*7c478bd9Sstevel@tonic-gate default: 1683*7c478bd9Sstevel@tonic-gate return (REP_PROTOCOL_FAIL_BAD_REQUEST); 1684*7c478bd9Sstevel@tonic-gate } 1685*7c478bd9Sstevel@tonic-gate } 1686*7c478bd9Sstevel@tonic-gate 1687*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 1688*7c478bd9Sstevel@tonic-gate static void 1689*7c478bd9Sstevel@tonic-gate client_wait(repcache_client_t *cp, const void *in, size_t insz, 1690*7c478bd9Sstevel@tonic-gate void *out_arg, size_t *outsz, void *arg) 1691*7c478bd9Sstevel@tonic-gate { 1692*7c478bd9Sstevel@tonic-gate int result; 1693*7c478bd9Sstevel@tonic-gate repcache_entity_t *ep; 1694*7c478bd9Sstevel@tonic-gate const struct rep_protocol_wait_request *rpr = in; 1695*7c478bd9Sstevel@tonic-gate struct rep_protocol_fmri_response *out = out_arg; 1696*7c478bd9Sstevel@tonic-gate 1697*7c478bd9Sstevel@tonic-gate assert(*outsz == sizeof (*out)); 1698*7c478bd9Sstevel@tonic-gate 1699*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&cp->rc_lock); 1700*7c478bd9Sstevel@tonic-gate if (cp->rc_notify_thr != 0) { 1701*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&cp->rc_lock); 1702*7c478bd9Sstevel@tonic-gate out->rpr_response = REP_PROTOCOL_FAIL_EXISTS; 1703*7c478bd9Sstevel@tonic-gate *outsz = sizeof (out->rpr_response); 1704*7c478bd9Sstevel@tonic-gate return; 1705*7c478bd9Sstevel@tonic-gate } 1706*7c478bd9Sstevel@tonic-gate cp->rc_notify_thr = pthread_self(); 1707*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&cp->rc_lock); 1708*7c478bd9Sstevel@tonic-gate 1709*7c478bd9Sstevel@tonic-gate result = rc_notify_info_wait(&cp->rc_notify_info, &cp->rc_notify_ptr, 1710*7c478bd9Sstevel@tonic-gate out->rpr_fmri, sizeof (out->rpr_fmri)); 1711*7c478bd9Sstevel@tonic-gate 1712*7c478bd9Sstevel@tonic-gate if (result == REP_PROTOCOL_SUCCESS) { 1713*7c478bd9Sstevel@tonic-gate if ((ep = entity_find(cp, rpr->rpr_entityid)) != NULL) { 1714*7c478bd9Sstevel@tonic-gate if (ep->re_type == REP_PROTOCOL_ENTITY_PROPERTYGRP) { 1715*7c478bd9Sstevel@tonic-gate rc_node_ptr_assign(&ep->re_node, 1716*7c478bd9Sstevel@tonic-gate &cp->rc_notify_ptr); 1717*7c478bd9Sstevel@tonic-gate } else { 1718*7c478bd9Sstevel@tonic-gate result = REP_PROTOCOL_FAIL_TYPE_MISMATCH; 1719*7c478bd9Sstevel@tonic-gate } 1720*7c478bd9Sstevel@tonic-gate entity_release(ep); 1721*7c478bd9Sstevel@tonic-gate } else { 1722*7c478bd9Sstevel@tonic-gate result = REP_PROTOCOL_FAIL_UNKNOWN_ID; 1723*7c478bd9Sstevel@tonic-gate } 1724*7c478bd9Sstevel@tonic-gate rc_node_clear(&cp->rc_notify_ptr, 0); 1725*7c478bd9Sstevel@tonic-gate } 1726*7c478bd9Sstevel@tonic-gate 1727*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&cp->rc_lock); 1728*7c478bd9Sstevel@tonic-gate assert(cp->rc_notify_thr == pthread_self()); 1729*7c478bd9Sstevel@tonic-gate cp->rc_notify_thr = 0; 1730*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&cp->rc_lock); 1731*7c478bd9Sstevel@tonic-gate 1732*7c478bd9Sstevel@tonic-gate out->rpr_response = result; 1733*7c478bd9Sstevel@tonic-gate if (result != REP_PROTOCOL_SUCCESS) 1734*7c478bd9Sstevel@tonic-gate *outsz = sizeof (out->rpr_response); 1735*7c478bd9Sstevel@tonic-gate } 1736*7c478bd9Sstevel@tonic-gate 1737*7c478bd9Sstevel@tonic-gate /* 1738*7c478bd9Sstevel@tonic-gate * Can return: 1739*7c478bd9Sstevel@tonic-gate * _PERMISSION_DENIED not enough privileges to do request. 1740*7c478bd9Sstevel@tonic-gate * _BAD_REQUEST name is not valid or reserved 1741*7c478bd9Sstevel@tonic-gate * _TRUNCATED name is too long for current repository path 1742*7c478bd9Sstevel@tonic-gate * _UNKNOWN failed for unknown reason (details written to 1743*7c478bd9Sstevel@tonic-gate * console) 1744*7c478bd9Sstevel@tonic-gate * _BACKEND_READONLY backend is not writable 1745*7c478bd9Sstevel@tonic-gate * 1746*7c478bd9Sstevel@tonic-gate * _SUCCESS Backup completed successfully. 1747*7c478bd9Sstevel@tonic-gate */ 1748*7c478bd9Sstevel@tonic-gate static rep_protocol_responseid_t 1749*7c478bd9Sstevel@tonic-gate backup_repository(repcache_client_t *cp, 1750*7c478bd9Sstevel@tonic-gate struct rep_protocol_backup_request *rpr) 1751*7c478bd9Sstevel@tonic-gate { 1752*7c478bd9Sstevel@tonic-gate rep_protocol_responseid_t result; 1753*7c478bd9Sstevel@tonic-gate ucred_t *uc = get_ucred(); 1754*7c478bd9Sstevel@tonic-gate 1755*7c478bd9Sstevel@tonic-gate if (!client_is_privileged() && (uc == NULL || ucred_geteuid(uc) != 0)) 1756*7c478bd9Sstevel@tonic-gate return (REP_PROTOCOL_FAIL_PERMISSION_DENIED); 1757*7c478bd9Sstevel@tonic-gate 1758*7c478bd9Sstevel@tonic-gate rpr->rpr_name[REP_PROTOCOL_NAME_LEN - 1] = 0; 1759*7c478bd9Sstevel@tonic-gate if (strcmp(rpr->rpr_name, REPOSITORY_BOOT_BACKUP) == 0) 1760*7c478bd9Sstevel@tonic-gate return (REP_PROTOCOL_FAIL_BAD_REQUEST); 1761*7c478bd9Sstevel@tonic-gate 1762*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&cp->rc_lock); 1763*7c478bd9Sstevel@tonic-gate if (rpr->rpr_changeid != cp->rc_changeid) { 1764*7c478bd9Sstevel@tonic-gate result = backend_create_backup(rpr->rpr_name); 1765*7c478bd9Sstevel@tonic-gate if (result == REP_PROTOCOL_SUCCESS) 1766*7c478bd9Sstevel@tonic-gate cp->rc_changeid = rpr->rpr_changeid; 1767*7c478bd9Sstevel@tonic-gate } else { 1768*7c478bd9Sstevel@tonic-gate result = REP_PROTOCOL_SUCCESS; 1769*7c478bd9Sstevel@tonic-gate } 1770*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&cp->rc_lock); 1771*7c478bd9Sstevel@tonic-gate 1772*7c478bd9Sstevel@tonic-gate return (result); 1773*7c478bd9Sstevel@tonic-gate } 1774*7c478bd9Sstevel@tonic-gate 1775*7c478bd9Sstevel@tonic-gate 1776*7c478bd9Sstevel@tonic-gate typedef rep_protocol_responseid_t protocol_simple_f(repcache_client_t *cp, 1777*7c478bd9Sstevel@tonic-gate const void *rpr); 1778*7c478bd9Sstevel@tonic-gate 1779*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 1780*7c478bd9Sstevel@tonic-gate static void 1781*7c478bd9Sstevel@tonic-gate simple_handler(repcache_client_t *cp, const void *in, size_t insz, 1782*7c478bd9Sstevel@tonic-gate void *out_arg, size_t *outsz, void *arg) 1783*7c478bd9Sstevel@tonic-gate { 1784*7c478bd9Sstevel@tonic-gate protocol_simple_f *f = (protocol_simple_f *)arg; 1785*7c478bd9Sstevel@tonic-gate rep_protocol_response_t *out = out_arg; 1786*7c478bd9Sstevel@tonic-gate 1787*7c478bd9Sstevel@tonic-gate assert(*outsz == sizeof (*out)); 1788*7c478bd9Sstevel@tonic-gate assert(f != NULL); 1789*7c478bd9Sstevel@tonic-gate 1790*7c478bd9Sstevel@tonic-gate out->rpr_response = (*f)(cp, in); 1791*7c478bd9Sstevel@tonic-gate } 1792*7c478bd9Sstevel@tonic-gate 1793*7c478bd9Sstevel@tonic-gate typedef rep_protocol_responseid_t protocol_simple_fd_f(repcache_client_t *cp, 1794*7c478bd9Sstevel@tonic-gate const void *rpr, int *out_fd); 1795*7c478bd9Sstevel@tonic-gate 1796*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 1797*7c478bd9Sstevel@tonic-gate static void 1798*7c478bd9Sstevel@tonic-gate simple_fd_handler(repcache_client_t *cp, const void *in, size_t insz, 1799*7c478bd9Sstevel@tonic-gate void *out_arg, size_t *outsz, void *arg, int *out_fd) 1800*7c478bd9Sstevel@tonic-gate { 1801*7c478bd9Sstevel@tonic-gate protocol_simple_fd_f *f = (protocol_simple_fd_f *)arg; 1802*7c478bd9Sstevel@tonic-gate rep_protocol_response_t *out = out_arg; 1803*7c478bd9Sstevel@tonic-gate 1804*7c478bd9Sstevel@tonic-gate assert(*outsz == sizeof (*out)); 1805*7c478bd9Sstevel@tonic-gate assert(f != NULL); 1806*7c478bd9Sstevel@tonic-gate 1807*7c478bd9Sstevel@tonic-gate out->rpr_response = (*f)(cp, in, out_fd); 1808*7c478bd9Sstevel@tonic-gate } 1809*7c478bd9Sstevel@tonic-gate 1810*7c478bd9Sstevel@tonic-gate typedef void protocol_handler_f(repcache_client_t *, const void *in, 1811*7c478bd9Sstevel@tonic-gate size_t insz, void *out, size_t *outsz, void *arg); 1812*7c478bd9Sstevel@tonic-gate 1813*7c478bd9Sstevel@tonic-gate typedef void protocol_handler_fdret_f(repcache_client_t *, const void *in, 1814*7c478bd9Sstevel@tonic-gate size_t insz, void *out, size_t *outsz, void *arg, int *fd_out); 1815*7c478bd9Sstevel@tonic-gate 1816*7c478bd9Sstevel@tonic-gate #define PROTO(p, f, in) { \ 1817*7c478bd9Sstevel@tonic-gate p, #p, simple_handler, (void *)(&f), NULL, \ 1818*7c478bd9Sstevel@tonic-gate sizeof (in), sizeof (rep_protocol_response_t), 0 \ 1819*7c478bd9Sstevel@tonic-gate } 1820*7c478bd9Sstevel@tonic-gate 1821*7c478bd9Sstevel@tonic-gate #define PROTO_FD_OUT(p, f, in) { \ 1822*7c478bd9Sstevel@tonic-gate p, #p, NULL, (void *)(&f), simple_fd_handler, \ 1823*7c478bd9Sstevel@tonic-gate sizeof (in), \ 1824*7c478bd9Sstevel@tonic-gate sizeof (rep_protocol_response_t), \ 1825*7c478bd9Sstevel@tonic-gate PROTO_FLAG_RETFD \ 1826*7c478bd9Sstevel@tonic-gate } 1827*7c478bd9Sstevel@tonic-gate 1828*7c478bd9Sstevel@tonic-gate #define PROTO_VARIN(p, f, insz) { \ 1829*7c478bd9Sstevel@tonic-gate p, #p, &(f), NULL, NULL, \ 1830*7c478bd9Sstevel@tonic-gate insz, sizeof (rep_protocol_response_t), \ 1831*7c478bd9Sstevel@tonic-gate PROTO_FLAG_VARINPUT \ 1832*7c478bd9Sstevel@tonic-gate } 1833*7c478bd9Sstevel@tonic-gate 1834*7c478bd9Sstevel@tonic-gate #define PROTO_UINT_OUT(p, f, in) { \ 1835*7c478bd9Sstevel@tonic-gate p, #p, &(f), NULL, NULL, \ 1836*7c478bd9Sstevel@tonic-gate sizeof (in), \ 1837*7c478bd9Sstevel@tonic-gate sizeof (struct rep_protocol_integer_response), 0 \ 1838*7c478bd9Sstevel@tonic-gate } 1839*7c478bd9Sstevel@tonic-gate 1840*7c478bd9Sstevel@tonic-gate #define PROTO_NAME_OUT(p, f, in) { \ 1841*7c478bd9Sstevel@tonic-gate p, #p, &(f), NULL, NULL, \ 1842*7c478bd9Sstevel@tonic-gate sizeof (in), \ 1843*7c478bd9Sstevel@tonic-gate sizeof (struct rep_protocol_name_response), 0 \ 1844*7c478bd9Sstevel@tonic-gate } 1845*7c478bd9Sstevel@tonic-gate 1846*7c478bd9Sstevel@tonic-gate #define PROTO_FMRI_OUT(p, f, in) { \ 1847*7c478bd9Sstevel@tonic-gate p, #p, &(f), NULL, NULL, \ 1848*7c478bd9Sstevel@tonic-gate sizeof (in), \ 1849*7c478bd9Sstevel@tonic-gate sizeof (struct rep_protocol_fmri_response), 0 \ 1850*7c478bd9Sstevel@tonic-gate } 1851*7c478bd9Sstevel@tonic-gate 1852*7c478bd9Sstevel@tonic-gate #define PROTO_VALUE_OUT(p, f, in) { \ 1853*7c478bd9Sstevel@tonic-gate p, #p, &(f), NULL, NULL, \ 1854*7c478bd9Sstevel@tonic-gate sizeof (in), \ 1855*7c478bd9Sstevel@tonic-gate sizeof (struct rep_protocol_value_response), 0 \ 1856*7c478bd9Sstevel@tonic-gate } 1857*7c478bd9Sstevel@tonic-gate 1858*7c478bd9Sstevel@tonic-gate #define PROTO_PANIC(p) { p, #p, NULL, NULL, NULL, 0, 0, PROTO_FLAG_PANIC } 1859*7c478bd9Sstevel@tonic-gate #define PROTO_END() { 0, NULL, NULL, NULL, NULL, 0, 0, PROTO_FLAG_PANIC } 1860*7c478bd9Sstevel@tonic-gate 1861*7c478bd9Sstevel@tonic-gate #define PROTO_FLAG_PANIC 0x00000001 /* should never be called */ 1862*7c478bd9Sstevel@tonic-gate #define PROTO_FLAG_VARINPUT 0x00000004 /* in_size is minimum size */ 1863*7c478bd9Sstevel@tonic-gate #define PROTO_FLAG_RETFD 0x00000008 /* can also return an FD */ 1864*7c478bd9Sstevel@tonic-gate 1865*7c478bd9Sstevel@tonic-gate #define PROTO_ALL_FLAGS 0x0000000f /* all flags */ 1866*7c478bd9Sstevel@tonic-gate 1867*7c478bd9Sstevel@tonic-gate static struct protocol_entry { 1868*7c478bd9Sstevel@tonic-gate enum rep_protocol_requestid pt_request; 1869*7c478bd9Sstevel@tonic-gate const char *pt_name; 1870*7c478bd9Sstevel@tonic-gate protocol_handler_f *pt_handler; 1871*7c478bd9Sstevel@tonic-gate void *pt_arg; 1872*7c478bd9Sstevel@tonic-gate protocol_handler_fdret_f *pt_fd_handler; 1873*7c478bd9Sstevel@tonic-gate size_t pt_in_size; 1874*7c478bd9Sstevel@tonic-gate size_t pt_out_max; 1875*7c478bd9Sstevel@tonic-gate uint32_t pt_flags; 1876*7c478bd9Sstevel@tonic-gate } protocol_table[] = { 1877*7c478bd9Sstevel@tonic-gate PROTO_PANIC(REP_PROTOCOL_CLOSE), /* special case */ 1878*7c478bd9Sstevel@tonic-gate 1879*7c478bd9Sstevel@tonic-gate PROTO(REP_PROTOCOL_ENTITY_SETUP, entity_setup, 1880*7c478bd9Sstevel@tonic-gate struct rep_protocol_entity_setup), 1881*7c478bd9Sstevel@tonic-gate PROTO_NAME_OUT(REP_PROTOCOL_ENTITY_NAME, entity_name, 1882*7c478bd9Sstevel@tonic-gate struct rep_protocol_entity_name), 1883*7c478bd9Sstevel@tonic-gate PROTO_UINT_OUT(REP_PROTOCOL_ENTITY_PARENT_TYPE, entity_parent_type, 1884*7c478bd9Sstevel@tonic-gate struct rep_protocol_entity_parent_type), 1885*7c478bd9Sstevel@tonic-gate PROTO(REP_PROTOCOL_ENTITY_GET_CHILD, entity_get_child, 1886*7c478bd9Sstevel@tonic-gate struct rep_protocol_entity_get_child), 1887*7c478bd9Sstevel@tonic-gate PROTO(REP_PROTOCOL_ENTITY_GET_PARENT, entity_get_parent, 1888*7c478bd9Sstevel@tonic-gate struct rep_protocol_entity_parent), 1889*7c478bd9Sstevel@tonic-gate PROTO(REP_PROTOCOL_ENTITY_GET, entity_get, 1890*7c478bd9Sstevel@tonic-gate struct rep_protocol_entity_get), 1891*7c478bd9Sstevel@tonic-gate PROTO(REP_PROTOCOL_ENTITY_UPDATE, entity_update, 1892*7c478bd9Sstevel@tonic-gate struct rep_protocol_entity_update), 1893*7c478bd9Sstevel@tonic-gate PROTO(REP_PROTOCOL_ENTITY_CREATE_CHILD, entity_create_child, 1894*7c478bd9Sstevel@tonic-gate struct rep_protocol_entity_create_child), 1895*7c478bd9Sstevel@tonic-gate PROTO(REP_PROTOCOL_ENTITY_CREATE_PG, entity_create_pg, 1896*7c478bd9Sstevel@tonic-gate struct rep_protocol_entity_create_pg), 1897*7c478bd9Sstevel@tonic-gate PROTO(REP_PROTOCOL_ENTITY_DELETE, entity_delete, 1898*7c478bd9Sstevel@tonic-gate struct rep_protocol_entity_delete), 1899*7c478bd9Sstevel@tonic-gate PROTO(REP_PROTOCOL_ENTITY_RESET, entity_reset, 1900*7c478bd9Sstevel@tonic-gate struct rep_protocol_entity_reset), 1901*7c478bd9Sstevel@tonic-gate PROTO(REP_PROTOCOL_ENTITY_TEARDOWN, entity_teardown, 1902*7c478bd9Sstevel@tonic-gate struct rep_protocol_entity_teardown), 1903*7c478bd9Sstevel@tonic-gate 1904*7c478bd9Sstevel@tonic-gate PROTO(REP_PROTOCOL_ITER_SETUP, iter_setup, 1905*7c478bd9Sstevel@tonic-gate struct rep_protocol_iter_request), 1906*7c478bd9Sstevel@tonic-gate PROTO(REP_PROTOCOL_ITER_START, iter_start, 1907*7c478bd9Sstevel@tonic-gate struct rep_protocol_iter_start), 1908*7c478bd9Sstevel@tonic-gate PROTO(REP_PROTOCOL_ITER_READ, iter_read, 1909*7c478bd9Sstevel@tonic-gate struct rep_protocol_iter_read), 1910*7c478bd9Sstevel@tonic-gate PROTO_VALUE_OUT(REP_PROTOCOL_ITER_READ_VALUE, iter_read_value, 1911*7c478bd9Sstevel@tonic-gate struct rep_protocol_iter_read_value), 1912*7c478bd9Sstevel@tonic-gate PROTO(REP_PROTOCOL_ITER_RESET, iter_reset, 1913*7c478bd9Sstevel@tonic-gate struct rep_protocol_iter_request), 1914*7c478bd9Sstevel@tonic-gate PROTO(REP_PROTOCOL_ITER_TEARDOWN, iter_teardown, 1915*7c478bd9Sstevel@tonic-gate struct rep_protocol_iter_request), 1916*7c478bd9Sstevel@tonic-gate 1917*7c478bd9Sstevel@tonic-gate PROTO(REP_PROTOCOL_NEXT_SNAPLEVEL, next_snaplevel, 1918*7c478bd9Sstevel@tonic-gate struct rep_protocol_entity_pair), 1919*7c478bd9Sstevel@tonic-gate 1920*7c478bd9Sstevel@tonic-gate PROTO(REP_PROTOCOL_SNAPSHOT_TAKE, snapshot_take, 1921*7c478bd9Sstevel@tonic-gate struct rep_protocol_snapshot_take), 1922*7c478bd9Sstevel@tonic-gate PROTO(REP_PROTOCOL_SNAPSHOT_TAKE_NAMED, snapshot_take_named, 1923*7c478bd9Sstevel@tonic-gate struct rep_protocol_snapshot_take_named), 1924*7c478bd9Sstevel@tonic-gate PROTO(REP_PROTOCOL_SNAPSHOT_ATTACH, snapshot_attach, 1925*7c478bd9Sstevel@tonic-gate struct rep_protocol_snapshot_attach), 1926*7c478bd9Sstevel@tonic-gate 1927*7c478bd9Sstevel@tonic-gate PROTO_UINT_OUT(REP_PROTOCOL_PROPERTY_GET_TYPE, property_get_type, 1928*7c478bd9Sstevel@tonic-gate struct rep_protocol_property_request), 1929*7c478bd9Sstevel@tonic-gate PROTO_VALUE_OUT(REP_PROTOCOL_PROPERTY_GET_VALUE, property_get_value, 1930*7c478bd9Sstevel@tonic-gate struct rep_protocol_property_request), 1931*7c478bd9Sstevel@tonic-gate 1932*7c478bd9Sstevel@tonic-gate PROTO_FD_OUT(REP_PROTOCOL_PROPERTYGRP_SETUP_WAIT, propertygrp_notify, 1933*7c478bd9Sstevel@tonic-gate struct rep_protocol_propertygrp_request), 1934*7c478bd9Sstevel@tonic-gate PROTO(REP_PROTOCOL_PROPERTYGRP_TX_START, tx_start, 1935*7c478bd9Sstevel@tonic-gate struct rep_protocol_transaction_start), 1936*7c478bd9Sstevel@tonic-gate PROTO_VARIN(REP_PROTOCOL_PROPERTYGRP_TX_COMMIT, tx_commit, 1937*7c478bd9Sstevel@tonic-gate REP_PROTOCOL_TRANSACTION_COMMIT_MIN_SIZE), 1938*7c478bd9Sstevel@tonic-gate 1939*7c478bd9Sstevel@tonic-gate PROTO(REP_PROTOCOL_CLIENT_ADD_NOTIFY, client_add_notify, 1940*7c478bd9Sstevel@tonic-gate struct rep_protocol_notify_request), 1941*7c478bd9Sstevel@tonic-gate PROTO_FMRI_OUT(REP_PROTOCOL_CLIENT_WAIT, client_wait, 1942*7c478bd9Sstevel@tonic-gate struct rep_protocol_wait_request), 1943*7c478bd9Sstevel@tonic-gate 1944*7c478bd9Sstevel@tonic-gate PROTO(REP_PROTOCOL_BACKUP, backup_repository, 1945*7c478bd9Sstevel@tonic-gate struct rep_protocol_backup_request), 1946*7c478bd9Sstevel@tonic-gate 1947*7c478bd9Sstevel@tonic-gate PROTO_END() 1948*7c478bd9Sstevel@tonic-gate }; 1949*7c478bd9Sstevel@tonic-gate #undef PROTO 1950*7c478bd9Sstevel@tonic-gate #undef PROTO_FMRI_OUT 1951*7c478bd9Sstevel@tonic-gate #undef PROTO_NAME_OUT 1952*7c478bd9Sstevel@tonic-gate #undef PROTO_UINT_OUT 1953*7c478bd9Sstevel@tonic-gate #undef PROTO_PANIC 1954*7c478bd9Sstevel@tonic-gate #undef PROTO_END 1955*7c478bd9Sstevel@tonic-gate 1956*7c478bd9Sstevel@tonic-gate /* 1957*7c478bd9Sstevel@tonic-gate * The number of entries, sans PROTO_END() 1958*7c478bd9Sstevel@tonic-gate */ 1959*7c478bd9Sstevel@tonic-gate #define PROTOCOL_ENTRIES \ 1960*7c478bd9Sstevel@tonic-gate (sizeof (protocol_table) / sizeof (*protocol_table) - 1) 1961*7c478bd9Sstevel@tonic-gate 1962*7c478bd9Sstevel@tonic-gate #define PROTOCOL_PREFIX "REP_PROTOCOL_" 1963*7c478bd9Sstevel@tonic-gate 1964*7c478bd9Sstevel@tonic-gate int 1965*7c478bd9Sstevel@tonic-gate client_init(void) 1966*7c478bd9Sstevel@tonic-gate { 1967*7c478bd9Sstevel@tonic-gate int i; 1968*7c478bd9Sstevel@tonic-gate struct protocol_entry *e; 1969*7c478bd9Sstevel@tonic-gate 1970*7c478bd9Sstevel@tonic-gate if (!client_hash_init()) 1971*7c478bd9Sstevel@tonic-gate return (0); 1972*7c478bd9Sstevel@tonic-gate 1973*7c478bd9Sstevel@tonic-gate if (request_log_size > 0) { 1974*7c478bd9Sstevel@tonic-gate request_log = uu_zalloc(request_log_size * 1975*7c478bd9Sstevel@tonic-gate sizeof (request_log_entry_t)); 1976*7c478bd9Sstevel@tonic-gate } 1977*7c478bd9Sstevel@tonic-gate 1978*7c478bd9Sstevel@tonic-gate /* 1979*7c478bd9Sstevel@tonic-gate * update the names to not include REP_PROTOCOL_ 1980*7c478bd9Sstevel@tonic-gate */ 1981*7c478bd9Sstevel@tonic-gate for (i = 0; i < PROTOCOL_ENTRIES; i++) { 1982*7c478bd9Sstevel@tonic-gate e = &protocol_table[i]; 1983*7c478bd9Sstevel@tonic-gate assert(strncmp(e->pt_name, PROTOCOL_PREFIX, 1984*7c478bd9Sstevel@tonic-gate strlen(PROTOCOL_PREFIX)) == 0); 1985*7c478bd9Sstevel@tonic-gate e->pt_name += strlen(PROTOCOL_PREFIX); 1986*7c478bd9Sstevel@tonic-gate } 1987*7c478bd9Sstevel@tonic-gate /* 1988*7c478bd9Sstevel@tonic-gate * verify the protocol table is consistent 1989*7c478bd9Sstevel@tonic-gate */ 1990*7c478bd9Sstevel@tonic-gate for (i = 0; i < PROTOCOL_ENTRIES; i++) { 1991*7c478bd9Sstevel@tonic-gate e = &protocol_table[i]; 1992*7c478bd9Sstevel@tonic-gate assert(e->pt_request == (REP_PROTOCOL_BASE + i)); 1993*7c478bd9Sstevel@tonic-gate 1994*7c478bd9Sstevel@tonic-gate assert((e->pt_flags & ~PROTO_ALL_FLAGS) == 0); 1995*7c478bd9Sstevel@tonic-gate 1996*7c478bd9Sstevel@tonic-gate if (e->pt_flags & PROTO_FLAG_PANIC) 1997*7c478bd9Sstevel@tonic-gate assert(e->pt_in_size == 0 && e->pt_out_max == 0 && 1998*7c478bd9Sstevel@tonic-gate e->pt_handler == NULL); 1999*7c478bd9Sstevel@tonic-gate else 2000*7c478bd9Sstevel@tonic-gate assert(e->pt_in_size != 0 && e->pt_out_max != 0 && 2001*7c478bd9Sstevel@tonic-gate (e->pt_handler != NULL || 2002*7c478bd9Sstevel@tonic-gate e->pt_fd_handler != NULL)); 2003*7c478bd9Sstevel@tonic-gate } 2004*7c478bd9Sstevel@tonic-gate assert((REP_PROTOCOL_BASE + i) == REP_PROTOCOL_MAX_REQUEST); 2005*7c478bd9Sstevel@tonic-gate 2006*7c478bd9Sstevel@tonic-gate assert(protocol_table[i].pt_request == 0); 2007*7c478bd9Sstevel@tonic-gate 2008*7c478bd9Sstevel@tonic-gate return (1); 2009*7c478bd9Sstevel@tonic-gate } 2010*7c478bd9Sstevel@tonic-gate 2011*7c478bd9Sstevel@tonic-gate static void 2012*7c478bd9Sstevel@tonic-gate client_switcher(void *cookie, char *argp, size_t arg_size, door_desc_t *desc_in, 2013*7c478bd9Sstevel@tonic-gate uint_t n_desc) 2014*7c478bd9Sstevel@tonic-gate { 2015*7c478bd9Sstevel@tonic-gate thread_info_t *ti = thread_self(); 2016*7c478bd9Sstevel@tonic-gate 2017*7c478bd9Sstevel@tonic-gate repcache_client_t *cp; 2018*7c478bd9Sstevel@tonic-gate uint32_t id = (uint32_t)cookie; 2019*7c478bd9Sstevel@tonic-gate enum rep_protocol_requestid request_code; 2020*7c478bd9Sstevel@tonic-gate 2021*7c478bd9Sstevel@tonic-gate rep_protocol_responseid_t result = INVALID_RESULT; 2022*7c478bd9Sstevel@tonic-gate 2023*7c478bd9Sstevel@tonic-gate struct protocol_entry *e; 2024*7c478bd9Sstevel@tonic-gate 2025*7c478bd9Sstevel@tonic-gate char *retval = NULL; 2026*7c478bd9Sstevel@tonic-gate size_t retsize = 0; 2027*7c478bd9Sstevel@tonic-gate 2028*7c478bd9Sstevel@tonic-gate int retfd = -1; 2029*7c478bd9Sstevel@tonic-gate door_desc_t desc; 2030*7c478bd9Sstevel@tonic-gate request_log_entry_t *rlp; 2031*7c478bd9Sstevel@tonic-gate 2032*7c478bd9Sstevel@tonic-gate rlp = start_log(id); 2033*7c478bd9Sstevel@tonic-gate 2034*7c478bd9Sstevel@tonic-gate if (n_desc != 0) 2035*7c478bd9Sstevel@tonic-gate uu_die("can't happen: %d descriptors @%p (cookie %p)", 2036*7c478bd9Sstevel@tonic-gate n_desc, desc_in, cookie); 2037*7c478bd9Sstevel@tonic-gate 2038*7c478bd9Sstevel@tonic-gate if (argp == DOOR_UNREF_DATA) { 2039*7c478bd9Sstevel@tonic-gate client_destroy(id); 2040*7c478bd9Sstevel@tonic-gate goto bad_end; 2041*7c478bd9Sstevel@tonic-gate } 2042*7c478bd9Sstevel@tonic-gate 2043*7c478bd9Sstevel@tonic-gate thread_newstate(ti, TI_CLIENT_CALL); 2044*7c478bd9Sstevel@tonic-gate 2045*7c478bd9Sstevel@tonic-gate /* 2046*7c478bd9Sstevel@tonic-gate * To simplify returning just a result code, we set up for 2047*7c478bd9Sstevel@tonic-gate * that case here. 2048*7c478bd9Sstevel@tonic-gate */ 2049*7c478bd9Sstevel@tonic-gate retval = (char *)&result; 2050*7c478bd9Sstevel@tonic-gate retsize = sizeof (result); 2051*7c478bd9Sstevel@tonic-gate 2052*7c478bd9Sstevel@tonic-gate if (arg_size < sizeof (request_code)) { 2053*7c478bd9Sstevel@tonic-gate result = REP_PROTOCOL_FAIL_BAD_REQUEST; 2054*7c478bd9Sstevel@tonic-gate goto end_unheld; 2055*7c478bd9Sstevel@tonic-gate } 2056*7c478bd9Sstevel@tonic-gate 2057*7c478bd9Sstevel@tonic-gate ti->ti_client_request = (void *)argp; 2058*7c478bd9Sstevel@tonic-gate 2059*7c478bd9Sstevel@tonic-gate /* LINTED alignment */ 2060*7c478bd9Sstevel@tonic-gate request_code = *(uint32_t *)argp; 2061*7c478bd9Sstevel@tonic-gate 2062*7c478bd9Sstevel@tonic-gate if (rlp != NULL) { 2063*7c478bd9Sstevel@tonic-gate rlp->rl_request = request_code; 2064*7c478bd9Sstevel@tonic-gate } 2065*7c478bd9Sstevel@tonic-gate /* 2066*7c478bd9Sstevel@tonic-gate * In order to avoid locking problems on removal, we handle the 2067*7c478bd9Sstevel@tonic-gate * "close" case before doing a lookup. 2068*7c478bd9Sstevel@tonic-gate */ 2069*7c478bd9Sstevel@tonic-gate if (request_code == REP_PROTOCOL_CLOSE) { 2070*7c478bd9Sstevel@tonic-gate client_destroy(id); 2071*7c478bd9Sstevel@tonic-gate result = REP_PROTOCOL_SUCCESS; 2072*7c478bd9Sstevel@tonic-gate goto end_unheld; 2073*7c478bd9Sstevel@tonic-gate } 2074*7c478bd9Sstevel@tonic-gate 2075*7c478bd9Sstevel@tonic-gate cp = client_lookup(id); 2076*7c478bd9Sstevel@tonic-gate /* 2077*7c478bd9Sstevel@tonic-gate * cp is held 2078*7c478bd9Sstevel@tonic-gate */ 2079*7c478bd9Sstevel@tonic-gate 2080*7c478bd9Sstevel@tonic-gate if (cp == NULL) 2081*7c478bd9Sstevel@tonic-gate goto bad_end; 2082*7c478bd9Sstevel@tonic-gate 2083*7c478bd9Sstevel@tonic-gate if (rlp != NULL) 2084*7c478bd9Sstevel@tonic-gate rlp->rl_client = cp; 2085*7c478bd9Sstevel@tonic-gate 2086*7c478bd9Sstevel@tonic-gate ti->ti_active_client = cp; 2087*7c478bd9Sstevel@tonic-gate 2088*7c478bd9Sstevel@tonic-gate if (request_code < REP_PROTOCOL_BASE || 2089*7c478bd9Sstevel@tonic-gate request_code >= REP_PROTOCOL_BASE + PROTOCOL_ENTRIES) { 2090*7c478bd9Sstevel@tonic-gate result = REP_PROTOCOL_FAIL_BAD_REQUEST; 2091*7c478bd9Sstevel@tonic-gate goto end; 2092*7c478bd9Sstevel@tonic-gate } 2093*7c478bd9Sstevel@tonic-gate 2094*7c478bd9Sstevel@tonic-gate e = &protocol_table[request_code - REP_PROTOCOL_BASE]; 2095*7c478bd9Sstevel@tonic-gate 2096*7c478bd9Sstevel@tonic-gate assert(!(e->pt_flags & PROTO_FLAG_PANIC)); 2097*7c478bd9Sstevel@tonic-gate 2098*7c478bd9Sstevel@tonic-gate if (e->pt_flags & PROTO_FLAG_VARINPUT) { 2099*7c478bd9Sstevel@tonic-gate if (arg_size < e->pt_in_size) { 2100*7c478bd9Sstevel@tonic-gate result = REP_PROTOCOL_FAIL_BAD_REQUEST; 2101*7c478bd9Sstevel@tonic-gate goto end; 2102*7c478bd9Sstevel@tonic-gate } 2103*7c478bd9Sstevel@tonic-gate } else if (arg_size != e->pt_in_size) { 2104*7c478bd9Sstevel@tonic-gate result = REP_PROTOCOL_FAIL_BAD_REQUEST; 2105*7c478bd9Sstevel@tonic-gate goto end; 2106*7c478bd9Sstevel@tonic-gate } 2107*7c478bd9Sstevel@tonic-gate 2108*7c478bd9Sstevel@tonic-gate if (retsize != e->pt_out_max) { 2109*7c478bd9Sstevel@tonic-gate retsize = e->pt_out_max; 2110*7c478bd9Sstevel@tonic-gate retval = alloca(retsize); 2111*7c478bd9Sstevel@tonic-gate } 2112*7c478bd9Sstevel@tonic-gate 2113*7c478bd9Sstevel@tonic-gate if (e->pt_flags & PROTO_FLAG_RETFD) 2114*7c478bd9Sstevel@tonic-gate e->pt_fd_handler(cp, argp, arg_size, retval, &retsize, 2115*7c478bd9Sstevel@tonic-gate e->pt_arg, &retfd); 2116*7c478bd9Sstevel@tonic-gate else 2117*7c478bd9Sstevel@tonic-gate e->pt_handler(cp, argp, arg_size, retval, &retsize, e->pt_arg); 2118*7c478bd9Sstevel@tonic-gate 2119*7c478bd9Sstevel@tonic-gate end: 2120*7c478bd9Sstevel@tonic-gate ti->ti_active_client = NULL; 2121*7c478bd9Sstevel@tonic-gate client_release(cp); 2122*7c478bd9Sstevel@tonic-gate 2123*7c478bd9Sstevel@tonic-gate end_unheld: 2124*7c478bd9Sstevel@tonic-gate if (rlp != NULL) { 2125*7c478bd9Sstevel@tonic-gate /* LINTED alignment */ 2126*7c478bd9Sstevel@tonic-gate rlp->rl_response = *(uint32_t *)retval; 2127*7c478bd9Sstevel@tonic-gate end_log(); 2128*7c478bd9Sstevel@tonic-gate rlp = NULL; 2129*7c478bd9Sstevel@tonic-gate } 2130*7c478bd9Sstevel@tonic-gate ti->ti_client_request = NULL; 2131*7c478bd9Sstevel@tonic-gate thread_newstate(ti, TI_DOOR_RETURN); 2132*7c478bd9Sstevel@tonic-gate 2133*7c478bd9Sstevel@tonic-gate if (retval == (char *)&result) { 2134*7c478bd9Sstevel@tonic-gate assert(result != INVALID_RESULT && retsize == sizeof (result)); 2135*7c478bd9Sstevel@tonic-gate } else { 2136*7c478bd9Sstevel@tonic-gate /* LINTED alignment */ 2137*7c478bd9Sstevel@tonic-gate result = *(uint32_t *)retval; 2138*7c478bd9Sstevel@tonic-gate } 2139*7c478bd9Sstevel@tonic-gate if (retfd != -1) { 2140*7c478bd9Sstevel@tonic-gate desc.d_attributes = DOOR_DESCRIPTOR | DOOR_RELEASE; 2141*7c478bd9Sstevel@tonic-gate desc.d_data.d_desc.d_descriptor = retfd; 2142*7c478bd9Sstevel@tonic-gate (void) door_return(retval, retsize, &desc, 1); 2143*7c478bd9Sstevel@tonic-gate } else { 2144*7c478bd9Sstevel@tonic-gate (void) door_return(retval, retsize, NULL, 0); 2145*7c478bd9Sstevel@tonic-gate } 2146*7c478bd9Sstevel@tonic-gate bad_end: 2147*7c478bd9Sstevel@tonic-gate if (rlp != NULL) { 2148*7c478bd9Sstevel@tonic-gate rlp->rl_response = -1; 2149*7c478bd9Sstevel@tonic-gate end_log(); 2150*7c478bd9Sstevel@tonic-gate rlp = NULL; 2151*7c478bd9Sstevel@tonic-gate } 2152*7c478bd9Sstevel@tonic-gate (void) door_return(NULL, 0, NULL, 0); 2153*7c478bd9Sstevel@tonic-gate } 2154*7c478bd9Sstevel@tonic-gate 2155*7c478bd9Sstevel@tonic-gate int 2156*7c478bd9Sstevel@tonic-gate create_client(pid_t pid, uint32_t debugflags, int privileged, int *out_fd) 2157*7c478bd9Sstevel@tonic-gate { 2158*7c478bd9Sstevel@tonic-gate int fd; 2159*7c478bd9Sstevel@tonic-gate 2160*7c478bd9Sstevel@tonic-gate repcache_client_t *cp; 2161*7c478bd9Sstevel@tonic-gate 2162*7c478bd9Sstevel@tonic-gate struct door_info info; 2163*7c478bd9Sstevel@tonic-gate 2164*7c478bd9Sstevel@tonic-gate int door_flags = DOOR_UNREF | DOOR_REFUSE_DESC; 2165*7c478bd9Sstevel@tonic-gate #ifdef DOOR_NO_CANCEL 2166*7c478bd9Sstevel@tonic-gate door_flags |= DOOR_NO_CANCEL; 2167*7c478bd9Sstevel@tonic-gate #endif 2168*7c478bd9Sstevel@tonic-gate 2169*7c478bd9Sstevel@tonic-gate cp = client_alloc(); 2170*7c478bd9Sstevel@tonic-gate if (cp == NULL) 2171*7c478bd9Sstevel@tonic-gate return (REPOSITORY_DOOR_FAIL_NO_RESOURCES); 2172*7c478bd9Sstevel@tonic-gate 2173*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&client_lock); 2174*7c478bd9Sstevel@tonic-gate cp->rc_id = ++client_maxid; 2175*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&client_lock); 2176*7c478bd9Sstevel@tonic-gate 2177*7c478bd9Sstevel@tonic-gate cp->rc_all_auths = privileged; 2178*7c478bd9Sstevel@tonic-gate cp->rc_pid = pid; 2179*7c478bd9Sstevel@tonic-gate cp->rc_debug = debugflags; 2180*7c478bd9Sstevel@tonic-gate 2181*7c478bd9Sstevel@tonic-gate cp->rc_doorfd = door_create(client_switcher, (void *)cp->rc_id, 2182*7c478bd9Sstevel@tonic-gate door_flags); 2183*7c478bd9Sstevel@tonic-gate 2184*7c478bd9Sstevel@tonic-gate if (cp->rc_doorfd < 0) { 2185*7c478bd9Sstevel@tonic-gate client_free(cp); 2186*7c478bd9Sstevel@tonic-gate return (REPOSITORY_DOOR_FAIL_NO_RESOURCES); 2187*7c478bd9Sstevel@tonic-gate } 2188*7c478bd9Sstevel@tonic-gate #ifdef DOOR_PARAM_DATA_MIN 2189*7c478bd9Sstevel@tonic-gate (void) door_setparam(cp->rc_doorfd, DOOR_PARAM_DATA_MIN, 2190*7c478bd9Sstevel@tonic-gate sizeof (enum rep_protocol_requestid)); 2191*7c478bd9Sstevel@tonic-gate #endif 2192*7c478bd9Sstevel@tonic-gate 2193*7c478bd9Sstevel@tonic-gate if ((fd = dup(cp->rc_doorfd)) < 0 || 2194*7c478bd9Sstevel@tonic-gate door_info(cp->rc_doorfd, &info) < 0) { 2195*7c478bd9Sstevel@tonic-gate if (fd >= 0) 2196*7c478bd9Sstevel@tonic-gate (void) close(fd); 2197*7c478bd9Sstevel@tonic-gate (void) door_revoke(cp->rc_doorfd); 2198*7c478bd9Sstevel@tonic-gate cp->rc_doorfd = -1; 2199*7c478bd9Sstevel@tonic-gate client_free(cp); 2200*7c478bd9Sstevel@tonic-gate return (REPOSITORY_DOOR_FAIL_NO_RESOURCES); 2201*7c478bd9Sstevel@tonic-gate } 2202*7c478bd9Sstevel@tonic-gate 2203*7c478bd9Sstevel@tonic-gate rc_pg_notify_init(&cp->rc_pg_notify); 2204*7c478bd9Sstevel@tonic-gate rc_notify_info_init(&cp->rc_notify_info); 2205*7c478bd9Sstevel@tonic-gate 2206*7c478bd9Sstevel@tonic-gate client_insert(cp); 2207*7c478bd9Sstevel@tonic-gate 2208*7c478bd9Sstevel@tonic-gate cp->rc_doorid = info.di_uniquifier; 2209*7c478bd9Sstevel@tonic-gate *out_fd = fd; 2210*7c478bd9Sstevel@tonic-gate 2211*7c478bd9Sstevel@tonic-gate return (REPOSITORY_DOOR_SUCCESS); 2212*7c478bd9Sstevel@tonic-gate } 2213