
1: /* 2: * Copyright (c) 1995-1999 by Internet Software Consortium. 3: * 4: * Permission to use, copy, modify, and distribute this software for any 5: * purpose with or without fee is hereby granted, provided that the above 6: * copyright notice and this permission notice appear in all copies. 7: * 8: * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS 9: * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES 10: * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE 11: * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 12: * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 13: * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 14: * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 15: * SOFTWARE. 16: */ 17: 18: #include <atomic.h> 19: #include <limits.h> 20: #include <sys/types.h> 21: #include <netinet/in.h> 22: #include <arpa/nameser.h> 23: #include <resolv.h> 24: #include <bits/libc-lock.h> 25: 26: 27: /* The following bit is copied from res_data.c (where it is #ifdef'ed 28: out) since res_init() should go into libc.so but the rest of that 29: file should not. */ 30: 31: extern unsigned long long int __res_initstamp attribute_hidden; 32: /* We have atomic increment operations on 64-bit platforms. */ 33: #if __WORDSIZE == 64 34: # define atomicinclock(lock) (void) 0 35: # define atomicincunlock(lock) (void) 0 36: # define atomicinc(var) catomic_increment (&(var)) 37: #else 38: __libc_lock_define_initialized (static, lock); 39: # define atomicinclock(lock) __libc_lock_lock (lock) 40: # define atomicincunlock(lock) __libc_lock_unlock (lock) 41: # define atomicinc(var) ++var 42: #endif 43: 44: int 45: res_init(void) { 46: extern int __res_vinit(res_state, int); 47: 48: /* 49: * These three fields used to be statically initialized. This made 50: * it hard to use this code in a shared library. It is necessary, 51: * now that we're doing dynamic initialization here, that we preserve 52: * the old semantics: if an application modifies one of these three 53: * fields of _res before res_init() is called, res_init() will not 54: * alter them. Of course, if an application is setting them to 55: * _zero_ before calling res_init(), hoping to override what used 56: * to be the static default, we can't detect it and unexpected results 57: * will follow. Zero for any of these fields would make no sense, 58: * so one can safely assume that the applications were already getting 59: * unexpected results. 60: * 61: * _res.options is tricky since some apps were known to diddle the bits 62: * before res_init() was first called. We can't replicate that semantic 63: * with dynamic initialization (they may have turned bits off that are 64: * set in RES_DEFAULT). Our solution is to declare such applications 65: * "broken". They could fool us by setting RES_INIT but none do (yet). 66: */ 67: if (!_res.retrans) 68: _res.retrans = RES_TIMEOUT; 69: if (!_res.retry) 70: _res.retry = 4; 71: if (!(_res.options & RES_INIT)) 72: _res.options = RES_DEFAULT; 73: else if (_res.nscount > 0) 74: __res_iclose (&_res, true); /* Close any VC sockets. */ 75: 76: /* 77: * This one used to initialize implicitly to zero, so unless the app 78: * has set it to something in particular, we can randomize it now. 79: */ 80: if (!_res.id) 81: _res.id = res_randomid(); 82: 83: atomicinclock (lock); 84: /* Request all threads to re-initialize their resolver states, 85: resolv.conf might have changed. */ 86: atomicinc (__res_initstamp); 87: atomicincunlock (lock); 88: 89: return (__res_vinit(&_res, 1)); 90: } 91: 92: /* Initialize resp if RES_INIT is not yet set or if res_init in some other 93: thread requested re-initializing. */ 94: int 95: __res_maybe_init (res_state resp, int preinit) 96: { 97: if (resp->options & RES_INIT) { 98: if (__res_initstamp != resp->_u._ext.initstamp) { 99: if (resp->nscount > 0) { 100: __res_iclose (resp, true); 101: return __res_vinit (resp, 1); 102: } 103: } 104: return 0; 105: } else if (preinit) { 106: if (!resp->retrans) 107: resp->retrans = RES_TIMEOUT; 108: if (!resp->retry) 109: resp->retry = 4; 110: resp->options = RES_DEFAULT; 111: if (!resp->id) 112: resp->id = res_randomid (); 113: return __res_vinit (resp, 1); 114: } else 115: return __res_ninit (resp); 116: } 117: libc_hidden_def (__res_maybe_init) 118: ^L 119: /* This needs to be after the use of _res in res_init, above. */ 120: #undef _res 121: 122: /* The resolver state for use by single-threaded programs. 123: This differs from plain `struct __res_state _res;' in that it doesn't 124: create a common definition, but a plain symbol that resides in .bss, 125: which can have an alias. */ 126: struct __res_state _res __attribute__((section (".bss"))); 127: 128: #include <tls.h> 129: 130: #if USE___THREAD 131: #undef __resp 132: __thread struct __res_state *__resp = &_res; 133: extern __thread struct __res_state *__libc_resp 134: __attribute__ ((alias ("__resp"))) attribute_hidden; 135: #endif 136: 137: /* We declare this with compat_symbol so that it's not 138: visible at link time. Programs must use the accessor functions. */ 139: #if defined HAVE_ELF && defined SHARED && defined DO_VERSIONING 140: # include <shlib-compat.h> 141: compat_symbol (libc, _res, _res, GLIBC_2_0); 142: #endif 143: 144: #include <shlib-compat.h> 145: 146: #if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_2) 147: # undef res_init 148: extern int __res_init_weak (void); 149: weak_extern (__res_init_weak); 150: strong_alias (__res_init, __res_init_weak); 151: compat_symbol (libc, __res_init_weak, res_init, GLIBC_2_0); 152: #endif