1712b2f30Ssthen /*
2712b2f30Ssthen * testcode/unitmsgparse.c - unit test for msg parse routines.
3712b2f30Ssthen *
4712b2f30Ssthen * Copyright (c) 2007, NLnet Labs. All rights reserved.
5712b2f30Ssthen *
6712b2f30Ssthen * This software is open source.
7712b2f30Ssthen *
8712b2f30Ssthen * Redistribution and use in source and binary forms, with or without
9712b2f30Ssthen * modification, are permitted provided that the following conditions
10712b2f30Ssthen * are met:
11712b2f30Ssthen *
12712b2f30Ssthen * Redistributions of source code must retain the above copyright notice,
13712b2f30Ssthen * this list of conditions and the following disclaimer.
14712b2f30Ssthen *
15712b2f30Ssthen * Redistributions in binary form must reproduce the above copyright notice,
16712b2f30Ssthen * this list of conditions and the following disclaimer in the documentation
17712b2f30Ssthen * and/or other materials provided with the distribution.
18712b2f30Ssthen *
19712b2f30Ssthen * Neither the name of the NLNET LABS nor the names of its contributors may
20712b2f30Ssthen * be used to endorse or promote products derived from this software without
21712b2f30Ssthen * specific prior written permission.
22712b2f30Ssthen *
23712b2f30Ssthen * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24712b2f30Ssthen * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25712b2f30Ssthen * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26712b2f30Ssthen * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27712b2f30Ssthen * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28712b2f30Ssthen * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
29712b2f30Ssthen * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30712b2f30Ssthen * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31712b2f30Ssthen * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32712b2f30Ssthen * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33712b2f30Ssthen * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34712b2f30Ssthen *
35712b2f30Ssthen */
36712b2f30Ssthen /**
37712b2f30Ssthen * \file
38712b2f30Ssthen * Calls msg parse unit tests. Exits with code 1 on a failure.
39712b2f30Ssthen */
40712b2f30Ssthen
41712b2f30Ssthen #include "config.h"
42712b2f30Ssthen #include <sys/time.h>
43712b2f30Ssthen #include "util/log.h"
44712b2f30Ssthen #include "testcode/unitmain.h"
45712b2f30Ssthen #include "util/data/msgparse.h"
46712b2f30Ssthen #include "util/data/msgreply.h"
47712b2f30Ssthen #include "util/data/msgencode.h"
48712b2f30Ssthen #include "util/data/dname.h"
49712b2f30Ssthen #include "util/alloc.h"
50712b2f30Ssthen #include "util/regional.h"
51712b2f30Ssthen #include "util/net_help.h"
52712b2f30Ssthen #include "testcode/readhex.h"
53712b2f30Ssthen #include "testcode/testpkts.h"
54712b2f30Ssthen #include "sldns/sbuffer.h"
55712b2f30Ssthen #include "sldns/str2wire.h"
56712b2f30Ssthen #include "sldns/wire2str.h"
57712b2f30Ssthen
58712b2f30Ssthen /** verbose message parse unit test */
59712b2f30Ssthen static int vbmp = 0;
60712b2f30Ssthen /** do not accept formerr */
61712b2f30Ssthen static int check_formerr_gone = 0;
62712b2f30Ssthen /** if matching within a section should disregard the order of RRs. */
63712b2f30Ssthen static int matches_nolocation = 0;
64712b2f30Ssthen /** see if RRSIGs are properly matched to RRsets. */
65712b2f30Ssthen static int check_rrsigs = 0;
66712b2f30Ssthen /** do not check buffer sameness */
67712b2f30Ssthen static int check_nosameness = 0;
68712b2f30Ssthen
69712b2f30Ssthen /** see if buffers contain the same packet */
70712b2f30Ssthen static int
test_buffers(sldns_buffer * pkt,sldns_buffer * out)71712b2f30Ssthen test_buffers(sldns_buffer* pkt, sldns_buffer* out)
72712b2f30Ssthen {
73712b2f30Ssthen /* check binary same */
74712b2f30Ssthen if(sldns_buffer_limit(pkt) == sldns_buffer_limit(out) &&
75712b2f30Ssthen memcmp(sldns_buffer_begin(pkt), sldns_buffer_begin(out),
76712b2f30Ssthen sldns_buffer_limit(pkt)) == 0) {
77712b2f30Ssthen if(vbmp) printf("binary the same (length=%u)\n",
78712b2f30Ssthen (unsigned)sldns_buffer_limit(pkt));
79712b2f30Ssthen return 1;
80712b2f30Ssthen }
81712b2f30Ssthen
82712b2f30Ssthen if(vbmp) {
83712b2f30Ssthen size_t sz = 16;
84712b2f30Ssthen size_t count;
85712b2f30Ssthen size_t lim = sldns_buffer_limit(out);
86712b2f30Ssthen if(sldns_buffer_limit(pkt) < lim)
87712b2f30Ssthen lim = sldns_buffer_limit(pkt);
88712b2f30Ssthen for(count=0; count<lim; count+=sz) {
89712b2f30Ssthen size_t rem = sz;
90712b2f30Ssthen if(lim-count < sz) rem = lim-count;
91712b2f30Ssthen if(memcmp(sldns_buffer_at(pkt, count),
92712b2f30Ssthen sldns_buffer_at(out, count), rem) == 0) {
93712b2f30Ssthen log_info("same %d %d", (int)count, (int)rem);
94712b2f30Ssthen log_hex("same: ", sldns_buffer_at(pkt, count),
95712b2f30Ssthen rem);
96712b2f30Ssthen } else {
97712b2f30Ssthen log_info("diff %d %d", (int)count, (int)rem);
98712b2f30Ssthen log_hex("difp: ", sldns_buffer_at(pkt, count),
99712b2f30Ssthen rem);
100712b2f30Ssthen log_hex("difo: ", sldns_buffer_at(out, count),
101712b2f30Ssthen rem);
102712b2f30Ssthen }
103712b2f30Ssthen }
104712b2f30Ssthen }
105712b2f30Ssthen
106712b2f30Ssthen /* check if it 'means the same' */
107712b2f30Ssthen if(vbmp) {
108712b2f30Ssthen char* s1, *s2;
109712b2f30Ssthen log_buf(0, "orig in hex", pkt);
110712b2f30Ssthen log_buf(0, "unbound out in hex", out);
111712b2f30Ssthen printf("\npacket from unbound (%d):\n",
112712b2f30Ssthen (int)sldns_buffer_limit(out));
113712b2f30Ssthen s1 = sldns_wire2str_pkt(sldns_buffer_begin(out),
114712b2f30Ssthen sldns_buffer_limit(out));
115712b2f30Ssthen printf("%s\n", s1?s1:"null");
116712b2f30Ssthen free(s1);
117712b2f30Ssthen
118712b2f30Ssthen printf("\npacket original (%d):\n",
119712b2f30Ssthen (int)sldns_buffer_limit(pkt));
120712b2f30Ssthen s2 = sldns_wire2str_pkt(sldns_buffer_begin(pkt),
121712b2f30Ssthen sldns_buffer_limit(pkt));
122712b2f30Ssthen printf("%s\n", s2?s2:"null");
123712b2f30Ssthen free(s2);
124712b2f30Ssthen printf("\n");
125712b2f30Ssthen }
126712b2f30Ssthen /* if it had two EDNS sections, skip comparison */
127712b2f30Ssthen if(1) {
128712b2f30Ssthen char* s = sldns_wire2str_pkt(sldns_buffer_begin(pkt),
129712b2f30Ssthen sldns_buffer_limit(pkt));
130712b2f30Ssthen char* e1 = strstr(s, "; EDNS:");
131712b2f30Ssthen if(e1 && strstr(e1+4, "; EDNS:")) {
132712b2f30Ssthen free(s);
133712b2f30Ssthen return 0;
134712b2f30Ssthen }
135712b2f30Ssthen free(s);
136712b2f30Ssthen }
137712b2f30Ssthen /* compare packets */
138712b2f30Ssthen unit_assert(match_all(sldns_buffer_begin(pkt), sldns_buffer_limit(pkt),
139712b2f30Ssthen sldns_buffer_begin(out), sldns_buffer_limit(out), 1,
140*c2862f41Ssthen matches_nolocation, 0));
141712b2f30Ssthen return 0;
142712b2f30Ssthen }
143712b2f30Ssthen
144712b2f30Ssthen /** check if unbound formerr equals ldns formerr */
145712b2f30Ssthen static void
checkformerr(sldns_buffer * pkt)146712b2f30Ssthen checkformerr(sldns_buffer* pkt)
147712b2f30Ssthen {
148712b2f30Ssthen int status = 0;
149712b2f30Ssthen char* s = sldns_wire2str_pkt(sldns_buffer_begin(pkt),
150712b2f30Ssthen sldns_buffer_limit(pkt));
151712b2f30Ssthen if(!s) fatal_exit("out of memory");
152712b2f30Ssthen if(strstr(s, "Error")) status = 1;
153712b2f30Ssthen if(strstr(s, "error")) status = 1;
154712b2f30Ssthen if(status == 0) {
155712b2f30Ssthen printf("Formerr, but ldns gives packet:\n");
156712b2f30Ssthen printf("%s\n", s);
157712b2f30Ssthen free(s);
158712b2f30Ssthen exit(1);
159712b2f30Ssthen }
160712b2f30Ssthen free(s);
161712b2f30Ssthen unit_assert(status != 0);
162712b2f30Ssthen }
163712b2f30Ssthen
164712b2f30Ssthen /** performance test message encoding */
165712b2f30Ssthen 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)166712b2f30Ssthen perf_encode(struct query_info* qi, struct reply_info* rep, uint16_t id,
167712b2f30Ssthen uint16_t flags, sldns_buffer* out, time_t timenow,
168712b2f30Ssthen struct edns_data* edns)
169712b2f30Ssthen {
170712b2f30Ssthen static int num = 0;
171712b2f30Ssthen int ret;
172712b2f30Ssthen size_t max = 10000;
173712b2f30Ssthen size_t i;
174712b2f30Ssthen struct timeval start, end;
175712b2f30Ssthen double dt;
176712b2f30Ssthen struct regional* r2 = regional_create();
177712b2f30Ssthen if(gettimeofday(&start, NULL) < 0)
178712b2f30Ssthen fatal_exit("gettimeofday: %s", strerror(errno));
179712b2f30Ssthen /* encode a couple times */
180712b2f30Ssthen for(i=0; i<max; i++) {
181712b2f30Ssthen ret = reply_info_encode(qi, rep, id, flags, out, timenow,
182c981f76fSsthen r2, 65535, (int)(edns->bits & EDNS_DO), 0);
183712b2f30Ssthen unit_assert(ret != 0); /* udp packets should fit */
184712b2f30Ssthen attach_edns_record(out, edns);
185712b2f30Ssthen regional_free_all(r2);
186712b2f30Ssthen }
187712b2f30Ssthen if(gettimeofday(&end, NULL) < 0)
188712b2f30Ssthen fatal_exit("gettimeofday: %s", strerror(errno));
189712b2f30Ssthen /* time in millisec */
190712b2f30Ssthen dt = (double)(end.tv_sec - start.tv_sec)*1000. +
191712b2f30Ssthen ((double)end.tv_usec - (double)start.tv_usec)/1000.;
192712b2f30Ssthen printf("[%d] did %u in %g msec for %f encode/sec size %d\n", num++,
193712b2f30Ssthen (unsigned)max, dt, (double)max / (dt/1000.),
194712b2f30Ssthen (int)sldns_buffer_limit(out));
195712b2f30Ssthen regional_destroy(r2);
196712b2f30Ssthen }
197712b2f30Ssthen
198712b2f30Ssthen /** perf test a packet */
199712b2f30Ssthen static void
perftestpkt(sldns_buffer * pkt,struct alloc_cache * alloc,sldns_buffer * out,const char * hex)200712b2f30Ssthen perftestpkt(sldns_buffer* pkt, struct alloc_cache* alloc, sldns_buffer* out,
201712b2f30Ssthen const char* hex)
202712b2f30Ssthen {
203712b2f30Ssthen struct query_info qi;
204712b2f30Ssthen struct reply_info* rep = 0;
205712b2f30Ssthen int ret;
206712b2f30Ssthen uint16_t id;
207712b2f30Ssthen uint16_t flags;
208712b2f30Ssthen time_t timenow = 0;
209712b2f30Ssthen struct regional* region = regional_create();
210712b2f30Ssthen struct edns_data edns;
211712b2f30Ssthen
212712b2f30Ssthen hex_to_buf(pkt, hex);
213712b2f30Ssthen memmove(&id, sldns_buffer_begin(pkt), sizeof(id));
214712b2f30Ssthen if(sldns_buffer_limit(pkt) < 2)
215712b2f30Ssthen flags = 0;
216712b2f30Ssthen else memmove(&flags, sldns_buffer_at(pkt, 2), sizeof(flags));
217712b2f30Ssthen flags = ntohs(flags);
218712b2f30Ssthen ret = reply_info_parse(pkt, alloc, &qi, &rep, region, &edns);
219712b2f30Ssthen if(ret != 0) {
220712b2f30Ssthen char rbuf[16];
221712b2f30Ssthen sldns_wire2str_rcode_buf(ret, rbuf, sizeof(rbuf));
222712b2f30Ssthen if(vbmp) printf("parse code %d: %s\n", ret, rbuf);
223712b2f30Ssthen if(ret == LDNS_RCODE_FORMERR)
224712b2f30Ssthen checkformerr(pkt);
225712b2f30Ssthen unit_assert(ret != LDNS_RCODE_SERVFAIL);
226712b2f30Ssthen } else {
227712b2f30Ssthen perf_encode(&qi, rep, id, flags, out, timenow, &edns);
228712b2f30Ssthen }
229712b2f30Ssthen
230712b2f30Ssthen query_info_clear(&qi);
231712b2f30Ssthen reply_info_parsedelete(rep, alloc);
232712b2f30Ssthen regional_destroy(region);
233712b2f30Ssthen }
234712b2f30Ssthen
235712b2f30Ssthen /** print packed rrset */
236712b2f30Ssthen static void
print_rrset(struct ub_packed_rrset_key * rrset)237712b2f30Ssthen print_rrset(struct ub_packed_rrset_key* rrset)
238712b2f30Ssthen {
239712b2f30Ssthen struct packed_rrset_data* d = (struct packed_rrset_data*)rrset->
240712b2f30Ssthen entry.data;
241712b2f30Ssthen char buf[65535];
242712b2f30Ssthen size_t i;
243712b2f30Ssthen for(i=0; i<d->count+d->rrsig_count; i++) {
244712b2f30Ssthen if(!packed_rr_to_string(rrset, i, 0, buf, sizeof(buf)))
245712b2f30Ssthen printf("failedtoconvert %d\n", (int)i);
246712b2f30Ssthen else
247712b2f30Ssthen printf("%s\n", buf);
248712b2f30Ssthen }
249712b2f30Ssthen }
250712b2f30Ssthen
251712b2f30Ssthen /** debug print a packet that failed */
252712b2f30Ssthen static void
print_packet_rrsets(struct query_info * qinfo,struct reply_info * rep)253712b2f30Ssthen print_packet_rrsets(struct query_info* qinfo, struct reply_info* rep)
254712b2f30Ssthen {
255712b2f30Ssthen size_t i;
256712b2f30Ssthen log_query_info(0, "failed query", qinfo);
257712b2f30Ssthen printf(";; ANSWER SECTION (%d rrsets)\n", (int)rep->an_numrrsets);
258712b2f30Ssthen for(i=0; i<rep->an_numrrsets; i++) {
259712b2f30Ssthen printf("; rrset %d\n", (int)i);
260712b2f30Ssthen print_rrset(rep->rrsets[i]);
261712b2f30Ssthen }
262712b2f30Ssthen printf(";; AUTHORITY SECTION (%d rrsets)\n", (int)rep->ns_numrrsets);
263712b2f30Ssthen for(i=rep->an_numrrsets; i<rep->an_numrrsets+rep->ns_numrrsets; i++) {
264712b2f30Ssthen printf("; rrset %d\n", (int)i);
265712b2f30Ssthen print_rrset(rep->rrsets[i]);
266712b2f30Ssthen }
267712b2f30Ssthen printf(";; ADDITIONAL SECTION (%d rrsets)\n", (int)rep->ar_numrrsets);
268712b2f30Ssthen for(i=rep->an_numrrsets+rep->ns_numrrsets; i<rep->rrset_count; i++) {
269712b2f30Ssthen printf("; rrset %d\n", (int)i);
270712b2f30Ssthen print_rrset(rep->rrsets[i]);
271712b2f30Ssthen }
272712b2f30Ssthen printf(";; packet end\n");
273712b2f30Ssthen }
274712b2f30Ssthen
275712b2f30Ssthen /** check that there is no data element that matches the RRSIG */
276712b2f30Ssthen static int
no_data_for_rrsig(struct reply_info * rep,struct ub_packed_rrset_key * rrsig)277712b2f30Ssthen no_data_for_rrsig(struct reply_info* rep, struct ub_packed_rrset_key* rrsig)
278712b2f30Ssthen {
279712b2f30Ssthen size_t i;
280712b2f30Ssthen for(i=0; i<rep->rrset_count; i++) {
281712b2f30Ssthen if(ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_RRSIG)
282712b2f30Ssthen continue;
283712b2f30Ssthen if(query_dname_compare(rep->rrsets[i]->rk.dname,
284712b2f30Ssthen rrsig->rk.dname) == 0)
285712b2f30Ssthen /* only name is compared right now */
286712b2f30Ssthen return 0;
287712b2f30Ssthen }
288712b2f30Ssthen return 1;
289712b2f30Ssthen }
290712b2f30Ssthen
291712b2f30Ssthen /** check RRSIGs in packet */
292712b2f30Ssthen static void
check_the_rrsigs(struct query_info * qinfo,struct reply_info * rep)293712b2f30Ssthen check_the_rrsigs(struct query_info* qinfo, struct reply_info* rep)
294712b2f30Ssthen {
295712b2f30Ssthen /* every RRSIG must be matched to an RRset */
296712b2f30Ssthen size_t i;
297712b2f30Ssthen for(i=0; i<rep->rrset_count; i++) {
298712b2f30Ssthen struct ub_packed_rrset_key* s = rep->rrsets[i];
299712b2f30Ssthen if(ntohs(s->rk.type) == LDNS_RR_TYPE_RRSIG) {
300712b2f30Ssthen /* see if really a problem, i.e. is there a data
301712b2f30Ssthen * element. */
302712b2f30Ssthen if(no_data_for_rrsig(rep, rep->rrsets[i]))
303712b2f30Ssthen continue;
304712b2f30Ssthen log_dns_msg("rrsig failed for packet", qinfo, rep);
305712b2f30Ssthen print_packet_rrsets(qinfo, rep);
306712b2f30Ssthen printf("failed rrset is nr %d\n", (int)i);
307712b2f30Ssthen unit_assert(0);
308712b2f30Ssthen }
309712b2f30Ssthen }
310712b2f30Ssthen }
311712b2f30Ssthen
312712b2f30Ssthen /** test a packet */
313712b2f30Ssthen static void
testpkt(sldns_buffer * pkt,struct alloc_cache * alloc,sldns_buffer * out,const char * hex)314712b2f30Ssthen testpkt(sldns_buffer* pkt, struct alloc_cache* alloc, sldns_buffer* out,
315712b2f30Ssthen const char* hex)
316712b2f30Ssthen {
317712b2f30Ssthen struct query_info qi;
318712b2f30Ssthen struct reply_info* rep = 0;
319712b2f30Ssthen int ret;
320712b2f30Ssthen uint16_t id;
321712b2f30Ssthen uint16_t flags;
322712b2f30Ssthen uint32_t timenow = 0;
323712b2f30Ssthen struct regional* region = regional_create();
324712b2f30Ssthen struct edns_data edns;
325712b2f30Ssthen
326712b2f30Ssthen hex_to_buf(pkt, hex);
327712b2f30Ssthen memmove(&id, sldns_buffer_begin(pkt), sizeof(id));
328712b2f30Ssthen if(sldns_buffer_limit(pkt) < 2)
329712b2f30Ssthen flags = 0;
330712b2f30Ssthen else memmove(&flags, sldns_buffer_at(pkt, 2), sizeof(flags));
331712b2f30Ssthen flags = ntohs(flags);
332712b2f30Ssthen ret = reply_info_parse(pkt, alloc, &qi, &rep, region, &edns);
333712b2f30Ssthen if(ret != 0) {
334712b2f30Ssthen char rbuf[16];
335712b2f30Ssthen sldns_wire2str_rcode_buf(ret, rbuf, sizeof(rbuf));
336712b2f30Ssthen if(vbmp) printf("parse code %d: %s\n", ret, rbuf);
337712b2f30Ssthen if(ret == LDNS_RCODE_FORMERR) {
338712b2f30Ssthen unit_assert(!check_formerr_gone);
339712b2f30Ssthen checkformerr(pkt);
340712b2f30Ssthen }
341712b2f30Ssthen unit_assert(ret != LDNS_RCODE_SERVFAIL);
342712b2f30Ssthen } else if(!check_formerr_gone) {
343712b2f30Ssthen const size_t lim = 512;
344712b2f30Ssthen ret = reply_info_encode(&qi, rep, id, flags, out, timenow,
345c981f76fSsthen region, 65535, (int)(edns.bits & EDNS_DO), 0);
346712b2f30Ssthen unit_assert(ret != 0); /* udp packets should fit */
347712b2f30Ssthen attach_edns_record(out, &edns);
348712b2f30Ssthen if(vbmp) printf("inlen %u outlen %u\n",
349712b2f30Ssthen (unsigned)sldns_buffer_limit(pkt),
350712b2f30Ssthen (unsigned)sldns_buffer_limit(out));
351712b2f30Ssthen if(!check_nosameness)
352712b2f30Ssthen test_buffers(pkt, out);
353712b2f30Ssthen if(check_rrsigs)
354712b2f30Ssthen check_the_rrsigs(&qi, rep);
355712b2f30Ssthen
356712b2f30Ssthen if(sldns_buffer_limit(out) > lim) {
357712b2f30Ssthen ret = reply_info_encode(&qi, rep, id, flags, out,
358712b2f30Ssthen timenow, region,
359712b2f30Ssthen lim - calc_edns_field_size(&edns),
360c981f76fSsthen (int)(edns.bits & EDNS_DO), 0);
361712b2f30Ssthen unit_assert(ret != 0); /* should fit, but with TC */
362712b2f30Ssthen attach_edns_record(out, &edns);
363712b2f30Ssthen if( LDNS_QDCOUNT(sldns_buffer_begin(out)) !=
364712b2f30Ssthen LDNS_QDCOUNT(sldns_buffer_begin(pkt)) ||
365712b2f30Ssthen LDNS_ANCOUNT(sldns_buffer_begin(out)) !=
366712b2f30Ssthen LDNS_ANCOUNT(sldns_buffer_begin(pkt)) ||
367712b2f30Ssthen LDNS_NSCOUNT(sldns_buffer_begin(out)) !=
368712b2f30Ssthen LDNS_NSCOUNT(sldns_buffer_begin(pkt)))
369712b2f30Ssthen unit_assert(
370712b2f30Ssthen LDNS_TC_WIRE(sldns_buffer_begin(out)));
371712b2f30Ssthen /* must set TC bit if shortened */
372712b2f30Ssthen unit_assert(sldns_buffer_limit(out) <= lim);
373712b2f30Ssthen }
374712b2f30Ssthen }
375712b2f30Ssthen
376712b2f30Ssthen query_info_clear(&qi);
377712b2f30Ssthen reply_info_parsedelete(rep, alloc);
378712b2f30Ssthen regional_destroy(region);
379712b2f30Ssthen }
380712b2f30Ssthen
381712b2f30Ssthen /** simple test of parsing */
382712b2f30Ssthen static void
simpletest(sldns_buffer * pkt,struct alloc_cache * alloc,sldns_buffer * out)383712b2f30Ssthen simpletest(sldns_buffer* pkt, struct alloc_cache* alloc, sldns_buffer* out)
384712b2f30Ssthen {
385712b2f30Ssthen /* a root query drill -q - */
386712b2f30Ssthen testpkt(pkt, alloc, out,
387712b2f30Ssthen " c5 40 01 00 00 01 00 00 00 00 00 00 00 00 02 00 01 ");
388712b2f30Ssthen
389712b2f30Ssthen /* very small packet */
390712b2f30Ssthen testpkt(pkt, alloc, out,
391712b2f30Ssthen "; 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19\n"
392712b2f30Ssthen ";-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --\n"
393712b2f30Ssthen "74 0c 85 83 00 01 00 00 00 01 00 00 03 62 6c 61 09 6e 6c 6e ; 1- 20\n"
394712b2f30Ssthen "65 74 6c 61 62 73 02 6e 6c 00 00 0f 00 01 09 6e 6c 6e 65 74 ; 21- 40\n"
395712b2f30Ssthen "6c 61 62 73 02 6e 6c 00 00 06 00 01 00 00 46 50 00 40 04 6f ; 41- 60\n"
396712b2f30Ssthen "70 65 6e 09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 0a 68 6f ; 61- 80\n"
397712b2f30Ssthen "73 74 6d 61 73 74 65 72 09 6e 6c 6e 65 74 6c 61 62 73 02 6e ; 81- 100\n"
398712b2f30Ssthen "6c 00 77 a1 02 58 00 00 70 80 00 00 1c 20 00 09 3a 80 00 00 ; 101- 120\n"
399712b2f30Ssthen "46 50\n");
400712b2f30Ssthen
401712b2f30Ssthen /* a root reply drill -w - */
402712b2f30Ssthen testpkt(pkt, alloc, out,
403712b2f30Ssthen " ; 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19\n"
404712b2f30Ssthen " ;-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --\n"
405712b2f30Ssthen " 97 3f 81 80 00 01 00 0d 00 00 00 02 00 00 02 00 01 00 00 02 ; 1- 20\n"
406712b2f30Ssthen " 00 01 00 06 6d 38 00 14 01 49 0c 52 4f 4f 54 2d 53 45 52 56 ; 21- 40\n"
407712b2f30Ssthen " 45 52 53 03 4e 45 54 00 00 00 02 00 01 00 06 6d 38 00 14 01 ; 41- 60\n"
408712b2f30Ssthen " 4a 0c 52 4f 4f 54 2d 53 45 52 56 45 52 53 03 4e 45 54 00 00 ; 61- 80\n"
409712b2f30Ssthen " 00 02 00 01 00 06 6d 38 00 14 01 4b 0c 52 4f 4f 54 2d 53 45 ; 81- 100\n"
410712b2f30Ssthen " 52 56 45 52 53 03 4e 45 54 00 00 00 02 00 01 00 06 6d 38 00 ; 101- 120\n"
411712b2f30Ssthen " 14 01 4c 0c 52 4f 4f 54 2d 53 45 52 56 45 52 53 03 4e 45 54 ; 121- 140\n"
412712b2f30Ssthen " 00 00 00 02 00 01 00 06 6d 38 00 14 01 4d 0c 52 4f 4f 54 2d ; 141- 160\n"
413712b2f30Ssthen " 53 45 52 56 45 52 53 03 4e 45 54 00 00 00 02 00 01 00 06 6d ; 161- 180\n"
414712b2f30Ssthen " 38 00 14 01 41 0c 52 4f 4f 54 2d 53 45 52 56 45 52 53 03 4e ; 181- 200\n"
415712b2f30Ssthen " 45 54 00 00 00 02 00 01 00 06 6d 38 00 14 01 42 0c 52 4f 4f ; 201- 220\n"
416712b2f30Ssthen " 54 2d 53 45 52 56 45 52 53 03 4e 45 54 00 00 00 02 00 01 00 ; 221- 240\n"
417712b2f30Ssthen " 06 6d 38 00 14 01 43 0c 52 4f 4f 54 2d 53 45 52 56 45 52 53 ; 241- 260\n"
418712b2f30Ssthen " 03 4e 45 54 00 00 00 02 00 01 00 06 6d 38 00 14 01 44 0c 52 ; 261- 280\n"
419712b2f30Ssthen " 4f 4f 54 2d 53 45 52 56 45 52 53 03 4e 45 54 00 00 00 02 00 ; 281- 300\n"
420712b2f30Ssthen " 01 00 06 6d 38 00 14 01 45 0c 52 4f 4f 54 2d 53 45 52 56 45 ; 301- 320\n"
421712b2f30Ssthen " 52 53 03 4e 45 54 00 00 00 02 00 01 00 06 6d 38 00 14 01 46 ; 321- 340\n"
422712b2f30Ssthen " 0c 52 4f 4f 54 2d 53 45 52 56 45 52 53 03 4e 45 54 00 00 00 ; 341- 360\n"
423712b2f30Ssthen " 02 00 01 00 06 6d 38 00 14 01 47 0c 52 4f 4f 54 2d 53 45 52 ; 361- 380\n"
424712b2f30Ssthen " 56 45 52 53 03 4e 45 54 00 00 00 02 00 01 00 06 6d 38 00 14 ; 381- 400\n"
425712b2f30Ssthen " 01 48 0c 52 4f 4f 54 2d 53 45 52 56 45 52 53 03 4e 45 54 00 ; 401- 420\n"
426712b2f30Ssthen " 01 41 0c 52 4f 4f 54 2d 53 45 52 56 45 52 53 03 4e 45 54 00 ; 421- 440\n"
427712b2f30Ssthen " 00 01 00 01 00 02 64 b9 00 04 c6 29 00 04 01 4a 0c 52 4f 4f ; 441- 460\n"
428712b2f30Ssthen " 54 2d 53 45 52 56 45 52 53 03 4e 45 54 00 00 01 00 01 00 02 ; 461- 480\n"
429712b2f30Ssthen " 64 b9 00 04 c0 3a 80 1e ");
430712b2f30Ssthen
431712b2f30Ssthen /* root delegation from unbound trace with new AAAA glue */
432712b2f30Ssthen perftestpkt(pkt, alloc, out,
433712b2f30Ssthen "55BC84000001000D00000014000002000100000200010007E900001401610C726F6F742D73657276657273036E65740000000200010007E90000040162C01E00000200010007E90000040163C01E00000200010007E90000040164C01E00000200010007E90000040165C01E00000200010007E90000040166C01E00000200010007E90000040167C01E00000200010007E90000040168C01E00000200010007E90000040169C01E00000200010007E9000004016AC01E00000200010007E9000004016BC01E00000200010007E9000004016CC01E00000200010007E9000004016DC01EC01C000100010007E9000004C6290004C03B000100010007E9000004C0E44FC9C04A000100010007E9000004C021040CC059000100010007E900000480080A5AC068000100010007E9000004C0CBE60AC077000100010007E9000004C00505F1C086000100010007E9000004C0702404C095000100010007E9000004803F0235C0A4000100010007E9000004C0249411C0B3000100010007E9000004C03A801EC0C2000100010007E9000004C1000E81C0D1000100010007E9000004C707532AC0E0000100010007E9000004CA0C1B21C01C001C00010007E900001020010503BA3E00000000000000020030C077001C00010007E900001020010500002F0000000000000000000FC095001C00010007E90000102001050000010000"
434712b2f30Ssthen "00000000803F0235C0B3001C00010007E9000010200105030C2700000000000000020030C0C2001C00010007E9000010200107FD000000000000000000000001C0E0001C00010007E900001020010DC30000000000000000000000350000291000000000000000"
435712b2f30Ssthen );
436712b2f30Ssthen }
437712b2f30Ssthen
438712b2f30Ssthen /** simple test of parsing, pcat file */
439712b2f30Ssthen static void
testfromfile(sldns_buffer * pkt,struct alloc_cache * alloc,sldns_buffer * out,const char * fname)440712b2f30Ssthen testfromfile(sldns_buffer* pkt, struct alloc_cache* alloc, sldns_buffer* out,
441712b2f30Ssthen const char* fname)
442712b2f30Ssthen {
443712b2f30Ssthen FILE* in = fopen(fname, "r");
444712b2f30Ssthen char buf[102400];
445712b2f30Ssthen int no=0;
446712b2f30Ssthen if(!in) {
447712b2f30Ssthen perror("fname");
448712b2f30Ssthen return;
449712b2f30Ssthen }
450712b2f30Ssthen while(fgets(buf, (int)sizeof(buf), in)) {
451712b2f30Ssthen if(buf[0] == ';') /* comment */
452712b2f30Ssthen continue;
453712b2f30Ssthen if(strlen(buf) < 10) /* skip pcat line numbers. */
454712b2f30Ssthen continue;
455712b2f30Ssthen if(vbmp) {
456712b2f30Ssthen printf("test no %d: %s", no, buf);
457712b2f30Ssthen fflush(stdout);
458712b2f30Ssthen }
459712b2f30Ssthen testpkt(pkt, alloc, out, buf);
460712b2f30Ssthen no++;
461712b2f30Ssthen }
462712b2f30Ssthen fclose(in);
463712b2f30Ssthen }
464712b2f30Ssthen
465712b2f30Ssthen /** simple test of parsing, drill file */
466712b2f30Ssthen static void
testfromdrillfile(sldns_buffer * pkt,struct alloc_cache * alloc,sldns_buffer * out,const char * fname)467712b2f30Ssthen testfromdrillfile(sldns_buffer* pkt, struct alloc_cache* alloc,
468712b2f30Ssthen sldns_buffer* out, const char* fname)
469712b2f30Ssthen {
470712b2f30Ssthen /* ;-- is used to indicate a new message */
471712b2f30Ssthen FILE* in = fopen(fname, "r");
472712b2f30Ssthen char buf[102400];
473712b2f30Ssthen char* np = buf;
474712b2f30Ssthen buf[0]=0;
475712b2f30Ssthen if(!in) {
476712b2f30Ssthen perror("fname");
477712b2f30Ssthen return;
478712b2f30Ssthen }
479712b2f30Ssthen while(fgets(np, (int)sizeof(buf) - (np-buf), in)) {
480712b2f30Ssthen if(strncmp(np, ";--", 3) == 0) {
481712b2f30Ssthen /* new entry */
482712b2f30Ssthen /* test previous */
483712b2f30Ssthen if(np != buf)
484712b2f30Ssthen testpkt(pkt, alloc, out, buf);
485712b2f30Ssthen /* set for new entry */
486712b2f30Ssthen np = buf;
487712b2f30Ssthen buf[0]=0;
488712b2f30Ssthen continue;
489712b2f30Ssthen }
490712b2f30Ssthen if(np[0] == ';') /* comment */
491712b2f30Ssthen continue;
492712b2f30Ssthen np = &np[strlen(np)];
493712b2f30Ssthen }
494712b2f30Ssthen testpkt(pkt, alloc, out, buf);
495712b2f30Ssthen fclose(in);
496712b2f30Ssthen }
497712b2f30Ssthen
4987bc20e6dSsthen #define xstr(s) str(s)
4997bc20e6dSsthen #define str(s) #s
5007bc20e6dSsthen
5017bc20e6dSsthen #define SRCDIRSTR xstr(SRCDIR)
5027bc20e6dSsthen
msgparse_test(void)503712b2f30Ssthen void msgparse_test(void)
504712b2f30Ssthen {
505712b2f30Ssthen time_t origttl = MAX_NEG_TTL;
506712b2f30Ssthen sldns_buffer* pkt = sldns_buffer_new(65553);
507712b2f30Ssthen sldns_buffer* out = sldns_buffer_new(65553);
508712b2f30Ssthen struct alloc_cache super_a, alloc;
509712b2f30Ssthen MAX_NEG_TTL = 86400;
510712b2f30Ssthen /* init */
511712b2f30Ssthen alloc_init(&super_a, NULL, 0);
512712b2f30Ssthen alloc_init(&alloc, &super_a, 2);
513712b2f30Ssthen
514712b2f30Ssthen unit_show_feature("message parse");
515712b2f30Ssthen simpletest(pkt, &alloc, out);
516712b2f30Ssthen /* plain hex dumps, like pcat */
5177bc20e6dSsthen testfromfile(pkt, &alloc, out, SRCDIRSTR "/testdata/test_packets.1");
5187bc20e6dSsthen testfromfile(pkt, &alloc, out, SRCDIRSTR "/testdata/test_packets.2");
5197bc20e6dSsthen testfromfile(pkt, &alloc, out, SRCDIRSTR "/testdata/test_packets.3");
520712b2f30Ssthen /* like from drill -w - */
5217bc20e6dSsthen testfromdrillfile(pkt, &alloc, out, SRCDIRSTR "/testdata/test_packets.4");
5227bc20e6dSsthen testfromdrillfile(pkt, &alloc, out, SRCDIRSTR "/testdata/test_packets.5");
523712b2f30Ssthen
524712b2f30Ssthen matches_nolocation = 1; /* RR order not important for the next test */
5257bc20e6dSsthen testfromdrillfile(pkt, &alloc, out, SRCDIRSTR "/testdata/test_packets.6");
526712b2f30Ssthen check_rrsigs = 1;
5277bc20e6dSsthen testfromdrillfile(pkt, &alloc, out, SRCDIRSTR "/testdata/test_packets.7");
528712b2f30Ssthen check_rrsigs = 0;
529712b2f30Ssthen matches_nolocation = 0;
530712b2f30Ssthen
531712b2f30Ssthen check_formerr_gone = 1;
5327bc20e6dSsthen testfromdrillfile(pkt, &alloc, out, SRCDIRSTR "/testdata/test_packets.8");
533712b2f30Ssthen check_formerr_gone = 0;
534712b2f30Ssthen
535712b2f30Ssthen check_rrsigs = 1;
536712b2f30Ssthen check_nosameness = 1;
5377bc20e6dSsthen testfromdrillfile(pkt, &alloc, out, SRCDIRSTR "/testdata/test_packets.9");
538712b2f30Ssthen check_nosameness = 0;
539712b2f30Ssthen check_rrsigs = 0;
540712b2f30Ssthen
541712b2f30Ssthen /* cleanup */
542712b2f30Ssthen alloc_clear(&alloc);
543712b2f30Ssthen alloc_clear(&super_a);
544712b2f30Ssthen sldns_buffer_free(pkt);
545712b2f30Ssthen sldns_buffer_free(out);
546712b2f30Ssthen MAX_NEG_TTL = origttl;
547712b2f30Ssthen }
548