]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - testcode/testpkts.c
import unbound 1.4.22
[FreeBSD/FreeBSD.git] / testcode / testpkts.c
1 /*
2  * testpkts. Data file parse for test packets, and query matching.
3  *
4  * Data storage for specially crafted replies for testing purposes.
5  *
6  * (c) NLnet Labs, 2005, 2006, 2007, 2008
7  * See the file LICENSE for the license
8  */
9
10 /**
11  * \file
12  * This is a debugging aid. It is not efficient, especially
13  * with a long config file, but it can give any reply to any query.
14  * This can help the developer pre-script replies for queries.
15  *
16  * You can specify a packet RR by RR with header flags to return.
17  *
18  * Missing features:
19  *              - matching content different from reply content.
20  *              - find way to adjust mangled packets?
21  */
22
23 #include "config.h"
24 struct sockaddr_storage;
25 #include <errno.h>
26 #include <stdarg.h>
27 #include <ctype.h>
28 #include "testcode/testpkts.h"
29 #include "util/net_help.h"
30 #include "ldns/sbuffer.h"
31 #include "ldns/rrdef.h"
32 #include "ldns/pkthdr.h"
33 #include "ldns/str2wire.h"
34 #include "ldns/wire2str.h"
35
36 /** max size of a packet */
37 #define MAX_PACKETLEN 65536
38 /** max line length */
39 #define MAX_LINE   10240        
40 /** string to show in warnings and errors */
41 static const char* prog_name = "testpkts";
42
43 #ifndef UTIL_LOG_H
44 /** verbosity definition for compat */
45 enum verbosity_value { NO_VERBOSE=0 };
46 #endif
47 /** logging routine, provided by caller */
48 void verbose(enum verbosity_value lvl, const char* msg, ...) ATTR_FORMAT(printf, 2, 3);
49
50 /** print error and exit */
51 static void error(const char* msg, ...)
52 {
53         va_list args;
54         va_start(args, msg);
55         fprintf(stderr, "%s error: ", prog_name);
56         vfprintf(stderr, msg, args);
57         fprintf(stderr, "\n");
58         fflush(stderr);
59         va_end(args);
60         exit(EXIT_FAILURE);
61 }
62
63 /** return if string is empty or comment */
64 static int isendline(char c)
65 {
66         if(c == ';' || c == '#' 
67                 || c == '\n' || c == 0)
68                 return 1;
69         return 0;
70 }
71
72 /** true if the string starts with the keyword given. Moves the str ahead. 
73  * @param str: before keyword, afterwards after keyword and spaces.
74  * @param keyword: the keyword to match
75  * @return: true if keyword present. False otherwise, and str unchanged.
76 */
77 static int str_keyword(char** str, const char* keyword)
78 {
79         size_t len = strlen(keyword);
80         assert(str && keyword);
81         if(strncmp(*str, keyword, len) != 0)
82                 return 0;
83         *str += len;
84         while(isspace((int)**str))
85                 (*str)++;
86         return 1;
87 }
88
89 /** Add reply packet to entry */
90 static struct reply_packet*
91 entry_add_reply(struct entry* entry) 
92 {
93         struct reply_packet* pkt = (struct reply_packet*)malloc(
94                 sizeof(struct reply_packet));
95         struct reply_packet ** p = &entry->reply_list;
96         if(!pkt) error("out of memory");
97         pkt->next = NULL;
98         pkt->packet_sleep = 0;
99         pkt->reply_pkt = NULL;
100         pkt->reply_from_hex = NULL;
101         /* link at end */
102         while(*p)
103                 p = &((*p)->next);
104         *p = pkt;
105         return pkt;
106 }
107
108 /** parse MATCH line */
109 static void matchline(char* line, struct entry* e)
110 {
111         char* parse = line;
112         while(*parse) {
113                 if(isendline(*parse)) 
114                         return;
115                 if(str_keyword(&parse, "opcode")) {
116                         e->match_opcode = 1;
117                 } else if(str_keyword(&parse, "qtype")) {
118                         e->match_qtype = 1;
119                 } else if(str_keyword(&parse, "qname")) {
120                         e->match_qname = 1;
121                 } else if(str_keyword(&parse, "subdomain")) {
122                         e->match_subdomain = 1;
123                 } else if(str_keyword(&parse, "all")) {
124                         e->match_all = 1;
125                 } else if(str_keyword(&parse, "ttl")) {
126                         e->match_ttl = 1;
127                 } else if(str_keyword(&parse, "DO")) {
128                         e->match_do = 1;
129                 } else if(str_keyword(&parse, "noedns")) {
130                         e->match_noedns = 1;
131                 } else if(str_keyword(&parse, "UDP")) {
132                         e->match_transport = transport_udp;
133                 } else if(str_keyword(&parse, "TCP")) {
134                         e->match_transport = transport_tcp;
135                 } else if(str_keyword(&parse, "serial")) {
136                         e->match_serial = 1;
137                         if(*parse != '=' && *parse != ':')
138                                 error("expected = or : in MATCH: %s", line);
139                         parse++;
140                         e->ixfr_soa_serial = (uint32_t)strtol(parse, (char**)&parse, 10);
141                         while(isspace((int)*parse)) 
142                                 parse++;
143                 } else {
144                         error("could not parse MATCH: '%s'", parse);
145                 }
146         }
147 }
148
149 /** parse REPLY line */
150 static void replyline(char* line, uint8_t* reply, size_t reply_len,
151         int* do_flag)
152 {
153         char* parse = line;
154         if(reply_len < LDNS_HEADER_SIZE) error("packet too short for header");
155         while(*parse) {
156                 if(isendline(*parse)) 
157                         return;
158                         /* opcodes */
159                 if(str_keyword(&parse, "QUERY")) {
160                         LDNS_OPCODE_SET(reply, LDNS_PACKET_QUERY);
161                 } else if(str_keyword(&parse, "IQUERY")) {
162                         LDNS_OPCODE_SET(reply, LDNS_PACKET_IQUERY);
163                 } else if(str_keyword(&parse, "STATUS")) {
164                         LDNS_OPCODE_SET(reply, LDNS_PACKET_STATUS);
165                 } else if(str_keyword(&parse, "NOTIFY")) {
166                         LDNS_OPCODE_SET(reply, LDNS_PACKET_NOTIFY);
167                 } else if(str_keyword(&parse, "UPDATE")) {
168                         LDNS_OPCODE_SET(reply, LDNS_PACKET_UPDATE);
169                         /* rcodes */
170                 } else if(str_keyword(&parse, "NOERROR")) {
171                         LDNS_RCODE_SET(reply, LDNS_RCODE_NOERROR);
172                 } else if(str_keyword(&parse, "FORMERR")) {
173                         LDNS_RCODE_SET(reply, LDNS_RCODE_FORMERR);
174                 } else if(str_keyword(&parse, "SERVFAIL")) {
175                         LDNS_RCODE_SET(reply, LDNS_RCODE_SERVFAIL);
176                 } else if(str_keyword(&parse, "NXDOMAIN")) {
177                         LDNS_RCODE_SET(reply, LDNS_RCODE_NXDOMAIN);
178                 } else if(str_keyword(&parse, "NOTIMPL")) {
179                         LDNS_RCODE_SET(reply, LDNS_RCODE_NOTIMPL);
180                 } else if(str_keyword(&parse, "REFUSED")) {
181                         LDNS_RCODE_SET(reply, LDNS_RCODE_REFUSED);
182                 } else if(str_keyword(&parse, "YXDOMAIN")) {
183                         LDNS_RCODE_SET(reply, LDNS_RCODE_YXDOMAIN);
184                 } else if(str_keyword(&parse, "YXRRSET")) {
185                         LDNS_RCODE_SET(reply, LDNS_RCODE_YXRRSET);
186                 } else if(str_keyword(&parse, "NXRRSET")) {
187                         LDNS_RCODE_SET(reply, LDNS_RCODE_NXRRSET);
188                 } else if(str_keyword(&parse, "NOTAUTH")) {
189                         LDNS_RCODE_SET(reply, LDNS_RCODE_NOTAUTH);
190                 } else if(str_keyword(&parse, "NOTZONE")) {
191                         LDNS_RCODE_SET(reply, LDNS_RCODE_NOTZONE);
192                         /* flags */
193                 } else if(str_keyword(&parse, "QR")) {
194                         LDNS_QR_SET(reply);
195                 } else if(str_keyword(&parse, "AA")) {
196                         LDNS_AA_SET(reply);
197                 } else if(str_keyword(&parse, "TC")) {
198                         LDNS_TC_SET(reply);
199                 } else if(str_keyword(&parse, "RD")) {
200                         LDNS_RD_SET(reply);
201                 } else if(str_keyword(&parse, "CD")) {
202                         LDNS_CD_SET(reply);
203                 } else if(str_keyword(&parse, "RA")) {
204                         LDNS_RA_SET(reply);
205                 } else if(str_keyword(&parse, "AD")) {
206                         LDNS_AD_SET(reply);
207                 } else if(str_keyword(&parse, "DO")) {
208                         *do_flag = 1;
209                 } else {
210                         error("could not parse REPLY: '%s'", parse);
211                 }
212         }
213 }
214
215 /** parse ADJUST line */
216 static void adjustline(char* line, struct entry* e, 
217         struct reply_packet* pkt)
218 {
219         char* parse = line;
220         while(*parse) {
221                 if(isendline(*parse)) 
222                         return;
223                 if(str_keyword(&parse, "copy_id")) {
224                         e->copy_id = 1;
225                 } else if(str_keyword(&parse, "copy_query")) {
226                         e->copy_query = 1;
227                 } else if(str_keyword(&parse, "sleep=")) {
228                         e->sleeptime = (unsigned int) strtol(parse, (char**)&parse, 10);
229                         while(isspace((int)*parse)) 
230                                 parse++;
231                 } else if(str_keyword(&parse, "packet_sleep=")) {
232                         pkt->packet_sleep = (unsigned int) strtol(parse, (char**)&parse, 10);
233                         while(isspace((int)*parse)) 
234                                 parse++;
235                 } else {
236                         error("could not parse ADJUST: '%s'", parse);
237                 }
238         }
239 }
240
241 /** create new entry */
242 static struct entry* new_entry()
243 {
244         struct entry* e = (struct entry*)malloc(sizeof(struct entry));
245         if(!e) error("out of memory");
246         memset(e, 0, sizeof(*e));
247         e->match_opcode = 0;
248         e->match_qtype = 0;
249         e->match_qname = 0;
250         e->match_subdomain = 0;
251         e->match_all = 0;
252         e->match_ttl = 0;
253         e->match_do = 0;
254         e->match_noedns = 0;
255         e->match_serial = 0;
256         e->ixfr_soa_serial = 0;
257         e->match_transport = transport_any;
258         e->reply_list = NULL;
259         e->copy_id = 0;
260         e->copy_query = 0;
261         e->sleeptime = 0;
262         e->next = NULL;
263         return e;
264 }
265
266 /**
267  * Converts a hex string to binary data
268  * @param hexstr: string of hex.
269  * @param len: is the length of the string
270  * @param buf: is the buffer to store the result in
271  * @param offset: is the starting position in the result buffer
272  * @param buf_len: is the length of buf.
273  * @return This function returns the length of the result
274  */
275 static size_t
276 hexstr2bin(char *hexstr, int len, uint8_t *buf, size_t offset, size_t buf_len)
277 {
278         char c;
279         int i; 
280         uint8_t int8 = 0;
281         int sec = 0;
282         size_t bufpos = 0;
283         
284         if (len % 2 != 0) {
285                 return 0;
286         }
287
288         for (i=0; i<len; i++) {
289                 c = hexstr[i];
290
291                 /* case insensitive, skip spaces */
292                 if (c != ' ') {
293                         if (c >= '0' && c <= '9') {
294                                 int8 += c & 0x0f;  
295                         } else if (c >= 'a' && c <= 'z') {
296                                 int8 += (c & 0x0f) + 9;   
297                         } else if (c >= 'A' && c <= 'Z') {
298                                 int8 += (c & 0x0f) + 9;   
299                         } else {
300                                 return 0;
301                         }
302                          
303                         if (sec == 0) {
304                                 int8 = int8 << 4;
305                                 sec = 1;
306                         } else {
307                                 if (bufpos + offset + 1 <= buf_len) {
308                                         buf[bufpos+offset] = int8;
309                                         int8 = 0;
310                                         sec = 0; 
311                                         bufpos++;
312                                 } else {
313                                         fprintf(stderr, "Buffer too small in hexstr2bin");
314                                 }
315                         }
316                 }
317         }
318         return bufpos;
319 }
320
321 /** convert hex buffer to binary buffer */
322 static sldns_buffer *
323 hex_buffer2wire(sldns_buffer *data_buffer)
324 {
325         sldns_buffer *wire_buffer = NULL;
326         int c;
327         
328         /* stat hack
329          * 0 = normal
330          * 1 = comment (skip to end of line)
331          * 2 = unprintable character found, read binary data directly
332          */
333         size_t data_buf_pos = 0;
334         int state = 0;
335         uint8_t *hexbuf;
336         int hexbufpos = 0;
337         size_t wirelen;
338         uint8_t *data_wire = (uint8_t *) sldns_buffer_begin(data_buffer);
339         uint8_t *wire = (uint8_t*)malloc(MAX_PACKETLEN);
340         if(!wire) error("out of memory");
341         
342         hexbuf = (uint8_t*)malloc(MAX_PACKETLEN);
343         if(!hexbuf) error("out of memory");
344         for (data_buf_pos = 0; data_buf_pos < sldns_buffer_position(data_buffer); data_buf_pos++) {
345                 c = (int) data_wire[data_buf_pos];
346                 
347                 if (state < 2 && !isascii(c)) {
348                         /*verbose("non ascii character found in file: (%d) switching to raw mode\n", c);*/
349                         state = 2;
350                 }
351                 switch (state) {
352                         case 0:
353                                 if (    (c >= '0' && c <= '9') ||
354                                         (c >= 'a' && c <= 'f') ||
355                                         (c >= 'A' && c <= 'F') )
356                                 {
357                                         if (hexbufpos >= MAX_PACKETLEN) {
358                                                 error("buffer overflow");
359                                                 free(hexbuf);
360                                                 return 0;
361
362                                         }
363                                         hexbuf[hexbufpos] = (uint8_t) c;
364                                         hexbufpos++;
365                                 } else if (c == ';') {
366                                         state = 1;
367                                 } else if (c == ' ' || c == '\t' || c == '\n') {
368                                         /* skip whitespace */
369                                 } 
370                                 break;
371                         case 1:
372                                 if (c == '\n' || c == EOF) {
373                                         state = 0;
374                                 }
375                                 break;
376                         case 2:
377                                 if (hexbufpos >= MAX_PACKETLEN) {
378                                         error("buffer overflow");
379                                         free(hexbuf);
380                                         return 0;
381                                 }
382                                 hexbuf[hexbufpos] = (uint8_t) c;
383                                 hexbufpos++;
384                                 break;
385                 }
386         }
387
388         if (hexbufpos >= MAX_PACKETLEN) {
389                 /*verbose("packet size reached\n");*/
390         }
391         
392         /* lenient mode: length must be multiple of 2 */
393         if (hexbufpos % 2 != 0) {
394                 if (hexbufpos >= MAX_PACKETLEN) {
395                         error("buffer overflow");
396                         free(hexbuf);
397                         return 0;
398                 }
399                 hexbuf[hexbufpos] = (uint8_t) '0';
400                 hexbufpos++;
401         }
402
403         if (state < 2) {
404                 wirelen = hexstr2bin((char *) hexbuf, hexbufpos, wire, 0, MAX_PACKETLEN);
405                 wire_buffer = sldns_buffer_new(wirelen);
406                 sldns_buffer_new_frm_data(wire_buffer, wire, wirelen);
407         } else {
408                 error("Incomplete hex data, not at byte boundary\n");
409         }
410         free(wire);
411         free(hexbuf);
412         return wire_buffer;
413 }       
414
415 /** parse ORIGIN */
416 static void 
417 get_origin(const char* name, struct sldns_file_parse_state* pstate, char* parse)
418 {
419         /* snip off rest of the text so as to make the parse work in ldns */
420         char* end;
421         char store;
422         int status;
423
424         end=parse;
425         while(!isspace((int)*end) && !isendline(*end))
426                 end++;
427         store = *end;
428         *end = 0;
429         verbose(3, "parsing '%s'\n", parse);
430         status = sldns_str2wire_dname_buf(parse, pstate->origin,
431                 &pstate->origin_len);
432         *end = store;
433         if(status != 0)
434                 error("%s line %d:\n\t%s: %s", name, pstate->lineno,
435                         sldns_get_errorstr_parse(status), parse);
436 }
437
438 /** add RR to packet */
439 static void add_rr(char* rrstr, uint8_t* pktbuf, size_t pktsize,
440         size_t* pktlen, struct sldns_file_parse_state* pstate,
441         sldns_pkt_section add_section, const char* fname)
442 {
443         /* it must be a RR, parse and add to packet. */
444         size_t rr_len = pktsize - *pktlen;
445         size_t dname_len = 0;
446         int status;
447         uint8_t* origin = pstate->origin_len?pstate->origin:0;
448         uint8_t* prev = pstate->prev_rr_len?pstate->prev_rr:0;
449         if(*pktlen > pktsize || *pktlen < LDNS_HEADER_SIZE)
450                 error("packet overflow");
451
452         /* parse RR */
453         if(add_section == LDNS_SECTION_QUESTION)
454                 status = sldns_str2wire_rr_question_buf(rrstr, pktbuf+*pktlen,
455                         &rr_len, &dname_len, origin, pstate->origin_len,
456                         prev, pstate->prev_rr_len);
457         else status = sldns_str2wire_rr_buf(rrstr, pktbuf+*pktlen, &rr_len,
458                         &dname_len, pstate->default_ttl, origin,
459                         pstate->origin_len, prev, pstate->prev_rr_len);
460         if(status != 0)
461                 error("%s line %d:%d %s\n\t%s", fname, pstate->lineno,
462                         LDNS_WIREPARSE_OFFSET(status),
463                         sldns_get_errorstr_parse(status), rrstr);
464         *pktlen += rr_len;
465
466         /* increase RR count */
467         if(add_section == LDNS_SECTION_QUESTION)
468                 sldns_write_uint16(pktbuf+4, LDNS_QDCOUNT(pktbuf)+1);
469         else if(add_section == LDNS_SECTION_ANSWER)
470                 sldns_write_uint16(pktbuf+6, LDNS_ANCOUNT(pktbuf)+1);
471         else if(add_section == LDNS_SECTION_AUTHORITY)
472                 sldns_write_uint16(pktbuf+8, LDNS_NSCOUNT(pktbuf)+1);
473         else if(add_section == LDNS_SECTION_ADDITIONAL)
474                 sldns_write_uint16(pktbuf+10, LDNS_ARCOUNT(pktbuf)+1);
475         else error("internal error bad section %d", (int)add_section);
476 }
477
478 /* add EDNS 4096 DO opt record */
479 static void
480 add_do_flag(uint8_t* pktbuf, size_t pktsize, size_t* pktlen)
481 {
482         uint8_t edns[] = {0x00, /* root label */
483                 0x00, LDNS_RR_TYPE_OPT, /* type */
484                 0x10, 0x00, /* class is UDPSIZE 4096 */
485                 0x00, /* TTL[0] is ext rcode */
486                 0x00, /* TTL[1] is edns version */
487                 0x80, 0x00, /* TTL[2-3] is edns flags, DO */
488                 0x00, 0x00 /* rdatalength (0 options) */
489         };
490         if(*pktlen < LDNS_HEADER_SIZE)
491                 return;
492         if(*pktlen + sizeof(edns) > pktsize)
493                 error("not enough space for EDNS OPT record");
494         memmove(pktbuf+*pktlen, edns, sizeof(edns));
495         sldns_write_uint16(pktbuf+10, LDNS_ARCOUNT(pktbuf)+1);
496         *pktlen += sizeof(edns);
497 }
498
499 /* Reads one entry from file. Returns entry or NULL on error. */
500 struct entry*
501 read_entry(FILE* in, const char* name, struct sldns_file_parse_state* pstate,
502         int skip_whitespace)
503 {
504         struct entry* current = NULL;
505         char line[MAX_LINE];
506         char* parse;
507         sldns_pkt_section add_section = LDNS_SECTION_QUESTION;
508         struct reply_packet *cur_reply = NULL;
509         int reading_hex = 0;
510         sldns_buffer* hex_data_buffer = NULL;
511         uint8_t pktbuf[MAX_PACKETLEN];
512         size_t pktlen = LDNS_HEADER_SIZE;
513         int do_flag = 0; /* DO flag in EDNS */
514         memset(pktbuf, 0, pktlen); /* ID = 0, FLAGS="", and rr counts 0 */
515
516         while(fgets(line, (int)sizeof(line), in) != NULL) {
517                 line[MAX_LINE-1] = 0;
518                 parse = line;
519                 pstate->lineno++;
520
521                 while(isspace((int)*parse))
522                         parse++;
523                 /* test for keywords */
524                 if(isendline(*parse))
525                         continue; /* skip comment and empty lines */
526                 if(str_keyword(&parse, "ENTRY_BEGIN")) {
527                         if(current) {
528                                 error("%s line %d: previous entry does not ENTRY_END", 
529                                         name, pstate->lineno);
530                         }
531                         current = new_entry();
532                         current->lineno = pstate->lineno;
533                         cur_reply = entry_add_reply(current);
534                         continue;
535                 } else if(str_keyword(&parse, "$ORIGIN")) {
536                         get_origin(name, pstate, parse);
537                         continue;
538                 } else if(str_keyword(&parse, "$TTL")) {
539                         pstate->default_ttl = (uint32_t)atoi(parse);
540                         continue;
541                 }
542
543                 /* working inside an entry */
544                 if(!current) {
545                         error("%s line %d: expected ENTRY_BEGIN but got %s", 
546                                 name, pstate->lineno, line);
547                 }
548                 if(str_keyword(&parse, "MATCH")) {
549                         matchline(parse, current);
550                 } else if(str_keyword(&parse, "REPLY")) {
551                         replyline(parse, pktbuf, pktlen, &do_flag);
552                 } else if(str_keyword(&parse, "ADJUST")) {
553                         adjustline(parse, current, cur_reply);
554                 } else if(str_keyword(&parse, "EXTRA_PACKET")) {
555                         cur_reply = entry_add_reply(current);
556                 } else if(str_keyword(&parse, "SECTION")) {
557                         if(str_keyword(&parse, "QUESTION"))
558                                 add_section = LDNS_SECTION_QUESTION;
559                         else if(str_keyword(&parse, "ANSWER"))
560                                 add_section = LDNS_SECTION_ANSWER;
561                         else if(str_keyword(&parse, "AUTHORITY"))
562                                 add_section = LDNS_SECTION_AUTHORITY;
563                         else if(str_keyword(&parse, "ADDITIONAL"))
564                                 add_section = LDNS_SECTION_ADDITIONAL;
565                         else error("%s line %d: bad section %s", name, pstate->lineno, parse);
566                 } else if(str_keyword(&parse, "HEX_ANSWER_BEGIN")) {
567                         hex_data_buffer = sldns_buffer_new(MAX_PACKETLEN);
568                         reading_hex = 1;
569                 } else if(str_keyword(&parse, "HEX_ANSWER_END")) {
570                         if(!reading_hex) {
571                                 error("%s line %d: HEX_ANSWER_END read but no HEX_ANSWER_BEGIN keyword seen", name, pstate->lineno);
572                         }
573                         reading_hex = 0;
574                         cur_reply->reply_from_hex = hex_buffer2wire(hex_data_buffer);
575                         sldns_buffer_free(hex_data_buffer);
576                         hex_data_buffer = NULL;
577                 } else if(str_keyword(&parse, "ENTRY_END")) {
578                         if(hex_data_buffer)
579                                 sldns_buffer_free(hex_data_buffer);
580                         if(pktlen != 0) {
581                                 if(do_flag)
582                                         add_do_flag(pktbuf, sizeof(pktbuf),
583                                                 &pktlen);
584                                 cur_reply->reply_pkt = memdup(pktbuf, pktlen);
585                                 cur_reply->reply_len = pktlen;
586                                 if(!cur_reply->reply_pkt)
587                                         error("out of memory");
588                         }
589                         return current;
590                 } else if(reading_hex) {
591                         sldns_buffer_printf(hex_data_buffer, "%s", line);
592                 } else {
593                         add_rr(skip_whitespace?parse:line, pktbuf,
594                                 sizeof(pktbuf), &pktlen, pstate, add_section,
595                                 name);
596                 }
597
598         }
599         if (reading_hex) {
600                 error("%s: End of file reached while still reading hex, "
601                         "missing HEX_ANSWER_END\n", name);
602         }
603         if(current) {
604                 error("%s: End of file reached while reading entry. "
605                         "missing ENTRY_END\n", name);
606         }
607         return 0;
608 }
609
610 /* reads the canned reply file and returns a list of structs */
611 struct entry* 
612 read_datafile(const char* name, int skip_whitespace)
613 {
614         struct entry* list = NULL;
615         struct entry* last = NULL;
616         struct entry* current = NULL;
617         FILE *in;
618         struct sldns_file_parse_state pstate;
619         int entry_num = 0;
620         memset(&pstate, 0, sizeof(pstate));
621
622         if((in=fopen(name, "r")) == NULL) {
623                 error("could not open file %s: %s", name, strerror(errno));
624         }
625
626         while((current = read_entry(in, name, &pstate, skip_whitespace)))
627         {
628                 if(last)
629                         last->next = current;
630                 else    list = current;
631                 last = current;
632                 entry_num ++;
633         }
634         verbose(1, "%s: Read %d entries\n", prog_name, entry_num);
635
636         fclose(in);
637         return list;
638 }
639
640 /** get qtype from packet */
641 static sldns_rr_type get_qtype(uint8_t* pkt, size_t pktlen)
642 {
643         uint8_t* d;
644         size_t dl, sl=0;
645         char* snull = NULL;
646         if(pktlen < LDNS_HEADER_SIZE)
647                 return 0;
648         if(LDNS_QDCOUNT(pkt) == 0)
649                 return 0;
650         /* skip over dname with dname-scan routine */
651         d = pkt+LDNS_HEADER_SIZE;
652         dl = pktlen-LDNS_HEADER_SIZE;
653         (void)sldns_wire2str_dname_scan(&d, &dl, &snull, &sl, pkt, pktlen);
654         if(dl < 2)
655                 return 0;
656         return sldns_read_uint16(d);
657 }
658
659 /** get qtype from packet */
660 static size_t get_qname_len(uint8_t* pkt, size_t pktlen)
661 {
662         uint8_t* d;
663         size_t dl, sl=0;
664         char* snull = NULL;
665         if(pktlen < LDNS_HEADER_SIZE)
666                 return 0;
667         if(LDNS_QDCOUNT(pkt) == 0)
668                 return 0;
669         /* skip over dname with dname-scan routine */
670         d = pkt+LDNS_HEADER_SIZE;
671         dl = pktlen-LDNS_HEADER_SIZE;
672         (void)sldns_wire2str_dname_scan(&d, &dl, &snull, &sl, pkt, pktlen);
673         return pktlen-dl-LDNS_HEADER_SIZE;
674 }
675
676 /** returns owner from packet */
677 static uint8_t* get_qname(uint8_t* pkt, size_t pktlen)
678 {
679         if(pktlen < LDNS_HEADER_SIZE)
680                 return NULL;
681         if(LDNS_QDCOUNT(pkt) == 0)
682                 return NULL;
683         return pkt+LDNS_HEADER_SIZE;
684 }
685
686 /** returns opcode from packet */
687 static int get_opcode(uint8_t* pkt, size_t pktlen)
688 {
689         if(pktlen < LDNS_HEADER_SIZE)
690                 return 0;
691         return (int)LDNS_OPCODE_WIRE(pkt);
692 }
693
694 /** get authority section SOA serial value */
695 static uint32_t get_serial(uint8_t* p, size_t plen)
696 {
697         uint8_t* walk = p;
698         size_t walk_len = plen, sl=0;
699         char* snull = NULL;
700         uint16_t i;
701
702         if(walk_len < LDNS_HEADER_SIZE)
703                 return 0;
704         walk += LDNS_HEADER_SIZE;
705         walk_len -= LDNS_HEADER_SIZE;
706
707         /* skip other records with wire2str_scan */
708         for(i=0; i < LDNS_QDCOUNT(p); i++)
709                 (void)sldns_wire2str_rrquestion_scan(&walk, &walk_len,
710                         &snull, &sl, p, plen);
711         for(i=0; i < LDNS_ANCOUNT(p); i++)
712                 (void)sldns_wire2str_rr_scan(&walk, &walk_len, &snull, &sl,
713                         p, plen);
714
715         /* walk through authority section */
716         for(i=0; i < LDNS_NSCOUNT(p); i++) {
717                 /* if this is SOA then get serial, skip compressed dname */
718                 uint8_t* dstart = walk;
719                 size_t dlen = walk_len;
720                 (void)sldns_wire2str_dname_scan(&dstart, &dlen, &snull, &sl,
721                         p, plen);
722                 if(dlen >= 2 && sldns_read_uint16(dstart) == LDNS_RR_TYPE_SOA) {
723                         /* skip type, class, TTL, rdatalen */
724                         if(dlen < 10)
725                                 return 0;
726                         if(dlen < 10 + (size_t)sldns_read_uint16(dstart+8))
727                                 return 0;
728                         dstart += 10;
729                         dlen -= 10;
730                         /* check third rdf */
731                         (void)sldns_wire2str_dname_scan(&dstart, &dlen, &snull,
732                                 &sl, p, plen);
733                         (void)sldns_wire2str_dname_scan(&dstart, &dlen, &snull,
734                                 &sl, p, plen);
735                         if(dlen < 4)
736                                 return 0;
737                         verbose(3, "found serial %u in msg. ",
738                                 (int)sldns_read_uint32(dstart));
739                         return sldns_read_uint32(dstart);
740                 }
741                 /* move to next RR */
742                 (void)sldns_wire2str_rr_scan(&walk, &walk_len, &snull, &sl,
743                         p, plen);
744         }
745         return 0;
746 }
747
748 /** get ptr to EDNS OPT record (and remaining length); behind the type u16 */
749 static int
750 pkt_find_edns_opt(uint8_t** p, size_t* plen)
751 {
752         /* walk over the packet with scan routines */
753         uint8_t* w = *p;
754         size_t wlen = *plen, sl=0;
755         char* snull = NULL;
756         uint16_t i;
757
758         if(wlen < LDNS_HEADER_SIZE)
759                 return 0;
760         w += LDNS_HEADER_SIZE;
761         wlen -= LDNS_HEADER_SIZE;
762
763         /* skip other records with wire2str_scan */
764         for(i=0; i < LDNS_QDCOUNT(p); i++)
765                 (void)sldns_wire2str_rrquestion_scan(&w, &wlen, &snull, &sl,
766                         *p, *plen);
767         for(i=0; i < LDNS_ANCOUNT(p); i++)
768                 (void)sldns_wire2str_rr_scan(&w, &wlen, &snull, &sl, *p, *plen);
769         for(i=0; i < LDNS_NSCOUNT(p); i++)
770                 (void)sldns_wire2str_rr_scan(&w, &wlen, &snull, &sl, *p, *plen);
771
772         /* walk through additional section */
773         for(i=0; i < LDNS_ARCOUNT(p); i++) {
774                 /* if this is OPT then done */
775                 uint8_t* dstart = w;
776                 size_t dlen = wlen;
777                 (void)sldns_wire2str_dname_scan(&dstart, &dlen, &snull, &sl,
778                         *p, *plen);
779                 if(dlen >= 2 && sldns_read_uint16(dstart) == LDNS_RR_TYPE_OPT) {
780                         *p = dstart+2;
781                         *plen = dlen-2;
782                         return 1;
783                 }
784                 /* move to next RR */
785                 (void)sldns_wire2str_rr_scan(&w, &wlen, &snull, &sl, *p, *plen);
786         }
787         return 0;
788 }
789
790 /** return true if the packet has EDNS OPT record */
791 static int
792 get_has_edns(uint8_t* pkt, size_t len)
793 {
794         /* use arguments as temporary variables */
795         return pkt_find_edns_opt(&pkt, &len);
796 }
797
798 /** return true if the DO flag is set */
799 static int
800 get_do_flag(uint8_t* pkt, size_t len)
801 {
802         uint16_t edns_bits;
803         uint8_t* walk = pkt;
804         size_t walk_len = len;
805         if(pkt_find_edns_opt(&walk, &walk_len)) {
806                 return 1;
807         }
808         if(walk_len < 6)
809                 return 0; /* malformed */
810         edns_bits = sldns_read_uint16(walk+4);
811         return (int)(edns_bits&LDNS_EDNS_MASK_DO_BIT);
812 }
813
814 /** zero TTLs in packet */
815 static void
816 zerottls(uint8_t* pkt, size_t pktlen)
817 {
818         uint8_t* walk = pkt;
819         size_t walk_len = pktlen, sl=0;
820         char* snull = NULL;
821         uint16_t i;
822         uint16_t num = LDNS_ANCOUNT(pkt)+LDNS_NSCOUNT(pkt)+LDNS_ARCOUNT(pkt);
823         if(walk_len < LDNS_HEADER_SIZE)
824                 return;
825         walk += LDNS_HEADER_SIZE;
826         walk_len -= LDNS_HEADER_SIZE;
827         for(i=0; i < LDNS_QDCOUNT(pkt); i++)
828                 (void)sldns_wire2str_rrquestion_scan(&walk, &walk_len,
829                         &snull, &sl, pkt, pktlen);
830         for(i=0; i < num; i++) {
831                 /* wipe TTL */
832                 uint8_t* dstart = walk;
833                 size_t dlen = walk_len;
834                 (void)sldns_wire2str_dname_scan(&dstart, &dlen, &snull, &sl,
835                         pkt, pktlen);
836                 if(dlen < 8)
837                         return;
838                 sldns_write_uint32(dstart+4, 0);
839                 /* go to next RR */
840                 (void)sldns_wire2str_rr_scan(&walk, &walk_len, &snull, &sl,
841                         pkt, pktlen);
842         }
843 }
844
845 /** get one line (\n) from a string, move next to after the \n, zero \n */
846 static int
847 get_line(char** s, char** n)
848 {
849         /* at end of string? end */
850         if(*n == NULL || **n == 0)
851                 return 0;
852         /* result starts at next string */
853         *s = *n;
854         /* find \n after that */
855         *n = strchr(*s, '\n');
856         if(*n && **n != 0) {
857                 /* terminate line */
858                 (*n)[0] = 0;
859                 (*n)++;
860         }
861         return 1;
862 }
863
864 /** match two RR sections without ordering */
865 static int
866 match_noloc_section(char** q, char** nq, char** p, char** np, uint16_t num)
867 {
868         /* for max number of RRs in packet */
869         const uint16_t numarray = 3000;
870         char* qlines[numarray], *plines[numarray];
871         uint16_t i, j, numq=0, nump=0;
872         if(num > numarray) fatal_exit("too many RRs");
873         /* gather lines */
874         for(i=0; i<num; i++) {
875                 get_line(q, nq);
876                 get_line(p, np);
877                 qlines[numq++] = *q;
878                 plines[nump++] = *p;
879         }
880         /* see if they are all present in the other */
881         for(i=0; i<num; i++) {
882                 int found = 0;
883                 for(j=0; j<num; j++) {
884                         if(strcmp(qlines[i], plines[j]) == 0) {
885                                 found = 1;
886                                 break;
887                         }
888                 }
889                 if(!found) {
890                         verbose(3, "comparenoloc: failed for %s", qlines[i]);
891                         return 0;
892                 }
893         }
894         return 1;
895 }
896
897 /** match two strings for unordered equality of RRs and everything else */
898 static int
899 match_noloc(char* q, char* p, uint8_t* q_pkt, size_t q_pkt_len,
900         uint8_t* p_pkt, size_t p_pkt_len)
901 {
902         char* nq = q, *np = p;
903         /* if no header, compare bytes */
904         if(p_pkt_len < LDNS_HEADER_SIZE || q_pkt_len < LDNS_HEADER_SIZE) {
905                 if(p_pkt_len != q_pkt_len) return 0;
906                 return memcmp(p, q, p_pkt_len);
907         }
908         /* compare RR counts */
909         if(LDNS_QDCOUNT(p_pkt) != LDNS_QDCOUNT(q_pkt))
910                 return 0;
911         if(LDNS_ANCOUNT(p_pkt) != LDNS_ANCOUNT(q_pkt))
912                 return 0;
913         if(LDNS_NSCOUNT(p_pkt) != LDNS_NSCOUNT(q_pkt))
914                 return 0;
915         if(LDNS_ARCOUNT(p_pkt) != LDNS_ARCOUNT(q_pkt))
916                 return 0;
917         /* get a line from both; compare; at sections do section */
918         get_line(&q, &nq);
919         get_line(&p, &np);
920         if(strcmp(q, p) != 0) {
921                 /* header line opcode, rcode, id */
922                 return 0;
923         }
924         get_line(&q, &nq);
925         get_line(&p, &np);
926         if(strcmp(q, p) != 0) {
927                 /* header flags, rr counts */
928                 return 0;
929         }
930         /* ;; QUESTION SECTION */
931         get_line(&q, &nq);
932         get_line(&p, &np);
933         if(strcmp(q, p) != 0) return 0;
934         if(!match_noloc_section(&q, &nq, &p, &np, LDNS_QDCOUNT(p_pkt)))
935                 return 0;
936
937         /* empty line and ;; ANSWER SECTION */
938         get_line(&q, &nq);
939         get_line(&p, &np);
940         if(strcmp(q, p) != 0) return 0;
941         get_line(&q, &nq);
942         get_line(&p, &np);
943         if(strcmp(q, p) != 0) return 0;
944         if(!match_noloc_section(&q, &nq, &p, &np, LDNS_ANCOUNT(p_pkt)))
945                 return 0;
946
947         /* empty line and ;; AUTHORITY SECTION */
948         get_line(&q, &nq);
949         get_line(&p, &np);
950         if(strcmp(q, p) != 0) return 0;
951         get_line(&q, &nq);
952         get_line(&p, &np);
953         if(strcmp(q, p) != 0) return 0;
954         if(!match_noloc_section(&q, &nq, &p, &np, LDNS_NSCOUNT(p_pkt)))
955                 return 0;
956
957         /* empty line and ;; ADDITIONAL SECTION */
958         get_line(&q, &nq);
959         get_line(&p, &np);
960         if(strcmp(q, p) != 0) return 0;
961         get_line(&q, &nq);
962         get_line(&p, &np);
963         if(strcmp(q, p) != 0) return 0;
964         if(!match_noloc_section(&q, &nq, &p, &np, LDNS_ARCOUNT(p_pkt)))
965                 return 0;
966
967         return 1;
968 }
969
970 /** lowercase domain name - does not follow compression pointers */
971 static void lowercase_dname(uint8_t** p, size_t* remain)
972 {
973         unsigned i, llen;
974         if(*remain == 0) return;
975         while(**p != 0) {
976                 /* compressed? */
977                 if((**p & 0xc0) == 0xc0) {
978                         *p += 2;
979                         *remain -= 2;
980                         return;
981                 }
982                 llen = (unsigned int)**p;
983                 *p += 1;
984                 *remain -= 1;
985                 if(*remain < llen)
986                         llen = (unsigned int)*remain;
987                 for(i=0; i<llen; i++) {
988                         (*p)[i] = (uint8_t)tolower((int)(*p)[i]);
989                 }
990                 *p += llen;
991                 *remain -= llen;
992                 if(*remain == 0) return;
993         }
994         /* skip root label */
995         *p += 1;
996         *remain -= 1;
997 }
998
999 /** lowercase rdata of type */
1000 static void lowercase_rdata(uint8_t** p, size_t* remain,
1001         uint16_t rdatalen, uint16_t t)
1002 {
1003         const sldns_rr_descriptor *desc = sldns_rr_descript(t);
1004         uint8_t dname_count = 0;
1005         size_t i = 0;
1006         size_t rdataremain = rdatalen;
1007         if(!desc) {
1008                 /* unknown type */
1009                 *p += rdatalen;
1010                 *remain -= rdatalen;
1011                 return;
1012         }
1013         while(dname_count < desc->_dname_count) {
1014                 sldns_rdf_type f = sldns_rr_descriptor_field_type(desc, i++);
1015                 if(f == LDNS_RDF_TYPE_DNAME) {
1016                         lowercase_dname(p, &rdataremain);
1017                         dname_count++;
1018                 } else if(f == LDNS_RDF_TYPE_STR) {
1019                         uint8_t len;
1020                         if(rdataremain == 0) return;
1021                         len = **p;
1022                         *p += len+1;
1023                         rdataremain -= len+1;
1024                 } else {
1025                         int len = 0;
1026                         switch(f) {
1027                         case LDNS_RDF_TYPE_CLASS:
1028                         case LDNS_RDF_TYPE_ALG:
1029                         case LDNS_RDF_TYPE_INT8:
1030                                 len = 1;
1031                                 break;
1032                         case LDNS_RDF_TYPE_INT16:
1033                         case LDNS_RDF_TYPE_TYPE:
1034                         case LDNS_RDF_TYPE_CERT_ALG:
1035                                 len = 2;
1036                                 break;
1037                         case LDNS_RDF_TYPE_INT32:
1038                         case LDNS_RDF_TYPE_TIME:
1039                         case LDNS_RDF_TYPE_A:
1040                         case LDNS_RDF_TYPE_PERIOD:
1041                                 len = 4;
1042                                 break;
1043                         case LDNS_RDF_TYPE_TSIGTIME:
1044                                 len = 6;
1045                                 break;
1046                         case LDNS_RDF_TYPE_AAAA:
1047                                 len = 16;
1048                                 break;
1049                         default: error("bad rdf type in lowercase %d", (int)f);
1050                         }
1051                         *p += len;
1052                         rdataremain -= len;
1053                 }
1054         }
1055         /* skip remainder of rdata */
1056         *p += rdataremain;
1057         *remain -= rdatalen;
1058 }
1059
1060 /** lowercase all names in the message */
1061 static void lowercase_pkt(uint8_t* pkt, size_t pktlen)
1062 {
1063         uint16_t i;
1064         uint8_t* p = pkt;
1065         size_t remain = pktlen;
1066         uint16_t t, rdatalen;
1067         if(pktlen < LDNS_HEADER_SIZE)
1068                 return;
1069         p += LDNS_HEADER_SIZE;
1070         remain -= LDNS_HEADER_SIZE;
1071         for(i=0; i<LDNS_QDCOUNT(pkt); i++) {
1072                 lowercase_dname(&p, &remain);
1073                 if(remain < 4) return;
1074                 p += 4;
1075                 remain -= 4;
1076         }
1077         for(i=0; i<LDNS_ANCOUNT(pkt)+LDNS_NSCOUNT(pkt)+LDNS_ARCOUNT(pkt); i++) {
1078                 lowercase_dname(&p, &remain);
1079                 if(remain < 10) return;
1080                 t = sldns_read_uint16(p);
1081                 rdatalen = sldns_read_uint16(p+8);
1082                 p += 10;
1083                 remain -= 10;
1084                 if(remain < rdatalen) return;
1085                 lowercase_rdata(&p, &remain, rdatalen, t);
1086         }
1087 }
1088
1089 /** match all of the packet */
1090 int
1091 match_all(uint8_t* q, size_t qlen, uint8_t* p, size_t plen, int mttl,
1092         int noloc)
1093 {
1094         char* qstr, *pstr;
1095         uint8_t* qb = q, *pb = p;
1096         int r;
1097         /* zero TTLs */
1098         qb = memdup(q, qlen);
1099         pb = memdup(p, plen);
1100         if(!qb || !pb) error("out of memory");
1101         if(!mttl) {
1102                 zerottls(qb, qlen);
1103                 zerottls(pb, plen);
1104         }
1105         lowercase_pkt(qb, qlen);
1106         lowercase_pkt(pb, plen);
1107         qstr = sldns_wire2str_pkt(qb, qlen);
1108         pstr = sldns_wire2str_pkt(pb, plen);
1109         if(!qstr || !pstr) error("cannot pkt2string");
1110         r = (strcmp(qstr, pstr) == 0);
1111         if(!r) {
1112                 /* remove ;; MSG SIZE (at end of string) */
1113                 char* s = strstr(qstr, ";; MSG SIZE");
1114                 if(s) *s=0;
1115                 s = strstr(pstr, ";; MSG SIZE");
1116                 if(s) *s=0;
1117                 r = (strcmp(qstr, pstr) == 0);
1118                 if(!r && !noloc) {
1119                         /* we are going to fail see if it is because of EDNS */
1120                         char* a = strstr(qstr, "; EDNS");
1121                         char* b = strstr(pstr, "; EDNS");
1122                         if( (a&&!b) || (b&&!a) ) {
1123                                 verbose(3, "mismatch in EDNS\n");
1124                         }
1125                 }
1126         }
1127         if(!r && noloc) {
1128                 /* check for reordered sections */
1129                 r = match_noloc(qstr, pstr, q, qlen, p, plen);
1130         }
1131         free(qstr);
1132         free(pstr);
1133         free(qb);
1134         free(pb);
1135         return r;
1136 }
1137
1138 /** see if domain names are equal */
1139 static int equal_dname(uint8_t* q, size_t qlen, uint8_t* p, size_t plen)
1140 {
1141         uint8_t* qn = get_qname(q, qlen);
1142         uint8_t* pn = get_qname(p, plen);
1143         char qs[512], ps[512];
1144         size_t qslen = sizeof(qs), pslen = sizeof(ps);
1145         char* qss = qs, *pss = ps;
1146         if(!qn || !pn)
1147                 return 0;
1148         (void)sldns_wire2str_dname_scan(&qn, &qlen, &qss, &qslen, q, qlen);
1149         (void)sldns_wire2str_dname_scan(&pn, &plen, &pss, &pslen, p, plen);
1150         return (strcmp(qs, ps) == 0);
1151 }
1152
1153 /** see if domain names are subdomain q of p */
1154 static int subdomain_dname(uint8_t* q, size_t qlen, uint8_t* p, size_t plen)
1155 {
1156         /* we use the tostring routines so as to test unbound's routines
1157          * with something else */
1158         uint8_t* qn = get_qname(q, qlen);
1159         uint8_t* pn = get_qname(p, plen);
1160         char qs[5120], ps[5120];
1161         size_t qslen = sizeof(qs), pslen = sizeof(ps);
1162         char* qss = qs, *pss = ps;
1163         if(!qn || !pn)
1164                 return 0;
1165         /* decompresses domain names */
1166         (void)sldns_wire2str_dname_scan(&qn, &qlen, &qss, &qslen, q, qlen);
1167         (void)sldns_wire2str_dname_scan(&pn, &plen, &pss, &pslen, p, plen);
1168         /* same: false, (strict subdomain check)??? */
1169         if(strcmp(qs, ps) == 0)
1170                 return 1;
1171         /* qs must end in ps, at a dot, without \ in front */
1172         qslen = strlen(qs);
1173         pslen = strlen(ps);
1174         if(qslen > pslen && strcmp(qs + (qslen-pslen), ps) == 0 &&
1175                 qslen + 2 >= pslen && /* space for label and dot */
1176                 qs[qslen-pslen-1] == '.') {
1177                 unsigned int slashcount = 0;
1178                 size_t i = qslen-pslen-2;
1179                 while(i>0 && qs[i]=='\\') {
1180                         i++;
1181                         slashcount++;
1182                 }
1183                 if(slashcount%1 == 1) return 0; /* . preceded by \ */
1184                 return 1;
1185         }
1186         return 0;
1187 }
1188
1189 /* finds entry in list, or returns NULL */
1190 struct entry* 
1191 find_match(struct entry* entries, uint8_t* query_pkt, size_t len,
1192         enum transport_type transport)
1193 {
1194         struct entry* p = entries;
1195         uint8_t* reply;
1196         size_t rlen;
1197         for(p=entries; p; p=p->next) {
1198                 verbose(3, "comparepkt: ");
1199                 reply = p->reply_list->reply_pkt;
1200                 rlen = p->reply_list->reply_len;
1201                 if(p->match_opcode && get_opcode(query_pkt, len) != 
1202                         get_opcode(reply, rlen)) {
1203                         verbose(3, "bad opcode\n");
1204                         continue;
1205                 }
1206                 if(p->match_qtype && get_qtype(query_pkt, len) !=
1207                         get_qtype(reply, rlen)) {
1208                         verbose(3, "bad qtype %d %d\n", get_qtype(query_pkt, len), get_qtype(reply, rlen));
1209                         continue;
1210                 }
1211                 if(p->match_qname) {
1212                         if(!equal_dname(query_pkt, len, reply, rlen)) {
1213                                 verbose(3, "bad qname\n");
1214                                 continue;
1215                         }
1216                 }
1217                 if(p->match_subdomain) {
1218                         if(!subdomain_dname(query_pkt, len, reply, rlen)) {
1219                                 verbose(3, "bad subdomain\n");
1220                                 continue;
1221                         }
1222                 }
1223                 if(p->match_serial && get_serial(query_pkt, len) != p->ixfr_soa_serial) {
1224                                 verbose(3, "bad serial\n");
1225                                 continue;
1226                 }
1227                 if(p->match_do && !get_do_flag(query_pkt, len)) {
1228                         verbose(3, "no DO bit set\n");
1229                         continue;
1230                 }
1231                 if(p->match_noedns && get_has_edns(query_pkt, len)) {
1232                         verbose(3, "bad; EDNS OPT present\n");
1233                         continue;
1234                 }
1235                 if(p->match_transport != transport_any && p->match_transport != transport) {
1236                         verbose(3, "bad transport\n");
1237                         continue;
1238                 }
1239                 if(p->match_all && !match_all(query_pkt, len, reply, rlen,
1240                         (int)p->match_ttl, 0)) {
1241                         verbose(3, "bad allmatch\n");
1242                         continue;
1243                 }
1244                 verbose(3, "match!\n");
1245                 return p;
1246         }
1247         return NULL;
1248 }
1249
1250 void
1251 adjust_packet(struct entry* match, uint8_t** answer_pkt, size_t *answer_len,
1252         uint8_t* query_pkt, size_t query_len)
1253 {
1254         uint8_t* orig = *answer_pkt;
1255         size_t origlen = *answer_len;
1256         uint8_t* res;
1257         size_t reslen;
1258
1259         /* perform the copy; if possible; must be uncompressed */
1260         if(match->copy_query && origlen >= LDNS_HEADER_SIZE &&
1261                 query_len >= LDNS_HEADER_SIZE && LDNS_QDCOUNT(query_pkt)!=0
1262                 && LDNS_QDCOUNT(orig)==0) {
1263                 /* no qname in output packet, insert it */
1264                 size_t dlen = get_qname_len(query_pkt, query_len);
1265                 reslen = origlen + dlen + 4;
1266                 res = (uint8_t*)malloc(reslen);
1267                 if(!res) {
1268                         verbose(1, "out of memory; send without adjust\n");
1269                         return;
1270                 }
1271                 /* copy the header, query, remainder */
1272                 memcpy(res, orig, LDNS_HEADER_SIZE);
1273                 memmove(res+LDNS_HEADER_SIZE, query_pkt+LDNS_HEADER_SIZE,
1274                         dlen+4);
1275                 memmove(res+LDNS_HEADER_SIZE+dlen+4, orig+LDNS_HEADER_SIZE,
1276                         reslen-(LDNS_HEADER_SIZE+dlen+4));
1277                 /* set QDCOUNT */
1278                 sldns_write_uint16(res+4, 1);
1279         } else if(match->copy_query && origlen >= LDNS_HEADER_SIZE &&
1280                 query_len >= LDNS_HEADER_SIZE && LDNS_QDCOUNT(query_pkt)!=0
1281                 && get_qname_len(orig, origlen) == 0) {
1282                 /* QDCOUNT(orig)!=0 but qlen == 0, therefore, an error */
1283                 verbose(1, "error: malformed qname; send without adjust\n");
1284                 res = memdup(orig, origlen);
1285                 reslen = origlen;
1286         } else if(match->copy_query && origlen >= LDNS_HEADER_SIZE &&
1287                 query_len >= LDNS_HEADER_SIZE && LDNS_QDCOUNT(query_pkt)!=0
1288                 && LDNS_QDCOUNT(orig)!=0) {
1289                 /* in this case olen != 0 and QDCOUNT(orig)!=0 */
1290                 /* copy query section */
1291                 size_t dlen = get_qname_len(query_pkt, query_len);
1292                 size_t olen = get_qname_len(orig, origlen);
1293                 reslen = origlen + dlen - olen;
1294                 res = (uint8_t*)malloc(reslen);
1295                 if(!res) {
1296                         verbose(1, "out of memory; send without adjust\n");
1297                         return;
1298                 }
1299                 /* copy the header, query, remainder */
1300                 memcpy(res, orig, LDNS_HEADER_SIZE);
1301                 memmove(res+LDNS_HEADER_SIZE, query_pkt+LDNS_HEADER_SIZE,
1302                         dlen+4);
1303                 memmove(res+LDNS_HEADER_SIZE+dlen+4,
1304                         orig+LDNS_HEADER_SIZE+olen+4,
1305                         reslen-(LDNS_HEADER_SIZE+dlen+4));
1306         } else {
1307                 res = memdup(orig, origlen);
1308                 reslen = origlen;
1309         }
1310         if(!res) {
1311                 verbose(1, "out of memory; send without adjust\n");
1312                 return;
1313         }
1314         /* copy the ID */
1315         if(match->copy_id && reslen >= 2)
1316                 res[1] = orig[1];
1317         if(match->copy_id && reslen >= 1)
1318                 res[0] = orig[0];
1319
1320         if(match->sleeptime > 0) {
1321                 verbose(3, "sleeping for %d seconds\n", match->sleeptime);
1322 #ifdef HAVE_SLEEP
1323                 sleep(match->sleeptime);
1324 #else
1325                 Sleep(match->sleeptime * 1000);
1326 #endif
1327         }
1328         *answer_pkt = res;
1329         *answer_len = reslen;
1330 }
1331
1332 /*
1333  * Parses data buffer to a query, finds the correct answer 
1334  * and calls the given function for every packet to send.
1335  */
1336 void
1337 handle_query(uint8_t* inbuf, ssize_t inlen, struct entry* entries, int* count,
1338         enum transport_type transport, void (*sendfunc)(uint8_t*, size_t, void*),
1339         void* userdata, FILE* verbose_out)
1340 {
1341         struct reply_packet *p;
1342         uint8_t *outbuf = NULL;
1343         size_t outlen = 0;
1344         struct entry* entry = NULL;
1345
1346         verbose(1, "query %d: id %d: %s %d bytes: ", ++(*count),
1347                 (int)(inlen>=2?LDNS_ID_WIRE(inbuf):0), 
1348                 (transport==transport_tcp)?"TCP":"UDP", (int)inlen);
1349         if(verbose_out) {
1350                 char* out = sldns_wire2str_pkt(inbuf, (size_t)inlen);
1351                 printf("%s\n", out);
1352                 free(out);
1353         }
1354
1355         /* fill up answer packet */
1356         entry = find_match(entries, inbuf, (size_t)inlen, transport);
1357         if(!entry || !entry->reply_list) {
1358                 verbose(1, "no answer packet for this query, no reply.\n");
1359                 return;
1360         }
1361         for(p = entry->reply_list; p; p = p->next)
1362         {
1363                 verbose(3, "Answer pkt:\n");
1364                 if (p->reply_from_hex) {
1365                         /* try to adjust the hex packet, if it can be
1366                          * parsed, we can use adjust rules. if not,
1367                          * send packet literally */
1368                         /* still try to adjust ID if others fail */
1369                         outlen = sldns_buffer_limit(p->reply_from_hex);
1370                         outbuf = sldns_buffer_begin(p->reply_from_hex);
1371                 } else {
1372                         outbuf = p->reply_pkt;
1373                         outlen = p->reply_len;
1374                 }
1375                 if(!outbuf) {
1376                         verbose(1, "out of memory\n");
1377                         return;
1378                 }
1379                 /* copies outbuf in memory allocation */
1380                 adjust_packet(entry, &outbuf, &outlen, inbuf, (size_t)inlen);
1381                 verbose(1, "Answer packet size: %u bytes.\n", (unsigned int)outlen);
1382                 if(verbose_out) {
1383                         char* out = sldns_wire2str_pkt(outbuf, outlen);
1384                         printf("%s\n", out);
1385                         free(out);
1386                 }
1387                 if(p->packet_sleep) {
1388                         verbose(3, "sleeping for next packet %d secs\n", 
1389                                 p->packet_sleep);
1390 #ifdef HAVE_SLEEP
1391                         sleep(p->packet_sleep);
1392 #else
1393                         Sleep(p->packet_sleep * 1000);
1394 #endif
1395                         verbose(3, "wakeup for next packet "
1396                                 "(slept %d secs)\n", p->packet_sleep);
1397                 }
1398                 sendfunc(outbuf, outlen, userdata);
1399                 free(outbuf);
1400                 outbuf = NULL;
1401                 outlen = 0;
1402         }
1403 }
1404
1405 /** delete the list of reply packets */
1406 void delete_replylist(struct reply_packet* replist)
1407 {
1408         struct reply_packet *p=replist, *np;
1409         while(p) {
1410                 np = p->next;
1411                 free(p->reply_pkt);
1412                 sldns_buffer_free(p->reply_from_hex);
1413                 free(p);
1414                 p=np;
1415         }
1416 }
1417
1418 void delete_entry(struct entry* list)
1419 {
1420         struct entry *p=list, *np;
1421         while(p) {
1422                 np = p->next;
1423                 delete_replylist(p->reply_list);
1424                 free(p);
1425                 p = np;
1426         }
1427 }