summaryrefslogtreecommitdiff
blob: 9230e7583ddd6e6e273a48f067764711f6b41533 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
diff --git a/query.c b/query.c
index 46cdc00..4574e97 100644
--- a/query.c
+++ b/query.c
@@ -319,6 +319,29 @@ static int doit(struct query *z,int state)
       }
     }
 
+    if (typematch(DNS_T_SOA,dtype)) {
+      byte_copy(key,2,DNS_T_SOA);
+      cached = cache_get(key,dlen + 2,&cachedlen,&ttl);
+      if (cached && (cachedlen || byte_diff(dtype,2,DNS_T_ANY))) {
+        log_cachedanswer(d,DNS_T_SOA);
+        if (!rqa(z)) goto DIE;
+        pos = 0;
+        while (pos = dns_packet_copy(cached,cachedlen,pos,misc,20)) {
+          pos = dns_packet_getname(cached,cachedlen,pos,&t2);
+          if (!pos) break;
+          pos = dns_packet_getname(cached,cachedlen,pos,&t3);
+          if (!pos) break;
+          if (!response_rstart(d,DNS_T_SOA,ttl)) goto DIE;
+          if (!response_addname(t2)) goto DIE;
+          if (!response_addname(t3)) goto DIE;
+          if (!response_addbytes(misc,20)) goto DIE;
+          response_rfinish(RESPONSE_ANSWER);
+        }
+        cleanup(z);
+        return 1;
+      }
+    }
+
     if (typematch(DNS_T_A,dtype)) {
       byte_copy(key,2,DNS_T_A);
       cached = cache_get(key,dlen + 2,&cachedlen,&ttl);
@@ -351,7 +374,7 @@ static int doit(struct query *z,int state)
       }
     }
 
-    if (!typematch(DNS_T_ANY,dtype) && !typematch(DNS_T_AXFR,dtype) && !typematch(DNS_T_CNAME,dtype) && !typematch(DNS_T_NS,dtype) && !typematch(DNS_T_PTR,dtype) && !typematch(DNS_T_A,dtype) && !typematch(DNS_T_MX,dtype)) {
+    if (!typematch(DNS_T_ANY,dtype) && !typematch(DNS_T_AXFR,dtype) && !typematch(DNS_T_CNAME,dtype) && !typematch(DNS_T_NS,dtype) && !typematch(DNS_T_PTR,dtype) && !typematch(DNS_T_A,dtype) && !typematch(DNS_T_MX,dtype) && !typematch(DNS_T_SOA,dtype)) {
       byte_copy(key,2,dtype);
       cached = cache_get(key,dlen + 2,&cachedlen,&ttl);
       if (cached && (cachedlen || byte_diff(dtype,2,DNS_T_ANY))) {
@@ -585,15 +608,24 @@ static int doit(struct query *z,int state)
     else if (byte_equal(type,2,DNS_T_AXFR))
       ;
     else if (byte_equal(type,2,DNS_T_SOA)) {
+      int non_authority = 0;
+      save_start();
       while (i < j) {
         pos = dns_packet_skipname(buf,len,records[i]); if (!pos) goto DIE;
         pos = dns_packet_getname(buf,len,pos + 10,&t2); if (!pos) goto DIE;
         pos = dns_packet_getname(buf,len,pos,&t3); if (!pos) goto DIE;
         pos = dns_packet_copy(buf,len,pos,misc,20); if (!pos) goto DIE;
-        if (records[i] < posauthority)
+        if (records[i] < posauthority) {
           log_rrsoa(whichserver,t1,t2,t3,misc,ttl);
+          save_data(misc,20);
+          save_data(t2,dns_domain_length(t2));
+          save_data(t3,dns_domain_length(t3));
+          non_authority++;
+        }
         ++i;
       }
+      if (non_authority)
+        save_finish(DNS_T_SOA,t1,ttl);
     }
     else if (byte_equal(type,2,DNS_T_CNAME)) {
       pos = dns_packet_skipname(buf,len,records[j - 1]); if (!pos) goto DIE;