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