diff options
Diffstat (limited to 'libc/inet')
-rw-r--r-- | libc/inet/resolv.c | 141 |
1 files changed, 128 insertions, 13 deletions
diff --git a/libc/inet/resolv.c b/libc/inet/resolv.c index 627423b39..34dfbfa22 100644 --- a/libc/inet/resolv.c +++ b/libc/inet/resolv.c @@ -297,6 +297,7 @@ Domain name in a message can be represented as either: #include <features.h> #include <string.h> #include <stdio.h> +#include <stdio_ext.h> #include <signal.h> #include <errno.h> #include <sys/poll.h> @@ -3440,12 +3441,10 @@ static void res_sync_func(void) */ } -/* Our res_init never fails (always returns 0) */ -int res_init(void) +static int +__res_vinit(res_state rp, int preinit) { - struct __res_state *rp = &(_res); - int i; - int n; + int i, n, options, retrans, retry, ndots; #ifdef __UCLIBC_HAS_IPV6__ int m = 0; #endif @@ -3454,13 +3453,27 @@ int res_init(void) __close_nameservers(); __open_nameservers(); - __res_sync = res_sync_func; + if (preinit) { + options = rp->options; + retrans = rp->retrans; + retry = rp->retry; + ndots = rp->ndots; + } memset(rp, 0, sizeof(*rp)); - rp->options = RES_INIT; - rp->retrans = RES_TIMEOUT; - rp->retry = RES_DFLRETRY; - rp->ndots = 1; + + if (!preinit) { + rp->options = RES_DEFAULT; + rp->retrans = RES_TIMEOUT; + rp->retry = RES_DFLRETRY; + rp->ndots = 1; + } else { + rp->options = options; + rp->retrans = retrans; + rp->retry = retry; + rp->ndots = ndots; + } + #ifdef __UCLIBC_HAS_COMPAT_RES_STATE__ /* Was: "rp->id = random();" but: * - random() pulls in largish static buffers @@ -3526,13 +3539,14 @@ int res_init(void) rp->_u._ext.nscount = m; #endif + rp->options |= RES_INIT; + __UCLIBC_MUTEX_UNLOCK(__resolv_lock); return 0; } -libc_hidden_def(res_init) -#ifdef __UCLIBC_HAS_BSD_RES_CLOSE__ -void res_close(void) +static void +__res_iclose(res_state statp, int free_addr) { __UCLIBC_MUTEX_LOCK(__resolv_lock); __close_nameservers(); @@ -3552,6 +3566,26 @@ void res_close(void) memset(&_res, 0, sizeof(_res)); __UCLIBC_MUTEX_UNLOCK(__resolv_lock); } + +/* + * This routine is for closing the socket if a virtual circuit is used and + * the program wants to close it. This provides support for endhostent() + * which expects to close the socket. + * + * This routine is not expected to be user visible. + */ + +void +res_nclose(res_state statp) +{ + __res_iclose(statp, 1); +} + +#ifdef __UCLIBC_HAS_BSD_RES_CLOSE__ +void res_close(void) +{ + __res_iclose(&_res, 0); +} #endif /* __UCLIBC_HAS_BSD_RES_CLOSE__ */ /* This needs to be after the use of _res in res_init, above. */ @@ -3583,6 +3617,87 @@ struct __res_state *__resp = &_res; # endif #endif /* !__UCLIBC_HAS_THREADS__ */ +static unsigned int +res_randomid(void) { + return 0xffff & getpid(); +} + +/* Our res_init never fails (always returns 0) */ +int +res_init(void) +{ + /* + * These three fields used to be statically initialized. This made + * it hard to use this code in a shared library. It is necessary, + * now that we're doing dynamic initialization here, that we preserve + * the old semantics: if an application modifies one of these three + * fields of _res before res_init() is called, res_init() will not + * alter them. Of course, if an application is setting them to + * _zero_ before calling res_init(), hoping to override what used + * to be the static default, we can't detect it and unexpected results + * will follow. Zero for any of these fields would make no sense, + * so one can safely assume that the applications were already getting + * unexpected results. + * + * _res.options is tricky since some apps were known to diddle the bits + * before res_init() was first called. We can't replicate that semantic + * with dynamic initialization (they may have turned bits off that are + * set in RES_DEFAULT). Our solution is to declare such applications + * "broken". They could fool us by setting RES_INIT but none do (yet). + */ + + __UCLIBC_MUTEX_LOCK(__resolv_lock); + + if (!_res.retrans) + _res.retrans = RES_TIMEOUT; + if (!_res.retry) + _res.retry = 4; + if (!(_res.options & RES_INIT)) + _res.options = RES_DEFAULT; + + /* + * This one used to initialize implicitly to zero, so unless the app + * has set it to something in particular, we can randomize it now. + */ + if (!_res.id) + _res.id = res_randomid(); + __res_sync = res_sync_func; + + __UCLIBC_MUTEX_UNLOCK(__resolv_lock); + + __res_vinit(&_res, 1); + + return 0; +} +libc_hidden_def(res_init) + +/* + * Set up default settings. If the configuration file exist, the values + * there will have precedence. Otherwise, the server address is set to + * INADDR_ANY and the default domain name comes from the gethostname(). + * + * An interrim version of this code (BIND 4.9, pre-4.4BSD) used 127.0.0.1 + * rather than INADDR_ANY ("0.0.0.0") as the default name server address + * since it was noted that INADDR_ANY actually meant ``the first interface + * you "ifconfig"'d at boot time'' and if this was a SLIP or PPP interface, + * it had to be "up" in order for you to reach your own name server. It + * was later decided that since the recommended practice is to always + * install local static routes through 127.0.0.1 for all your network + * interfaces, that we could solve this problem without a code change. + * + * The configuration file should always be used, since it is the only way + * to specify a default domain. If you are running a server on your local + * machine, you should say "nameserver 0.0.0.0" or "nameserver 127.0.0.1" + * in the configuration file. + * + * Return 0 if completes successfully, -1 on error + */ +int +res_ninit(res_state statp) +{ + return __res_vinit(statp, 0); +} + #endif /* L_res_init */ #ifdef L_res_state |