--- deadwood-2.9.03/src/DwDnsStr.c	2010-08-06 09:41:59.000000000 -0700
+++ deadwood-2.9.04/src/DwDnsStr.c	2010-08-09 09:42:07.000000000 -0700
@@ -528,4 +528,31 @@
 
 }
 
+/* Convert any upper case letters in a DNS query in to lower case letters;
+ * This modifies the "query" string in place */
+int dwc_lower_case(dw_str *query) {
+	int length = 0, place = 0, counter = 0;
+	uint8_t c;
+
+	if(query == 0 || query->len == 0 || query->str == 0) {
+		return -1;
+	}
+
+	for(counter = 0 ; counter < query->len ; counter++) {
+		if(counter == place) {
+			length = *(query->str + place);
+			if(length == 0) {
+				break;
+			}
+			place += length + 1;
+		} else {
+			c = *(query->str + counter);
+			if(c >= 'A' && c <= 'Z') {
+				*(query->str + counter) += 32; /* Lower case */
+			}
+		}
+	}	
+		
+	return 1;
+}
 
--- deadwood-2.9.03/src/DwDnsStr.h	2010-08-06 09:41:59.000000000 -0700
+++ deadwood-2.9.04/src/DwDnsStr.h	2010-08-09 09:42:07.000000000 -0700
@@ -67,4 +67,8 @@
  * we got an error */
 int dwc_has_bad_ip(dw_str *answer, dwd_dict *blacklist_hash);
 
+/* Convert any upper case letters in a DNS query in to lower case letters;
+ * This modifies the "query" string in place */
+int dwc_lower_case(dw_str *query);
+
 #endif  /* __DWDNSSTR_H_DEFINED__ */
--- deadwood-2.9.04/src/DwUdpSocket.c.orig	2010-08-09 09:42:07.000000000 -0700
+++ deadwood-2.9.04/src/DwUdpSocket.c	2010-08-09 10:12:13.000000000 -0700
@@ -273,6 +273,7 @@
         }
 
         query = dw_get_dname_type(a,12,len);
+	dwc_lower_case(query);
         if(query == 0) {
                 goto catch_find_inflight_query;
         }
@@ -320,6 +321,7 @@
                 return;
         }
         rem[b].query = dw_get_dname_type(a,12,len);
