]>
git.saurik.com Git - apple/network_cmds.git/blob - unbound/testcode/unitmsgparse.c
b33a2408d4e72f8fa5fb95cbc6f210904c2db5ad
2 * testcode/unitmsgparse.c - unit test for msg parse routines.
4 * Copyright (c) 2007, NLnet Labs. All rights reserved.
6 * This software is open source.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
12 * Redistributions of source code must retain the above copyright notice,
13 * this list of conditions and the following disclaimer.
15 * Redistributions in binary form must reproduce the above copyright notice,
16 * this list of conditions and the following disclaimer in the documentation
17 * and/or other materials provided with the distribution.
19 * Neither the name of the NLNET LABS nor the names of its contributors may
20 * be used to endorse or promote products derived from this software without
21 * specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
29 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 * Calls msg parse unit tests. Exits with code 1 on a failure.
44 #include "testcode/unitmain.h"
45 #include "util/data/msgparse.h"
46 #include "util/data/msgreply.h"
47 #include "util/data/msgencode.h"
48 #include "util/data/dname.h"
49 #include "util/alloc.h"
50 #include "util/regional.h"
51 #include "util/net_help.h"
52 #include "testcode/readhex.h"
53 #include "testcode/testpkts.h"
54 #include "ldns/sbuffer.h"
55 #include "ldns/str2wire.h"
56 #include "ldns/wire2str.h"
58 /** verbose message parse unit test */
60 /** do not accept formerr */
61 static int check_formerr_gone
= 0;
62 /** if matching within a section should disregard the order of RRs. */
63 static int matches_nolocation
= 0;
64 /** see if RRSIGs are properly matched to RRsets. */
65 static int check_rrsigs
= 0;
66 /** do not check buffer sameness */
67 static int check_nosameness
= 0;
69 /** see if buffers contain the same packet */
71 test_buffers(sldns_buffer
* pkt
, sldns_buffer
* out
)
73 /* check binary same */
74 if(sldns_buffer_limit(pkt
) == sldns_buffer_limit(out
) &&
75 memcmp(sldns_buffer_begin(pkt
), sldns_buffer_begin(out
),
76 sldns_buffer_limit(pkt
)) == 0) {
77 if(vbmp
) printf("binary the same (length=%u)\n",
78 (unsigned)sldns_buffer_limit(pkt
));
85 size_t lim
= sldns_buffer_limit(out
);
86 if(sldns_buffer_limit(pkt
) < lim
)
87 lim
= sldns_buffer_limit(pkt
);
88 for(count
=0; count
<lim
; count
+=sz
) {
90 if(lim
-count
< sz
) rem
= lim
-count
;
91 if(memcmp(sldns_buffer_at(pkt
, count
),
92 sldns_buffer_at(out
, count
), rem
) == 0) {
93 log_info("same %d %d", (int)count
, (int)rem
);
94 log_hex("same: ", sldns_buffer_at(pkt
, count
),
97 log_info("diff %d %d", (int)count
, (int)rem
);
98 log_hex("difp: ", sldns_buffer_at(pkt
, count
),
100 log_hex("difo: ", sldns_buffer_at(out
, count
),
106 /* check if it 'means the same' */
109 log_buf(0, "orig in hex", pkt
);
110 log_buf(0, "unbound out in hex", out
);
111 printf("\npacket from unbound (%d):\n",
112 (int)sldns_buffer_limit(out
));
113 s1
= sldns_wire2str_pkt(sldns_buffer_begin(out
),
114 sldns_buffer_limit(out
));
115 printf("%s\n", s1
?s1
:"null");
118 printf("\npacket original (%d):\n",
119 (int)sldns_buffer_limit(pkt
));
120 s2
= sldns_wire2str_pkt(sldns_buffer_begin(pkt
),
121 sldns_buffer_limit(pkt
));
122 printf("%s\n", s2
?s2
:"null");
126 /* if it had two EDNS sections, skip comparison */
128 char* s
= sldns_wire2str_pkt(sldns_buffer_begin(pkt
),
129 sldns_buffer_limit(pkt
));
130 char* e1
= strstr(s
, "; EDNS:");
131 if(e1
&& strstr(e1
+4, "; EDNS:")) {
137 /* compare packets */
138 unit_assert(match_all(sldns_buffer_begin(pkt
), sldns_buffer_limit(pkt
),
139 sldns_buffer_begin(out
), sldns_buffer_limit(out
), 1,
140 matches_nolocation
));
144 /** check if unbound formerr equals ldns formerr */
146 checkformerr(sldns_buffer
* pkt
)
149 char* s
= sldns_wire2str_pkt(sldns_buffer_begin(pkt
),
150 sldns_buffer_limit(pkt
));
151 if(!s
) fatal_exit("out of memory");
152 if(strstr(s
, "Error")) status
= 1;
153 if(strstr(s
, "error")) status
= 1;
155 printf("Formerr, but ldns gives packet:\n");
161 unit_assert(status
!= 0);
164 /** performance test message encoding */
166 perf_encode(struct query_info
* qi
, struct reply_info
* rep
, uint16_t id
,
167 uint16_t flags
, sldns_buffer
* out
, time_t timenow
,
168 struct edns_data
* edns
)
174 struct timeval start
, end
;
176 struct regional
* r2
= regional_create();
177 if(gettimeofday(&start
, NULL
) < 0)
178 fatal_exit("gettimeofday: %s", strerror(errno
));
179 /* encode a couple times */
180 for(i
=0; i
<max
; i
++) {
181 ret
= reply_info_encode(qi
, rep
, id
, flags
, out
, timenow
,
182 r2
, 65535, (int)(edns
->bits
& EDNS_DO
) );
183 unit_assert(ret
!= 0); /* udp packets should fit */
184 attach_edns_record(out
, edns
);
185 regional_free_all(r2
);
187 if(gettimeofday(&end
, NULL
) < 0)
188 fatal_exit("gettimeofday: %s", strerror(errno
));
189 /* time in millisec */
190 dt
= (double)(end
.tv_sec
- start
.tv_sec
)*1000. +
191 ((double)end
.tv_usec
- (double)start
.tv_usec
)/1000.;
192 printf("[%d] did %u in %g msec for %f encode/sec size %d\n", num
++,
193 (unsigned)max
, dt
, (double)max
/ (dt
/1000.),
194 (int)sldns_buffer_limit(out
));
195 regional_destroy(r2
);
198 /** perf test a packet */
200 perftestpkt(sldns_buffer
* pkt
, struct alloc_cache
* alloc
, sldns_buffer
* out
,
203 struct query_info qi
;
204 struct reply_info
* rep
= 0;
209 struct regional
* region
= regional_create();
210 struct edns_data edns
;
212 hex_to_buf(pkt
, hex
);
213 memmove(&id
, sldns_buffer_begin(pkt
), sizeof(id
));
214 if(sldns_buffer_limit(pkt
) < 2)
216 else memmove(&flags
, sldns_buffer_at(pkt
, 2), sizeof(flags
));
217 flags
= ntohs(flags
);
218 ret
= reply_info_parse(pkt
, alloc
, &qi
, &rep
, region
, &edns
);
221 sldns_wire2str_rcode_buf(ret
, rbuf
, sizeof(rbuf
));
222 if(vbmp
) printf("parse code %d: %s\n", ret
, rbuf
);
223 if(ret
== LDNS_RCODE_FORMERR
)
225 unit_assert(ret
!= LDNS_RCODE_SERVFAIL
);
227 perf_encode(&qi
, rep
, id
, flags
, out
, timenow
, &edns
);
230 query_info_clear(&qi
);
231 reply_info_parsedelete(rep
, alloc
);
232 regional_destroy(region
);
235 /** print packed rrset */
237 print_rrset(struct ub_packed_rrset_key
* rrset
)
239 struct packed_rrset_data
* d
= (struct packed_rrset_data
*)rrset
->
243 for(i
=0; i
<d
->count
+d
->rrsig_count
; i
++) {
244 if(!packed_rr_to_string(rrset
, i
, 0, buf
, sizeof(buf
)))
245 printf("failedtoconvert %d\n", (int)i
);
251 /** debug print a packet that failed */
253 print_packet_rrsets(struct query_info
* qinfo
, struct reply_info
* rep
)
256 log_query_info(0, "failed query", qinfo
);
257 printf(";; ANSWER SECTION (%d rrsets)\n", (int)rep
->an_numrrsets
);
258 for(i
=0; i
<rep
->an_numrrsets
; i
++) {
259 printf("; rrset %d\n", (int)i
);
260 print_rrset(rep
->rrsets
[i
]);
262 printf(";; AUTHORITY SECTION (%d rrsets)\n", (int)rep
->ns_numrrsets
);
263 for(i
=rep
->an_numrrsets
; i
<rep
->an_numrrsets
+rep
->ns_numrrsets
; i
++) {
264 printf("; rrset %d\n", (int)i
);
265 print_rrset(rep
->rrsets
[i
]);
267 printf(";; ADDITIONAL SECTION (%d rrsets)\n", (int)rep
->ar_numrrsets
);
268 for(i
=rep
->an_numrrsets
+rep
->ns_numrrsets
; i
<rep
->rrset_count
; i
++) {
269 printf("; rrset %d\n", (int)i
);
270 print_rrset(rep
->rrsets
[i
]);
272 printf(";; packet end\n");
275 /** check that there is no data element that matches the RRSIG */
277 no_data_for_rrsig(struct reply_info
* rep
, struct ub_packed_rrset_key
* rrsig
)
280 for(i
=0; i
<rep
->rrset_count
; i
++) {
281 if(ntohs(rep
->rrsets
[i
]->rk
.type
) == LDNS_RR_TYPE_RRSIG
)
283 if(query_dname_compare(rep
->rrsets
[i
]->rk
.dname
,
284 rrsig
->rk
.dname
) == 0)
285 /* only name is compared right now */
291 /** check RRSIGs in packet */
293 check_the_rrsigs(struct query_info
* qinfo
, struct reply_info
* rep
)
295 /* every RRSIG must be matched to an RRset */
297 for(i
=0; i
<rep
->rrset_count
; i
++) {
298 struct ub_packed_rrset_key
* s
= rep
->rrsets
[i
];
299 if(ntohs(s
->rk
.type
) == LDNS_RR_TYPE_RRSIG
) {
300 /* see if really a problem, i.e. is there a data
302 if(no_data_for_rrsig(rep
, rep
->rrsets
[i
]))
304 log_dns_msg("rrsig failed for packet", qinfo
, rep
);
305 print_packet_rrsets(qinfo
, rep
);
306 printf("failed rrset is nr %d\n", (int)i
);
314 testpkt(sldns_buffer
* pkt
, struct alloc_cache
* alloc
, sldns_buffer
* out
,
317 struct query_info qi
;
318 struct reply_info
* rep
= 0;
322 uint32_t timenow
= 0;
323 struct regional
* region
= regional_create();
324 struct edns_data edns
;
326 hex_to_buf(pkt
, hex
);
327 memmove(&id
, sldns_buffer_begin(pkt
), sizeof(id
));
328 if(sldns_buffer_limit(pkt
) < 2)
330 else memmove(&flags
, sldns_buffer_at(pkt
, 2), sizeof(flags
));
331 flags
= ntohs(flags
);
332 ret
= reply_info_parse(pkt
, alloc
, &qi
, &rep
, region
, &edns
);
335 sldns_wire2str_rcode_buf(ret
, rbuf
, sizeof(rbuf
));
336 if(vbmp
) printf("parse code %d: %s\n", ret
, rbuf
);
337 if(ret
== LDNS_RCODE_FORMERR
) {
338 unit_assert(!check_formerr_gone
);
341 unit_assert(ret
!= LDNS_RCODE_SERVFAIL
);
342 } else if(!check_formerr_gone
) {
343 const size_t lim
= 512;
344 ret
= reply_info_encode(&qi
, rep
, id
, flags
, out
, timenow
,
345 region
, 65535, (int)(edns
.bits
& EDNS_DO
) );
346 unit_assert(ret
!= 0); /* udp packets should fit */
347 attach_edns_record(out
, &edns
);
348 if(vbmp
) printf("inlen %u outlen %u\n",
349 (unsigned)sldns_buffer_limit(pkt
),
350 (unsigned)sldns_buffer_limit(out
));
351 if(!check_nosameness
)
352 test_buffers(pkt
, out
);
354 check_the_rrsigs(&qi
, rep
);
356 if(sldns_buffer_limit(out
) > lim
) {
357 ret
= reply_info_encode(&qi
, rep
, id
, flags
, out
,
359 lim
- calc_edns_field_size(&edns
),
360 (int)(edns
.bits
& EDNS_DO
));
361 unit_assert(ret
!= 0); /* should fit, but with TC */
362 attach_edns_record(out
, &edns
);
363 if( LDNS_QDCOUNT(sldns_buffer_begin(out
)) !=
364 LDNS_QDCOUNT(sldns_buffer_begin(pkt
)) ||
365 LDNS_ANCOUNT(sldns_buffer_begin(out
)) !=
366 LDNS_ANCOUNT(sldns_buffer_begin(pkt
)) ||
367 LDNS_NSCOUNT(sldns_buffer_begin(out
)) !=
368 LDNS_NSCOUNT(sldns_buffer_begin(pkt
)))
370 LDNS_TC_WIRE(sldns_buffer_begin(out
)));
371 /* must set TC bit if shortened */
372 unit_assert(sldns_buffer_limit(out
) <= lim
);
376 query_info_clear(&qi
);
377 reply_info_parsedelete(rep
, alloc
);
378 regional_destroy(region
);
381 /** simple test of parsing */
383 simpletest(sldns_buffer
* pkt
, struct alloc_cache
* alloc
, sldns_buffer
* out
)
385 /* a root query drill -q - */
386 testpkt(pkt
, alloc
, out
,
387 " c5 40 01 00 00 01 00 00 00 00 00 00 00 00 02 00 01 ");
389 /* very small packet */
390 testpkt(pkt
, alloc
, out
,
391 "; 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19\n"
392 ";-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --\n"
393 "74 0c 85 83 00 01 00 00 00 01 00 00 03 62 6c 61 09 6e 6c 6e ; 1- 20\n"
394 "65 74 6c 61 62 73 02 6e 6c 00 00 0f 00 01 09 6e 6c 6e 65 74 ; 21- 40\n"
395 "6c 61 62 73 02 6e 6c 00 00 06 00 01 00 00 46 50 00 40 04 6f ; 41- 60\n"
396 "70 65 6e 09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 0a 68 6f ; 61- 80\n"
397 "73 74 6d 61 73 74 65 72 09 6e 6c 6e 65 74 6c 61 62 73 02 6e ; 81- 100\n"
398 "6c 00 77 a1 02 58 00 00 70 80 00 00 1c 20 00 09 3a 80 00 00 ; 101- 120\n"
401 /* a root reply drill -w - */
402 testpkt(pkt
, alloc
, out
,
403 " ; 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19\n"
404 " ;-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --\n"
405 " 97 3f 81 80 00 01 00 0d 00 00 00 02 00 00 02 00 01 00 00 02 ; 1- 20\n"
406 " 00 01 00 06 6d 38 00 14 01 49 0c 52 4f 4f 54 2d 53 45 52 56 ; 21- 40\n"
407 " 45 52 53 03 4e 45 54 00 00 00 02 00 01 00 06 6d 38 00 14 01 ; 41- 60\n"
408 " 4a 0c 52 4f 4f 54 2d 53 45 52 56 45 52 53 03 4e 45 54 00 00 ; 61- 80\n"
409 " 00 02 00 01 00 06 6d 38 00 14 01 4b 0c 52 4f 4f 54 2d 53 45 ; 81- 100\n"
410 " 52 56 45 52 53 03 4e 45 54 00 00 00 02 00 01 00 06 6d 38 00 ; 101- 120\n"
411 " 14 01 4c 0c 52 4f 4f 54 2d 53 45 52 56 45 52 53 03 4e 45 54 ; 121- 140\n"
412 " 00 00 00 02 00 01 00 06 6d 38 00 14 01 4d 0c 52 4f 4f 54 2d ; 141- 160\n"
413 " 53 45 52 56 45 52 53 03 4e 45 54 00 00 00 02 00 01 00 06 6d ; 161- 180\n"
414 " 38 00 14 01 41 0c 52 4f 4f 54 2d 53 45 52 56 45 52 53 03 4e ; 181- 200\n"
415 " 45 54 00 00 00 02 00 01 00 06 6d 38 00 14 01 42 0c 52 4f 4f ; 201- 220\n"
416 " 54 2d 53 45 52 56 45 52 53 03 4e 45 54 00 00 00 02 00 01 00 ; 221- 240\n"
417 " 06 6d 38 00 14 01 43 0c 52 4f 4f 54 2d 53 45 52 56 45 52 53 ; 241- 260\n"
418 " 03 4e 45 54 00 00 00 02 00 01 00 06 6d 38 00 14 01 44 0c 52 ; 261- 280\n"
419 " 4f 4f 54 2d 53 45 52 56 45 52 53 03 4e 45 54 00 00 00 02 00 ; 281- 300\n"
420 " 01 00 06 6d 38 00 14 01 45 0c 52 4f 4f 54 2d 53 45 52 56 45 ; 301- 320\n"
421 " 52 53 03 4e 45 54 00 00 00 02 00 01 00 06 6d 38 00 14 01 46 ; 321- 340\n"
422 " 0c 52 4f 4f 54 2d 53 45 52 56 45 52 53 03 4e 45 54 00 00 00 ; 341- 360\n"
423 " 02 00 01 00 06 6d 38 00 14 01 47 0c 52 4f 4f 54 2d 53 45 52 ; 361- 380\n"
424 " 56 45 52 53 03 4e 45 54 00 00 00 02 00 01 00 06 6d 38 00 14 ; 381- 400\n"
425 " 01 48 0c 52 4f 4f 54 2d 53 45 52 56 45 52 53 03 4e 45 54 00 ; 401- 420\n"
426 " 01 41 0c 52 4f 4f 54 2d 53 45 52 56 45 52 53 03 4e 45 54 00 ; 421- 440\n"
427 " 00 01 00 01 00 02 64 b9 00 04 c6 29 00 04 01 4a 0c 52 4f 4f ; 441- 460\n"
428 " 54 2d 53 45 52 56 45 52 53 03 4e 45 54 00 00 01 00 01 00 02 ; 461- 480\n"
429 " 64 b9 00 04 c0 3a 80 1e ");
431 /* root delegation from unbound trace with new AAAA glue */
432 perftestpkt(pkt
, alloc
, out
,
433 "55BC84000001000D00000014000002000100000200010007E900001401610C726F6F742D73657276657273036E65740000000200010007E90000040162C01E00000200010007E90000040163C01E00000200010007E90000040164C01E00000200010007E90000040165C01E00000200010007E90000040166C01E00000200010007E90000040167C01E00000200010007E90000040168C01E00000200010007E90000040169C01E00000200010007E9000004016AC01E00000200010007E9000004016BC01E00000200010007E9000004016CC01E00000200010007E9000004016DC01EC01C000100010007E9000004C6290004C03B000100010007E9000004C0E44FC9C04A000100010007E9000004C021040CC059000100010007E900000480080A5AC068000100010007E9000004C0CBE60AC077000100010007E9000004C00505F1C086000100010007E9000004C0702404C095000100010007E9000004803F0235C0A4000100010007E9000004C0249411C0B3000100010007E9000004C03A801EC0C2000100010007E9000004C1000E81C0D1000100010007E9000004C707532AC0E0000100010007E9000004CA0C1B21C01C001C00010007E900001020010503BA3E00000000000000020030C077001C00010007E900001020010500002F0000000000000000000FC095001C00010007E90000102001050000010000"
434 "00000000803F0235C0B3001C00010007E9000010200105030C2700000000000000020030C0C2001C00010007E9000010200107FD000000000000000000000001C0E0001C00010007E900001020010DC30000000000000000000000350000291000000000000000"
438 /** simple test of parsing, pcat file */
440 testfromfile(sldns_buffer
* pkt
, struct alloc_cache
* alloc
, sldns_buffer
* out
,
443 FILE* in
= fopen(fname
, "r");
450 while(fgets(buf
, (int)sizeof(buf
), in
)) {
451 if(buf
[0] == ';') /* comment */
453 if(strlen(buf
) < 10) /* skip pcat line numbers. */
456 printf("test no %d: %s", no
, buf
);
459 testpkt(pkt
, alloc
, out
, buf
);
465 /** simple test of parsing, drill file */
467 testfromdrillfile(sldns_buffer
* pkt
, struct alloc_cache
* alloc
,
468 sldns_buffer
* out
, const char* fname
)
470 /* ;-- is used to indicate a new message */
471 FILE* in
= fopen(fname
, "r");
479 while(fgets(np
, (int)sizeof(buf
) - (np
-buf
), in
)) {
480 if(strncmp(np
, ";--", 3) == 0) {
484 testpkt(pkt
, alloc
, out
, buf
);
485 /* set for new entry */
490 if(np
[0] == ';') /* comment */
492 np
= &np
[strlen(np
)];
494 testpkt(pkt
, alloc
, out
, buf
);
498 void msgparse_test(void)
500 sldns_buffer
* pkt
= sldns_buffer_new(65553);
501 sldns_buffer
* out
= sldns_buffer_new(65553);
502 struct alloc_cache super_a
, alloc
;
504 alloc_init(&super_a
, NULL
, 0);
505 alloc_init(&alloc
, &super_a
, 2);
507 unit_show_feature("message parse");
508 simpletest(pkt
, &alloc
, out
);
509 /* plain hex dumps, like pcat */
510 testfromfile(pkt
, &alloc
, out
, "testdata/test_packets.1");
511 testfromfile(pkt
, &alloc
, out
, "testdata/test_packets.2");
512 testfromfile(pkt
, &alloc
, out
, "testdata/test_packets.3");
513 /* like from drill -w - */
514 testfromdrillfile(pkt
, &alloc
, out
, "testdata/test_packets.4");
515 testfromdrillfile(pkt
, &alloc
, out
, "testdata/test_packets.5");
517 matches_nolocation
= 1; /* RR order not important for the next test */
518 testfromdrillfile(pkt
, &alloc
, out
, "testdata/test_packets.6");
520 testfromdrillfile(pkt
, &alloc
, out
, "testdata/test_packets.7");
522 matches_nolocation
= 0;
524 check_formerr_gone
= 1;
525 testfromdrillfile(pkt
, &alloc
, out
, "testdata/test_packets.8");
526 check_formerr_gone
= 0;
529 check_nosameness
= 1;
530 testfromdrillfile(pkt
, &alloc
, out
, "testdata/test_packets.9");
531 check_nosameness
= 0;
536 alloc_clear(&super_a
);
537 sldns_buffer_free(pkt
);
538 sldns_buffer_free(out
);