Fail earlier if no lex or yacc is found; fix resolver DNS bug.
[ircu2.10.12-pk.git] / ircd / ircd_res.c
index 3e339d22685dc0cbeea22dde44a639619c343a05..e56c6cd9956a1af657788383a800ad8eb4d35368 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>
 #error this code needs to be able to address individual octets 
 #endif
 
-/** Resolver UDP socket. */
-static struct Socket res_socket;
+/** IPv4 resolver UDP socket. */
+static struct Socket res_socket_v4;
+/** IPv6 resolver UDP socket. */
+static struct Socket res_socket_v6;
 /** 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.
@@ -166,28 +171,24 @@ restart_resolver(void)
   if (!request_list.next)
     request_list.next = request_list.prev = &request_list;
 
-  if (!s_active(&res_socket))
+  if (!s_active(&res_socket_v4))
   {
-    int fd;
-    fd = os_socket(NULL, SOCK_DGRAM, "Resolver UDP socket");
-    if (fd < 0) return;
-    if (!socket_add(&res_socket, res_readreply, NULL, SS_DATAGRAM,
-                    SOCK_EVENT_READABLE, fd)) return;
-    timer_init(&res_timeout);
+    int fd = os_socket(&VirtualHost_v4, SOCK_DGRAM, "Resolver UDPv4 socket");
+    if (fd >= 0)
+      socket_add(&res_socket_v4, res_readreply, NULL,
+                 SS_DATAGRAM, SOCK_EVENT_READABLE, fd);
   }
-}
 
-/** 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));
+  if (!s_active(&res_socket_v6))
+  {
+    int fd = os_socket(&VirtualHost_v6, SOCK_DGRAM, "Resolver UDPv6 socket");
+    if (fd >= 0)
+      socket_add(&res_socket_v6, res_readreply, NULL,
+                 SS_DATAGRAM, SOCK_EVENT_READABLE, fd);
+  }
+
+  if (s_active(&res_socket_v4) || s_active(&res_socket_v6))
+    timer_init(&res_timeout);
 }
 
 /** Append local domain to hostname if needed.
@@ -251,6 +252,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));
 
@@ -274,7 +278,7 @@ check_resolver_timeout(time_t when)
 {
   if (when > CurrentTime + AR_TTL)
     when = CurrentTime + AR_TTL;
-  if (!t_active(&res_timeout))
+  if (!t_onqueue(&res_timeout))
     timer_add(&res_timeout, timeout_resolver, NULL, TT_ABSOLUTE, when);
   else if (when < t_expire(&res_timeout))
     timer_chg(&res_timeout, TT_ABSOLUTE, when);
@@ -336,13 +340,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);
+      }
     }
   }
 }
@@ -366,9 +372,11 @@ send_res_msg(const char *msg, int len, int rcount)
   if (max_queries == 0)
     max_queries = 1;
 
-  for (i = 0; i < max_queries; i++)
-    if (os_sendto_nonb(s_fd(&res_socket), msg, len, NULL, 0, &irc_nsaddr_list[i]) == IO_SUCCESS)
+  for (i = 0; i < max_queries; i++) {
+    int fd = irc_in_addr_is_ipv4(&irc_nsaddr_list[i].addr) ? s_fd(&res_socket_v4) : s_fd(&res_socket_v6);
+    if (os_sendto_nonb(fd, msg, len, NULL, 0, &irc_nsaddr_list[i]) == IO_SUCCESS)
       ++sent;
+  }
 
   return(sent);
 }
@@ -537,7 +545,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;
@@ -734,7 +742,7 @@ res_readreply(struct Event *ev)
   unsigned int rc;
   int answer_count;
 
-  assert(ev_socket(ev) == &res_socket);
+  assert((ev_socket(ev) == &res_socket_v4) || (ev_socket(ev) == &res_socket_v6));
   sock = ev_socket(ev);
 
   if (IO_SUCCESS != os_recvfrom_nonb(s_fd(sock), buf, sizeof(buf), &rc, &lsin)
@@ -906,67 +914,17 @@ 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,
             ":Resolver: requests %d(%d)", request_count, request_mem);
   return request_mem;
 }
-
-/** Check whether an address looks valid.
- * This means not all 0s and not all 1s.
- * @param[in] addr Address to check for validity.
- * @return Non-zero if the address looks valid.
- */
-int irc_in_addr_valid(const struct irc_in_addr *addr)
-{
-  unsigned int ii;
-  unsigned short val;
-
-  val = addr->in6_16[0];
-  if (val != 0 && val != 0xffff)
-    return 1;
-  for (ii = 1; ii < 8; ii++)
-    if (addr->in6_16[ii] != val)
-      return 1;
-  return 0;
-}
-
-/** Compare two IP addresses.
- * @param[in] a First address to compare.
- * @param[in] b Second address to compare.
- * @return Non-zero if the two addresses differ, zero if they are identical.
- */
-int irc_in_addr_cmp(const struct irc_in_addr *a, const struct irc_in_addr *b)
-{
-  if (irc_in_addr_is_ipv4(a))
-    return a->in6_16[6] != b->in6_16[6]
-        || a->in6_16[7] != b->in6_16[7]
-        || !irc_in_addr_is_ipv4(b);
-  else
-    return memcmp(a, b, sizeof(*a));
-}
-
-/** Indicate whether an IP address is a loopback address.
- * @param[in] addr Address to check.
- * @return Non-zero if the address is loopback; zero if not.
- */
-int irc_in_addr_is_loopback(const struct irc_in_addr *addr)
-{
-  if (addr->in6_16[0] != 0
-    || addr->in6_16[1] != 0
-    || addr->in6_16[2] != 0
-    || addr->in6_16[3] != 0
-    || addr->in6_16[4] != 0)
-    return 0;
-  if ((addr->in6_16[5] == 0xffff) || (addr->in6_16[5] == 0 && addr->in6_16[6] != 0))
-    return (ntohs(addr->in6_16[6]) & 0xff00) == 0x7f00;
-  else
-    return addr->in6_16[5] == 0 && addr->in6_16[6] == 0 && htons(addr->in6_16[7]) == 1;
-}