From 7f74de5d4d6d10baafab4b37bb3d472f5c5f0e8c Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Wed, 13 Jul 2011 00:30:54 +0200 Subject: inet/resolv: add res_ninit and res_nclose Some reordering of existing functions was necessary in order to provide this functionality. Signed-off-by: Daniel Mack --- include/resolv.h | 8 +-- libc/inet/resolv.c | 141 ++++++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 132 insertions(+), 17 deletions(-) diff --git a/include/resolv.h b/include/resolv.h index 96ad4abf5..186b78112 100644 --- a/include/resolv.h +++ b/include/resolv.h @@ -337,6 +337,8 @@ __END_DECLS #define dn_comp __dn_comp #define dn_expand __dn_expand #define dn_skipname __dn_skipname +#define res_ninit __res_ninit +#define res_nclose __res_nclose #if 0 #define fp_resstat __fp_resstat #define loc_aton __loc_aton @@ -359,8 +361,6 @@ __END_DECLS #define res_hostalias __res_hostalias #define res_mailok __res_mailok #define res_nameinquery __res_nameinquery -#define res_nclose __res_nclose -#define res_ninit __res_ninit #define res_nmkquery __res_nmkquery #define res_npquery __res_npquery #define res_nquery __res_nquery @@ -409,6 +409,8 @@ int dn_comp (const char *, u_char *, int, u_char **, u_char **) __THROW; int dn_expand (const u_char *, const u_char *, const u_char *, char *, int) __THROW; +int res_ninit (res_state) __THROW; +void res_nclose (res_state) __THROW; #if 0 u_int res_randomid (void) __THROW; int res_nameinquery (const char *, int, int, @@ -417,7 +419,6 @@ int res_queriesmatch (const u_char *, const u_char *, const u_char *, const u_char *) __THROW; const char * p_section (int section, int opcode) __THROW; /* Things involving a resolver context. */ -int res_ninit (res_state) __THROW; int res_nisourserver (const res_state, const struct sockaddr_in *) __THROW; void fp_resstat (const res_state, FILE *) __THROW; @@ -436,7 +437,6 @@ int res_nmkquery (res_state, int, const char *, int, int, int) __THROW; int res_nsend (res_state, const u_char *, int, u_char *, int) __THROW; -void res_nclose (res_state) __THROW; #endif __END_DECLS 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 #include #include +#include #include #include #include @@ -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 -- cgit v1.2.3