added basic ssl support to ircu
[ircu2.10.12-pk.git] / ircd / ircd_res.c
index 0996822dda96294393126a619c0652d3ef05362f..627e12e826fa813361d0a2737b7e8543aa383ec9 100644 (file)
@@ -56,6 +56,10 @@ static struct Socket res_socket_v4;
 static struct Socket res_socket_v6;
 /** Next DNS lookup timeout. */
 static struct Timer res_timeout;
+/** Local address for IPv4 DNS lookups. */
+struct irc_sockaddr VirtualHost_dns_v4;
+/** Local address for IPv6 DNS lookups. */
+struct irc_sockaddr VirtualHost_dns_v6;
 /** Check for whether the resolver has been initialized yet. */
 #define resolver_started() (request_list.next != NULL)
 
@@ -142,6 +146,16 @@ extern struct irc_sockaddr irc_nsaddr_list[IRCD_MAXNS];
 extern int irc_nscount;
 extern char irc_domain[HOSTLEN];
 
+/** Prepare the resolver library to (optionally) accept a list of
+ * DNS servers through add_dns_server().
+ */
+void clear_nameservers(void)
+{
+  irc_nscount = 0;
+  memset(&VirtualHost_dns_v4, 0, sizeof(VirtualHost_dns_v4));
+  memset(&VirtualHost_dns_v6, 0, sizeof(VirtualHost_dns_v6));
+}
+
 /** 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.
@@ -166,26 +180,43 @@ res_ourserver(const struct irc_sockaddr *inp)
 void
 restart_resolver(void)
 {
+  int need_v4;
+  int need_v6;
+  int ns;
+
   irc_res_init();
 
   if (!request_list.next)
     request_list.next = request_list.prev = &request_list;
 
-  if (!s_active(&res_socket_v4))
+  /* Check which address family (or families) our nameservers use. */
+  for (need_v4 = need_v6 = ns = 0; ns < irc_nscount; ns++)
   {
-    int fd = os_socket(&VirtualHost_v4, SOCK_DGRAM, "Resolver UDPv4 socket");
+    if (irc_in_addr_is_ipv4(&irc_nsaddr_list[ns].addr))
+      need_v4 = 1;
+    else
+      need_v6 = 1;
+  }
+
+  /* If we need an IPv4 socket, and don't have one, open it. */
+  if (need_v4 && !s_active(&res_socket_v4))
+  {
+    int fd = os_socket(&VirtualHost_dns_v4, SOCK_DGRAM, "Resolver UDPv4 socket", AF_INET);
     if (fd >= 0)
       socket_add(&res_socket_v4, res_readreply, NULL,
                  SS_DATAGRAM, SOCK_EVENT_READABLE, fd);
   }
 
-  if (!s_active(&res_socket_v6))
+#ifdef AF_INET6
+  /* If we need an IPv6 socket, and don't have one, open it. */
+  if (need_v6 && !s_active(&res_socket_v6))
   {
-    int fd = os_socket(&VirtualHost_v6, SOCK_DGRAM, "Resolver UDPv6 socket");
+    int fd = os_socket(&VirtualHost_dns_v6, SOCK_DGRAM, "Resolver UDPv6 socket", AF_INET6);
     if (fd >= 0)
       socket_add(&res_socket_v6, res_readreply, NULL,
                  SS_DATAGRAM, SOCK_EVENT_READABLE, fd);
   }
+#endif
 
   if (s_active(&res_socket_v4) || s_active(&res_socket_v6))
     timer_init(&res_timeout);
@@ -602,7 +633,6 @@ proc_answer(struct reslist *request, HEADER* header, char* buf, char* eob)
 {
   char hostbuf[HOSTLEN + 100]; /* working buffer */
   unsigned char *current;      /* current position in buf */
-  int query_class;             /* answer class */
   int type;                    /* answer type */
   int n;                       /* temp count */
   int rd_length;
@@ -656,9 +686,8 @@ proc_answer(struct reslist *request, HEADER* header, char* buf, char* eob)
     type = irc_ns_get16(current);
     current += TYPE_SIZE;
 
-    query_class = irc_ns_get16(current);
+    /* We do not use the class or TTL values. */
     current += CLASS_SIZE;
-
     current += TTL_SIZE;
 
     rd_length = irc_ns_get16(current);
@@ -706,9 +735,6 @@ proc_answer(struct reslist *request, HEADER* header, char* buf, char* eob)
         break;
       case T_CNAME: /* first check we already haven't started looking
                        into a cname */
-        if (request->type != T_PTR)
-          return(0);
-
         if (request->state == REQ_CNAME)
         {
           n = irc_dn_expand((unsigned char *)buf, (unsigned char *)eob,
@@ -787,8 +813,16 @@ res_readreply(struct Event *ev)
 
   if ((header->rcode != NO_ERRORS) || (header->ancount == 0))
   {
-    if (SERVFAIL == header->rcode)
-      resend_query(request);
+    if (SERVFAIL == header->rcode || NXDOMAIN == header->rcode)
+    {
+        /*
+         * If a bad error was returned, we stop here and don't send
+         * send any more (no retries granted).
+         */
+        Debug((DEBUG_DNS, "Request %p has bad response (state %d type %d rcode %d)", request, request->state, request->type, header->rcode));
+        (*request->callback)(request->callback_ctx, NULL, NULL);
+       rem_request(request);
+    }
     else
     {
       /*
@@ -808,16 +842,6 @@ res_readreply(struct Event *ev)
         request->timeout += feature_int(FEAT_IRCD_RES_TIMEOUT);
         resend_query(request);
       }
-      else
-      {
-        /*
-         * If a bad error was returned, we stop here and don't send
-         * send any more (no retries granted).
-         */
-        Debug((DEBUG_DNS, "Request %p has bad response (state %d type %d rcode %d)", request, request->state, request->type, header->rcode));
-        (*request->callback)(request->callback_ctx, NULL, NULL);
-       rem_request(request);
-      }
     }
 
     return;