Author: Bleep <helveytw@home.com>
[ircu2.10.12-pk.git] / ircd / res.c
index 755e897f8980fd0c4c69312dec7c1c9fc2ec656f..9da34d4da782d48bff4fe07d34d94fa273a7e04f 100644 (file)
@@ -16,7 +16,9 @@
 #include "ircd_alloc.h"
 #include "ircd_log.h"
 #include "ircd_osdep.h"
+#include "ircd_reply.h"
 #include "ircd_string.h"
+#include "msg.h"
 #include "numeric.h"
 #include "s_bsd.h"
 #include "s_debug.h"
@@ -35,6 +37,7 @@
 #include <sys/socket.h>
 #include <fcntl.h>
 #include <unistd.h>
+#include <regex.h>
 
 #include <arpa/nameser.h>
 #include <resolv.h>
  *  Nov. 17, 1997 --Bleep
  */
 
-typedef struct Hostent {
+struct Hostent {
   struct hostent h;      /* the hostent struct we are passing around */
   char*          buf;    /* buffer for data pointed to from hostent */
-} aHostent;
+};
 
 struct ResRequest {
   struct ResRequest* next;
@@ -174,7 +177,7 @@ struct ResRequest {
   struct in_addr     addr;
   char*              name;
   struct DNSQuery    query;         /* query callback for this request */
-  aHostent           he;
+  struct Hostent     he;
 };
 
 struct CacheEntry {
@@ -235,7 +238,7 @@ static struct CacheEntry*  find_cache_number(struct ResRequest* request,
                                              const char* addr);
 static struct ResRequest*   find_id(int);
 
-static  struct cacheinfo {
+static struct cacheinfo {
   int  ca_adds;
   int  ca_dels;
   int  ca_expires;
@@ -275,7 +278,7 @@ extern u_int    _getlong(const u_char *);
  *      paul vixie, 29may94
  */
 static int
-res_ourserver(const struct __res_state* statp, const struct sockaddr_in *inp) 
+res_ourserver(const struct __res_state* statp, const struct sockaddr_ininp) 
 {
   struct sockaddr_in ina;
   int ns;
@@ -351,12 +354,14 @@ int init_resolver(void)
   memset(hashtable, 0, sizeof(hashtable));
   memset(&reinfo,   0, sizeof(reinfo));
 
-  requestListHead = requestListTail = NULL;
+  requestListHead = requestListTail = 0;
 
   errno = h_errno = 0;
+
   start_resolver();
   Debug((DEBUG_DNS, "Resolver: fd %d errno: %d h_errno: %d: %s",
-         ResolverFileDescriptor, errno, h_errno, strerror(errno)));
+         ResolverFileDescriptor, errno, h_errno, 
+         (strerror(errno)) ? strerror(errno) : "Unknown"));
   return ResolverFileDescriptor;
 }
 
@@ -369,6 +374,18 @@ void restart_resolver(void)
   start_resolver();
 }
 
+static int validate_hostent(const struct hostent* hp)
+{
+  const char* name;
+  int  i = 0;
+  assert(0 != hp);
+  for (name = hp->h_name; name; name = hp->h_aliases[i++]) {
+    if (!string_is_hostname(name))
+      return 0;
+  }
+  return 1;
+}
+
 /*
  * add_request - place a new request in the request list
  */
@@ -561,7 +578,8 @@ static int send_res_msg(const u_char* msg, int len, int rcount)
       ++sent;
     }
     else
-      ircd_log(L_ERROR, "Resolver: send failed %s", strerror(errno));
+      ircd_log(L_ERROR, "Resolver: send failed %s", 
+               (strerror(errno)) ? strerror(errno) : "Unknown");
   }
   return sent;
 }
@@ -680,7 +698,7 @@ static void query_name(const char* name, int query_class,
   Debug((DEBUG_DNS, "Resolver: query_name: %s %d %d", name, query_class, type));
   memset(buf, 0, sizeof(buf));
   if ((request_len = res_mkquery(QUERY, name, query_class, type, 
-                                 NULL, 0, NULL, buf, sizeof(buf))) > 0) {
+                                 0, 0, 0, (unsigned char*) buf, sizeof(buf))) > 0) {
     HEADER* header = (HEADER*) buf;
 #ifndef LRAND48
     int            k = 0;
@@ -707,7 +725,7 @@ static void query_name(const char* name, int query_class,
     ++request->sends;
     Debug((DEBUG_DNS, "Resolver: query_name %d: %s %d %d", request->id, 
           name, query_class, type));
-    request->sent += send_res_msg(buf, request_len, request->sends);
+    request->sent += send_res_msg((const unsigned char*) buf, request_len, request->sends);
   }
 }
 
