Often times, a misconfigured DNS server will give us an empty DNS packet.
For example, if a web hosting account is suspended for non-payment, the
hosting provider will often times simply remove the zone from their database,
resulting in having the authoritative DNS servers replying to queries with
a blank packet marked "QUERY REFUSED".  

Some broken DNS servers will just give a blank DNS packet as a reply
when an AAAA (IPv6 IP) record is requested (offender here: The DNS
servers for wwwchase.gslb.bankone.com handled by jpmorganchase.com).

This patch updates Deadwood to handle these packets by creating a
synthetic "not there" reply.  In other words, if we get an empty packet,
Deadwood now pretends we actually got a SOA-in-NS-section "not there"
or "NXDOMAIN" packet.

Note that we do not have to verify out is 0 in the code removed from
DwStr.c because dw_put_u16 and dw_addchar both do this.

--- deadwood-2.9.06/src/DwRecurse.c.orig	2010-09-01 10:54:23.000000000 -0700
+++ deadwood-2.9.06/src/DwRecurse.c	2010-09-01 12:42:48.000000000 -0700
@@ -1521,7 +1521,33 @@
         return out;
 }
 
+/* Create a synthetic "not there" reply; this is used for empty replies 
+ * because a lot of broken DNS servers on the internet will give out a
+ * reply with 0 DNS records when they don't have an answer for our query 
+ */
+
+dw_str *dwx_synth_notthere(dw_str *query) {
+	dw_str *hack, *out;
+
+	/*dw_px("Empty reply, making synth nothere\n");*//*DEBUG*/
+	hack = malloc(sizeof(dw_str));
+	if(hack == 0) {
+		return 0;
+	}
+	hack->str = (uint8_t *)make_synth_not_there_answer(0,20,1);
+	hack->len = 40;
+	hack->sane = 114;
+	hack->max = 59;
+	dw_put_u16(hack,0,-1);/*ancount*/
+	dw_put_u16(hack,1,-1);/*nscount*/
+	dw_put_u16(hack,0,-1);/*arcount*/
+	dw_put_u8(hack,TYPE_NOT_THERE,-1);/* type */
+	out = dwc_decompress(query,hack);
+	dw_destroy(hack);
 
+	return out; 
+}
+	
 /* Look at a DNS reply and determine how to proceed
  *
  * Input: The reply we got ("in"), and the query we sent ("query")
@@ -1534,10 +1560,14 @@
         dw_str *out = 0;
         int type = 0;
 
+	if(in->len == 7) { /* Blank packet */
+		return dwx_synth_notthere(query);
+	}
+
         view = dwx_create_dns_details(in,query);
 
         if(view == 0 ||
-           dwx_check_answer_section(in,query,view) == -1 ||
+	   dwx_check_answer_section(in,query,view) == -1 ||
            dwx_if_an_then_no_ns_nor_ar(view) == -1 ||
            dwx_cleanup_ns_ar(view) == -1) {
                 goto catch_dwx_dissect_packet;
--- deadwood-2.9.06/src/DwSocket.h.orig	2010-09-01 12:42:00.000000000 -0700
+++ deadwood-2.9.06/src/DwSocket.h	2010-09-01 12:44:13.000000000 -0700
@@ -377,4 +377,8 @@
 int inet_pton(int z, char *c, uint8_t *ip);
 #endif /* NO_INET_PTON */
 
+/* Make the actual answer for a synthetic "not there" reply */
+unsigned char *make_synth_not_there_answer(unsigned char *a, int count,
+                int type);
+
 #endif /* __DW_SOCKET_DEFINED__ */
--- deadwood-2.9.06/src/DwUdpSocket.c.orig	2010-09-01 11:08:10.000000000 -0700
+++ deadwood-2.9.06/src/DwUdpSocket.c	2010-09-01 12:30:04.000000000 -0700
@@ -769,7 +769,9 @@
                 }
 
                 ttl = dw_get_a_dnsttl(answer,0,31536000,ancount);
-
+		if(ttl == -1 && decomp != 0 && decomp->len == 7) {
+			ttl = 30; /* Special case: Blank reply upstream */
+		}
                 if(ttl == -1) {
                         goto catch_cache_dns_reply;
                 }
@@ -830,7 +832,8 @@
 }
 
 /* Make the actual answer for a synthetic "not there" reply */
-unsigned char *make_synth_not_there_answer(unsigned char *a, int count) {
+unsigned char *make_synth_not_there_answer(unsigned char *a, int count,
+		int type) {
         /* This is the answer for a "not there" reply */
         unsigned char not_there[41] =
         "\xc0\x0c" /* Name */
@@ -845,6 +848,17 @@
         int counter = 0;
 
         answer = malloc(count + 43);
+	if(answer == 0) {
+		return 0;
+	}
+
+	if(type == 1) { /* Special case: Return just synth "not there" */
+		for(counter = 0; counter < 40; counter++) {
+			answer[counter] = not_there[counter];	
+		}
+		return answer;
+	}
+
         /* Copy the header they sent us to our reply */
         for(counter = 0; counter < 12 && counter < count; counter++) {
                 answer[counter] = a[counter];
@@ -889,7 +903,7 @@
         }
 
         /* Copy original header and question in to answer */
-        answer = make_synth_not_there_answer(a,count);
+        answer = make_synth_not_there_answer(a,count,0);
         if(answer == 0) {
                 return;
         }
--- deadwood-2.9.06/src/DwStr.c.orig	2010-09-01 12:57:03.000000000 -0700
+++ deadwood-2.9.06/src/DwStr.c	2010-09-01 12:59:30.000000000 -0700
@@ -1047,12 +1047,6 @@
         }
         offset += 4;
         out = dw_substr(hack,offset,-1,7);
-        if(out == 0 || out->len == 0) {
-#ifndef STANDALONE
-                dw_log_string("Warning: Empty packet!",10);
-#endif /* STANDALONE */
-                goto catch_dw_packet_to_cache;
-        }
         dw_put_u16(out,ancount,-1);
         dw_put_u16(out,nscount,-1);
         dw_put_u16(out,arcount,-1);
