e->match_qname = true;
} else if(str_keyword(&parse, "all")) {
e->match_all = true;
+ } else if(str_keyword(&parse, "ttl")) {
+ e->match_ttl = true;
} else if(str_keyword(&parse, "UDP")) {
e->match_transport = transport_udp;
} else if(str_keyword(&parse, "TCP")) {
e->match_qtype = false;
e->match_qname = false;
e->match_all = false;
+ e->match_ttl = false;
e->match_serial = false;
e->ixfr_soa_serial = 0;
e->match_transport = transport_any;
/** match two rr lists */
static int
-match_list(ldns_rr_list* q, ldns_rr_list *p)
+match_list(ldns_rr_list* q, ldns_rr_list *p, bool mttl)
{
size_t i;
if(ldns_rr_list_rr_count(q) != ldns_rr_list_rr_count(p))
verbose(3, "rr %d different", i);
return 0;
}
+ if(mttl && ldns_rr_ttl(ldns_rr_list_rr(q, i)) !=
+ ldns_rr_ttl(ldns_rr_list_rr(p, i))) {
+ verbose(3, "rr %d ttl different", i);
+ return 0;
+ }
}
return 1;
}
/** match all of the packet */
static int
-match_all(ldns_pkt* q, ldns_pkt* p)
+match_all(ldns_pkt* q, ldns_pkt* p, bool mttl)
{
if(ldns_pkt_get_opcode(q) != ldns_pkt_get_opcode(p))
{ verbose(3, "allmatch: opcode different"); return 0;}
{ verbose(3, "allmatch: nscount different"); return 0;}
if(ldns_pkt_arcount(q) != ldns_pkt_arcount(p))
{ verbose(3, "allmatch: arcount different"); return 0;}
- if(!match_list(ldns_pkt_question(q), ldns_pkt_question(p)))
+ if(!match_list(ldns_pkt_question(q), ldns_pkt_question(p), mttl))
{ verbose(3, "allmatch: qd section different"); return 0;}
- if(!match_list(ldns_pkt_answer(q), ldns_pkt_answer(p)))
+ if(!match_list(ldns_pkt_answer(q), ldns_pkt_answer(p), mttl))
{ verbose(3, "allmatch: an section different"); return 0;}
- if(!match_list(ldns_pkt_authority(q), ldns_pkt_authority(p)))
+ if(!match_list(ldns_pkt_authority(q), ldns_pkt_authority(p), mttl))
{ verbose(3, "allmatch: ar section different"); return 0;}
- if(!match_list(ldns_pkt_additional(q), ldns_pkt_additional(p)))
+ if(!match_list(ldns_pkt_additional(q), ldns_pkt_additional(p), mttl))
{ verbose(3, "allmatch: ns section different"); return 0;}
return 1;
}
verbose(3, "bad transport\n");
continue;
}
- if(p->match_all && !match_all(query_pkt, reply)) {
+ if(p->match_all && !match_all(query_pkt, reply, p->match_ttl)) {
verbose(3, "bad allmatch\n");
continue;
}
; 'qname' makes the query match the qname from the reply
; 'serial=1023' makes the query match if ixfr serial is 1023.
; 'all' has to match header byte for byte and all rrs in packet.
- MATCH [opcode] [qtype] [qname] [serial=<value>] [all]
+ ; 'ttl' used with all, rrs in packet must also have matching TTLs.
+ MATCH [opcode] [qtype] [qname] [serial=<value>] [all] [ttl]
MATCH [UDP|TCP]
MATCH ...
; Then the REPLY header is specified.
bool match_serial;
/** match all of the packet */
bool match_all;
+ /** match ttls in the packet */
+ bool match_ttl;
/** match query serial with this value. */
uint32_t ixfr_soa_serial;
/** match on UDP/TCP */
--- /dev/null
+; This is a comment.
+; config options go here.
+CONFIG_END
+
+SCENARIO_BEGIN RRset TTL is updated from message.
+
+STEP 1 QUERY
+ENTRY_BEGIN
+ REPLY RD
+ SECTION QUESTION
+ www.example.com. IN A
+ENTRY_END
+; the query is sent to the forwarder - no cache yet.
+STEP 2 CHECK_OUT_QUERY
+ENTRY_BEGIN
+ MATCH qname qtype opcode
+ SECTION QUESTION
+ www.example.com. IN A
+ENTRY_END
+STEP 3 REPLY
+ENTRY_BEGIN
+ MATCH opcode qtype qname
+ ADJUST copy_id
+ ; authoritative answer
+ REPLY QR AA RD RA NOERROR
+ SECTION QUESTION
+ www.example.com. IN A
+ SECTION ANSWER
+ www.example.com. IN A 10.20.30.40
+ SECTION AUTHORITY
+ example.com. 100 IN NS ns.example.com.
+ SECTION ADDITIONAL
+ ns.example.com. IN A 10.20.30.50
+ENTRY_END
+STEP 4 CHECK_ANSWER
+ENTRY_BEGIN
+ MATCH all ttl
+ ; first reply, have AA set.
+ REPLY QR AA RD RA
+ SECTION QUESTION
+ www.example.com. IN A
+ SECTION ANSWER
+ www.example.com. IN A 10.20.30.40
+ SECTION AUTHORITY
+ example.com. 100 IN NS ns.example.com.
+ SECTION ADDITIONAL
+ ns.example.com. IN A 10.20.30.50
+ENTRY_END
+
+; another query passes along
+STEP 6 QUERY
+ENTRY_BEGIN
+ REPLY RD
+ SECTION QUESTION
+ bla.example.com. IN A
+ENTRY_END
+STEP 7 CHECK_OUT_QUERY
+ENTRY_BEGIN
+ MATCH qname qtype opcode
+ SECTION QUESTION
+ bla.example.com. IN A
+ENTRY_END
+STEP 8 REPLY
+; This answer has a fresh TTL
+ENTRY_BEGIN
+ MATCH opcode qtype qname
+ ADJUST copy_id
+ ; authoritative answer
+ REPLY QR AA RD RA NOERROR
+ SECTION QUESTION
+ bla.example.com. IN A
+ SECTION ANSWER
+ bla.example.com. IN A 10.20.30.140
+ SECTION AUTHORITY
+ example.com. 200 IN NS ns.example.com.
+ SECTION ADDITIONAL
+ ns.example.com. IN A 10.20.30.50
+ENTRY_END
+STEP 9 CHECK_ANSWER
+ENTRY_BEGIN
+ MATCH all ttl
+ ; first reply, have AA set.
+ REPLY QR AA RD RA
+ SECTION QUESTION
+ bla.example.com. IN A
+ SECTION ANSWER
+ bla.example.com. IN A 10.20.30.140
+ SECTION AUTHORITY
+ example.com. 200 IN NS ns.example.com.
+ SECTION ADDITIONAL
+ ns.example.com. IN A 10.20.30.50
+ENTRY_END
+
+
+; original www.example.com query
+STEP 10 QUERY
+ENTRY_BEGIN
+ REPLY RD
+ SECTION QUESTION
+ www.example.com. IN A
+ENTRY_END
+; immediate answer without an OUT_QUERY happening (checked on exit)
+; also, the answer does not have AA set
+; NS rrset has been updated.
+STEP 11 CHECK_ANSWER
+ENTRY_BEGIN
+ MATCH all ttl
+ REPLY QR RD RA
+ SECTION QUESTION
+ www.example.com. IN A
+ SECTION ANSWER
+ www.example.com. IN A 10.20.30.40
+ SECTION AUTHORITY
+ example.com. 200 IN NS ns.example.com.
+ SECTION ADDITIONAL
+ ns.example.com. IN A 10.20.30.50
+ENTRY_END
+
+SCENARIO_END