diff --git a/Makefile.inc b/Makefile.inc
index 6a68fce..acfd282 100644
--- a/Makefile.inc
+++ b/Makefile.inc
@@ -16,6 +16,7 @@ CSOURCES = ares__close_sockets.c	\
   ares_getnameinfo.c			\
   ares_getsock.c			\
   ares_init.c				\
+  ares_reinit.c				\
   ares_library_init.c			\
   ares_llist.c				\
   ares_mkquery.c			\
diff --git a/ares.h b/ares.h
index 9456a14..3436237 100644
--- a/ares.h
+++ b/ares.h
@@ -306,6 +306,8 @@ CARES_EXTERN int ares_save_options(ares_channel channel,
 
 CARES_EXTERN void ares_destroy_options(struct ares_options *options);
 
+CARES_EXTERN int ares_reinit(ares_channel channel);
+
 CARES_EXTERN int ares_dup(ares_channel *dest,
                           ares_channel src);
 
diff --git a/ares_gethostbyaddr.c b/ares_gethostbyaddr.c
index 0de2cf2..b2284bb 100644
--- a/ares_gethostbyaddr.c
+++ b/ares_gethostbyaddr.c
@@ -72,6 +72,8 @@ void ares_gethostbyaddr(ares_channel channel, const void *addr, int addrlen,
 {
   struct addr_query *aquery;
 
+  ares__maybe_reinit(channel);
+
   if (family != AF_INET && family != AF_INET6)
     {
       callback(arg, ARES_ENOTIMP, 0, NULL);
diff --git a/ares_gethostbyname.c b/ares_gethostbyname.c
index 4469ffe..2c3578a 100644
--- a/ares_gethostbyname.c
+++ b/ares_gethostbyname.c
@@ -88,6 +88,8 @@ void ares_gethostbyname(ares_channel channel, const char *name, int family,
 {
   struct host_query *hquery;
 
+  ares__maybe_reinit(channel);
+
   /* Right now we only know how to look up Internet addresses - and unspec
      means try both basically. */
   switch (family) {
diff --git a/ares_init.c b/ares_init.c
index d2f4a72..fe31ce8 100644
--- a/ares_init.c
+++ b/ares_init.c
@@ -176,6 +176,7 @@ int ares_init_options(ares_channel *channelptr, struct ares_options *options,
 
   channel->last_server = 0;
   channel->last_timeout_processed = (time_t)now.tv_sec;
+  channel->last_reinit = (time_t)now.tv_sec;
 
   memset(&channel->local_dev_name, 0, sizeof(channel->local_dev_name));
   channel->local_ip4 = 0;
diff --git a/ares_private.h b/ares_private.h
index bf21abd..6c795bf 100644
--- a/ares_private.h
+++ b/ares_private.h
@@ -300,6 +300,8 @@ struct ares_channeldata {
 
   ares_sock_create_callback sock_create_cb;
   void *sock_create_cb_data;
+
+  time_t last_reinit;
 };
 
 /* return true if now is exactly check time or later */
@@ -327,6 +329,7 @@ int ares__expand_name_for_response(const unsigned char *encoded,
                                    char **s, long *enclen);
 void ares__init_servers_state(ares_channel channel);
 void ares__destroy_servers_state(ares_channel channel);
+int ares__maybe_reinit(ares_channel channel);
 #if 0 /* Not used */
 long ares__tvdiff(struct timeval t1, struct timeval t2);
 #endif
diff --git a/ares_reinit.3 b/ares_reinit.3
index e69de29..775b2df 100644
--- a/ares_reinit.3
+++ b/ares_reinit.3
@@ -0,0 +1,23 @@
+.TH ARES_REINIT 3 "11 February 2011"
+.SH NAME
+ares_reinit \- Reinitialize a resolver channel
+.SH SYNOPSIS
+.nf
+.B #include <ares.h>
+.PP
+.B int ares_reinit(ares_channel \fIchannel\fP)
+.fi
+.SH DESCRIPTION
+The \fBares_reinit\fP function checks if configuration files have changed and
+if so reads configuration files to get default domain name, search order and
+name server address(es).
+.PP
+The \fBares_reinit\fP function may cancel all lookups/requests made on the the
+name service channel identified by \fIchannel\fP.
+.SH SEE ALSO
+.BR ares_init (3)
+.BR ares_cancel (3)
+.SH NOTES
+This function was added in c-ares 1.7.5
+.SH AUTHOR
+Dima Tisnek
diff --git a/ares_reinit.c b/ares_reinit.c
index e69de29..7bf2d24 100644
--- a/ares_reinit.c
+++ b/ares_reinit.c
@@ -0,0 +1,123 @@
+#include "ares_setup.h"
+#include "ares.h"
+#include "ares_private.h"
+#include "bitncmp.h"
+
+static int apatterncmp(struct apattern* a, struct apattern* b);
+static int addrcmp(struct ares_addr* a, struct ares_addr* b);
+
+int ares__maybe_reinit(ares_channel channel)
+{
+  struct timeval now;
+  now = ares__tvnow();
+  /* only 1-second granularity here
+   * could use timeval in channel for better precision */
+  if (now.tv_sec > channel->last_reinit + channel->timeout/1000)
+    return ares_reinit(channel);
+}
+
+int apatterncmp(struct apattern* a, struct apattern* b)
+{
+  if (a->type != b->type) return a->type - b->type;
+  if (a->family != b-> family) return a->family - b->family;
+  switch (a->type) {
+    case PATTERN_MASK:
+      /* masks only valid for ipv4 */
+      return memcmp(&a->addrV4, &b->addrV4, sizeof(a->addrV4));
+    case PATTERN_CIDR:
+      if (a->mask.bits != b->mask.bits) return a->mask.bits - b->mask.bits; 
+      return ares_bitncmp(&a->addr, &b->addr, a->mask.bits);
+  }
+  return 0;
+}
+
+int addrcmp(struct ares_addr* a, struct ares_addr* b)
+{
+  if (a->family != b->family) return a->family - b->family;
+  switch (a->family) {
+    case AF_INET: return memcmp(&a->addrV4, &b->addrV4, sizeof(a->addrV4));
+    case AF_INET6: return memcmp(&a->addrV6, &b->addrV6, sizeof(a->addrV6));
+  }
+  return 0;
+}
+
+int ares_reinit(ares_channel channel)
+{
+  ares_channel another=0;
+  int i, rv, diff=0;
+  int nservers, nsort, ndomains;
+  char **domains;
+  struct apattern *sortlist;
+  char *lookups;
+  struct server_state *servers;
+  struct timeval now;
+  rv = ares_init(&another);
+  if (rv != ARES_SUCCESS) return rv;
+
+  if (channel->ndots    != another->ndots)      diff = 1;
+  if (channel->timeout  != another->timeout)    diff = 1;
+  if (channel->tries    != another->tries)      diff = 1;
+  if (channel->rotate   != another->rotate)     diff = 1;
+
+  if (channel->nservers != another->nservers)   diff = 1;
+  for (i=0; !diff && i < channel->nservers; i++)
+    if (addrcmp(&channel->servers[i].addr, &another->servers[i].addr))
+      diff = 1;
+
+  if (channel->nsort    != another->nsort)      diff = 1;
+  for (i=0; !diff && i < channel->nsort; i++)
+    if (apatterncmp(&channel->sortlist[i], &another->sortlist[i]))
+      diff = 1;
+
+  if (channel->ndomains != another->ndomains)   diff = 1;
+  for (i=0; !diff && i < channel->ndomains; i++)
+    if (strcmp(channel->domains[i], another->domains[i]))
+      diff = 1;
+
+  if (!!channel->lookups != !!another->lookups) diff = 1;
+  if (channel->lookups && strcmp(channel->lookups, another->lookups)) diff = 1;
+
+  if (diff)
+  {
+    ares_cancel(channel);
+
+    channel->ndots   = another->ndots;
+    channel->timeout = another->timeout;
+    channel->tries   = another->tries;
+    channel->rotate  = another->rotate;
+    channel->last_server = 0;
+
+    nservers = channel->nservers;
+    servers  = channel->servers;
+    channel->nservers = another->nservers;
+    channel->servers  = another->servers;
+    another->nservers = nservers;
+    another->servers  = servers;
+    for (i=0; i<channel->nservers; i++) channel->servers[i].channel = channel;
+    for (i=0; i<another->nservers; i++) another->servers[i].channel = another;
+
+    nsort    = channel->nsort;
+    sortlist = channel->sortlist;
+    channel->nsort    = another->nsort;
+    channel->sortlist = another->sortlist;
+    another->nsort    = nsort;
+    another->sortlist = sortlist;
+
+    ndomains = channel->ndomains;
+    domains  = channel->domains;
+    channel->ndomains = another->ndomains;
+    channel->domains  = another->domains;
+    another->ndomains = ndomains;
+    another->domains  = domains;
+
+    lookups = channel->lookups;
+    channel->lookups = another->lookups;
+    another->lookups = lookups;
+  }
+
+  now = ares__tvnow();
+  channel->last_reinit = (time_t)now.tv_sec;
+
+  ares_destroy(another);
+  return rv;
+}
