diff --git a/Changes b/Changes index 6e01f9e13..250c9c4f1 100644 --- a/Changes +++ b/Changes @@ -1110,3 +1110,13 @@ (#0002879). - Made doc/compiling_win32.txt a bit more ugly (mention that only vstudio 7.x actually works at this moment). +- c-ares (currently, a forked off version) enhancements: + - '/quote dns i' now shows the nameserver settings (which is taken from /etc/resolv.conf + on *NIX, and from the registry on Windows) + - We no longer depend on a C++ compiler (was useless c-ares dependency caused by libtool) + - '/REHASH -dns' now rereads the resolver data from resolv.conf/registry, no IRCd restart + needed anymore. It's currently kinda experimental however, but I *think* it will work ok. + Unfortunately the above features required some ugly hacks if curl was enabled, so if you + use curl (Remote includes), feel free to test on your OS (Linux, but especially FreeBSD + and the other *NIXes) to see if things still compile (make clean; ./Config && make). +(...win32 build is now broken, will be fixed within an hour..) diff --git a/autoconf/aclocal.m4 b/autoconf/aclocal.m4 index edb831b27..6c9651bad 100644 --- a/autoconf/aclocal.m4 +++ b/autoconf/aclocal.m4 @@ -52,14 +52,23 @@ AC_DEFUN(CHECK_LIBCURL, [AC_HELP_STRING([--enable-libcurl=DIR],[enable libcurl (remote include) support])], [ CURLCFLAG=`$enableval/bin/curl-config --cflags` - CFLAGS="$CFLAGS $CURLCFLAG -DUSE_LIBCURL" CURLLIBS=`$enableval/bin/curl-config --libs` - dnl curl-7.11.0 and up will include the ares info, older versions do not - if test "x`echo $CURLLIBS |grep .*ares.*`" = x ; then - CURLLIBS="$CURLLIBS -lares" + dnl Ok this is ugly, basically we need to strip the version of c-ares that curl uses + dnl because we want to use our own version (which is hopefully fully binary + dnl compatible with the curl one as well). + dnl Therefore we need to strip the cares libs in a weird way... + dnl If anyone can come up with something better and still portable (no awk!?) + dnl then let us know. + if test "x`echo $CURLLIBS |grep ares`" != x ; then + CURLLIBS="`echo "$CURLLIBS"|sed -r 's/(@<:@^ @:>@+ @<:@^ @:>@+ )(@<:@^ @:>@+ @<:@^ @:>@+ )(.+)/\1\3/g'`" + if test x"$CURLLIBS" = x; then + AC_MSG_ERROR([sed appears to be broken. It is needed for a remote includes compile hack.]) + fi fi + IRCDLIBS="$IRCDLIBS $CURLLIBS" + CFLAGS="$CFLAGS $CURLCFLAG -DUSE_LIBCURL" URL="url.o" AC_SUBST(URL) ]) diff --git a/configure b/configure index e17ecf794..6cda93f9a 100755 --- a/configure +++ b/configure @@ -12143,13 +12143,19 @@ if test "${enable_libcurl+set}" = set; then enableval="$enable_libcurl" CURLCFLAG=`$enableval/bin/curl-config --cflags` - CFLAGS="$CFLAGS $CURLCFLAG -DUSE_LIBCURL" CURLLIBS=`$enableval/bin/curl-config --libs` - if test "x`echo $CURLLIBS |grep .*ares.*`" = x ; then - CURLLIBS="$CURLLIBS -lares" + if test "x`echo $CURLLIBS |grep ares`" != x ; then + CURLLIBS="`echo "$CURLLIBS"|sed -r 's/([^ ]+ [^ ]+ )([^ ]+ [^ ]+ )(.+)/\1\3/g'`" + if test x"$CURLLIBS" = x; then + { { echo "$as_me:$LINENO: error: sed appears to be broken. It is needed for a remote includes compile hack." >&5 +echo "$as_me: error: sed appears to be broken. It is needed for a remote includes compile hack." >&2;} + { (exit 1); exit 1; }; } + fi fi + IRCDLIBS="$IRCDLIBS $CURLLIBS" + CFLAGS="$CFLAGS $CURLCFLAG -DUSE_LIBCURL" URL="url.o" diff --git a/extras/c-ares.tar.gz b/extras/c-ares.tar.gz index f44054dc1..5a0311bad 100644 Binary files a/extras/c-ares.tar.gz and b/extras/c-ares.tar.gz differ diff --git a/include/h.h b/include/h.h index 7bcd71174..17a3c0a40 100644 --- a/include/h.h +++ b/include/h.h @@ -386,7 +386,7 @@ extern struct hostent *get_res(char *); extern struct hostent *gethost_byaddr(char *, Link *); extern struct hostent *gethost_byname(char *, Link *); extern void flush_cache(); -extern void init_resolver(void); +extern void init_resolver(int firsttime); extern time_t timeout_query_list(time_t); extern time_t expire_cache(time_t); extern void del_queries(char *); @@ -769,7 +769,7 @@ extern int isipv6(struct IN_ADDR *addr); extern void inet4_to_inet6(const void *src_in, void *dst_in); extern void unrealdns_delreq_bycptr(aClient *cptr); extern void inet6_to_inet4(const void *src, void *dst); -extern void sendtxtnumeric(aClient *to, char *pattern, ...); +extern void sendtxtnumeric(aClient *to, char *pattern, ...) __attribute__((format(printf,2,3)));; extern void unrealdns_gethostbyname_link(char *name, ConfigItem_link *conf); extern void unrealdns_delasyncconnects(void); extern int is_autojoin_chan(char *chname); diff --git a/include/res.h b/include/res.h index 577344c1e..9417bbcd0 100644 --- a/include/res.h +++ b/include/res.h @@ -77,6 +77,6 @@ struct _dnsstats { extern ares_channel resolver_channel; -extern void init_resolver(void); +extern void init_resolver(int); struct hostent *unrealdns_doclient(aClient *cptr); diff --git a/src/ircd.c b/src/ircd.c index d4a4eb3ac..a92a16f80 100644 --- a/src/ircd.c +++ b/src/ircd.c @@ -948,7 +948,7 @@ int InitwIRCD(int argc, char *argv[]) if (geteuid() != 0) fprintf(stderr, "WARNING: IRCd compiled with CHROOTDIR but effective user id is not root!? " "Booting is very likely to fail...\n"); - init_resolver(); + init_resolver(1); { struct stat sb; mode_t umaskold; diff --git a/src/res.c b/src/res.c index 1fbded254..f2736e8bd 100644 --- a/src/res.c +++ b/src/res.c @@ -75,15 +75,19 @@ static DNSCache *cache_hashtbl[DNS_HASH_SIZE]; /**< Hash table of cache */ static unsigned int unrealdns_num_cache = 0; /**< # of cache entries in memory */ -void init_resolver(void) +void init_resolver(int firsttime) { struct ares_options options; int n; if (requests) abort(); /* should never happen */ - memset(&cache_hashtbl, 0, sizeof(cache_hashtbl)); - memset(&dnsstats, 0, sizeof(dnsstats)); + + if (firsttime) + { + memset(&cache_hashtbl, 0, sizeof(cache_hashtbl)); + memset(&dnsstats, 0, sizeof(dnsstats)); + } options.timeout = 3; options.tries = 2; @@ -99,6 +103,32 @@ int n; } } +void reinit_resolver(aClient *sptr) +{ +#ifdef CHROOTDIR + /* Prevent people from killing their ircd accidently if in CHROOTDIR mode... */ +FILE *fd; + + fd = fopen("/etc/resolv.conf", "r"); + if (!fd) + { + sendnotice(sptr, "Rehashing DNS with CHROOTDIR enabled seems a BAD idea since /etc/resolv.conf " + "is missing in your chroot. This is usually perfectly fine and normal, but " + "prevents this exact rehash feature from working for obvious technical reasons " + "(HINT: it is impossible to read the system /etc/resolv.conf since it's outside the chroot)."); + return; + } + fclose(fd); +#endif + + sendto_realops("%s requested reinitalization of resolver!", sptr->name); + sendto_realops("Destroying resolver channel, along with all currently pending queries..."); + ares_destroy(resolver_channel); + sendto_realops("Initializing resolver again..."); + init_resolver(0); + sendto_realops("Reinitalization finished successfully."); +} + void unrealdns_addreqtolist(DNSReq *r) { if (requests) @@ -632,9 +662,21 @@ char *param; } else if (*param == 'i') /* INFORMATION */ { - sendtxtnumeric(sptr, "DNS Configuration info:"); - sendtxtnumeric(sptr, " c-ares version %s",ares_version(NULL)); - /* TODO: hmm... we cannot get the nameservers from c-ares, can we? */ + struct ares_config_info inf; + int i; + + ares_get_config(&inf, resolver_channel); + + sendtxtnumeric(sptr, "****** DNS Configuration Information ******"); + sendtxtnumeric(sptr, " c-ares version: %s",ares_version(NULL)); + sendtxtnumeric(sptr, " timeout: %d", inf.timeout); + sendtxtnumeric(sptr, " tries: %d", inf.tries); + sendtxtnumeric(sptr, " # of servers: %d", inf.numservers); + for (i = 0; i < inf.numservers; i++) + sendtxtnumeric(sptr, " server #%d: %s", i+1, inf.servers[i] ? inf.servers[i] : "[???]"); + + /* TODO: free or get memleak ! */ + sendtxtnumeric(sptr, "****** End of DNS Configuration Info ******"); } else /* STATISTICS */ { sendtxtnumeric(sptr, "DNS CACHE Stats:"); diff --git a/src/s_bsd.c b/src/s_bsd.c index ca6f0b864..0a51d7bdb 100644 --- a/src/s_bsd.c +++ b/src/s_bsd.c @@ -659,7 +659,7 @@ init_dgram: #endif /*_WIN32*/ #ifndef CHROOTDIR - init_resolver(); + init_resolver(1); #endif return; } diff --git a/src/s_serv.c b/src/s_serv.c index f501e615b..7bbd2fcd9 100644 --- a/src/s_serv.c +++ b/src/s_serv.c @@ -580,6 +580,8 @@ void reread_motdsandrules() opermotd = (aMotd *) read_file(OPATH, &opermotd); } +extern void reinit_resolver(aClient *sptr); + /* ** m_rehash ** remote rehash by binary @@ -665,6 +667,11 @@ CMD_FUNC(m_rehash) RunHook3(HOOKTYPE_REHASHFLAG, cptr, sptr, parv[1]); return 0; } + if (!strnicmp("-dns", parv[1], 4)) + { + reinit_resolver(sptr); + return 0; + } if (!_match("-o*motd", parv[1])) { sendto_ops diff --git a/src/url.c b/src/url.c index c40b63fff..09f7af6f2 100644 --- a/src/url.c +++ b/src/url.c @@ -170,6 +170,10 @@ char *download_file(char *url, char **error) curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); curl_easy_setopt(curl, CURLOPT_TIMEOUT, 45); curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 15); +#if LIBCURL_VERSION_NUM >= 0x070f01 + curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1); + curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 1); +#endif #ifdef USE_SSL set_curl_ssl_options(curl); @@ -271,6 +275,11 @@ void download_file_async(char *url, time_t cachetime, vFP callback) curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); curl_easy_setopt(curl, CURLOPT_TIMEOUT, 45); curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 15); +#if LIBCURL_VERSION_NUM >= 0x070f01 + curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1); + curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 1); +#endif + curl_multi_add_handle(multihandle, curl); }