1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * Copyright (c) 1998-2000 by Sun Microsystems, Inc. 3*0Sstevel@tonic-gate */ 4*0Sstevel@tonic-gate 5*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 6*0Sstevel@tonic-gate 7*0Sstevel@tonic-gate #include <port_before.h> 8*0Sstevel@tonic-gate #include <thread.h> 9*0Sstevel@tonic-gate #include <errno.h> 10*0Sstevel@tonic-gate #include <netdb.h> 11*0Sstevel@tonic-gate #include <malloc.h> 12*0Sstevel@tonic-gate #include <string.h> 13*0Sstevel@tonic-gate #include <resolv_mt.h> 14*0Sstevel@tonic-gate #include <irs.h> 15*0Sstevel@tonic-gate #include <port_after.h> 16*0Sstevel@tonic-gate 17*0Sstevel@tonic-gate static int thr_keycreate_ret = 0; 18*0Sstevel@tonic-gate 19*0Sstevel@tonic-gate static thread_key_t key; 20*0Sstevel@tonic-gate static int mt_key_initialized = 0; 21*0Sstevel@tonic-gate 22*0Sstevel@tonic-gate static mtctxres_t sharedctx; 23*0Sstevel@tonic-gate 24*0Sstevel@tonic-gate static int __res_init_ctx(thread_key_t); 25*0Sstevel@tonic-gate static void __res_destroy_ctx(void *); 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate #pragma init (_mtctxres_init) 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate /* 30*0Sstevel@tonic-gate * Initialize the TSD key. By doing this at library load time, we're 31*0Sstevel@tonic-gate * implicitly running without interference from other threads, so there's 32*0Sstevel@tonic-gate * no need for locking. 33*0Sstevel@tonic-gate */ 34*0Sstevel@tonic-gate static void 35*0Sstevel@tonic-gate _mtctxres_init(void) { 36*0Sstevel@tonic-gate 37*0Sstevel@tonic-gate if ((thr_keycreate_ret = thr_keycreate(&key, __res_destroy_ctx)) == 0) { 38*0Sstevel@tonic-gate mt_key_initialized = 1; 39*0Sstevel@tonic-gate } 40*0Sstevel@tonic-gate } 41*0Sstevel@tonic-gate 42*0Sstevel@tonic-gate 43*0Sstevel@tonic-gate /* 44*0Sstevel@tonic-gate * To support binaries that used the private MT-safe interface in 45*0Sstevel@tonic-gate * on998 or on28, we still need to provide the __res_enable_mt() 46*0Sstevel@tonic-gate * and __res_disable_mt() entry points. They're do-nothing routines. 47*0Sstevel@tonic-gate */ 48*0Sstevel@tonic-gate int 49*0Sstevel@tonic-gate __res_enable_mt(void) { 50*0Sstevel@tonic-gate return (-1); 51*0Sstevel@tonic-gate } 52*0Sstevel@tonic-gate 53*0Sstevel@tonic-gate int 54*0Sstevel@tonic-gate __res_disable_mt(void) { 55*0Sstevel@tonic-gate return (0); 56*0Sstevel@tonic-gate } 57*0Sstevel@tonic-gate 58*0Sstevel@tonic-gate 59*0Sstevel@tonic-gate static int 60*0Sstevel@tonic-gate __res_init_ctx(thread_key_t key) { 61*0Sstevel@tonic-gate 62*0Sstevel@tonic-gate mtctxres_t *mt; 63*0Sstevel@tonic-gate int ret; 64*0Sstevel@tonic-gate 65*0Sstevel@tonic-gate 66*0Sstevel@tonic-gate if (thr_getspecific(key, (void **)&mt) == 0 && mt != 0) { 67*0Sstevel@tonic-gate /* Already exists */ 68*0Sstevel@tonic-gate return (0); 69*0Sstevel@tonic-gate } 70*0Sstevel@tonic-gate 71*0Sstevel@tonic-gate if ((mt = malloc(sizeof (mtctxres_t))) == 0) { 72*0Sstevel@tonic-gate errno = ENOMEM; 73*0Sstevel@tonic-gate return (-1); 74*0Sstevel@tonic-gate } 75*0Sstevel@tonic-gate 76*0Sstevel@tonic-gate memset(mt, 0, sizeof (*mt)); 77*0Sstevel@tonic-gate 78*0Sstevel@tonic-gate if ((ret = thr_setspecific(key, mt)) != 0) { 79*0Sstevel@tonic-gate errno = ret; 80*0Sstevel@tonic-gate free(mt); 81*0Sstevel@tonic-gate return (-1); 82*0Sstevel@tonic-gate } 83*0Sstevel@tonic-gate 84*0Sstevel@tonic-gate return (0); 85*0Sstevel@tonic-gate 86*0Sstevel@tonic-gate } 87*0Sstevel@tonic-gate 88*0Sstevel@tonic-gate 89*0Sstevel@tonic-gate static void 90*0Sstevel@tonic-gate __res_destroy_ctx(void *value) { 91*0Sstevel@tonic-gate 92*0Sstevel@tonic-gate mtctxres_t *mt = (mtctxres_t *)value; 93*0Sstevel@tonic-gate 94*0Sstevel@tonic-gate if (mt != 0) { 95*0Sstevel@tonic-gate free(mt); 96*0Sstevel@tonic-gate } 97*0Sstevel@tonic-gate } 98*0Sstevel@tonic-gate 99*0Sstevel@tonic-gate 100*0Sstevel@tonic-gate mtctxres_t * 101*0Sstevel@tonic-gate ___mtctxres() { 102*0Sstevel@tonic-gate 103*0Sstevel@tonic-gate mtctxres_t *mt; 104*0Sstevel@tonic-gate 105*0Sstevel@tonic-gate 106*0Sstevel@tonic-gate if (mt_key_initialized) { 107*0Sstevel@tonic-gate if ((thr_getspecific(key, (void **)&mt) == 0 && mt != 0) || 108*0Sstevel@tonic-gate (__res_init_ctx(key) == 0 && 109*0Sstevel@tonic-gate thr_getspecific(key, (void **)&mt) == 0 && mt != 0)) { 110*0Sstevel@tonic-gate return (mt); 111*0Sstevel@tonic-gate } 112*0Sstevel@tonic-gate } 113*0Sstevel@tonic-gate 114*0Sstevel@tonic-gate return (&sharedctx); 115*0Sstevel@tonic-gate } 116*0Sstevel@tonic-gate 117*0Sstevel@tonic-gate 118*0Sstevel@tonic-gate /* 119*0Sstevel@tonic-gate * There used to be a private, MT-safe resolver interface that used TSD 120*0Sstevel@tonic-gate * to store per-thread _res, h_errno, etc. We continue to provide the 121*0Sstevel@tonic-gate * access functions __res_get_res() and __res_get_h_errno() so that binaries 122*0Sstevel@tonic-gate * that used the private interface will continue to work. 123*0Sstevel@tonic-gate */ 124*0Sstevel@tonic-gate 125*0Sstevel@tonic-gate #ifdef _res 126*0Sstevel@tonic-gate #undef _res 127*0Sstevel@tonic-gate #endif 128*0Sstevel@tonic-gate 129*0Sstevel@tonic-gate extern struct __res_state *__res_state(void); 130*0Sstevel@tonic-gate 131*0Sstevel@tonic-gate struct __res_state * 132*0Sstevel@tonic-gate __res_get_res(void) { 133*0Sstevel@tonic-gate return (__res_state()); 134*0Sstevel@tonic-gate } 135*0Sstevel@tonic-gate 136*0Sstevel@tonic-gate 137*0Sstevel@tonic-gate #ifdef h_errno 138*0Sstevel@tonic-gate #undef h_errno 139*0Sstevel@tonic-gate #endif 140*0Sstevel@tonic-gate 141*0Sstevel@tonic-gate extern int *__h_errno(void); 142*0Sstevel@tonic-gate 143*0Sstevel@tonic-gate int * 144*0Sstevel@tonic-gate __res_get_h_errno(void) { 145*0Sstevel@tonic-gate return (__h_errno()); 146*0Sstevel@tonic-gate } 147*0Sstevel@tonic-gate 148*0Sstevel@tonic-gate 149*0Sstevel@tonic-gate #ifdef SUNW_HOSTS_FALLBACK 150*0Sstevel@tonic-gate 151*0Sstevel@tonic-gate /* 152*0Sstevel@tonic-gate * When the name service switch calls libresolv, it doesn't want fallback 153*0Sstevel@tonic-gate * to /etc/hosts, so we provide a method to turn it off. 154*0Sstevel@tonic-gate */ 155*0Sstevel@tonic-gate 156*0Sstevel@tonic-gate void 157*0Sstevel@tonic-gate __res_set_no_hosts_fallback(void) { 158*0Sstevel@tonic-gate ___mtctxres()->no_hosts_fallback_private = 1; 159*0Sstevel@tonic-gate } 160*0Sstevel@tonic-gate 161*0Sstevel@tonic-gate void 162*0Sstevel@tonic-gate __res_unset_no_hosts_fallback(void) { 163*0Sstevel@tonic-gate ___mtctxres()->no_hosts_fallback_private = 0; 164*0Sstevel@tonic-gate } 165*0Sstevel@tonic-gate 166*0Sstevel@tonic-gate int 167*0Sstevel@tonic-gate __res_no_hosts_fallback(void) { 168*0Sstevel@tonic-gate return (___mtctxres()->no_hosts_fallback_private); 169*0Sstevel@tonic-gate } 170*0Sstevel@tonic-gate 171*0Sstevel@tonic-gate #endif /* SUNW_HOSTS_FALLBACK */ 172*0Sstevel@tonic-gate 173*0Sstevel@tonic-gate #ifdef SUNW_OVERRIDE_RETRY 174*0Sstevel@tonic-gate 175*0Sstevel@tonic-gate /* 176*0Sstevel@tonic-gate * The NS switch wants to be able to override the number of retries. 177*0Sstevel@tonic-gate */ 178*0Sstevel@tonic-gate 179*0Sstevel@tonic-gate int 180*0Sstevel@tonic-gate __res_override_retry(int retry) { 181*0Sstevel@tonic-gate ___mtctxres()->retry_private = retry; 182*0Sstevel@tonic-gate /* 183*0Sstevel@tonic-gate * This function doesn't really need a return value; saving the 184*0Sstevel@tonic-gate * old retry setting, and restoring it, is handled by __res_retry() 185*0Sstevel@tonic-gate * and __res_retry_reset() below. However, the nss_dns library 186*0Sstevel@tonic-gate * must have a private version of this function to be used when 187*0Sstevel@tonic-gate * running with an old libresolv. That private nss_dns function 188*0Sstevel@tonic-gate * needs a return value, and a function pointer is used to select 189*0Sstevel@tonic-gate * the right function at runtime. Thus, __res_override_retry 190*0Sstevel@tonic-gate * must have a function prototype consistent with the private 191*0Sstevel@tonic-gate * nss_dns function, i.e., one that returns an int. 192*0Sstevel@tonic-gate * 193*0Sstevel@tonic-gate * Given that we do have a return value, that value must be zero. 194*0Sstevel@tonic-gate * That's because retry_private == 0 is used to indicate that 195*0Sstevel@tonic-gate * no override retry value is in effect, and the way we expect 196*0Sstevel@tonic-gate * nss_dns to call us is: 197*0Sstevel@tonic-gate * 198*0Sstevel@tonic-gate * int oldretry = __res_override_retry(N); 199*0Sstevel@tonic-gate * <whatever> 200*0Sstevel@tonic-gate * (void)__res_override_retry(old_retry); 201*0Sstevel@tonic-gate */ 202*0Sstevel@tonic-gate return (0); 203*0Sstevel@tonic-gate } 204*0Sstevel@tonic-gate 205*0Sstevel@tonic-gate int 206*0Sstevel@tonic-gate __res_retry(int retry) { 207*0Sstevel@tonic-gate mtctxres_t *mt = ___mtctxres(); 208*0Sstevel@tonic-gate 209*0Sstevel@tonic-gate mt->retry_save = retry; 210*0Sstevel@tonic-gate return ((mt->retry_private != 0) ? mt->retry_private : retry); 211*0Sstevel@tonic-gate } 212*0Sstevel@tonic-gate 213*0Sstevel@tonic-gate int 214*0Sstevel@tonic-gate __res_retry_reset(void) { 215*0Sstevel@tonic-gate mtctxres_t *mt = ___mtctxres(); 216*0Sstevel@tonic-gate 217*0Sstevel@tonic-gate return (mt->retry_save); 218*0Sstevel@tonic-gate } 219*0Sstevel@tonic-gate 220*0Sstevel@tonic-gate #endif /* SUNW_OVERRIDE_RETRY */ 221