Allow the resolver source address to be specified in the configuration.
[ircu2.10.12-pk.git] / ircd / ircd_res.c
index 3e339d22685dc0cbeea22dde44a639619c343a05..a37654931a9c59499b9c60f890d0eb66b4055a48 100644 (file)
@@ -31,6 +31,7 @@
 #include "ircd.h"
 #include "numeric.h"
 #include "fileio.h" /* for fbopen / fbclose / fbputs */
+#include "random.h"
 #include "s_bsd.h"
 #include "s_debug.h"
 #include "s_stats.h"
@@ -39,7 +40,7 @@
 #include "res.h"
 #include "ircd_reslib.h"
 
-#include <assert.h>
+/* #include <assert.h> -- Now using assert in ircd_log.h */
 #include <string.h>
 #include <sys/time.h>
 #include <sys/socket.h>
@@ -53,6 +54,8 @@
 static struct Socket res_socket;
 /** Next DNS lookup timeout. */
 static struct Timer res_timeout;
+/** Check for whether the resolver has been initialized yet. */
+#define resolver_started() (request_list.next != NULL)
 
 /** Maximum DNS packet length.
  * RFC says 512, but we add extra for expanded names.
@@ -137,6 +140,8 @@ extern struct irc_sockaddr irc_nsaddr_list[IRCD_MAXNS];
 extern int irc_nscount;
 extern char irc_domain[HOSTLEN];
 
+struct irc_sockaddr ResolverAddr;
+
 /** Check whether \a inp is a nameserver we use.
  * @param[in] inp Nameserver address.
  * @return Non-zero if we trust \a inp; zero if not.
@@ -168,8 +173,10 @@ restart_resolver(void)
 
   if (!s_active(&res_socket))
   {
+    struct irc_sockaddr *local;
     int fd;
-    fd = os_socket(NULL, SOCK_DGRAM, "Resolver UDP socket");
+    local = irc_in_addr_valid(&ResolverAddr) ? &ResolverAddr : &VirtualHost;
+    fd = os_socket(local, SOCK_DGRAM, "Resolver UDP socket");
     if (fd < 0) return;
     if (!socket_add(&res_socket, res_readreply, NULL, SS_DATAGRAM,
                     SOCK_EVENT_READABLE, fd)) return;
@@ -177,19 +184,6 @@ restart_resolver(void)
   }
 }
 
-/** Initialize resolver.
- * This seends the pseudo-random number generator and calls
- * restart_resolver().
- * @return Resolver socket file descriptor.
- */
-int
-init_resolver(void)
-{
-  srand(CurrentTime);
-  restart_resolver();
-  return(s_fd(&res_socket));
-}
-
 /** Append local domain to hostname if needed.
  * If \a hname does not contain any '.'s, append #irc_domain to it.
  * @param[in,out] hname Hostname to check.
@@ -251,6 +245,9 @@ make_request(const struct DNSQuery* query)
 {
   struct reslist *request;
 
+  if (!resolver_started())
+    restart_resolver();
+
   request = (struct reslist *)MyMalloc(sizeof(struct reslist));
   memset(request, 0, sizeof(struct reslist));
 
@@ -336,13 +333,15 @@ delete_resolver_queries(const void *vptr)
   struct dlink *ptr, *next_ptr;
   struct reslist *request;
 
-  for (ptr = request_list.next; ptr != &request_list; ptr = next_ptr)
-  {
-    next_ptr = ptr->next;
-    request = (struct reslist*)ptr;
-    if (vptr == request->query.vptr) {
-      Debug((DEBUG_DNS, "Removing request %p with vptr %p", request, vptr));
-      rem_request(request);
+  if (request_list.next) {
+    for (ptr = request_list.next; ptr != &request_list; ptr = next_ptr)
+    {
+      next_ptr = ptr->next;
+      request = (struct reslist*)ptr;
+      if (vptr == request->query.vptr) {
+        Debug((DEBUG_DNS, "Removing request %p with vptr %p", request, vptr));
+        rem_request(request);
+      }
     }
   }
 }
@@ -537,7 +536,7 @@ query_name(const char *name, int query_class, int type,
      */
     do
     {
-      header->id = (header->id + rand()) & 0xffff;
+      header->id = (header->id + ircrandom()) & 0xffff;
     } while (find_id(header->id));
     request->id = header->id;
     ++request->sends;
@@ -906,12 +905,14 @@ cres_mem(struct Client* sptr)
   size_t request_mem   = 0;
   int    request_count = 0;
 
-  for (dlink = request_list.next; dlink != &request_list; dlink = dlink->next) {
-    request = (struct reslist*)dlink;
-    request_mem += sizeof(*request);
-    if (request->name)
-      request_mem += strlen(request->name) + 1;
-    ++request_count;
+  if (request_list.next) {
+    for (dlink = request_list.next; dlink != &request_list; dlink = dlink->next) {
+      request = (struct reslist*)dlink;
+      request_mem += sizeof(*request);
+      if (request->name)
+        request_mem += strlen(request->name) + 1;
+      ++request_count;
+    }
   }
 
   send_reply(sptr, SND_EXPLICIT | RPL_STATSDEBUG,