+	dwc_lower_case(rem[b].query);
         rem[b].local = malloc(num_alloc * sizeof(local_T *));
         if(rem[b].local == 0) {
                 return;
@@ -348,7 +350,7 @@
  * to be passed to the function. */
 int forward_local_udp_packet(SOCKET sock, int32_t local_id,
      ip_addr_T *from_ip, uint16_t from_port, unsigned char *a,
-     int len, int tcp_num) {
+     int len, int tcp_num, dw_str *orig_query) {
         int32_t b = 0;
         int num_alloc = 0;
 
@@ -381,6 +383,7 @@
         }
 
         rem[b].local[rem[b].num_locals - 1] = malloc(sizeof(local_T));
+	rem[b].local[rem[b].num_locals - 1]->orig_query = 0;
         if(rem[b].socket == INVALID_SOCKET ||
            rem[b].local[rem[b].num_locals - 1] == 0) {
                 reset_rem(b);
@@ -395,6 +398,7 @@
         rem[b].local[rem[b].num_locals - 1]->local_id = local_id;
         rem[b].local[rem[b].num_locals - 1]->glueless_type = 0;
         rem[b].local[rem[b].num_locals - 1]->glueless_conn = -1;
+        rem[b].local[rem[b].num_locals - 1]->orig_query = dw_copy(orig_query);
         rem[b].die = get_time() + ((int64_t)timeout_seconds << 8);
         return 0;
 }
@@ -500,7 +504,7 @@
  * from the cache */
 int get_reply_from_cache(dw_str *query, sockaddr_all_T *client,
                          SOCKET sock, int32_t id, int resurrect,
-                         int tcp_num) {
+                         int tcp_num, dw_str *orig_query) {
         dw_str *value = 0; /* Element in cache */
         dw_str *comp = 0; /* Compressed DNS packet */
         dw_str *packet = 0;
@@ -544,7 +548,7 @@
         }
 
         dw_log_dwstr_str("Fetching ",query," from cache",100);
-        packet = make_dns_packet(query,comp,id);
+        packet = make_dns_packet(orig_query,comp,id);
         if(packet == 0) {
                 goto catch_get_reply_from_cache;
         }
@@ -576,20 +580,21 @@
    expired element with the data we want. */
 void try_forward_local_udp_packet(SOCKET sock, int32_t local_id,
      ip_addr_T *from_ip, uint16_t from_port, unsigned char *packet,
-     int len, sockaddr_all_T *client,dw_str *query, int tcp_num) {
+     int len, sockaddr_all_T *client,dw_str *query, int tcp_num,
+     dw_str *orig_query) {
 
         /* If not cached, get a reply that we will cache and send back to
          * the client */
         if(forward_local_udp_packet(sock,local_id,from_ip,from_port,
-                                    packet,len,tcp_num) != -1) {
+                                    packet,len,tcp_num,orig_query) != -1) {
                 return; /* Success! */
         }
 
         /* OK, at this point it failed so we'll see if we get a
          * "resurrected" cache entry */
         if(resurrections == 1 &&
-           get_reply_from_cache(query,client,sock,local_id,1,tcp_num)
-             == 1) {
+           get_reply_from_cache(query,client,sock,local_id,1,tcp_num,
+			orig_query) == 1) {
                 dw_log_string("Resurrected from cache",11);
                 return; /* Resurrected entry; we're done */
         }
@@ -608,7 +613,7 @@
         ip_addr_T from_ip = {0,{0,0},0,0};
         uint16_t from_port = 0;
         int32_t local_id = -1;
-        dw_str *query = 0;
+        dw_str *query = 0, *orig_query = 0;
 #ifdef VALGRIND_NOERRORS
         memset(packet,0,522);
 #endif /* VALGRIND_NOERRORS */
@@ -654,24 +659,31 @@
         /* See if we have something in the cache; destroyed at end of
          * function */
         query = dw_get_dname_type(packet,12,len);
+	orig_query = dw_copy(query);
+	dwc_lower_case(query);
         dw_log_dwstr("Got DNS query for ",query,100); /* Log it */
         if(query == 0) {
                 goto catch_get_local_udp_packet;
         }
-        if(get_reply_from_cache(query,&client,sock,local_id,0,-1)
+        if(get_reply_from_cache(query,&client,sock,local_id,0,-1,orig_query)
                 == 1) {
                 goto catch_get_local_udp_packet; /* In cache; we're done */
         }
 
         /* Nothing in cache; lets try sending the packet upstream */
         try_forward_local_udp_packet(sock,local_id,&from_ip,from_port,
-                        packet,len,&client,query,INVALID_SOCKET);
+                        packet,len,&client,query,INVALID_SOCKET,
+			orig_query);
 
 catch_get_local_udp_packet:
         if(query != 0) {
                 dw_destroy(query);
                 query = 0;
         }
+        if(orig_query != 0) {
+                dw_destroy(orig_query);
+                query = 0;
+        }
 }
 
 /* Forward a remote reply back to the client over UDP */
@@ -965,7 +977,8 @@
         }
 
         get_reply_from_cache(query,&client,rem[b].local[l]->from_socket,
-                        rem[b].local[l]->local_id, 0,-1);
+                        rem[b].local[l]->local_id, 0,-1,
+			rem[b].local[l]->orig_query);
 
 catch_send_reply_from_cache:
         if(query != 0) {
--- deadwood-2.9.03/src/DwSocket.c	2010-08-06 09:41:59.000000000 -0700
+++ deadwood-2.9.04/src/DwSocket.c	2010-08-09 09:42:07.000000000 -0700
@@ -707,7 +707,7 @@
         }
 
         if(rem[b].ns == 0) {
-                return addr;
+                return addr; /* Error; returns invalid addr */
         }
 
         return dwx_ns_getip(rem[b].ns,rng_seed,b);
--- deadwood-2.9.03/src/DwRecurse.c	2010-08-06 09:41:59.000000000 -0700
+++ deadwood-2.9.04/src/DwRecurse.c	2010-08-09 10:11:43.000000000 -0700
@@ -2010,6 +2010,7 @@
         offset = dw_fetch_u16(action, -2);
         offset += 2; /* Go past two-byte length */
         real_query = dw_get_dname(action->str, offset, 260);
+	dwc_lower_case(real_query);
         if(real_query == 0) {
                 goto catch_dwx_handle_cname_refer;
         }
@@ -2432,6 +2433,7 @@
 
         /* See if it is in the cache */
         query = dw_get_dname(list->str + 3, offset, 256);
+	dwc_lower_case(query);
         if(query == 0 || dw_push_u16(type,query) == -1) {
                 goto catch_dwx_ns_getip_glueless;
         }
@@ -2695,6 +2697,7 @@
         rem[new_conn_num].die = get_time() + ((int64_t)timeout_seconds << 8);
         rem[new_conn_num].num_locals = 1;
         rem[new_conn_num].local[0] = malloc(sizeof(local_T));
