]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
- testbound understands Deckard MATCH rcode question answer commands.
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Mon, 13 Mar 2017 08:15:07 +0000 (08:15 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Mon, 13 Mar 2017 08:15:07 +0000 (08:15 +0000)
git-svn-id: file:///svn/unbound/trunk@4048 be551aaa-1e26-0410-a405-d3ace91eadb9

doc/Changelog
testcode/testpkts.c
testcode/testpkts.h

index ea6d80f1bc8a672a7a92bd18f6eb642f67e03eba..96a3021a24ec37d12328d0908f7a6e66c62c29e5 100644 (file)
@@ -1,3 +1,6 @@
+13 March 2017: Wouter
+       - testbound understands Deckard MATCH rcode question answer commands.
+
 10 March 2017: Wouter
        - Fix #1234: shortening DNAME loop produces duplicate DNAME records
          in ANSWER section.
index e47184ab2f6ec69376f8b3736bd07821d91a4b85..5e180834062f0bbcc0be6c461057e713fe741d6c 100644 (file)
@@ -118,6 +118,12 @@ static void matchline(char* line, struct entry* e)
                        e->match_qtype = 1;
                } else if(str_keyword(&parse, "qname")) {
                        e->match_qname = 1;
+               } else if(str_keyword(&parse, "rcode")) {
+                       e->match_rcode = 1;
+               } else if(str_keyword(&parse, "question")) {
+                       e->match_question = 1;
+               } else if(str_keyword(&parse, "answer")) {
+                       e->match_answer = 1;
                } else if(str_keyword(&parse, "subdomain")) {
                        e->match_subdomain = 1;
                } else if(str_keyword(&parse, "all")) {
@@ -247,6 +253,9 @@ static struct entry* new_entry(void)
        e->match_opcode = 0;
        e->match_qtype = 0;
        e->match_qname = 0;
+       e->match_rcode = 0;
+       e->match_question = 0;
+       e->match_answer = 0;
        e->match_subdomain = 0;
        e->match_all = 0;
        e->match_ttl = 0;
@@ -691,6 +700,14 @@ static int get_opcode(uint8_t* pkt, size_t pktlen)
        return (int)LDNS_OPCODE_WIRE(pkt);
 }
 
+/** returns rcode from packet */
+static int get_rcode(uint8_t* pkt, size_t pktlen)
+{
+       if(pktlen < LDNS_HEADER_SIZE)
+               return 0;
+       return (int)LDNS_RCODE_WIRE(pkt);
+}
+
 /** get authority section SOA serial value */
 static uint32_t get_serial(uint8_t* p, size_t plen)
 {
@@ -1086,6 +1103,138 @@ static void lowercase_pkt(uint8_t* pkt, size_t pktlen)
        }
 }
 
