2 * testpkts. Data file parse for test packets, and query matching.
4 * Data storage for specially crafted replies for testing purposes.
6 * (c) NLnet Labs, 2005, 2006, 2007, 2008
7 * See the file LICENSE for the license
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.
16 * You can specify a packet RR by RR with header flags to return.
19 * - matching content different from reply content.
20 * - find way to adjust mangled packets?
24 struct sockaddr_storage
;
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"
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";
44 /** verbosity definition for compat */
45 enum verbosity_value
{ NO_VERBOSE
=0 };
47 /** logging routine, provided by caller */
48 void verbose(enum verbosity_value lvl
, const char* msg
, ...) ATTR_FORMAT(printf
, 2, 3);
50 /** print error and exit */
51 static void error(const char* msg
, ...)
55 fprintf(stderr
, "%s error: ", prog_name
);
56 vfprintf(stderr
, msg
, args
);
57 fprintf(stderr
, "\n");
63 /** return if string is empty or comment */
64 static int isendline(char c
)
66 if(c
== ';' || c
== '#'
67 || c
== '\n' || c
== 0)
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.
77 static int str_keyword(char** str
, const char* keyword
)
79 size_t len
= strlen(keyword
);
80 assert(str
&& keyword
);
81 if(strncmp(*str
, keyword
, len
) != 0)
84 while(isspace((unsigned char)**str
))
89 /** Add reply packet to entry */
90 static struct reply_packet
*
91 entry_add_reply(struct entry
* entry
)
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");
98 pkt
->packet_sleep
= 0;
99 pkt
->reply_pkt
= NULL
;
100 pkt
->reply_from_hex
= NULL
;
108 /** parse MATCH line */
109 static void matchline(char* line
, struct entry
* e
)
113 if(isendline(*parse
))
115 if(str_keyword(&parse
, "opcode")) {
117 } else if(str_keyword(&parse
, "qtype")) {
119 } else if(str_keyword(&parse
, "qname")) {
121 } else if(str_keyword(&parse
, "subdomain")) {
122 e
->match_subdomain
= 1;
123 } else if(str_keyword(&parse
, "all")) {
125 } else if(str_keyword(&parse
, "ttl")) {
127 } else if(str_keyword(&parse
, "DO")) {
129 } else if(str_keyword(&parse
, "noedns")) {
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")) {
137 if(*parse
!= '=' && *parse
!= ':')
138 error("expected = or : in MATCH: %s", line
);
140 e
->ixfr_soa_serial
= (uint32_t)strtol(parse
, (char**)&parse
, 10);
141 while(isspace((unsigned char)*parse
))
144 error("could not parse MATCH: '%s'", parse
);
149 /** parse REPLY line */
150 static void replyline(char* line
, uint8_t* reply
, size_t reply_len
,
154 if(reply_len
< LDNS_HEADER_SIZE
) error("packet too short for header");
156 if(isendline(*parse
))
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
);
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
);
193 } else if(str_keyword(&parse
, "QR")) {
195 } else if(str_keyword(&parse
, "AA")) {
197 } else if(str_keyword(&parse
, "TC")) {
199 } else if(str_keyword(&parse
, "RD")) {
201 } else if(str_keyword(&parse
, "CD")) {
203 } else if(str_keyword(&parse
, "RA")) {
205 } else if(str_keyword(&parse
, "AD")) {
207 } else if(str_keyword(&parse
, "DO")) {
210 error("could not parse REPLY: '%s'", parse
);
215 /** parse ADJUST line */
216 static void adjustline(char* line
, struct entry
* e
,
217 struct reply_packet
* pkt
)
221 if(isendline(*parse
))
223 if(str_keyword(&parse
, "copy_id")) {
225 } else if(str_keyword(&parse
, "copy_query")) {
227 } else if(str_keyword(&parse
, "sleep=")) {
228 e
->sleeptime
= (unsigned int) strtol(parse
, (char**)&parse
, 10);
229 while(isspace((unsigned char)*parse
))
231 } else if(str_keyword(&parse
, "packet_sleep=")) {
232 pkt
->packet_sleep
= (unsigned int) strtol(parse
, (char**)&parse
, 10);
233 while(isspace((unsigned char)*parse
))
236 error("could not parse ADJUST: '%s'", parse
);
241 /** create new entry */
242 static struct entry
* new_entry()
244 struct entry
* e
= (struct entry
*)malloc(sizeof(struct entry
));
245 if(!e
) error("out of memory");
246 memset(e
, 0, sizeof(*e
));
250 e
->match_subdomain
= 0;
256 e
->ixfr_soa_serial
= 0;
257 e
->match_transport
= transport_any
;
258 e
->reply_list
= NULL
;
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
276 hexstr2bin(char *hexstr
, int len
, uint8_t *buf
, size_t offset
, size_t buf_len
)
288 for (i
=0; i
<len
; i
++) {
291 /* case insensitive, skip spaces */
293 if (c
>= '0' && c
<= '9') {
295 } else if (c
>= 'a' && c
<= 'z') {
296 int8
+= (c
& 0x0f) + 9;
297 } else if (c
>= 'A' && c
<= 'Z') {
298 int8
+= (c
& 0x0f) + 9;
307 if (bufpos
+ offset
+ 1 <= buf_len
) {
308 buf
[bufpos
+offset
] = int8
;
313 fprintf(stderr
, "Buffer too small in hexstr2bin");
321 /** convert hex buffer to binary buffer */
322 static sldns_buffer
*
323 hex_buffer2wire(sldns_buffer
*data_buffer
)
325 sldns_buffer
*wire_buffer
= NULL
;
330 * 1 = comment (skip to end of line)
331 * 2 = unprintable character found, read binary data directly
333 size_t data_buf_pos
= 0;
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");
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
];
347 if (state
< 2 && !isascii((unsigned char)c
)) {
348 /*verbose("non ascii character found in file: (%d) switching to raw mode\n", c);*/
353 if ( (c
>= '0' && c
<= '9') ||
354 (c
>= 'a' && c
<= 'f') ||
355 (c
>= 'A' && c
<= 'F') )
357 if (hexbufpos
>= MAX_PACKETLEN
) {
358 error("buffer overflow");
363 hexbuf
[hexbufpos
] = (uint8_t) c
;
365 } else if (c
== ';') {
367 } else if (c
== ' ' || c
== '\t' || c
== '\n') {
368 /* skip whitespace */
372 if (c
== '\n' || c
== EOF
) {
377 if (hexbufpos
>= MAX_PACKETLEN
) {
378 error("buffer overflow");
382 hexbuf
[hexbufpos
] = (uint8_t) c
;
388 if (hexbufpos
>= MAX_PACKETLEN
) {
389 /*verbose("packet size reached\n");*/
392 /* lenient mode: length must be multiple of 2 */
393 if (hexbufpos
% 2 != 0) {
394 if (hexbufpos
>= MAX_PACKETLEN
) {
395 error("buffer overflow");
399 hexbuf
[hexbufpos
] = (uint8_t) '0';
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
);
408 error("Incomplete hex data, not at byte boundary\n");
417 get_origin(const char* name
, struct sldns_file_parse_state
* pstate
, char* parse
)
419 /* snip off rest of the text so as to make the parse work in ldns */
425 while(!isspace((unsigned char)*end
) && !isendline(*end
))
429 verbose(3, "parsing '%s'\n", parse
);
430 status
= sldns_str2wire_dname_buf(parse
, pstate
->origin
,
431 &pstate
->origin_len
);
434 error("%s line %d:\n\t%s: %s", name
, pstate
->lineno
,
435 sldns_get_errorstr_parse(status
), parse
);
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
)
443 /* it must be a RR, parse and add to packet. */
444 size_t rr_len
= pktsize
- *pktlen
;
445 size_t dname_len
= 0;
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");
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
);
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
);
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
);
478 /* add EDNS 4096 DO opt record */
480 add_do_flag(uint8_t* pktbuf
, size_t pktsize
, size_t* pktlen
)
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) */
490 if(*pktlen
< LDNS_HEADER_SIZE
)
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
);
499 /* Reads one entry from file. Returns entry or NULL on error. */
501 read_entry(FILE* in
, const char* name
, struct sldns_file_parse_state
* pstate
,
504 struct entry
* current
= NULL
;
507 sldns_pkt_section add_section
= LDNS_SECTION_QUESTION
;
508 struct reply_packet
*cur_reply
= NULL
;
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 */
516 while(fgets(line
, (int)sizeof(line
), in
) != NULL
) {
517 line
[MAX_LINE
-1] = 0;
521 while(isspace((unsigned char)*parse
))
523 /* test for keywords */
524 if(isendline(*parse
))
525 continue; /* skip comment and empty lines */
526 if(str_keyword(&parse
, "ENTRY_BEGIN")) {
528 error("%s line %d: previous entry does not ENTRY_END",
529 name
, pstate
->lineno
);
531 current
= new_entry();
532 current
->lineno
= pstate
->lineno
;
533 cur_reply
= entry_add_reply(current
);
535 } else if(str_keyword(&parse
, "$ORIGIN")) {
536 get_origin(name
, pstate
, parse
);
538 } else if(str_keyword(&parse
, "$TTL")) {
539 pstate
->default_ttl
= (uint32_t)atoi(parse
);
543 /* working inside an entry */
545 error("%s line %d: expected ENTRY_BEGIN but got %s",
546 name
, pstate
->lineno
, line
);
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
);
569 } else if(str_keyword(&parse
, "HEX_ANSWER_END")) {
571 error("%s line %d: HEX_ANSWER_END read but no HEX_ANSWER_BEGIN keyword seen", name
, pstate
->lineno
);
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")) {
579 sldns_buffer_free(hex_data_buffer
);
582 add_do_flag(pktbuf
, sizeof(pktbuf
),
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");
590 } else if(reading_hex
) {
591 sldns_buffer_printf(hex_data_buffer
, "%s", line
);
593 add_rr(skip_whitespace
?parse
:line
, pktbuf
,
594 sizeof(pktbuf
), &pktlen
, pstate
, add_section
,
600 error("%s: End of file reached while still reading hex, "
601 "missing HEX_ANSWER_END\n", name
);
604 error("%s: End of file reached while reading entry. "
605 "missing ENTRY_END\n", name
);
610 /* reads the canned reply file and returns a list of structs */
612 read_datafile(const char* name
, int skip_whitespace
)
614 struct entry
* list
= NULL
;
615 struct entry
* last
= NULL
;
616 struct entry
* current
= NULL
;
618 struct sldns_file_parse_state pstate
;
620 memset(&pstate
, 0, sizeof(pstate
));
622 if((in
=fopen(name
, "r")) == NULL
) {
623 error("could not open file %s: %s", name
, strerror(errno
));
626 while((current
= read_entry(in
, name
, &pstate
, skip_whitespace
)))
629 last
->next
= current
;
634 verbose(1, "%s: Read %d entries\n", prog_name
, entry_num
);
640 /** get qtype from packet */
641 static sldns_rr_type
get_qtype(uint8_t* pkt
, size_t pktlen
)
646 if(pktlen
< LDNS_HEADER_SIZE
)
648 if(LDNS_QDCOUNT(pkt
) == 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
);
656 return sldns_read_uint16(d
);
659 /** get qtype from packet */
660 static size_t get_qname_len(uint8_t* pkt
, size_t pktlen
)
665 if(pktlen
< LDNS_HEADER_SIZE
)
667 if(LDNS_QDCOUNT(pkt
) == 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
;
676 /** returns owner from packet */
677 static uint8_t* get_qname(uint8_t* pkt
, size_t pktlen
)
679 if(pktlen
< LDNS_HEADER_SIZE
)
681 if(LDNS_QDCOUNT(pkt
) == 0)
683 return pkt
+LDNS_HEADER_SIZE
;
686 /** returns opcode from packet */
687 static int get_opcode(uint8_t* pkt
, size_t pktlen
)
689 if(pktlen
< LDNS_HEADER_SIZE
)
691 return (int)LDNS_OPCODE_WIRE(pkt
);
694 /** get authority section SOA serial value */
695 static uint32_t get_serial(uint8_t* p
, size_t plen
)
698 size_t walk_len
= plen
, sl
=0;
702 if(walk_len
< LDNS_HEADER_SIZE
)
704 walk
+= LDNS_HEADER_SIZE
;
705 walk_len
-= LDNS_HEADER_SIZE
;
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
,
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
,
722 if(dlen
>= 2 && sldns_read_uint16(dstart
) == LDNS_RR_TYPE_SOA
) {
723 /* skip type, class, TTL, rdatalen */
726 if(dlen
< 10 + (size_t)sldns_read_uint16(dstart
+8))
730 /* check third rdf */
731 (void)sldns_wire2str_dname_scan(&dstart
, &dlen
, &snull
,
733 (void)sldns_wire2str_dname_scan(&dstart
, &dlen
, &snull
,
737 verbose(3, "found serial %u in msg. ",
738 (int)sldns_read_uint32(dstart
));
739 return sldns_read_uint32(dstart
);
741 /* move to next RR */
742 (void)sldns_wire2str_rr_scan(&walk
, &walk_len
, &snull
, &sl
,
748 /** get ptr to EDNS OPT record (and remaining length); behind the type u16 */
750 pkt_find_edns_opt(uint8_t** p
, size_t* plen
)
752 /* walk over the packet with scan routines */
754 size_t wlen
= *plen
, sl
=0;
758 if(wlen
< LDNS_HEADER_SIZE
)
760 w
+= LDNS_HEADER_SIZE
;
761 wlen
-= LDNS_HEADER_SIZE
;
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
,
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
);
772 /* walk through additional section */
773 for(i
=0; i
< LDNS_ARCOUNT(p
); i
++) {
774 /* if this is OPT then done */
777 (void)sldns_wire2str_dname_scan(&dstart
, &dlen
, &snull
, &sl
,
779 if(dlen
>= 2 && sldns_read_uint16(dstart
) == LDNS_RR_TYPE_OPT
) {
784 /* move to next RR */
785 (void)sldns_wire2str_rr_scan(&w
, &wlen
, &snull
, &sl
, *p
, *plen
);
790 /** return true if the packet has EDNS OPT record */
792 get_has_edns(uint8_t* pkt
, size_t len
)
794 /* use arguments as temporary variables */
795 return pkt_find_edns_opt(&pkt
, &len
);
798 /** return true if the DO flag is set */
800 get_do_flag(uint8_t* pkt
, size_t len
)
804 size_t walk_len
= len
;
805 if(pkt_find_edns_opt(&walk
, &walk_len
)) {
809 return 0; /* malformed */
810 edns_bits
= sldns_read_uint16(walk
+4);
811 return (int)(edns_bits
&LDNS_EDNS_MASK_DO_BIT
);
814 /** zero TTLs in packet */
816 zerottls(uint8_t* pkt
, size_t pktlen
)
819 size_t walk_len
= pktlen
, sl
=0;
822 uint16_t num
= LDNS_ANCOUNT(pkt
)+LDNS_NSCOUNT(pkt
)+LDNS_ARCOUNT(pkt
);
823 if(walk_len
< LDNS_HEADER_SIZE
)
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
++) {
832 uint8_t* dstart
= walk
;
833 size_t dlen
= walk_len
;
834 (void)sldns_wire2str_dname_scan(&dstart
, &dlen
, &snull
, &sl
,
838 sldns_write_uint32(dstart
+4, 0);
840 (void)sldns_wire2str_rr_scan(&walk
, &walk_len
, &snull
, &sl
,
845 /** get one line (\n) from a string, move next to after the \n, zero \n */
847 get_line(char** s
, char** n
)
849 /* at end of string? end */
850 if(*n
== NULL
|| **n
== 0)
852 /* result starts at next string */
854 /* find \n after that */
855 *n
= strchr(*s
, '\n');
864 /** match two RR sections without ordering */
866 match_noloc_section(char** q
, char** nq
, char** p
, char** np
, uint16_t num
)
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");
874 for(i
=0; i
<num
; i
++) {
880 /* see if they are all present in the other */
881 for(i
=0; i
<num
; i
++) {
883 for(j
=0; j
<num
; j
++) {
884 if(strcmp(qlines
[i
], plines
[j
]) == 0) {
890 verbose(3, "comparenoloc: failed for %s", qlines
[i
]);
897 /** match two strings for unordered equality of RRs and everything else */
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
)
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
);
908 /* compare RR counts */
909 if(LDNS_QDCOUNT(p_pkt
) != LDNS_QDCOUNT(q_pkt
))
911 if(LDNS_ANCOUNT(p_pkt
) != LDNS_ANCOUNT(q_pkt
))
913 if(LDNS_NSCOUNT(p_pkt
) != LDNS_NSCOUNT(q_pkt
))
915 if(LDNS_ARCOUNT(p_pkt
) != LDNS_ARCOUNT(q_pkt
))
917 /* get a line from both; compare; at sections do section */
920 if(strcmp(q
, p
) != 0) {
921 /* header line opcode, rcode, id */
926 if(strcmp(q
, p
) != 0) {
927 /* header flags, rr counts */
930 /* ;; QUESTION SECTION */
933 if(strcmp(q
, p
) != 0) return 0;
934 if(!match_noloc_section(&q
, &nq
, &p
, &np
, LDNS_QDCOUNT(p_pkt
)))
937 /* empty line and ;; ANSWER SECTION */
940 if(strcmp(q
, p
) != 0) return 0;
943 if(strcmp(q
, p
) != 0) return 0;
944 if(!match_noloc_section(&q
, &nq
, &p
, &np
, LDNS_ANCOUNT(p_pkt
)))
947 /* empty line and ;; AUTHORITY SECTION */
950 if(strcmp(q
, p
) != 0) return 0;
953 if(strcmp(q
, p
) != 0) return 0;
954 if(!match_noloc_section(&q
, &nq
, &p
, &np
, LDNS_NSCOUNT(p_pkt
)))
957 /* empty line and ;; ADDITIONAL SECTION */
960 if(strcmp(q
, p
) != 0) return 0;
963 if(strcmp(q
, p
) != 0) return 0;
964 if(!match_noloc_section(&q
, &nq
, &p
, &np
, LDNS_ARCOUNT(p_pkt
)))
970 /** lowercase domain name - does not follow compression pointers */
971 static void lowercase_dname(uint8_t** p
, size_t* remain
)
974 if(*remain
== 0) return;
977 if((**p
& 0xc0) == 0xc0) {
982 llen
= (unsigned int)**p
;
986 llen
= (unsigned int)*remain
;
987 for(i
=0; i
<llen
; i
++) {
988 (*p
)[i
] = (uint8_t)tolower((int)(*p
)[i
]);
992 if(*remain
== 0) return;
994 /* skip root label */
999 /** lowercase rdata of type */
1000 static void lowercase_rdata(uint8_t** p
, size_t* remain
,
1001 uint16_t rdatalen
, uint16_t t
)
1003 const sldns_rr_descriptor
*desc
= sldns_rr_descript(t
);
1004 uint8_t dname_count
= 0;
1006 size_t rdataremain
= rdatalen
;
1010 *remain
-= rdatalen
;
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
);
1018 } else if(f
== LDNS_RDF_TYPE_STR
) {
1020 if(rdataremain
== 0) return;
1023 rdataremain
-= len
+1;
1027 case LDNS_RDF_TYPE_CLASS
:
1028 case LDNS_RDF_TYPE_ALG
:
1029 case LDNS_RDF_TYPE_INT8
:
1032 case LDNS_RDF_TYPE_INT16
:
1033 case LDNS_RDF_TYPE_TYPE
:
1034 case LDNS_RDF_TYPE_CERT_ALG
:
1037 case LDNS_RDF_TYPE_INT32
:
1038 case LDNS_RDF_TYPE_TIME
:
1039 case LDNS_RDF_TYPE_A
:
1040 case LDNS_RDF_TYPE_PERIOD
:
1043 case LDNS_RDF_TYPE_TSIGTIME
:
1046 case LDNS_RDF_TYPE_AAAA
:
1049 default: error("bad rdf type in lowercase %d", (int)f
);
1055 /* skip remainder of rdata */
1057 *remain
-= rdatalen
;
1060 /** lowercase all names in the message */
1061 static void lowercase_pkt(uint8_t* pkt
, size_t pktlen
)
1065 size_t remain
= pktlen
;
1066 uint16_t t
, rdatalen
;
1067 if(pktlen
< LDNS_HEADER_SIZE
)
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;
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);
1084 if(remain
< rdatalen
) return;
1085 lowercase_rdata(&p
, &remain
, rdatalen
, t
);
1089 /** match all of the packet */
1091 match_all(uint8_t* q
, size_t qlen
, uint8_t* p
, size_t plen
, int mttl
,
1095 uint8_t* qb
= q
, *pb
= p
;
1098 qb
= memdup(q
, qlen
);
1099 pb
= memdup(p
, plen
);
1100 if(!qb
|| !pb
) error("out of memory");
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);
1112 /* remove ;; MSG SIZE (at end of string) */
1113 char* s
= strstr(qstr
, ";; MSG SIZE");
1115 s
= strstr(pstr
, ";; MSG SIZE");
1117 r
= (strcmp(qstr
, pstr
) == 0);
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");
1128 /* check for reordered sections */
1129 r
= match_noloc(qstr
, pstr
, q
, qlen
, p
, plen
);
1138 /** see if domain names are equal */
1139 static int equal_dname(uint8_t* q
, size_t qlen
, uint8_t* p
, size_t plen
)
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
;
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);
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
)
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
;
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)
1171 /* qs must end in ps, at a dot, without \ in front */
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
]=='\\') {
1183 if(slashcount%1
== 1) return 0; /* . preceded by \ */
1189 /* finds entry in list, or returns NULL */
1191 find_match(struct entry
* entries
, uint8_t* query_pkt
, size_t len
,
1192 enum transport_type transport
)
1194 struct entry
* p
= entries
;
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");
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
));
1211 if(p
->match_qname
) {
1212 if(!equal_dname(query_pkt
, len
, reply
, rlen
)) {
1213 verbose(3, "bad qname\n");
1217 if(p
->match_subdomain
) {
1218 if(!subdomain_dname(query_pkt
, len
, reply
, rlen
)) {
1219 verbose(3, "bad subdomain\n");
1223 if(p
->match_serial
&& get_serial(query_pkt
, len
) != p
->ixfr_soa_serial
) {
1224 verbose(3, "bad serial\n");
1227 if(p
->match_do
&& !get_do_flag(query_pkt
, len
)) {
1228 verbose(3, "no DO bit set\n");
1231 if(p
->match_noedns
&& get_has_edns(query_pkt
, len
)) {
1232 verbose(3, "bad; EDNS OPT present\n");
1235 if(p
->match_transport
!= transport_any
&& p
->match_transport
!= transport
) {
1236 verbose(3, "bad transport\n");
1239 if(p
->match_all
&& !match_all(query_pkt
, len
, reply
, rlen
,
1240 (int)p
->match_ttl
, 0)) {
1241 verbose(3, "bad allmatch\n");
1244 verbose(3, "match!\n");
1251 adjust_packet(struct entry
* match
, uint8_t** answer_pkt
, size_t *answer_len
,
1252 uint8_t* query_pkt
, size_t query_len
)
1254 uint8_t* orig
= *answer_pkt
;
1255 size_t origlen
= *answer_len
;
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
);
1268 verbose(1, "out of memory; send without adjust\n");
1271 /* copy the header, query, remainder */
1272 memcpy(res
, orig
, LDNS_HEADER_SIZE
);
1273 memmove(res
+LDNS_HEADER_SIZE
, query_pkt
+LDNS_HEADER_SIZE
,
1275 memmove(res
+LDNS_HEADER_SIZE
+dlen
+4, orig
+LDNS_HEADER_SIZE
,
1276 reslen
-(LDNS_HEADER_SIZE
+dlen
+4));
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
);
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
);
1296 verbose(1, "out of memory; send without adjust\n");
1299 /* copy the header, query, remainder */
1300 memcpy(res
, orig
, LDNS_HEADER_SIZE
);
1301 memmove(res
+LDNS_HEADER_SIZE
, query_pkt
+LDNS_HEADER_SIZE
,
1303 memmove(res
+LDNS_HEADER_SIZE
+dlen
+4,
1304 orig
+LDNS_HEADER_SIZE
+olen
+4,
1305 reslen
-(LDNS_HEADER_SIZE
+dlen
+4));
1307 res
= memdup(orig
, origlen
);
1311 verbose(1, "out of memory; send without adjust\n");
1315 if(match
->copy_id
&& reslen
>= 2)
1317 if(match
->copy_id
&& reslen
>= 1)
1320 if(match
->sleeptime
> 0) {
1321 verbose(3, "sleeping for %d seconds\n", match
->sleeptime
);
1323 sleep(match
->sleeptime
);
1325 Sleep(match
->sleeptime
* 1000);
1329 *answer_len
= reslen
;
1333 * Parses data buffer to a query, finds the correct answer
1334 * and calls the given function for every packet to send.
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
)
1341 struct reply_packet
*p
;
1342 uint8_t *outbuf
= NULL
;
1344 struct entry
* entry
= NULL
;
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
);
1350 char* out
= sldns_wire2str_pkt(inbuf
, (size_t)inlen
);
1351 printf("%s\n", out
);
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");
1361 for(p
= entry
->reply_list
; p
; p
= p
->next
)
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
);
1372 outbuf
= p
->reply_pkt
;
1373 outlen
= p
->reply_len
;
1376 verbose(1, "out of memory\n");
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
);
1383 char* out
= sldns_wire2str_pkt(outbuf
, outlen
);
1384 printf("%s\n", out
);
1387 if(p
->packet_sleep
) {
1388 verbose(3, "sleeping for next packet %d secs\n",
1391 sleep(p
->packet_sleep
);
1393 Sleep(p
->packet_sleep
* 1000);
1395 verbose(3, "wakeup for next packet "
1396 "(slept %d secs)\n", p
->packet_sleep
);
1398 sendfunc(outbuf
, outlen
, userdata
);
1405 /** delete the list of reply packets */
1406 void delete_replylist(struct reply_packet
* replist
)
1408 struct reply_packet
*p
=replist
, *np
;
1412 sldns_buffer_free(p
->reply_from_hex
);
1418 void delete_entry(struct entry
* list
)
1420 struct entry
*p
=list
, *np
;
1423 delete_replylist(p
->reply_list
);