1
diff -ur deadwood-2.9.02/src/DwRecurse.h deadwood-2.9.03/src/DwRecurse.h
2
--- deadwood-2.9.02/src/DwRecurse.h 2010-07-29 10:39:10.000000000 -0700
3
+++ deadwood-2.9.03/src/DwRecurse.h 2010-08-02 08:49:55.000000000 -0700
6
#define TYPE_NXDOMAIN 1
7
#define TYPE_NOT_THERE 2 /* Non-NXDOMAIN negative reply */
8
+#define TYPE_TRUNCATED 3 /* Non-NXDOMAIN truncated reply */
9
+#define TYPE_TRUNCATED_NXDOMAIN 4 /* NXDOMAIN truncated reply */
10
#define TYPE_NS_REFER 16 /* NS referral */
11
#define TYPE_CNAME_REFER 17 /* CNAME referral */
12
#define TYPE_SERVER_TIMEOUT 18
13
#define TYPE_NO_USEFUL_DATA 19
15
-#define TYPE_TRUNCATED 21
16
#define TYPE_UPSTREAM_REFER 22 /* Upstream server; set RD and stop here */
17
/* These won't be used by Deadwood, but may be useful if I ever
18
* expand DwHash to support for datatypes for elements besides
19
diff -ur deadwood-2.9.02/src/DwStr.c deadwood-2.9.03/src/DwStr.c
20
--- deadwood-2.9.02/src/DwStr.c 2010-07-29 10:39:10.000000000 -0700
21
+++ deadwood-2.9.03/src/DwStr.c 2010-08-02 09:16:06.000000000 -0700
24
* Should this function succeed, it will return a 0. Otherwise, it
27
+ * BUG: Does not work correctly with length-1 (1-byte) strings
30
int dw_put_u8(dw_str *obj, uint8_t value, int32_t offset) {
31
diff -ur deadwood-2.9.02/src/DwUdpSocket.c deadwood-2.9.03/src/DwUdpSocket.c
32
--- deadwood-2.9.02/src/DwUdpSocket.c 2010-07-29 10:39:09.000000000 -0700
33
+++ deadwood-2.9.03/src/DwUdpSocket.c 2010-08-02 10:32:13.000000000 -0700
37
is_nxdomain = dw_pop_u8(answer);
38
- arcount = dw_pop_u16(answer);
39
- nscount = dw_pop_u16(answer);
40
- ancount = dw_pop_u16(answer);
41
+ if(is_nxdomain != TYPE_TRUNCATED &&
42
+ is_nxdomain != TYPE_TRUNCATED_NXDOMAIN) {
43
+ arcount = dw_pop_u16(answer);
44
+ nscount = dw_pop_u16(answer);
45
+ ancount = dw_pop_u16(answer);
48
if(is_nxdomain == 0 || is_nxdomain == 2) {
49
/* 0x8180: QR = 1; Opcode = 0; AA = 0; TC = 0; RD = 1; RA = 1;
51
} else if(is_nxdomain == 1) {
52
/* Same header as before, but with RCODE of "name error" */
53
out = make_dns_header(id,0x8183,ancount,nscount,arcount);
54
+ } else if(is_nxdomain == TYPE_TRUNCATED) {
56
+ out = make_dns_header(id,0x8380,0,0,0);
57
+ } else if(is_nxdomain == TYPE_TRUNCATED_NXDOMAIN) {
58
+ /* TC 1; RCODE "name error" */
59
+ out = make_dns_header(id,0x8383,0,0,0);
61
goto catch_make_dns_packet;
64
if(dw_append(question,out) == -1 ||
65
- dw_put_u16(out,1,-1) == -1 || /* QCLASS: 1 */
66
- dw_append(answer,out) == -1) {
67
+ dw_put_u16(out,1,-1) == -1 /* QCLASS: 1 */ ) {
68
goto catch_make_dns_packet;
71
+ if(is_nxdomain != TYPE_TRUNCATED &&
72
+ is_nxdomain != TYPE_TRUNCATED_NXDOMAIN &&
73
+ dw_append(answer,out) == -1) {
74
+ goto catch_make_dns_packet;
79
catch_make_dns_packet:
81
dw_str *comp = 0; /* Compressed DNS packet */
83
socklen_t c_len = sizeof(struct sockaddr_in);
84
- int ret = -1, type = 0;
85
+ int ret = -1, type = 0, cache_type = 0;
88
if (client->Family == AF_INET6) {
90
dwc_process(cache,query,3); /* RR rotation, TTL aging, etc. */
92
value = dwh_get(cache,query,resurrect,1);
93
- comp = dwc_compress(query,value);
94
+ cache_type = dw_fetch_u8(value,-1);
95
+ if(cache_type != TYPE_TRUNCATED &&
96
+ cache_type != TYPE_TRUNCATED_NXDOMAIN) {
97
+ comp = dwc_compress(query,value);
99
+ /* Immediately zap truncated from cache when fetched */
100
+ dwh_zap(cache,query,0,1);
101
+ if(client == 0) { /* DNS-over-TCP */
103
+ goto catch_get_reply_from_cache;
105
+ comp = dw_copy(value);
109
- goto catch_get_reply_from_cache;
110
+ goto catch_get_reply_from_cache;
113
if(comp->len == 7) { /* Empty packet; workaround */
116
/* Add a reply we have received from the remote (upstream) DNS server to
118
-int cache_dns_reply(unsigned char *packet, int count, int b) {
119
+int cache_dns_reply(unsigned char *packet, int count, int b, int truncated) {
123
@@ -683,35 +709,46 @@
124
if((packet[3] & 0x0f) == 3) {
127
- answer = dw_packet_to_cache(packet,count,is_nxdomain);
128
- decomp = dwc_decompress(question,answer);
129
- if(dwc_has_bad_ip(decomp,blacklist_dict) ||
130
- (qtype == 28 /* AAAA */ && key_n[DWM_N_reject_aaaa] == 1)) {
131
- ret = -2; /* Tell caller we need synth "not there" */
132
- goto catch_cache_dns_reply;
134
- ancount = dw_cachepacket_to_ancount(answer);
136
- ancount = 32; /* So we can correctly cache negative answers */
139
- if(question == 0 || answer == 0 || ancount == -1) {
140
- goto catch_cache_dns_reply;
143
- ttl = dw_get_a_dnsttl(answer,0,31536000,ancount);
146
- goto catch_cache_dns_reply;
152
- /* Have routines in DwRecurse.c process the packet and let us know
153
- * what kind of packet we got upstream (so we know how to continue)
155
- ret = dwx_cache_reply(cache,question,decomp,ttl,b);
156
+ if(truncated == 1) {
158
+ answer = dw_create(2);
159
+ if(dw_put_u8(answer, is_nxdomain, 0) == -1) {
160
+ goto catch_cache_dns_reply;
162
+ dwh_add(cache,question,answer,7,1);
165
+ answer = dw_packet_to_cache(packet,count,is_nxdomain);
166
+ decomp = dwc_decompress(question,answer);
167
+ if(dwc_has_bad_ip(decomp,blacklist_dict) ||
168
+ (qtype == 28 /* AAAA */ && key_n[DWM_N_reject_aaaa] == 1)) {
169
+ ret = -2; /* Tell caller we need synth "not there" */
170
+ goto catch_cache_dns_reply;
172
+ ancount = dw_cachepacket_to_ancount(answer);
174
+ ancount = 32; /* Correct negative answer caching */
177
+ if(question == 0 || answer == 0 || ancount == -1) {
178
+ goto catch_cache_dns_reply;
181
+ ttl = dw_get_a_dnsttl(answer,0,31536000,ancount);
184
+ goto catch_cache_dns_reply;
190
+ /* Routines in DwRecurse.c process the packet and let us know
191
+ * what kind of packet we got upstream (so we know how to
194
+ ret = dwx_cache_reply(cache,question,decomp,ttl,b);
197
catch_cache_dns_reply:
200
if (rem[b].local[l]->glueless_type != 0) {
201
conn_num = rem[b].local[l]->glueless_conn;
202
if(rem[b].local[l]->glueless_type == 1) { /* Glueless NS */
203
- if(rem[conn_num].child_id == b) {
204
+ if(rem[conn_num].child_id == b) { /* Sanity check */
205
dwx_glueless_done(query, conn_num);
207
ret = 4; /* Yes, we want to end the connection */
210
if((a[2] & 0x02) == 0x00) { /* If not truncated */
212
- cache_dns_reply_return_value = cache_dns_reply(a,count,b);
213
+ cache_dns_reply_return_value = cache_dns_reply(a,count,b,0);
214
if(cache_dns_reply_return_value == -2) { /* Make synth NX */
215
make_synth_not_there(b,sock,a,count);
216
return -1; /* Bad reply and they got a Synth NX */
218
* we can fully process the TCP connection */
219
rem[b].die = get_time() + ((int64_t)timeout_seconds << 10);
220
return 2; /* Don't kill pending UDP connection */
222
+ } else { /* Truncated over UDP; just given them a blank "truncated"
224
+ cache_dns_reply(a,count,b,1);
227
/* Now make sure the ID is the same as the one the client
228
* originally sent us */
229
--- deadwood-2.9.02/doc/Deadwood.ej 2010-07-29 10:39:09.000000000 -0700
230
+++ deadwood-2.9.03/doc/Deadwood.ej 2010-08-02 10:39:59.000000000 -0700
231
@@ -567,11 +567,12 @@
234
DNS-over-TCP needs to be explicitly enabled. Note that DNS-over-TCP is
238
+almost never used. Also,
239
Deadwood does not cache DNS packets larger than 512 bytes in size that
240
-need to be sent using TCP. Again, DNS-over-TCP is almost never used.
241
+need to be sent using TCP. In addition, DNS-over-TCP packets which
242
+are "incomplete" DNS replies (replies which a stub resolver can not use,
243
+namely either a NS referral or an incomplete CNAME reply) are not
244
+handled correctly by Deadwood. Again, DNS-over-TCP is very rare.
247
Deadwood can not process DNS resource record types with numbers between