From: Yuri Schaeffer Date: Fri, 18 Jan 2013 15:03:49 +0000 (+0000) Subject: compare edns payload to raw bytes X-Git-Tag: release-1.6.17rc1~145 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4e5585488e91fcca4d27767de11d72d11e1891da;p=thirdparty%2Fldns.git compare edns payload to raw bytes --- diff --git a/examples/ldns-testpkts.c b/examples/ldns-testpkts.c index be94eb2f..81fb1b36 100644 --- a/examples/ldns-testpkts.c +++ b/examples/ldns-testpkts.c @@ -118,6 +118,8 @@ static void matchline(char* line, struct entry* e) e->match_do = true; } else if(str_keyword(&parse, "noedns")) { e->match_noedns = true; + } else if(str_keyword(&parse, "ednsdata")) { + e->match_ednsdata_raw = true; } else if(str_keyword(&parse, "UDP")) { e->match_transport = transport_udp; } else if(str_keyword(&parse, "TCP")) { @@ -434,7 +436,9 @@ read_entry(FILE* in, const char* name, int *lineno, uint32_t* default_ttl, ldns_pkt_section add_section = LDNS_SECTION_QUESTION; struct reply_packet *cur_reply = NULL; bool reading_hex = false; + bool reading_hex_ednsdata = false; ldns_buffer* hex_data_buffer = NULL; + ldns_buffer* hex_ednsdata_buffer = NULL; while(fgets(line, (int)sizeof(line), in) != NULL) { line[MAX_LINE-1] = 0; @@ -497,12 +501,26 @@ read_entry(FILE* in, const char* name, int *lineno, uint32_t* default_ttl, cur_reply->reply_from_hex = data_buffer2wire(hex_data_buffer); ldns_buffer_free(hex_data_buffer); hex_data_buffer = NULL; + } else if(reading_hex) { + ldns_buffer_printf(hex_data_buffer, line); + } else if(str_keyword(&parse, "HEX_EDNSDATA_BEGIN")) { + hex_ednsdata_buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN); + reading_hex_ednsdata = true; + } else if(str_keyword(&parse, "HEX_EDNSDATA_END")) { + if (!reading_hex_ednsdata) { + error("%s line %d: HEX_EDNSDATA_END read but no" + "HEX_EDNSDATA_BEGIN keyword seen", name, *lineno); + } + reading_hex_ednsdata = false; + cur_reply->raw_ednsdata = data_buffer2wire(hex_ednsdata_buffer); + ldns_buffer_free(hex_ednsdata_buffer); + hex_ednsdata_buffer = NULL; + } else if(reading_hex_ednsdata) { + ldns_buffer_printf(hex_ednsdata_buffer, line); } else if(str_keyword(&parse, "ENTRY_END")) { if (hex_data_buffer) ldns_buffer_free(hex_data_buffer); return current; - } else if(reading_hex) { - ldns_buffer_printf(hex_data_buffer, line); } else { /* it must be a RR, parse and add to packet. */ ldns_rr* n = NULL; @@ -674,6 +692,40 @@ match_all(ldns_pkt* q, ldns_pkt* p, bool mttl) return 1; } +/** Convert to hexstring and call verbose(), prepend with header */ +void +verbose_hex(int lvl, uint8_t *data, size_t datalen, char *header) +{ + size_t i; + char errmsg[strlen(header) + datalen*3]; + strcpy(errmsg, header); + for(i = 0; i < datalen; i++) + sprintf(errmsg + strlen(header) + i*3, "%02x ", data[i]); + errmsg[strlen(header) + datalen*3 - 1] = 0; + verbose(lvl, errmsg); +} + +/** Match q edns data to p raw edns data */ +static int +match_ednsdata(ldns_pkt* q, struct reply_packet* p) +{ + size_t qdlen, pdlen; + uint8_t *qd, *pd; + if(!ldns_pkt_edns(q) || !ldns_pkt_edns_data(q)) { + verbose(3, "No EDNS data\n"); + return 0; + } + qdlen = ldns_rdf_size(ldns_pkt_edns_data(q)); + pdlen = ldns_buffer_limit(p->raw_ednsdata); + qd = ldns_rdf_data(ldns_pkt_edns_data(q)); + pd = ldns_buffer_begin(p->raw_ednsdata); + if( qdlen == pdlen && 0 == memcmp(qd, pd, qdlen) ) return 1; + verbose(3, "EDNS data does not match.\n"); + verbose_hex(3, qd, qdlen, "q: "); + verbose_hex(3, pd, pdlen, "p: "); + return 0; +} + /* finds entry in list, or returns NULL */ struct entry* find_match(struct entry* entries, ldns_pkt* query_pkt, @@ -724,6 +776,11 @@ find_match(struct entry* entries, ldns_pkt* query_pkt, verbose(3, "bad; EDNS OPT present\n"); continue; } + if(p->match_ednsdata_raw && + !match_ednsdata(query_pkt, p->reply_list)) { + verbose(3, "bad EDNS data match.\n"); + continue; + } if(p->match_transport != transport_any && p->match_transport != transport) { verbose(3, "bad transport\n"); continue;