xref: /netbsd-src/external/bsd/unbound/dist/testcode/unitmsgparse.c (revision 7a540f2bd4f5b968566c2607d6462c7f2fb452cf)
13b6c3722Schristos /*
23b6c3722Schristos  * testcode/unitmsgparse.c - unit test for msg parse routines.
33b6c3722Schristos  *
43b6c3722Schristos  * Copyright (c) 2007, NLnet Labs. All rights reserved.
53b6c3722Schristos  *
63b6c3722Schristos  * This software is open source.
73b6c3722Schristos  *
83b6c3722Schristos  * Redistribution and use in source and binary forms, with or without
93b6c3722Schristos  * modification, are permitted provided that the following conditions
103b6c3722Schristos  * are met:
113b6c3722Schristos  *
123b6c3722Schristos  * Redistributions of source code must retain the above copyright notice,
133b6c3722Schristos  * this list of conditions and the following disclaimer.
143b6c3722Schristos  *
153b6c3722Schristos  * Redistributions in binary form must reproduce the above copyright notice,
163b6c3722Schristos  * this list of conditions and the following disclaimer in the documentation
173b6c3722Schristos  * and/or other materials provided with the distribution.
183b6c3722Schristos  *
193b6c3722Schristos  * Neither the name of the NLNET LABS nor the names of its contributors may
203b6c3722Schristos  * be used to endorse or promote products derived from this software without
213b6c3722Schristos  * specific prior written permission.
223b6c3722Schristos  *
233b6c3722Schristos  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
243b6c3722Schristos  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
253b6c3722Schristos  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
263b6c3722Schristos  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
273b6c3722Schristos  * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
283b6c3722Schristos  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
293b6c3722Schristos  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
303b6c3722Schristos  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
313b6c3722Schristos  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
323b6c3722Schristos  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
333b6c3722Schristos  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
343b6c3722Schristos  *
353b6c3722Schristos  */
363b6c3722Schristos /**
373b6c3722Schristos  * \file
383b6c3722Schristos  * Calls msg parse unit tests. Exits with code 1 on a failure.
393b6c3722Schristos  */
403b6c3722Schristos 
413b6c3722Schristos #include "config.h"
423b6c3722Schristos #include <sys/time.h>
433b6c3722Schristos #include "util/log.h"
443b6c3722Schristos #include "testcode/unitmain.h"
453b6c3722Schristos #include "util/data/msgparse.h"
463b6c3722Schristos #include "util/data/msgreply.h"
473b6c3722Schristos #include "util/data/msgencode.h"
483b6c3722Schristos #include "util/data/dname.h"
493b6c3722Schristos #include "util/alloc.h"
503b6c3722Schristos #include "util/regional.h"
513b6c3722Schristos #include "util/net_help.h"
523b6c3722Schristos #include "testcode/readhex.h"
533b6c3722Schristos #include "testcode/testpkts.h"
543b6c3722Schristos #include "sldns/sbuffer.h"
553b6c3722Schristos #include "sldns/str2wire.h"
563b6c3722Schristos #include "sldns/wire2str.h"
573b6c3722Schristos 
583b6c3722Schristos /** verbose message parse unit test */
593b6c3722Schristos static int vbmp = 0;
603b6c3722Schristos /** do not accept formerr */
613b6c3722Schristos static int check_formerr_gone = 0;
623b6c3722Schristos /** if matching within a section should disregard the order of RRs. */
633b6c3722Schristos static int matches_nolocation = 0;
643b6c3722Schristos /** see if RRSIGs are properly matched to RRsets. */
653b6c3722Schristos static int check_rrsigs = 0;
663b6c3722Schristos /** do not check buffer sameness */
673b6c3722Schristos static int check_nosameness = 0;
683b6c3722Schristos 
693b6c3722Schristos /** see if buffers contain the same packet */
703b6c3722Schristos static int
test_buffers(sldns_buffer * pkt,sldns_buffer * out)713b6c3722Schristos test_buffers(sldns_buffer* pkt, sldns_buffer* out)
723b6c3722Schristos {
733b6c3722Schristos 	/* check binary same */
743b6c3722Schristos 	if(sldns_buffer_limit(pkt) == sldns_buffer_limit(out) &&
753b6c3722Schristos 		memcmp(sldns_buffer_begin(pkt), sldns_buffer_begin(out),
763b6c3722Schristos 			sldns_buffer_limit(pkt)) == 0) {
773b6c3722Schristos 		if(vbmp) printf("binary the same (length=%u)\n",
783b6c3722Schristos 				(unsigned)sldns_buffer_limit(pkt));
793b6c3722Schristos 		return 1;
803b6c3722Schristos 	}
813b6c3722Schristos 
823b6c3722Schristos 	if(vbmp) {
833b6c3722Schristos 		size_t sz = 16;
843b6c3722Schristos 		size_t count;
853b6c3722Schristos 		size_t lim = sldns_buffer_limit(out);
863b6c3722Schristos 		if(sldns_buffer_limit(pkt) < lim)
873b6c3722Schristos 			lim = sldns_buffer_limit(pkt);
883b6c3722Schristos 		for(count=0; count<lim; count+=sz) {
893b6c3722Schristos 			size_t rem = sz;
903b6c3722Schristos 			if(lim-count < sz) rem = lim-count;
913b6c3722Schristos 			if(memcmp(sldns_buffer_at(pkt, count),
923b6c3722Schristos 				sldns_buffer_at(out, count), rem) == 0) {
933b6c3722Schristos 				log_info("same %d %d", (int)count, (int)rem);
943b6c3722Schristos 				log_hex("same: ", sldns_buffer_at(pkt, count),
953b6c3722Schristos 					rem);
963b6c3722Schristos 			} else {
973b6c3722Schristos 				log_info("diff %d %d", (int)count, (int)rem);
983b6c3722Schristos 				log_hex("difp: ", sldns_buffer_at(pkt, count),
993b6c3722Schristos 					rem);
1003b6c3722Schristos 				log_hex("difo: ", sldns_buffer_at(out, count),
1013b6c3722Schristos 					rem);
1023b6c3722Schristos 			}
1033b6c3722Schristos 		}
1043b6c3722Schristos 	}
1053b6c3722Schristos 
1063b6c3722Schristos 	/* check if it 'means the same' */
1073b6c3722Schristos 	if(vbmp) {
1083b6c3722Schristos 		char* s1, *s2;
1093b6c3722Schristos 		log_buf(0, "orig in hex", pkt);
1103b6c3722Schristos 		log_buf(0, "unbound out in hex", out);
1113b6c3722Schristos 		printf("\npacket from unbound (%d):\n",
1123b6c3722Schristos 			(int)sldns_buffer_limit(out));
1133b6c3722Schristos 		s1 = sldns_wire2str_pkt(sldns_buffer_begin(out),
1143b6c3722Schristos 			sldns_buffer_limit(out));
1153b6c3722Schristos 		printf("%s\n", s1?s1:"null");
1163b6c3722Schristos 		free(s1);
1173b6c3722Schristos 
1183b6c3722Schristos 		printf("\npacket original (%d):\n",
1193b6c3722Schristos 			(int)sldns_buffer_limit(pkt));
1203b6c3722Schristos 		s2 = sldns_wire2str_pkt(sldns_buffer_begin(pkt),
1213b6c3722Schristos 			sldns_buffer_limit(pkt));
1223b6c3722Schristos 		printf("%s\n", s2?s2:"null");
1233b6c3722Schristos 		free(s2);
1243b6c3722Schristos 		printf("\n");
1253b6c3722Schristos 	}
1263b6c3722Schristos 	/* if it had two EDNS sections, skip comparison */
1273b6c3722Schristos 	if(1) {
1283b6c3722Schristos 		char* s = sldns_wire2str_pkt(sldns_buffer_begin(pkt),
1293b6c3722Schristos 			sldns_buffer_limit(pkt));
1303b6c3722Schristos 		char* e1 = strstr(s, "; EDNS:");
1313b6c3722Schristos 		if(e1 && strstr(e1+4, "; EDNS:")) {
1323b6c3722Schristos 			free(s);
1333b6c3722Schristos 			return 0;
1343b6c3722Schristos 		}
1353b6c3722Schristos 		free(s);
1363b6c3722Schristos 	}
1373b6c3722Schristos 	/* compare packets */
1383b6c3722Schristos 	unit_assert(match_all(sldns_buffer_begin(pkt), sldns_buffer_limit(pkt),
1393b6c3722Schristos 		sldns_buffer_begin(out), sldns_buffer_limit(out), 1,
140*7a540f2bSchristos 		matches_nolocation, 0));
1413b6c3722Schristos 	return 0;
1423b6c3722Schristos }
1433b6c3722Schristos 
1443b6c3722Schristos /** check if unbound formerr equals ldns formerr */
1453b6c3722Schristos static void
checkformerr(sldns_buffer * pkt)1463b6c3722Schristos checkformerr(sldns_buffer* pkt)
1473b6c3722Schristos {
1483b6c3722Schristos 	int status = 0;
1493b6c3722Schristos 	char* s = sldns_wire2str_pkt(sldns_buffer_begin(pkt),
1503b6c3722Schristos 		sldns_buffer_limit(pkt));
1513b6c3722Schristos 	if(!s) fatal_exit("out of memory");
1523b6c3722Schristos 	if(strstr(s, "Error")) status = 1;
1533b6c3722Schristos 	if(strstr(s, "error")) status = 1;
1543b6c3722Schristos 	if(status == 0) {
1553b6c3722Schristos 		printf("Formerr, but ldns gives packet:\n");
1563b6c3722Schristos 		printf("%s\n", s);
1573b6c3722Schristos 		free(s);
1583b6c3722Schristos 		exit(1);
1593b6c3722Schristos 	}
1603b6c3722Schristos 	free(s);
1613b6c3722Schristos 	unit_assert(status != 0);
1623b6c3722Schristos }
1633b6c3722Schristos 
1643b6c3722Schristos /** performance test message encoding */
1653b6c3722Schristos static void
perf_encode(struct query_info * qi,struct reply_info * rep,uint16_t id,uint16_t flags,sldns_buffer * out,time_t timenow,struct edns_data * edns)1663b6c3722Schristos perf_encode(struct query_info* qi, struct reply_info* rep, uint16_t id,
1673b6c3722Schristos 	uint16_t flags, sldns_buffer* out, time_t timenow,
1683b6c3722Schristos 	struct edns_data* edns)
1693b6c3722Schristos {
1703b6c3722Schristos 	static int num = 0;
1713b6c3722Schristos 	int ret;
1723b6c3722Schristos 	size_t max = 10000;
1733b6c3722Schristos 	size_t i;
1743b6c3722Schristos 	struct timeval start, end;
1753b6c3722Schristos 	double dt;
1763b6c3722Schristos 	struct regional* r2 = regional_create();
1773b6c3722Schristos 	if(gettimeofday(&start, NULL) < 0)
1783b6c3722Schristos 		fatal_exit("gettimeofday: %s", strerror(errno));
1793b6c3722Schristos 	/* encode a couple times */
1803b6c3722Schristos 	for(i=0; i<max; i++) {
1813b6c3722Schristos 		ret = reply_info_encode(qi, rep, id, flags, out, timenow,
18201049ae6Schristos 			r2, 65535, (int)(edns->bits & EDNS_DO), 0);
1833b6c3722Schristos 		unit_assert(ret != 0); /* udp packets should fit */
1843b6c3722Schristos 		attach_edns_record(out, edns);
1853b6c3722Schristos 		regional_free_all(r2);
1863b6c3722Schristos 	}
1873b6c3722Schristos 	if(gettimeofday(&end, NULL) < 0)
1883b6c3722Schristos 		fatal_exit("gettimeofday: %s", strerror(errno));
1893b6c3722Schristos 	/* time in millisec */
1903b6c3722Schristos 	dt = (double)(end.tv_sec - start.tv_sec)*1000. +
1913b6c3722Schristos 		((double)end.tv_usec - (double)start.tv_usec)/1000.;
1923b6c3722Schristos 	printf("[%d] did %u in %g msec for %f encode/sec size %d\n", num++,
1933b6c3722Schristos 		(unsigned)max, dt, (double)max / (dt/1000.),
1943b6c3722Schristos 		(int)sldns_buffer_limit(out));
1953b6c3722Schristos 	regional_destroy(r2);
1963b6c3722Schristos }
1973b6c3722Schristos 
1983b6c3722Schristos /** perf test a packet */
1993b6c3722Schristos static void
perftestpkt(sldns_buffer * pkt,struct alloc_cache * alloc,sldns_buffer * out,const char * hex)2003b6c3722Schristos perftestpkt(sldns_buffer* pkt, struct alloc_cache* alloc, sldns_buffer* out,
2013b6c3722Schristos 	const char* hex)
2023b6c3722Schristos {
2033b6c3722Schristos 	struct query_info qi;
2043b6c3722Schristos 	struct reply_info* rep = 0;
2053b6c3722Schristos 	int ret;
2063b6c3722Schristos 	uint16_t id;
2073b6c3722Schristos 	uint16_t flags;
2083b6c3722Schristos 	time_t timenow = 0;
2093b6c3722Schristos 	struct regional* region = regional_create();
2103b6c3722Schristos 	struct edns_data edns;
2113b6c3722Schristos 
2123b6c3722Schristos 	hex_to_buf(pkt, hex);
2133b6c3722Schristos 	memmove(&id, sldns_buffer_begin(pkt), sizeof(id));
2143b6c3722Schristos 	if(sldns_buffer_limit(pkt) < 2)
2153b6c3722Schristos 		flags = 0;
2163b6c3722Schristos 	else	memmove(&flags, sldns_buffer_at(pkt, 2), sizeof(flags));
2173b6c3722Schristos 	flags = ntohs(flags);
2183b6c3722Schristos 	ret = reply_info_parse(pkt, alloc, &qi, &rep, region, &edns);
2193b6c3722Schristos 	if(ret != 0) {
2203b6c3722Schristos 		char rbuf[16];
2213b6c3722Schristos 		sldns_wire2str_rcode_buf(ret, rbuf, sizeof(rbuf));
2223b6c3722Schristos 		if(vbmp) printf("parse code %d: %s\n", ret, rbuf);
2233b6c3722Schristos 		if(ret == LDNS_RCODE_FORMERR)
2243b6c3722Schristos 			checkformerr(pkt);
2253b6c3722Schristos 		unit_assert(ret != LDNS_RCODE_SERVFAIL);
2263b6c3722Schristos 	} else {
2273b6c3722Schristos 		perf_encode(&qi, rep, id, flags, out, timenow, &edns);
2283b6c3722Schristos 	}
2293b6c3722Schristos 
2303b6c3722Schristos 	query_info_clear(&qi);
2313b6c3722Schristos 	reply_info_parsedelete(rep, alloc);
2323b6c3722Schristos 	regional_destroy(region);
2333b6c3722Schristos }
2343b6c3722Schristos 
2353b6c3722Schristos /** print packed rrset */
2363b6c3722Schristos static void
print_rrset(struct ub_packed_rrset_key * rrset)2373b6c3722Schristos print_rrset(struct ub_packed_rrset_key* rrset)
2383b6c3722Schristos {
2393b6c3722Schristos 	struct packed_rrset_data* d = (struct packed_rrset_data*)rrset->
2403b6c3722Schristos 	                entry.data;
2413b6c3722Schristos 	char buf[65535];
2423b6c3722Schristos 	size_t i;
2433b6c3722Schristos 	for(i=0; i<d->count+d->rrsig_count; i++) {
2443b6c3722Schristos 		if(!packed_rr_to_string(rrset, i, 0, buf, sizeof(buf)))
2453b6c3722Schristos 			printf("failedtoconvert %d\n", (int)i);
2463b6c3722Schristos 		else
2473b6c3722Schristos 			printf("%s\n", buf);
2483b6c3722Schristos 	}
2493b6c3722Schristos }
2503b6c3722Schristos 
2513b6c3722Schristos /** debug print a packet that failed */
2523b6c3722Schristos static void
print_packet_rrsets(struct query_info * qinfo,struct reply_info * rep)2533b6c3722Schristos print_packet_rrsets(struct query_info* qinfo, struct reply_info* rep)
2543b6c3722Schristos {
2553b6c3722Schristos 	size_t i;
2563b6c3722Schristos 	log_query_info(0, "failed query", qinfo);
2573b6c3722Schristos 	printf(";; ANSWER SECTION (%d rrsets)\n", (int)rep->an_numrrsets);
2583b6c3722Schristos 	for(i=0; i<rep->an_numrrsets; i++) {
2593b6c3722Schristos 		printf("; rrset %d\n", (int)i);
2603b6c3722Schristos 		print_rrset(rep->rrsets[i]);
2613b6c3722Schristos 	}
2623b6c3722Schristos 	printf(";; AUTHORITY SECTION (%d rrsets)\n", (int)rep->ns_numrrsets);
2633b6c3722Schristos 	for(i=rep->an_numrrsets; i<rep->an_numrrsets+rep->ns_numrrsets; i++) {
2643b6c3722Schristos 		printf("; rrset %d\n", (int)i);
2653b6c3722Schristos 		print_rrset(rep->rrsets[i]);
2663b6c3722Schristos 	}
2673b6c3722Schristos 	printf(";; ADDITIONAL SECTION (%d rrsets)\n", (int)rep->ar_numrrsets);
2683b6c3722Schristos 	for(i=rep->an_numrrsets+rep->ns_numrrsets; i<rep->rrset_count; i++) {
2693b6c3722Schristos 		printf("; rrset %d\n", (int)i);
2703b6c3722Schristos 		print_rrset(rep->rrsets[i]);
2713b6c3722Schristos 	}
2723b6c3722Schristos 	printf(";; packet end\n");
2733b6c3722Schristos }
2743b6c3722Schristos 
2753b6c3722Schristos /** check that there is no data element that matches the RRSIG */
2763b6c3722Schristos static int
no_data_for_rrsig(struct reply_info * rep,struct ub_packed_rrset_key * rrsig)2773b6c3722Schristos no_data_for_rrsig(struct reply_info* rep, struct ub_packed_rrset_key* rrsig)
2783b6c3722Schristos {
2793b6c3722Schristos 	size_t i;
2803b6c3722Schristos 	for(i=0; i<rep->rrset_count; i++) {
2813b6c3722Schristos 		if(ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_RRSIG)
2823b6c3722Schristos 			continue;
2833b6c3722Schristos 		if(query_dname_compare(rep->rrsets[i]->rk.dname,
2843b6c3722Schristos 			rrsig->rk.dname) == 0)
2853b6c3722Schristos 			/* only name is compared right now */
2863b6c3722Schristos 			return 0;
2873b6c3722Schristos 	}
2883b6c3722Schristos 	return 1;
2893b6c3722Schristos }
2903b6c3722Schristos 
2913b6c3722Schristos /** check RRSIGs in packet */
2923b6c3722Schristos static void
check_the_rrsigs(struct query_info * qinfo,struct reply_info * rep)2933b6c3722Schristos check_the_rrsigs(struct query_info* qinfo, struct reply_info* rep)
2943b6c3722Schristos {
2953b6c3722Schristos 	/* every RRSIG must be matched to an RRset */
2963b6c3722Schristos 	size_t i;
2973b6c3722Schristos 	for(i=0; i<rep->rrset_count; i++) {
2983b6c3722Schristos 		struct ub_packed_rrset_key* s = rep->rrsets[i];
2993b6c3722Schristos 		if(ntohs(s->rk.type) == LDNS_RR_TYPE_RRSIG) {
3003b6c3722Schristos 			/* see if really a problem, i.e. is there a data
3013b6c3722Schristos 			 * element. */
3023b6c3722Schristos 			if(no_data_for_rrsig(rep, rep->rrsets[i]))
3033b6c3722Schristos 				continue;
3043b6c3722Schristos 			log_dns_msg("rrsig failed for packet", qinfo, rep);
3053b6c3722Schristos 			print_packet_rrsets(qinfo, rep);
3063b6c3722Schristos 			printf("failed rrset is nr %d\n", (int)i);
3073b6c3722Schristos 			unit_assert(0);
3083b6c3722Schristos 		}
3093b6c3722Schristos 	}
3103b6c3722Schristos }
3113b6c3722Schristos 
3123b6c3722Schristos /** test a packet */
3133b6c3722Schristos static void
testpkt(sldns_buffer * pkt,struct alloc_cache * alloc,sldns_buffer * out,const char * hex)3143b6c3722Schristos testpkt(sldns_buffer* pkt, struct alloc_cache* alloc, sldns_buffer* out,
3153b6c3722Schristos 	const char* hex)
3163b6c3722Schristos {
3173b6c3722Schristos 	struct query_info qi;
3183b6c3722Schristos 	struct reply_info* rep = 0;
3193b6c3722Schristos 	int ret;
3203b6c3722Schristos 	uint16_t id;
3213b6c3722Schristos 	uint16_t flags;
3223b6c3722Schristos 	uint32_t timenow = 0;
3233b6c3722Schristos 	struct regional* region = regional_create();
3243b6c3722Schristos 	struct edns_data edns;
3253b6c3722Schristos 
3263b6c3722Schristos 	hex_to_buf(pkt, hex);
3273b6c3722Schristos 	memmove(&id, sldns_buffer_begin(pkt), sizeof(id));
3283b6c3722Schristos 	if(sldns_buffer_limit(pkt) < 2)
3293b6c3722Schristos 		flags = 0;
3303b6c3722Schristos 	else	memmove(&flags, sldns_buffer_at(pkt, 2), sizeof(flags));
3313b6c3722Schristos 	flags = ntohs(flags);
3323b6c3722Schristos 	ret = reply_info_parse(pkt, alloc, &qi, &rep, region, &edns);
3333b6c3722Schristos 	if(ret != 0) {
3343b6c3722Schristos 		char rbuf[16];
3353b6c3722Schristos 		sldns_wire2str_rcode_buf(ret, rbuf, sizeof(rbuf));
3363b6c3722Schristos 		if(vbmp) printf("parse code %d: %s\n", ret, rbuf);
3373b6c3722Schristos 		if(ret == LDNS_RCODE_FORMERR) {
3383b6c3722Schristos 			unit_assert(!check_formerr_gone);
3393b6c3722Schristos 			checkformerr(pkt);
3403b6c3722Schristos 		}
3413b6c3722Schristos 		unit_assert(ret != LDNS_RCODE_SERVFAIL);
3423b6c3722Schristos 	} else if(!check_formerr_gone) {
3433b6c3722Schristos 		const size_t lim = 512;
3443b6c3722Schristos 		ret = reply_info_encode(&qi, rep, id, flags, out, timenow,
34501049ae6Schristos 			region, 65535, (int)(edns.bits & EDNS_DO), 0);
3463b6c3722Schristos 		unit_assert(ret != 0); /* udp packets should fit */
3473b6c3722Schristos 		attach_edns_record(out, &edns);
3483b6c3722Schristos 		if(vbmp) printf("inlen %u outlen %u\n",
3493b6c3722Schristos 			(unsigned)sldns_buffer_limit(pkt),
3503b6c3722Schristos 			(unsigned)sldns_buffer_limit(out));
3513b6c3722Schristos 		if(!check_nosameness)
3523b6c3722Schristos 			test_buffers(pkt, out);
3533b6c3722Schristos 		if(check_rrsigs)
3543b6c3722Schristos 			check_the_rrsigs(&qi, rep);
3553b6c3722Schristos 
3563b6c3722Schristos 		if(sldns_buffer_limit(out) > lim) {
3573b6c3722Schristos 			ret = reply_info_encode(&qi, rep, id, flags, out,
3583b6c3722Schristos 				timenow, region,
3593b6c3722Schristos 				lim - calc_edns_field_size(&edns),
36001049ae6Schristos 				(int)(edns.bits & EDNS_DO), 0);
3613b6c3722Schristos 			unit_assert(ret != 0); /* should fit, but with TC */
3623b6c3722Schristos 			attach_edns_record(out, &edns);
3633b6c3722Schristos 			if( LDNS_QDCOUNT(sldns_buffer_begin(out)) !=
3643b6c3722Schristos 				LDNS_QDCOUNT(sldns_buffer_begin(pkt)) ||
3653b6c3722Schristos 				LDNS_ANCOUNT(sldns_buffer_begin(out)) !=
3663b6c3722Schristos 				LDNS_ANCOUNT(sldns_buffer_begin(pkt)) ||
3673b6c3722Schristos 				LDNS_NSCOUNT(sldns_buffer_begin(out)) !=
3683b6c3722Schristos 				LDNS_NSCOUNT(sldns_buffer_begin(pkt)))
3693b6c3722Schristos 				unit_assert(
3703b6c3722Schristos 				LDNS_TC_WIRE(sldns_buffer_begin(out)));
3713b6c3722Schristos 				/* must set TC bit if shortened */
3723b6c3722Schristos 			unit_assert(sldns_buffer_limit(out) <= lim);
3733b6c3722Schristos 		}
3743b6c3722Schristos 	}
3753b6c3722Schristos 
3763b6c3722Schristos 	query_info_clear(&qi);
3773b6c3722Schristos 	reply_info_parsedelete(rep, alloc);
3783b6c3722Schristos 	regional_destroy(region);
3793b6c3722Schristos }
3803b6c3722Schristos 
3813b6c3722Schristos /** simple test of parsing */
3823b6c3722Schristos static void
simpletest(sldns_buffer * pkt,struct alloc_cache * alloc,sldns_buffer * out)3833b6c3722Schristos simpletest(sldns_buffer* pkt, struct alloc_cache* alloc, sldns_buffer* out)
3843b6c3722Schristos {
3853b6c3722Schristos 	/* a root query  drill -q - */
3863b6c3722Schristos 	testpkt(pkt, alloc, out,
3873b6c3722Schristos 		" c5 40 01 00 00 01 00 00 00 00 00 00 00 00 02 00 01 ");
3883b6c3722Schristos 
3893b6c3722Schristos 	/* very small packet */
3903b6c3722Schristos 	testpkt(pkt, alloc, out,
3913b6c3722Schristos "; 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19\n"
3923b6c3722Schristos ";-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --\n"
3933b6c3722Schristos "74 0c 85 83 00 01 00 00 00 01 00 00 03 62 6c 61 09 6e 6c 6e    ;          1-  20\n"
3943b6c3722Schristos "65 74 6c 61 62 73 02 6e 6c 00 00 0f 00 01 09 6e 6c 6e 65 74    ;         21-  40\n"
3953b6c3722Schristos "6c 61 62 73 02 6e 6c 00 00 06 00 01 00 00 46 50 00 40 04 6f    ;         41-  60\n"
3963b6c3722Schristos "70 65 6e 09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 0a 68 6f    ;         61-  80\n"
3973b6c3722Schristos "73 74 6d 61 73 74 65 72 09 6e 6c 6e 65 74 6c 61 62 73 02 6e    ;         81- 100\n"
3983b6c3722Schristos "6c 00 77 a1 02 58 00 00 70 80 00 00 1c 20 00 09 3a 80 00 00    ;        101- 120\n"
3993b6c3722Schristos "46 50\n");
4003b6c3722Schristos 
4013b6c3722Schristos 	/* a root reply  drill -w - */
4023b6c3722Schristos 	testpkt(pkt, alloc, out,
4033b6c3722Schristos 	" ; 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19\n"
4043b6c3722Schristos 	" ;-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --\n"
4053b6c3722Schristos 	" 97 3f 81 80 00 01 00 0d 00 00 00 02 00 00 02 00 01 00 00 02    ;          1-  20\n"
4063b6c3722Schristos 	" 00 01 00 06 6d 38 00 14 01 49 0c 52 4f 4f 54 2d 53 45 52 56    ;         21-  40\n"
4073b6c3722Schristos 	" 45 52 53 03 4e 45 54 00 00 00 02 00 01 00 06 6d 38 00 14 01    ;         41-  60\n"
4083b6c3722Schristos 	" 4a 0c 52 4f 4f 54 2d 53 45 52 56 45 52 53 03 4e 45 54 00 00    ;         61-  80\n"
4093b6c3722Schristos 	" 00 02 00 01 00 06 6d 38 00 14 01 4b 0c 52 4f 4f 54 2d 53 45    ;         81- 100\n"
4103b6c3722Schristos 	" 52 56 45 52 53 03 4e 45 54 00 00 00 02 00 01 00 06 6d 38 00    ;        101- 120\n"
4113b6c3722Schristos 	" 14 01 4c 0c 52 4f 4f 54 2d 53 45 52 56 45 52 53 03 4e 45 54    ;        121- 140\n"
4123b6c3722Schristos 	" 00 00 00 02 00 01 00 06 6d 38 00 14 01 4d 0c 52 4f 4f 54 2d    ;        141- 160\n"
4133b6c3722Schristos 	" 53 45 52 56 45 52 53 03 4e 45 54 00 00 00 02 00 01 00 06 6d    ;        161- 180\n"
4143b6c3722Schristos 	" 38 00 14 01 41 0c 52 4f 4f 54 2d 53 45 52 56 45 52 53 03 4e    ;        181- 200\n"
4153b6c3722Schristos 	" 45 54 00 00 00 02 00 01 00 06 6d 38 00 14 01 42 0c 52 4f 4f    ;        201- 220\n"
4163b6c3722Schristos 	" 54 2d 53 45 52 56 45 52 53 03 4e 45 54 00 00 00 02 00 01 00    ;        221- 240\n"
4173b6c3722Schristos 	" 06 6d 38 00 14 01 43 0c 52 4f 4f 54 2d 53 45 52 56 45 52 53    ;        241- 260\n"
4183b6c3722Schristos 	" 03 4e 45 54 00 00 00 02 00 01 00 06 6d 38 00 14 01 44 0c 52    ;        261- 280\n"
4193b6c3722Schristos 	" 4f 4f 54 2d 53 45 52 56 45 52 53 03 4e 45 54 00 00 00 02 00    ;        281- 300\n"
4203b6c3722Schristos 	" 01 00 06 6d 38 00 14 01 45 0c 52 4f 4f 54 2d 53 45 52 56 45    ;        301- 320\n"
4213b6c3722Schristos 	" 52 53 03 4e 45 54 00 00 00 02 00 01 00 06 6d 38 00 14 01 46    ;        321- 340\n"
4223b6c3722Schristos 	" 0c 52 4f 4f 54 2d 53 45 52 56 45 52 53 03 4e 45 54 00 00 00    ;        341- 360\n"
4233b6c3722Schristos 	" 02 00 01 00 06 6d 38 00 14 01 47 0c 52 4f 4f 54 2d 53 45 52    ;        361- 380\n"
4243b6c3722Schristos 	" 56 45 52 53 03 4e 45 54 00 00 00 02 00 01 00 06 6d 38 00 14    ;        381- 400\n"
4253b6c3722Schristos 	" 01 48 0c 52 4f 4f 54 2d 53 45 52 56 45 52 53 03 4e 45 54 00    ;        401- 420\n"
4263b6c3722Schristos 	" 01 41 0c 52 4f 4f 54 2d 53 45 52 56 45 52 53 03 4e 45 54 00    ;        421- 440\n"
4273b6c3722Schristos 	" 00 01 00 01 00 02 64 b9 00 04 c6 29 00 04 01 4a 0c 52 4f 4f    ;        441- 460\n"
4283b6c3722Schristos 	" 54 2d 53 45 52 56 45 52 53 03 4e 45 54 00 00 01 00 01 00 02    ;        461- 480\n"
4293b6c3722Schristos 	" 64 b9 00 04 c0 3a 80 1e  ");
4303b6c3722Schristos 
4313b6c3722Schristos 	/* root delegation from unbound trace with new AAAA glue */
4323b6c3722Schristos 	perftestpkt(pkt, alloc, out,
4333b6c3722Schristos 	"55BC84000001000D00000014000002000100000200010007E900001401610C726F6F742D73657276657273036E65740000000200010007E90000040162C01E00000200010007E90000040163C01E00000200010007E90000040164C01E00000200010007E90000040165C01E00000200010007E90000040166C01E00000200010007E90000040167C01E00000200010007E90000040168C01E00000200010007E90000040169C01E00000200010007E9000004016AC01E00000200010007E9000004016BC01E00000200010007E9000004016CC01E00000200010007E9000004016DC01EC01C000100010007E9000004C6290004C03B000100010007E9000004C0E44FC9C04A000100010007E9000004C021040CC059000100010007E900000480080A5AC068000100010007E9000004C0CBE60AC077000100010007E9000004C00505F1C086000100010007E9000004C0702404C095000100010007E9000004803F0235C0A4000100010007E9000004C0249411C0B3000100010007E9000004C03A801EC0C2000100010007E9000004C1000E81C0D1000100010007E9000004C707532AC0E0000100010007E9000004CA0C1B21C01C001C00010007E900001020010503BA3E00000000000000020030C077001C00010007E900001020010500002F0000000000000000000FC095001C00010007E90000102001050000010000"
4343b6c3722Schristos 	"00000000803F0235C0B3001C00010007E9000010200105030C2700000000000000020030C0C2001C00010007E9000010200107FD000000000000000000000001C0E0001C00010007E900001020010DC30000000000000000000000350000291000000000000000"
4353b6c3722Schristos 	);
4363b6c3722Schristos }
4373b6c3722Schristos 
4383b6c3722Schristos /** simple test of parsing, pcat file */
4393b6c3722Schristos static void
testfromfile(sldns_buffer * pkt,struct alloc_cache * alloc,sldns_buffer * out,const char * fname)4403b6c3722Schristos testfromfile(sldns_buffer* pkt, struct alloc_cache* alloc, sldns_buffer* out,
4413b6c3722Schristos 	const char* fname)
4423b6c3722Schristos {
4433b6c3722Schristos 	FILE* in = fopen(fname, "r");
4443b6c3722Schristos 	char buf[102400];
4453b6c3722Schristos 	int no=0;
4463b6c3722Schristos 	if(!in) {
4473b6c3722Schristos 		perror("fname");
4483b6c3722Schristos 		return;
4493b6c3722Schristos 	}
4503b6c3722Schristos 	while(fgets(buf, (int)sizeof(buf), in)) {
4513b6c3722Schristos 		if(buf[0] == ';') /* comment */
4523b6c3722Schristos 			continue;
4533b6c3722Schristos 		if(strlen(buf) < 10) /* skip pcat line numbers. */
4543b6c3722Schristos 			continue;
4553b6c3722Schristos 		if(vbmp) {
4563b6c3722Schristos 			printf("test no %d: %s", no, buf);
4573b6c3722Schristos 			fflush(stdout);
4583b6c3722Schristos 		}
4593b6c3722Schristos 		testpkt(pkt, alloc, out, buf);
4603b6c3722Schristos 		no++;
4613b6c3722Schristos 	}
4623b6c3722Schristos 	fclose(in);
4633b6c3722Schristos }
4643b6c3722Schristos 
4653b6c3722Schristos /** simple test of parsing, drill file */
4663b6c3722Schristos static void
testfromdrillfile(sldns_buffer * pkt,struct alloc_cache * alloc,sldns_buffer * out,const char * fname)4673b6c3722Schristos testfromdrillfile(sldns_buffer* pkt, struct alloc_cache* alloc,
4683b6c3722Schristos 	sldns_buffer* out, const char* fname)
4693b6c3722Schristos {
4703b6c3722Schristos 	/*  ;-- is used to indicate a new message */
4713b6c3722Schristos 	FILE* in = fopen(fname, "r");
4723b6c3722Schristos 	char buf[102400];
4733b6c3722Schristos 	char* np = buf;
4743b6c3722Schristos 	buf[0]=0;
4753b6c3722Schristos 	if(!in) {
4763b6c3722Schristos 		perror("fname");
4773b6c3722Schristos 		return;
4783b6c3722Schristos 	}
4793b6c3722Schristos 	while(fgets(np, (int)sizeof(buf) - (np-buf), in)) {
4803b6c3722Schristos 		if(strncmp(np, ";--", 3) == 0) {
4813b6c3722Schristos 			/* new entry */
4823b6c3722Schristos 			/* test previous */
4833b6c3722Schristos 			if(np != buf)
4843b6c3722Schristos 				testpkt(pkt, alloc, out, buf);
4853b6c3722Schristos 			/* set for new entry */
4863b6c3722Schristos 			np = buf;
4873b6c3722Schristos 			buf[0]=0;
4883b6c3722Schristos 			continue;
4893b6c3722Schristos 		}
4903b6c3722Schristos 		if(np[0] == ';') /* comment */
4913b6c3722Schristos 			continue;
4923b6c3722Schristos 		np = &np[strlen(np)];
4933b6c3722Schristos 	}
4943b6c3722Schristos 	testpkt(pkt, alloc, out, buf);
4953b6c3722Schristos 	fclose(in);
4963b6c3722Schristos }
4973b6c3722Schristos 
498f42d8de7Schristos #define xstr(s) str(s)
499f42d8de7Schristos #define str(s) #s
500f42d8de7Schristos 
501f42d8de7Schristos #define SRCDIRSTR xstr(SRCDIR)
502f42d8de7Schristos 
msgparse_test(void)5033b6c3722Schristos void msgparse_test(void)
5043b6c3722Schristos {
5053b6c3722Schristos 	time_t origttl = MAX_NEG_TTL;
5063b6c3722Schristos 	sldns_buffer* pkt = sldns_buffer_new(65553);
5073b6c3722Schristos 	sldns_buffer* out = sldns_buffer_new(65553);
5083b6c3722Schristos 	struct alloc_cache super_a, alloc;
5093b6c3722Schristos 	MAX_NEG_TTL = 86400;
5103b6c3722Schristos 	/* init */
5113b6c3722Schristos 	alloc_init(&super_a, NULL, 0);
5123b6c3722Schristos 	alloc_init(&alloc, &super_a, 2);
5133b6c3722Schristos 
5143b6c3722Schristos 	unit_show_feature("message parse");
5153b6c3722Schristos 	simpletest(pkt, &alloc, out);
5163b6c3722Schristos 	/* plain hex dumps, like pcat */
517f42d8de7Schristos 	testfromfile(pkt, &alloc, out, SRCDIRSTR "/testdata/test_packets.1");
518f42d8de7Schristos 	testfromfile(pkt, &alloc, out, SRCDIRSTR "/testdata/test_packets.2");
519f42d8de7Schristos 	testfromfile(pkt, &alloc, out, SRCDIRSTR "/testdata/test_packets.3");
5203b6c3722Schristos 	/* like from drill -w - */
521f42d8de7Schristos 	testfromdrillfile(pkt, &alloc, out, SRCDIRSTR "/testdata/test_packets.4");
522f42d8de7Schristos 	testfromdrillfile(pkt, &alloc, out, SRCDIRSTR "/testdata/test_packets.5");
5233b6c3722Schristos 
5243b6c3722Schristos 	matches_nolocation = 1; /* RR order not important for the next test */
525f42d8de7Schristos 	testfromdrillfile(pkt, &alloc, out, SRCDIRSTR "/testdata/test_packets.6");
5263b6c3722Schristos 	check_rrsigs = 1;
527f42d8de7Schristos 	testfromdrillfile(pkt, &alloc, out, SRCDIRSTR "/testdata/test_packets.7");
5283b6c3722Schristos 	check_rrsigs = 0;
5293b6c3722Schristos 	matches_nolocation = 0;
5303b6c3722Schristos 
5313b6c3722Schristos 	check_formerr_gone = 1;
532f42d8de7Schristos 	testfromdrillfile(pkt, &alloc, out, SRCDIRSTR "/testdata/test_packets.8");
5333b6c3722Schristos 	check_formerr_gone = 0;
5343b6c3722Schristos 
5353b6c3722Schristos 	check_rrsigs = 1;
5363b6c3722Schristos 	check_nosameness = 1;
537f42d8de7Schristos 	testfromdrillfile(pkt, &alloc, out, SRCDIRSTR "/testdata/test_packets.9");
5383b6c3722Schristos 	check_nosameness = 0;
5393b6c3722Schristos 	check_rrsigs = 0;
5403b6c3722Schristos 
5413b6c3722Schristos 	/* cleanup */
5423b6c3722Schristos 	alloc_clear(&alloc);
5433b6c3722Schristos 	alloc_clear(&super_a);
5443b6c3722Schristos 	sldns_buffer_free(pkt);
5453b6c3722Schristos 	sldns_buffer_free(out);
5463b6c3722Schristos 	MAX_NEG_TTL = origttl;
5473b6c3722Schristos }
548