summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Mack <zonque@gmail.com>2011-07-13 00:30:54 +0200
committerBernhard Reutner-Fischer <rep.dot.nop@gmail.com>2011-08-26 09:29:54 +0200
commit7f74de5d4d6d10baafab4b37bb3d472f5c5f0e8c (patch)
tree4036823c10d4e9fced3256b7a3e928250a5f6ca2
parenta863daff6844e330183045f513dcc1b421af426c (diff)
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 <zonque@gmail.com>
-rw-r--r--include/resolv.h8
-rw-r--r--libc/inet/resolv.c141
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 <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