+	rem[new_conn_num].local[0]->orig_query = 0;
         dwx_init_conn_local(new_conn_num,0);
         if(rem[new_conn_num].socket == INVALID_SOCKET ||
            rem[new_conn_num].local[0] == 0) {
--- deadwood-2.9.03/src/DwSocket.h	2010-08-06 09:41:59.000000000 -0700
+++ deadwood-2.9.04/src/DwSocket.h	2010-08-09 09:47:27.000000000 -0700
@@ -146,6 +146,7 @@
         uint16_t port; /* Port local request came from */
         uint8_t glueless_type;
         int glueless_conn; /* Remote connection number needing glueless */
+	dw_str *orig_query; /* Case-preserved form of query */
 } local_T;
 
 /* A pending remote connection */
@@ -259,6 +260,8 @@
                         int qq; \
                         for(qq = 0; qq < rem[a].num_locals; qq++) { \
                                 if(rem[a].local[qq] != 0) { \
+					dw_destroy(rem[a].local[qq]-> \
+						orig_query); \
                                         free(rem[a].local[qq]); \
                                         rem[a].local[qq] = 0; } \
                                 } \
--- deadwood-2.9.03/src/DwTcpSocket.h	2010-08-06 09:41:59.000000000 -0700
+++ deadwood-2.9.04/src/DwTcpSocket.h	2010-08-09 09:53:46.000000000 -0700
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009 Sam Trenholme
+/* Copyright (c) 2009-2010 Sam Trenholme
  *
  * TERMS
  *
@@ -66,21 +66,22 @@
  * from the cache */
 int get_reply_from_cache(dw_str *query, sockaddr_all_T *client,
                          SOCKET sock, int32_t id, int resurrect,
-                         int tcp_num);
+                         int tcp_num, dw_str *orig_query);
 
 /* Given a connection we will send on, try and send the connection on.
    If we're unable to send the connection on, see if we have an
    expired element with the data we want. */
 void try_forward_local_udp_packet(SOCKET sock, int32_t local_id,
      ip_addr_T *from_ip, uint16_t from_port, unsigned char *packet,
-     int len, sockaddr_all_T *client,dw_str *query, int tcp_num);
+     int len, sockaddr_all_T *client,dw_str *query, int tcp_num,
+     dw_str *orig_query);
 
 /* Send a local DNS request to the upstream (remote) server; this
  * requires a few parameters having to do with the connection
  * to be passed to the function */
 int forward_local_udp_packet(SOCKET sock, int32_t local_id,
      ip_addr_T *from_ip, uint16_t from_port, unsigned char *a,
-     int len, int tcp_num);
+     int len, int tcp_num, dw_str *orig_query);
 
 /* Handle all TCP connections with data pending to be sent */
 void tcp_handle_all(int b);
--- deadwood-2.9.03/src/DwTcpSocket.c	2010-08-06 09:41:59.000000000 -0700
+++ deadwood-2.9.04/src/DwTcpSocket.c	2010-08-09 10:14:06.000000000 -0700
@@ -18,6 +18,7 @@
 
 #include "DwSocket.h"
 #include "DwTcpSocket.h"
+#include "DwDnsStr.h"
 #include <signal.h>
 #include <errno.h>
 
@@ -251,7 +252,7 @@
  * the cache or send upstream via UDP */
 void tcp_to_udp(int b) {
         int32_t local_id = -1;
-        dw_str *query = 0;
+        dw_str *query = 0, *orig_query = 0;
 
         local_id = get_dns_qid((void *)tcp_pend[b].buffer, tcp_pend[b].wanted,
                         2);
@@ -269,11 +270,14 @@
                 reset_tcp_pend(b);
                 return;
         }
+	orig_query = dw_copy(query);
+	dwc_lower_case(query);	
 
-        if(get_reply_from_cache(query,0,0,local_id,0,b) != 1) {
+        if(get_reply_from_cache(query,0,0,local_id,0,b,orig_query) != 1) {
                 /* If not cached, make the buffer a UDP connection upstream */
                 forward_local_udp_packet(1,local_id,0,0,
-                        (void *)tcp_pend[b].buffer,tcp_pend[b].wanted,b);
+                        (void *)tcp_pend[b].buffer,tcp_pend[b].wanted,b,
+				orig_query);
                 tcp_pend[b].state = 1; /* Awaiting UDP reply */
 
                 /* "<< 10" instead of "<< 8" because we need more time to
@@ -283,6 +287,7 @@
         }
 
         dw_destroy(query);
+        dw_destroy(orig_query);
 }
 
 /* Called from the "UDP" code, this tells Deadwood to buffer a TCP
