]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
- Introduce 'ede=<info-code>' and 'all_noedns' as options in the MATCH line for
authorGeorge Thessalonikefs <george@nlnetlabs.nl>
Wed, 13 Oct 2021 09:59:36 +0000 (11:59 +0200)
committerGeorge Thessalonikefs <george@nlnetlabs.nl>
Wed, 13 Oct 2021 10:01:36 +0000 (12:01 +0200)
  replay test packets.

testcode/testpkts.c
testcode/testpkts.h
testcode/unitmsgparse.c
testdata/autotrust_init_fail.rpl

index dee45176167a993b98019359c036911b443e35e0..4a5cf69ca6117c6ffe8d19a8b39c4d52107d0f31 100644 (file)
@@ -128,6 +128,8 @@ static void matchline(char* line, struct entry* e)
                        e->match_answer = 1;
                } else if(str_keyword(&parse, "subdomain")) {
                        e->match_subdomain = 1;
+               } else if(str_keyword(&parse, "all_noedns")) {
+                       e->match_all_noedns = 1;
                } else if(str_keyword(&parse, "all")) {
                        e->match_all = 1;
                } else if(str_keyword(&parse, "ttl")) {
@@ -148,7 +150,15 @@ static void matchline(char* line, struct entry* e)
                                error("expected = or : in MATCH: %s", line);
                        parse++;
                        e->ixfr_soa_serial = (uint32_t)strtol(parse, (char**)&parse, 10);
-                       while(isspace((unsigned char)*parse)) 
+                       while(isspace((unsigned char)*parse))
+                               parse++;
+               } else if(str_keyword(&parse, "ede")) {
+                       e->match_ede = 1;
+                       if(*parse != '=' && *parse != ':')
+                               error("expected = or : in MATCH: %s", line);
+                       parse++;
+                       e->ede_info_code = (uint16_t)strtol(parse, (char**)&parse, 10);
+                       while(isspace((unsigned char)*parse))
                                parse++;
                } else {
                        error("could not parse MATCH: '%s'", parse);
@@ -266,11 +276,14 @@ static struct entry* new_entry(void)
        e->match_answer = 0;
        e->match_subdomain = 0;
        e->match_all = 0;
+       e->match_all_noedns = 0;
        e->match_ttl = 0;
        e->match_do = 0;
        e->match_noedns = 0;
        e->match_serial = 0;
        e->ixfr_soa_serial = 0;
+       e->match_ede = 0;
+       e->ede_info_code = 0;
        e->match_transport = transport_any;
        e->reply_list = NULL;
        e->copy_id = 0;
@@ -817,7 +830,7 @@ static uint32_t get_serial(uint8_t* p, size_t plen)
        return 0;
 }
 
-/** get ptr to EDNS OPT record (and remaining length); behind the type u16 */
+/** get ptr to EDNS OPT record (and remaining length); after the type u16 */
 static int
 pkt_find_edns_opt(uint8_t** p, size_t* plen)
 {
@@ -884,6 +897,30 @@ get_do_flag(uint8_t* pkt, size_t len)
        return (int)(edns_bits&LDNS_EDNS_MASK_DO_BIT);
 }
 
+/** return the EDNS EDE INFO-CODE if found, else 0 */
+static uint16_t
+get_ede_info_code(uint8_t* pkt, size_t len)
+{
+       uint8_t *rdata;
+       uint16_t rdlen, optlen;
+       /* use arguments as temporary variables */
+       if(!pkt_find_edns_opt(&pkt, &len)) return 0;
+       if(len < 8) return 0; /* malformed */
+       rdlen = sldns_read_uint16(pkt+6);
+       rdata = pkt + 8;
+       while(rdlen > 0) {
+               if(rdlen < 4) return 0; /* malformed */
+               if(sldns_read_uint16(rdata) == LDNS_EDNS_EDE) {
+                       if(rdlen < 6) return 0; /* malformed */
+                       return sldns_read_uint16(rdata+4);
+               }
+               optlen = sldns_read_uint16(rdata+2);
+               rdlen -= optlen;
+               rdata += 4 + optlen;
+       }
+       return 0;
+}
+
 /** zero TTLs in packet */
 static void
 zerottls(uint8_t* pkt, size_t pktlen)
@@ -1201,7 +1238,7 @@ match_question(uint8_t* q, size_t qlen, uint8_t* p, size_t plen, int mttl)
                return 0;
        }
        
-       /* remove after answer section, (;; AUTH, ;; ADD, ;; MSG size ..) */
+       /* remove after answer section, (;; ANS, ;; AUTH, ;; ADD  ..) */
        s = strstr(qcmpstr, ";; ANSWER SECTION");
        if(!s) s = strstr(qcmpstr, ";; AUTHORITY SECTION");
        if(!s) s = strstr(qcmpstr, ";; ADDITIONAL SECTION");
@@ -1292,10 +1329,28 @@ match_answer(uint8_t* q, size_t qlen, uint8_t* p, size_t plen, int mttl)
        return r;
 }
 
