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")) {
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;
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;
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,
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;