+/** match question section of packet */
+static int
+match_question(uint8_t* q, size_t qlen, uint8_t* p, size_t plen, int mttl)
+{
+       char* qstr, *pstr, *s, *qcmpstr, *pcmpstr;
+       uint8_t* qb = q, *pb = p;
+       int r;
+       /* zero TTLs */
+       qb = memdup(q, qlen);
+       pb = memdup(p, plen);
+       if(!qb || !pb) error("out of memory");
+       if(!mttl) {
+               zerottls(qb, qlen);
+               zerottls(pb, plen);
+       }
+       lowercase_pkt(qb, qlen);
+       lowercase_pkt(pb, plen);
+       qstr = sldns_wire2str_pkt(qb, qlen);
+       pstr = sldns_wire2str_pkt(pb, plen);
+       if(!qstr || !pstr) error("cannot pkt2string");
+
+       /* remove before ;; QUESTION */
+       s = strstr(qstr, ";; QUESTION SECTION");
+       qcmpstr = s;
+       s = strstr(pstr, ";; QUESTION SECTION");
+       pcmpstr = s;
+       if(!qcmpstr && !pcmpstr) {
+               free(qstr);
+               free(pstr);
+               free(qb);
+               free(pb);
+               return 1;
+       }
+       if(!qcmpstr || !pcmpstr) {
+               free(qstr);
+               free(pstr);
+               free(qb);
+               free(pb);
+               return 0;
+       }
+       
+       /* remove after answer section, (;; AUTH, ;; ADD, ;; MSG size ..) */
+       s = strstr(qcmpstr, ";; ANSWER SECTION");
+       if(!s) s = strstr(qcmpstr, ";; AUTHORITY SECTION");
+       if(!s) s = strstr(qcmpstr, ";; ADDITIONAL SECTION");
+       if(!s) s = strstr(qcmpstr, ";; MSG SIZE");
+       if(s) s = 0;
+       s = strstr(pcmpstr, ";; ANSWER SECTION");
+       if(!s) s = strstr(pcmpstr, ";; AUTHORITY SECTION");
+       if(!s) s = strstr(pcmpstr, ";; ADDITIONAL SECTION");
+       if(!s) s = strstr(pcmpstr, ";; MSG SIZE");
+       if(s) s = 0;
+
+       r = (strcmp(qcmpstr, pcmpstr) == 0);
+
+       if(!r) {
+               verbose(3, "mismatch question section '%s' and '%s'",
+                       qcmpstr, pcmpstr);
+       }
+
+       free(qstr);
+       free(pstr);
+       free(qb);
+       free(pb);
+       return r;
+}
+
+/** match answer section of packet */
+static int
+match_answer(uint8_t* q, size_t qlen, uint8_t* p, size_t plen, int mttl)
+{
+       char* qstr, *pstr, *s, *qcmpstr, *pcmpstr;
+       uint8_t* qb = q, *pb = p;
+       int r;
+       /* zero TTLs */
+       qb = memdup(q, qlen);
+       pb = memdup(p, plen);
+       if(!qb || !pb) error("out of memory");
+       if(!mttl) {
+               zerottls(qb, qlen);
+               zerottls(pb, plen);
+       }
+       lowercase_pkt(qb, qlen);
+       lowercase_pkt(pb, plen);
+       qstr = sldns_wire2str_pkt(qb, qlen);
+       pstr = sldns_wire2str_pkt(pb, plen);
+       if(!qstr || !pstr) error("cannot pkt2string");
+
+       /* remove before ;; ANSWER */
+       s = strstr(qstr, ";; ANSWER SECTION");
+       qcmpstr = s;
+       s = strstr(pstr, ";; ANSWER SECTION");
+       pcmpstr = s;
+       if(!qcmpstr && !pcmpstr) {
+               free(qstr);
+               free(pstr);
+               free(qb);
+               free(pb);
+               return 1;
+       }
+       if(!qcmpstr || !pcmpstr) {
+               free(qstr);
+               free(pstr);
+               free(qb);
+               free(pb);
+               return 0;
+       }
+       
+       /* remove after answer section, (;; AUTH, ;; ADD, ;; MSG size ..) */
+       s = strstr(qcmpstr, ";; AUTHORITY SECTION");
+       if(!s) s = strstr(qcmpstr, ";; ADDITIONAL SECTION");
+       if(!s) s = strstr(qcmpstr, ";; MSG SIZE");
+       if(s) s = 0;
+       s = strstr(pcmpstr, ";; AUTHORITY SECTION");
+       if(!s) s = strstr(pcmpstr, ";; ADDITIONAL SECTION");
+       if(!s) s = strstr(pcmpstr, ";; MSG SIZE");
+       if(s) s = 0;
+
+       r = (strcmp(qcmpstr, pcmpstr) == 0);
+
+       if(!r) {
+               verbose(3, "mismatch answer section '%s' and '%s'",
+                       qcmpstr, pcmpstr);
+       }
+
+       free(qstr);
+       free(pstr);
+       free(qb);
+       free(pb);
+       return r;
+}
+
 /** match all of the packet */
 int
 match_all(uint8_t* q, size_t qlen, uint8_t* p, size_t plen, int mttl,
@@ -1217,6 +1366,31 @@ find_match(struct entry* entries, uint8_t* query_pkt, size_t len,
                                continue;
                        }
                }
+               if(p->match_rcode) {
+                       if(get_rcode(query_pkt, len) != get_rcode(reply, rlen)) {
+                               char *r1 = sldns_wire2str_rcode(get_rcode(query_pkt, len));
+                               char *r2 = sldns_wire2str_rcode(get_rcode(reply, rlen));
+                               verbose(3, "bad rcode %s instead of %s\n",
+                                       r1, r2);
+                               free(r1);
+                               free(r2);
+                               continue;
+                       }
+               }
+               if(p->match_question) {
+                       if(!match_question(query_pkt, len, reply, rlen,
+                               (int)p->match_ttl)) {
+                               verbose(3, "bad question section\n");
+                               continue;
+                       }
+               }
+               if(p->match_answer) {
+                       if(!match_answer(query_pkt, len, reply, rlen,
+                               (int)p->match_ttl)) {
+                               verbose(3, "bad answer section\n");
+                               continue;
+                       }
+               }
                if(p->match_subdomain) {
                        if(!subdomain_dname(query_pkt, len, reply, rlen)) {
                                verbose(3, "bad subdomain\n");
index 5c000546fed679def80692302a4bc6ee1b3269f4..d045d366d69e8f488fd43dbcd9737e6f4f526308 100644 (file)
@@ -50,6 +50,9 @@ struct sldns_file_parse_state;
        ; 'ttl' used with all, rrs in packet must also have matching TTLs.
        ; 'DO' will match only queries with DO bit set.
        ; 'noedns' matches queries without EDNS OPT records.
+       ; 'rcode' makes the query match the rcode from the reply
+       ; 'question' makes the query match the question section
+       ; 'answer' makes the query match the answer section
        MATCH [opcode] [qtype] [qname] [serial=<value>] [all] [ttl]
        MATCH [UDP|TCP] DO
        MATCH ...
@@ -161,6 +164,12 @@ struct entry {
        uint8_t match_qtype;  
        /** match qname with answer qname */
        uint8_t match_qname;  
+       /** match rcode with answer rcode */
+       uint8_t match_rcode;
+       /** match question section */
+       uint8_t match_question;
+       /** match answer section */
+       uint8_t match_answer;
        /** match qname as subdomain of answer qname */
        uint8_t match_subdomain;  
        /** match SOA serial number, from auth section */