@@ -961,11 +979,12 @@ int resolver_read(void)
 
   Debug((DEBUG_DNS, "Resolver: read"));
   if (IO_SUCCESS != os_recvfrom_nonb(ResolverFileDescriptor,
-                                     buf, sizeof(buf), &rc, &sin)) {
+                                     (char*) buf, sizeof(buf), &rc, &sin)) {
     return 0;
   }
   if (rc < sizeof(HEADER)) {
-    Debug((DEBUG_DNS, "Resolver: short reply %d: %s", rc, strerror(errno)));
+    Debug((DEBUG_DNS, "Resolver: short reply %d: %s", rc, 
+           (strerror(errno)) ? strerror(errno) : "Unknown"));
     return 0;
   }
   /*
@@ -990,8 +1009,7 @@ int resolver_read(void)
    * check against possibly fake replies
    */
   if (!res_ourserver(&_res, &sin)) {
-    Debug((DEBUG_DNS, "Resolver: fake reply from: %s",
-           (const char*) &sin.sin_addr));
+    Debug((DEBUG_DNS, "Resolver: fake reply from: %s", (const char*) &sin.sin_addr));
     ++reinfo.re_unkrep;
     return 1;
   }
@@ -1044,7 +1062,7 @@ int resolver_read(void)
   answer_count = proc_answer(request, header, buf, buf + rc);
   if (answer_count) {
     if (T_PTR == request->type) {
-      struct DNSReply* reply = NULL;
+      struct DNSReply* reply = 0;
       if (0 == request->he.h.h_name) {
         /*
          * got a PTR response with no name, something bogus is happening
@@ -1063,7 +1081,10 @@ int resolver_read(void)
        * extra kludges.
        */
       reply = gethost_byname(request->he.h.h_name, &request->query);
-      if (0 == reply) {
+      if (reply) {
+        (*request->query.callback)(request->query.vptr, reply);
+      }
+      else {
         /*
          * If name wasn't found, a request has been queued and it will
          * be the last one queued.  This is rather nasty way to keep
@@ -1074,8 +1095,6 @@ int resolver_read(void)
         request->he.buf = 0;
         memcpy(&requestListTail->he.h, &request->he.h, sizeof(struct hostent));
       }
-      else
-        (*request->query.callback)(request->query.vptr, reply);
       rem_request(request);
     }
     else {
@@ -1086,9 +1105,12 @@ int resolver_read(void)
        * PTR returned a CNAME, cp was not checked before so the
        * callback was being called with a value of 0x2C != NULL.
        */
-      cp = make_cache(request);
-      (*request->query.callback)(request->query.vptr,
-                                 (cp) ? &cp->reply : 0);
+      struct DNSReply* reply = 0;
+      if (validate_hostent(&request->he.h)) {
+        if ((cp = make_cache(request)))
+          reply = &cp->reply;
+      }
+      (*request->query.callback)(request->query.vptr, reply);
       rem_request(request);
     }
   }
@@ -1147,7 +1169,7 @@ static size_t calc_hostent_buffer_size(const struct hostent* hp)
  * dup_hostent - Duplicate a hostent struct, allocate only enough memory for
  * the data we're putting in it.
  */
-static void dup_hostent(aHostent* new_hp, struct hostent* hp)
+static void dup_hostent(struct Hostent* new_hp, struct hostent* hp)
 {
   char*  p;
   char** ap;
@@ -1212,7 +1234,7 @@ static void dup_hostent(aHostent* new_hp, struct hostent* hp)
 /*
  * update_hostent - Add records to a Hostent struct in place.
  */
-static void update_hostent(aHostent* hp, char** addr, char** alias)
+static void update_hostent(struct Hostent* hp, char** addr, char** alias)
 {
   char*  p;
   char** ap;
@@ -1356,7 +1378,7 @@ static struct CacheEntry* add_to_cache(struct CacheEntry* ocp)
   ocp->hname_next = hashtable[hashv].name_list;
   hashtable[hashv].name_list = ocp;
 
-  hashv = hash_number(ocp->he.h.h_addr);
+  hashv = hash_number((const unsigned char*) ocp->he.h.h_addr);
 
   ocp->hnum_next = hashtable[hashv].num_list;
   hashtable[hashv].num_list = ocp;
@@ -1501,7 +1523,7 @@ static struct CacheEntry* find_cache_number(struct ResRequest* request,
   int     i;
 
   assert(0 != addr);
-  hashv = hash_number(addr);
+  hashv = hash_number((const unsigned char*) addr);
   cp = hashtable[hashv].num_list;
 
   for (; cp; cp = cp->hnum_next) {
@@ -1520,7 +1542,7 @@ static struct CacheEntry* find_cache_number(struct ResRequest* request,
      * are looking for, its been done already.
      */
     if (!cp->he.h.h_addr_list[1] || 
-        hashv == hash_number(cp->he.h.h_addr_list[0]))
+        hashv == hash_number((const unsigned char*) cp->he.h.h_addr_list[0]))
       continue;
     for (i = 1; cp->he.h.h_addr_list[i]; ++i) {
       if (!memcmp(cp->he.h.h_addr_list[i], addr, sizeof(struct in_addr))) {
@@ -1625,7 +1647,7 @@ static void rem_cache(struct CacheEntry* ocp)
   /*
    * remove cache entry from hashed number list
    */
-  hashv = hash_number(hp->h_addr);
+  hashv = hash_number((const unsigned char*) hp->h_addr);
   assert(-1 < hashv);
 
   for (cp = &hashtable[hashv].num_list; *cp; cp = &((*cp)->hnum_next)) {
@@ -1664,35 +1686,35 @@ int m_dns(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
   if (parv[1] && *parv[1] == 'l') {
     for(cp = cacheTop; cp; cp = cp->list_next) {
       hp = &cp->he.h;
-      sendto_one(sptr, "NOTICE %s :Ex %d ttl %d host %s(%s)",
-                 parv[0], cp->expireat - CurrentTime, cp->ttl,
-                 hp->h_name, ircd_ntoa(hp->h_addr));
+      sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :Ex %d ttl %d host %s(%s)",
+                   sptr, cp->expireat - CurrentTime, cp->ttl,
+                   hp->h_name, ircd_ntoa(hp->h_addr));
       for (i = 0; hp->h_aliases[i]; i++)
-        sendto_one(sptr,"NOTICE %s : %s = %s (CN)",
-                   parv[0], hp->h_name, hp->h_aliases[i]);
+        sendcmdto_one(&me, CMD_NOTICE, sptr, "%C : %s = %s (CN)", sptr,
+                     hp->h_name, hp->h_aliases[i]);
       for (i = 1; hp->h_addr_list[i]; i++)
-        sendto_one(sptr,"NOTICE %s : %s = %s (IP)",
-                   parv[0], hp->h_name, ircd_ntoa(hp->h_addr_list[i]));
+        sendcmdto_one(&me, CMD_NOTICE, sptr, "%C : %s = %s (IP)", sptr,
+                     hp->h_name, ircd_ntoa(hp->h_addr_list[i]));
     }
     return 0;
   }
   if (parv[1] && *parv[1] == 'd') {
-    sendto_one(sptr, "NOTICE %s :ResolverFileDescriptor = %d", 
-               parv[0], ResolverFileDescriptor);
+    sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :ResolverFileDescriptor = %d", 
+                 sptr, ResolverFileDescriptor);
     return 0;
   }
-  sendto_one(sptr,"NOTICE %s :Ca %d Cd %d Ce %d Cl %d Ch %d:%d Cu %d",
-             sptr->name,
-             cainfo.ca_adds, cainfo.ca_dels, cainfo.ca_expires,
-             cainfo.ca_lookups, cainfo.ca_na_hits, cainfo.ca_nu_hits, 
-             cainfo.ca_updates);
+  sendcmdto_one(&me, CMD_NOTICE, sptr,"%C :Ca %d Cd %d Ce %d Cl %d Ch %d:%d "
+               "Cu %d", sptr,
+               cainfo.ca_adds, cainfo.ca_dels, cainfo.ca_expires,
+               cainfo.ca_lookups, cainfo.ca_na_hits, cainfo.ca_nu_hits, 
+               cainfo.ca_updates);
   
-  sendto_one(sptr,"NOTICE %s :Re %d Rl %d/%d Rp %d Rq %d",
-             sptr->name, reinfo.re_errors, reinfo.re_nu_look,
-             reinfo.re_na_look, reinfo.re_replies, reinfo.re_requests);
-  sendto_one(sptr,"NOTICE %s :Ru %d Rsh %d Rs %d(%d) Rt %d", sptr->name,
-             reinfo.re_unkrep, reinfo.re_shortttl, reinfo.re_sent,
-             reinfo.re_resends, reinfo.re_timeouts);
+  sendcmdto_one(&me, CMD_NOTICE, sptr,"%C :Re %d Rl %d/%d Rp %d Rq %d",
+               sptr, reinfo.re_errors, reinfo.re_nu_look,
+               reinfo.re_na_look, reinfo.re_replies, reinfo.re_requests);
+  sendcmdto_one(&me, CMD_NOTICE, sptr,"%C :Ru %d Rsh %d Rs %d(%d) Rt %d", sptr,
+               reinfo.re_unkrep, reinfo.re_shortttl, reinfo.re_sent,
+               reinfo.re_resends, reinfo.re_timeouts);
 #endif
   return 0;
 }
@@ -1719,15 +1741,16 @@ size_t cres_mem(struct Client* sptr)
       request_mem += MAXGETHOSTLEN + 1;
     ++request_count;
   }
+
   if (cachedCount != cache_count) {
-    sendto_one(sptr, 
-               ":%s %d %s :Resolver: cache count mismatch: %d != %d",
-               me.name, RPL_STATSDEBUG, sptr->name, cachedCount, cache_count);
+    send_reply(sptr, SND_EXPLICIT | RPL_STATSDEBUG,
+              ":Resolver: cache count mismatch: %d != %d", cachedCount,
+              cache_count);
     assert(cachedCount == cache_count);
   }
-  sendto_one(sptr, ":%s %d %s :Resolver: cache %d(%d) requests %d(%d)",
-             me.name, RPL_STATSDEBUG, sptr->name, cache_count, cache_mem,
-             request_count, request_mem);
+  send_reply(sptr, SND_EXPLICIT | RPL_STATSDEBUG,
+            ":Resolver: cache %d(%d) requests %d(%d)", cache_count,
+            cache_mem, request_count, request_mem);
   return cache_mem + request_mem;
 }