+/** ignore EDNS lines in the string by overwriting them with what's left or
+ *  zero out if at end of the string */
+static int
+ignore_edns_lines(char* str) {
+       char* current = str, *edns = str, *n;
+       size_t str_len = strlen(str);
+       while((edns = strstr(edns, "; EDNS"))) {
+               n = strchr(edns, '\n');
+               if(!n) {
+                       /* EDNS at end of string; zero */
+                       *edns = 0;
+                       break;
+               }
+               memmove(edns, n+1, str_len-(n-str));
+       }
+       return 1;
+}
+
 /** match all of the packet */
 int
 match_all(uint8_t* q, size_t qlen, uint8_t* p, size_t plen, int mttl,
-       int noloc)
+       int noloc, int noedns)
 {
        char* qstr, *pstr;
        uint8_t* qb = q, *pb = p;
@@ -1313,6 +1368,11 @@ match_all(uint8_t* q, size_t qlen, uint8_t* p, size_t plen, int mttl,
        qstr = sldns_wire2str_pkt(qb, qlen);
        pstr = sldns_wire2str_pkt(pb, plen);
        if(!qstr || !pstr) error("cannot pkt2string");
+       /* should we ignore EDNS lines? */
+       if(noedns) {
+               ignore_edns_lines(qstr);
+               ignore_edns_lines(pstr);
+       }
        r = (strcmp(qstr, pstr) == 0);
        if(!r) {
                /* remove ;; MSG SIZE (at end of string) */
@@ -1321,8 +1381,8 @@ match_all(uint8_t* q, size_t qlen, uint8_t* p, size_t plen, int mttl,
                s = strstr(pstr, ";; MSG SIZE");
                if(s) *s=0;
                r = (strcmp(qstr, pstr) == 0);
-               if(!r && !noloc) {
-                       /* we are going to fail see if it is because of EDNS */
+               if(!r && !noloc && !noedns) {
+                       /* we are going to fail, see if the cause is EDNS */
                        char* a = strstr(qstr, "; EDNS");
                        char* b = strstr(pstr, "; EDNS");
                        if( (a&&!b) || (b&&!a) ) {
@@ -1434,7 +1494,7 @@ find_match(struct entry* entries, uint8_t* query_pkt, size_t len,
                verbose(3, "comparepkt: ");
                reply = p->reply_list->reply_pkt;
                rlen = p->reply_list->reply_len;
-               if(p->match_opcode && get_opcode(query_pkt, len) != 
+               if(p->match_opcode && get_opcode(query_pkt, len) !=
                        get_opcode(reply, rlen)) {
                        verbose(3, "bad opcode\n");
                        continue;
@@ -1485,6 +1545,10 @@ find_match(struct entry* entries, uint8_t* query_pkt, size_t len,
                                verbose(3, "bad serial\n");
                                continue;
                }
+               if(p->match_ede && get_ede_info_code(query_pkt, len) != p->ede_info_code) {
+                               verbose(3, "bad EDE INFO-CODE\n");
+                               continue;
+               }
                if(p->match_do && !get_do_flag(query_pkt, len)) {
                        verbose(3, "no DO bit set\n");
                        continue;
@@ -1502,8 +1566,13 @@ find_match(struct entry* entries, uint8_t* query_pkt, size_t len,
                        verbose(3, "bad transport\n");
                        continue;
                }
+               if(p->match_all_noedns && !match_all(query_pkt, len, reply,
+                       rlen, (int)p->match_ttl, 0, 1)) {
+                       verbose(3, "bad all_noedns match\n");
+                       continue;
+               }
                if(p->match_all && !match_all(query_pkt, len, reply, rlen,
-                       (int)p->match_ttl, 0)) {
+                       (int)p->match_ttl, 0, 0)) {
                        verbose(3, "bad allmatch\n");
                        continue;
                }
index 6e032fa90a65b4b572a8f7403d3b3ea740b152f9..d9dd043dfd5af84cbcfb9700ac8c80518094a0ad 100644 (file)
@@ -40,20 +40,25 @@ struct sldns_file_parse_state;
        ENTRY_BEGIN
        ; first give MATCH lines, that say what queries are matched
        ; by this entry.
-       ; 'opcode' makes the query match the opcode from the reply
-       ; if you leave it out, any opcode matches this entry.
-       ; 'qtype' makes the query match the qtype from the reply
-       ; 'qname' makes the query match the qname from the reply
-       ; 'subdomain' makes the query match subdomains of qname from the reply
-       ; 'serial=1023' makes the query match if ixfr serial is 1023. 
+       ; 'opcode' makes the query match the opcode from the reply;
+       ;       if you leave it out, any opcode matches this entry.
+       ; 'qtype' makes the query match the qtype from the reply.
+       ; 'qname' makes the query match the qname from the reply.
+       ; 'subdomain' makes the query match subdomains of 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.
+       ; 'all_noedns' has to match header byte for byte and all rrs in packet;
+       ;       ignoring EDNS.
        ; '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
+       ; '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.
        ; 'ednsdata' matches queries to HEX_EDNS section.
+       ; 'UDP' matches if the transport is UDP.
+       ; 'TCP' matches if the transport is TCP.
+       ; 'ede=2' makes the query match if the EDNS EDE info-code is 2.
        MATCH [opcode] [qtype] [qname] [serial=<value>] [all] [ttl]
        MATCH [UDP|TCP] DO
        MATCH ...
@@ -72,6 +77,12 @@ struct sldns_file_parse_state;
        ; 'sleep=10' sleeps for 10 seconds before giving the answer (TCP is open)
        ADJUST [sleep=<num>]    ; sleep before giving any reply
        ADJUST [packet_sleep=<num>]  ; sleep before this packet in sequence
+       ; 'copy_ednsdata_assume_clientsubnet' copies ednsdata to reply, assumes
+       ; it is clientsubnet and adjusts scopemask to match sourcemask.
+       ADJUST copy_ednsdata_assume_clientsubnet
+       ; 'increment_ecs_scope' increments the ECS scope copied from the
+       ;  sourcemask by one.
+       ADJUST increment_ecs_scope
        SECTION QUESTION
        <RRs, one per line>    ; the RRcount is determined automatically.
        SECTION ANSWER
@@ -167,11 +178,11 @@ struct entry {
        /* match */
        /* How to match an incoming query with this canned reply */
        /** match query opcode with answer opcode */
-       uint8_t match_opcode; 
+       uint8_t match_opcode;
        /** match qtype with answer qtype */
-       uint8_t match_qtype;  
+       uint8_t match_qtype;
        /** match qname with answer qname */
-       uint8_t match_qname;  
+       uint8_t match_qname;
        /** match rcode with answer rcode */
        uint8_t match_rcode;
        /** match question section */
@@ -179,11 +190,15 @@ struct entry {
        /** match answer section */
        uint8_t match_answer;
        /** match qname as subdomain of answer qname */
-       uint8_t match_subdomain;  
+       uint8_t match_subdomain;
        /** match SOA serial number, from auth section */
-       uint8_t match_serial; 
+       uint8_t match_serial;
+       /** match EDNS EDE info-code */
+       uint8_t match_ede;
        /** match all of the packet */
        uint8_t match_all;
+       /** match all of the packet; ignore EDNS */
+       uint8_t match_all_noedns;
        /** match ttls in the packet */
        uint8_t match_ttl;
        /** match DO bit */
@@ -193,9 +208,11 @@ struct entry {
        /** match edns data field given in hex */
        uint8_t match_ednsdata_raw;
        /** match query serial with this value. */
-       uint32_t ixfr_soa_serial; 
+       uint32_t ixfr_soa_serial;
        /** match on UDP/TCP */
-       enum transport_type match_transport; 
+       enum transport_type match_transport;
+       /** match EDNS EDE info-code with this value. */
+       uint16_t ede_info_code;
 
        /** pre canned reply */
        struct reply_packet *reply_list;
@@ -260,10 +277,11 @@ struct entry* find_match(struct entry* entries, uint8_t* query_pkt,
  * @param mttl: if true, ttls must match, if false, ttls do not need to match
  * @param noloc: if true, rrs may be reordered in their packet-section.
  *     rrs are then matches without location of the rr being important.
+ * @param noedns: if true, edns is not compared, if false, edns must match.
  * @return true if matched.
  */
 int match_all(uint8_t* q, size_t qlen, uint8_t* p, size_t plen, int mttl,
-       int noloc);
+       int noloc, int noedns);
 
 /**
  * copy & adjust packet, mallocs a copy.
index 6f1edc6e9d6e559966cc5d7640c50be16ad2849e..a87314019d1fddbf2a2fe9069647bf5fbbc3365b 100644 (file)
@@ -137,7 +137,7 @@ test_buffers(sldns_buffer* pkt, sldns_buffer* out)
        /* compare packets */
        unit_assert(match_all(sldns_buffer_begin(pkt), sldns_buffer_limit(pkt),
                sldns_buffer_begin(out), sldns_buffer_limit(out), 1,
-               matches_nolocation));
+               matches_nolocation, 0));
        return 0;
 }
 
index b7507e8eb33a54b969f1950cb058651aebf31030..8c2ac68272ac37c8bdfd5e1aed9bb57229b91d93 100644 (file)
@@ -150,15 +150,11 @@ ENTRY_END
 
 STEP 20 CHECK_ANSWER
 ENTRY_BEGIN
-MATCH all
+MATCH all_noedns ede=6
 REPLY QR RD RA DO SERVFAIL
 SECTION QUESTION
 www.example.com. IN A
 SECTION ANSWER
-SECTION ADDITIONAL
-HEX_EDNSDATA_BEGIN
-000F 0079 000676616C69646174696F6E206661696C757265203C7777772E6578616D706C652E636F6D2E204120494E3E3A206E6F20444E534B455920727273657420666F7220747275737420616E63686F72206578616D706C652E636F6D2E207768696C65206275696C64696E6720636861696E206F66207472757374
-HEX_EDNSDATA_END
 ENTRY_END
 
 ; The autotrust anchor was probed due to the query.