2 * Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 * You can also choose to distribute this program under the terms of
20 * the Unmodified Binary Distribution Licence (as given in the file
21 * COPYING.UBDL), provided that you have satisfied its requirements.
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL
);
32 /* Forcibly enable assertions */
38 #include <ipxe/test.h>
40 /** Define inline data */
41 #define DATA(...) { __VA_ARGS__ }
43 /** A DNS encoding test */
44 struct dns_encode_test
{
49 /** Length of encoded string */
54 * Define a DNS encoding test
57 * @v _string Test string
58 * @v _data Expected encoded data
59 * @ret test DNS encoding test
61 #define DNS_ENCODE( _name, _string, _data ) \
62 static const uint8_t _name ## __data[] = _data; \
63 static struct dns_encode_test _name = { \
65 .data = _name ## __data, \
66 .len = sizeof ( _name ## __data ), \
70 * Report DNS encoding test result
72 * @v test DNS encoding test
73 * @v file Test code file
74 * @v line Test code line
76 static void dns_encode_okx ( struct dns_encode_test
*test
, const char *file
,
78 uint8_t data
[ test
->len
];
82 /* Check ability to determine length with no buffer */
83 memset ( &name
, 0, sizeof ( name
) );
84 len
= dns_encode ( test
->string
, &name
);
85 okx ( len
>= 0, file
, line
);
86 okx ( len
== test
->len
, file
, line
);
88 /* Check encoded name */
90 name
.len
= sizeof ( data
);
91 len
= dns_encode ( test
->string
, &name
);
92 okx ( len
>= 0, file
, line
);
94 okx ( len
== test
->len
, file
, line
);
95 okx ( memcmp ( data
, test
->data
, test
->len
) == 0, file
, line
);
96 DBGC ( test
, "DNS encoded \"%s\" to:\n", test
->string
);
97 DBGC_HDA ( test
, 0, data
, len
);
100 #define dns_encode_ok( test ) dns_encode_okx ( test, __FILE__, __LINE__ )
103 * Report DNS encoding failure test result
105 * @v test DNS encoding test
106 * @v file Test code file
107 * @v line Test code line
109 static void dns_encode_fail_okx ( struct dns_encode_test
*test
,
110 const char *file
, unsigned int line
) {
111 struct dns_name name
= { .data
= NULL
, .len
= 0 };
114 len
= dns_encode ( test
->string
, &name
);
115 okx ( len
< 0, file
, line
);
117 #define dns_encode_fail_ok( test ) \
118 dns_encode_fail_okx ( test, __FILE__, __LINE__ )
120 /** A DNS decoding test */
121 struct dns_decode_test
{
123 struct dns_name name
;
124 /** Expected string */
129 * Define a DNS decoding test
132 * @v _data RFC1035-encoded data
133 * @v _offset Starting offset within encoded data
134 * @v _string Expected decoded string
135 * @ret test DNS decoding test
137 #define DNS_DECODE( _name, _data, _offset, _string ) \
138 static uint8_t _name ## __data[] = _data; \
139 static struct dns_decode_test _name = { \
141 .data = _name ## __data, \
143 .len = sizeof ( _name ## __data ), \
149 * Report DNS decoding test result
151 * @v test DNS decoding test
152 * @v file Test code file
153 * @v line Test code line
155 static void dns_decode_okx ( struct dns_decode_test
*test
, const char *file
,
156 unsigned int line
) {
157 char string
[ strlen ( test
->string
) + 1 /* NUL */ ];
160 /* Check ability to determine length with no buffer */
161 len
= dns_decode ( &test
->name
, NULL
, 0 );
162 okx ( len
>= 0, file
, line
);
163 okx ( len
== ( ( int ) strlen ( test
->string
) ), file
, line
);
165 /* Check decoded string */
166 len
= dns_decode ( &test
->name
, string
, sizeof ( string
) );
167 okx ( len
>= 0, file
, line
);
169 okx ( strcmp ( string
, test
->string
) == 0, file
, line
);
170 DBGC ( test
, "DNS decoded \"%s\" from offset %#zx in:\n",
171 string
, test
->name
.offset
);
172 DBGC_HDA ( test
, 0, test
->name
.data
, test
->name
.len
);
175 #define dns_decode_ok( test ) dns_decode_okx ( test, __FILE__, __LINE__ )
178 * Report DNS decoding failure test result
180 * @v test DNS decoding test
181 * @v file Test code file
182 * @v line Test code line
184 static void dns_decode_fail_okx ( struct dns_decode_test
*test
,
185 const char *file
, unsigned int line
) {
188 len
= dns_decode ( &test
->name
, NULL
, 0 );
189 okx ( len
< 0, file
, line
);
191 #define dns_decode_fail_ok( test ) \
192 dns_decode_fail_okx ( test, __FILE__, __LINE__ )
194 /** A DNS comparison test */
195 struct dns_compare_test
{
197 struct dns_name first
;
199 struct dns_name second
;
203 * Define a DNS comparison test
206 * @v _first_data First RFC1035-encoded data
207 * @v _first_offset Starting offset within first encoded data
208 * @v _second_data Second RFC1035-encoded data
209 * @v _second_offset Starting offset within second encoded data
210 * @ret test DNS comparison test
212 #define DNS_COMPARE( _name, _first_data, _first_offset, _second_data, \
214 static uint8_t _name ## __first_data[] = _first_data; \
215 static uint8_t _name ## __second_data[] = _second_data; \
216 static struct dns_compare_test _name = { \
218 .data = _name ## __first_data, \
219 .offset = _first_offset, \
220 .len = sizeof ( _name ## __first_data ), \
223 .data = _name ## __second_data, \
224 .offset = _second_offset, \
225 .len = sizeof ( _name ## __second_data ), \
230 * Report DNS comparison test result
232 * @v test DNS comparison test
233 * @v file Test code file
234 * @v line Test code line
236 static void dns_compare_okx ( struct dns_compare_test
*test
, const char *file
,
237 unsigned int line
) {
239 okx ( dns_compare ( &test
->first
, &test
->second
) == 0, file
, line
);
241 #define dns_compare_ok( test ) dns_compare_okx ( test, __FILE__, __LINE__ )
244 * Report DNS comparison test failure result
246 * @v test DNS comparison test
247 * @v file Test code file
248 * @v line Test code line
250 static void dns_compare_fail_okx ( struct dns_compare_test
*test
,
251 const char *file
, unsigned int line
) {
253 okx ( dns_compare ( &test
->first
, &test
->second
) != 0, file
, line
);
255 #define dns_compare_fail_ok( test ) \
256 dns_compare_fail_okx ( test, __FILE__, __LINE__ )
258 /** A DNS copying test */
259 struct dns_copy_test
{
262 /** Expected copied name */
267 * Define a DNS copying test
270 * @v _src_data Source RFC1035-encoded data
271 * @v _src_offset Starting offset within source encoded data
272 * @v _dst_data Expected copied RFC1035-encoded data
273 * @v _dst_offset Starting offset withint copied encoded data
274 * @ret test DNS copying test
276 #define DNS_COPY( _name, _src_data, _src_offset, _dst_data, \
278 static uint8_t _name ## __src_data[] = _src_data; \
279 static uint8_t _name ## __dst_data[] = _dst_data; \
280 static struct dns_copy_test _name = { \
282 .data = _name ## __src_data, \
283 .offset = _src_offset, \
284 .len = sizeof ( _name ## __src_data ), \
287 .data = _name ## __dst_data, \
288 .offset = _dst_offset, \
289 .len = sizeof ( _name ## __dst_data ), \
294 * Report a DNS copying test result
296 * @v test DNS copying test
297 * @v file Test code file
298 * @v line Test code line
300 static void dns_copy_okx ( struct dns_copy_test
*test
,
301 const char *file
, unsigned int line
) {
302 uint8_t data
[ test
->dst
.len
];
306 /* Check ability to determine length with no buffer */
307 memset ( &dst
, 0, sizeof ( dst
) );
308 len
= dns_copy ( &test
->src
, &dst
);
309 okx ( len
>= 0, file
, line
);
310 okx ( len
== ( ( int ) ( test
->dst
.len
- test
->dst
.offset
) ),
313 /* Check copied name */
315 dst
.offset
= test
->dst
.offset
;
316 dst
.len
= sizeof ( data
);
317 memcpy ( dst
.data
, test
->dst
.data
, test
->dst
.offset
);
318 len
= dns_copy ( &test
->src
, &dst
);
319 okx ( len
>= 0, file
, line
);
320 okx ( len
== ( ( int ) ( test
->dst
.len
- test
->dst
.offset
) ),
322 okx ( memcmp ( data
, test
->dst
.data
, sizeof ( data
) ) == 0,
324 DBGC ( test
, "DNS copied:\n" );
325 DBGC_HDA ( test
, 0, test
->src
.data
, test
->src
.len
);
326 DBGC_HDA ( test
, 0, data
, ( test
->dst
.offset
+ len
) );
328 #define dns_copy_ok( test ) dns_copy_okx ( test, __FILE__, __LINE__ )
331 * Report a DNS copying failure test result
333 * @v test DNS copying test
334 * @v file Test code file
335 * @v line Test code line
337 static void dns_copy_fail_okx ( struct dns_copy_test
*test
,
338 const char *file
, unsigned int line
) {
342 memset ( &dst
, 0, sizeof ( dst
) );
343 len
= dns_copy ( &test
->src
, &dst
);
344 okx ( len
< 0, file
, line
);
346 #define dns_copy_fail_ok( test ) dns_copy_fail_okx ( test, __FILE__, __LINE__ )
348 /** A DNS search list test */
349 struct dns_list_test
{
351 struct dns_name list
;
352 /** Expected decoded search list */
353 const char **strings
;
354 /** Number of expected decoded string */
359 * Define a DNS search list test
362 * @v _list RFC1035-encoded data
363 * @v _strings Expected decoded strings
364 * @ret test DNS search list test
366 #define DNS_LIST( _name, _list, _strings ) \
367 static uint8_t _name ## __list[] = _list; \
368 static const char * _name ## __strings[] = _strings; \
369 static struct dns_list_test _name = { \
371 .data = _name ## __list, \
373 .len = sizeof ( _name ## __list ), \
375 .strings = _name ## __strings, \
376 .count = ( sizeof ( _name ## __strings ) / \
377 sizeof ( _name ## __strings[0] ) ), \
381 * Report DNS search list test result
383 * @v test DNS search list test
384 * @v file Test code file
385 * @v line Test code line
387 static void dns_list_okx ( struct dns_list_test
*test
, const char *file
,
388 unsigned int line
) {
389 struct dns_name name
;
392 DBGC ( test
, "DNS search list:\n" );
393 DBGC_HDA ( test
, 0, test
->list
.data
, test
->list
.len
);
394 memcpy ( &name
, &test
->list
, sizeof ( name
) );
395 for ( i
= 0 ; i
< test
->count
; i
++ ) {
396 char buf
[ strlen ( test
->strings
[i
] ) + 1 /* NUL */ ];
400 /* Decode this name */
401 len
= dns_decode ( &name
, buf
, sizeof ( buf
) );
402 okx ( len
>= 0, file
, line
);
404 okx ( len
== ( ( int ) strlen ( test
->strings
[i
] ) ),
406 okx ( strcmp ( buf
, test
->strings
[i
] ) == 0,
408 DBGC ( test
, "DNS search list found \"%s\" at offset "
409 "%#zx\n", buf
, name
.offset
);
412 /* Skip to next name */
413 offset
= dns_skip ( &name
);
414 okx ( offset
>= 0, file
, line
);
415 name
.offset
= offset
;
418 /* Check that we have consumed the whole search list */
419 okx ( name
.offset
== name
.len
, file
, line
);
421 #define dns_list_ok( test ) dns_list_okx ( test, __FILE__, __LINE__ )
423 /* Simple encoding test */
424 DNS_ENCODE ( encode_simple
, "ipxe.org",
425 DATA ( 4, 'i', 'p', 'x', 'e', 3, 'o', 'r', 'g', 0 ) );
427 /* Single-word encoding test */
428 DNS_ENCODE ( encode_single
, "foo", DATA ( 3, 'f', 'o', 'o', 0 ) );
430 /* Absolute encoding test */
431 DNS_ENCODE ( encode_absolute
, "git.ipxe.org.",
432 DATA ( 3, 'g', 'i', 't', 4, 'i', 'p', 'x', 'e', 3, 'o', 'r', 'g',
435 /* Empty string encoding test */
436 DNS_ENCODE ( encode_empty
, "", DATA ( 0 ) );
438 /* Root domain encoding test */
439 DNS_ENCODE ( encode_root
, ".", DATA ( 0 ) );
441 /* Invalid initial dot encoding test */
442 DNS_ENCODE ( encode_initial_dot
, ".foo", DATA() );
444 /* Invalid double dot encoding test */
445 DNS_ENCODE ( encode_double_dot
, "ipxe..org", DATA() );
447 /* Invalid solo double dot encoding test */
448 DNS_ENCODE ( encode_solo_double_dot
, "..", DATA() );
450 /* Invalid trailing double dot encoding test */
451 DNS_ENCODE ( encode_trailing_double_dot
, "ipxe.org..", DATA() );
453 /* Invalid overlength label encoding test */
454 DNS_ENCODE ( encode_overlength
,
455 "this-label-is-maliciously-long-in-an-attempt-to-overflow-the-"
456 "length-field-and-generate-a-length-which-looks-like-a-"
457 "compression-pointer", DATA() );
459 /* Simple decoding test */
460 DNS_DECODE ( decode_simple
,
461 DATA ( 4, 'i', 'p', 'x', 'e', 3, 'o', 'r', 'g', 0 ), 0,
464 /* Compression pointer decoding test */
465 DNS_DECODE ( decode_ptr
,
466 DATA ( 3, 'o', 'r', 'g', 0, 3, 'g', 'i', 't', 4, 'i', 'p', 'x',
467 'e', 0xc0, 0x00 ), 5,
470 /* Root decoding test */
471 DNS_DECODE ( decode_root
,
474 /* Incomplete name decoding test */
475 DNS_DECODE ( decode_incomplete_name
,
476 DATA ( 4, 'i', 'p', 'x', 'e' ), 0, NULL
);
478 /* Incomplete label decoding test */
479 DNS_DECODE ( decode_incomplete_label
,
480 DATA ( 4, 'i', 'p', 'x' ), 0, NULL
);
482 /* Incomplete compression pointer decoding test */
483 DNS_DECODE ( decode_incomplete_ptr
,
484 DATA ( 3, 'o', 'r', 'g', 0, 4, 'i', 'p', 'x', 'e', 0xc0 ), 5,
487 /* Forward reference decoding test */
488 DNS_DECODE ( decode_forward
,
489 DATA ( 0xc0, 0x02, 3, 'f', 'o', 'o', 0 ), 0, NULL
);
491 /* Infinite loop decoding test */
492 DNS_DECODE ( decode_infinite
,
493 DATA ( 4, 'i', 'p', 'x', 'e', 0xc0, 0x00 ), 0, NULL
);
495 /* Empty decoding test */
496 DNS_DECODE ( decode_empty
,
499 /* Simple comparison test */
500 DNS_COMPARE ( compare_simple
,
501 DATA ( 4, 'i', 'p', 'x', 'e', 3, 'o', 'r', 'g', 0 ), 0,
502 DATA ( 4, 'i', 'p', 'x', 'e', 3, 'o', 'r', 'g', 0 ), 0 );
504 /* Compression pointer comparison test */
505 DNS_COMPARE ( compare_ptr
,
506 DATA ( 4, 'i', 'p', 'x', 'e', 3, 'o', 'r', 'g', 0 ), 0,
507 DATA ( 3, 'o', 'r', 'g', 0, 4, 'i', 'p', 'x', 'e',
510 /* Case insensitive comparison test */
511 DNS_COMPARE ( compare_case
,
512 DATA ( 4, 'i', 'p', 'x', 'e', 3, 'o', 'r', 'g', 0 ), 0,
513 DATA ( 4, 'i', 'p', 'x', 'e', 3, 'O', 'R', 'G', 0 ), 0 );
515 /* Mismatch comparison test */
516 DNS_COMPARE ( compare_mismatch
,
517 DATA ( 4, 'i', 'p', 'x', 'e', 3, 'o', 'r', 'g', 0 ), 0,
518 DATA ( 4, 'g', 'p', 'x', 'e', 3, 'o', 'r', 'g', 0 ), 0 );
520 /* Infinite loop comparison test */
521 DNS_COMPARE ( compare_infinite
,
522 DATA ( 3, 'f', 'o', 'o', 0xc0, 0x00 ), 0,
523 DATA ( 3, 'f', 'o', 'o', 0xc0, 0x00 ), 0 );
525 /* Simple copying test */
526 DNS_COPY ( copy_simple
,
527 DATA ( 4, 'i', 'p', 'x', 'e', 3, 'o', 'r', 'g', 0 ), 0,
528 DATA ( 4, 'i', 'p', 'x', 'e', 3, 'o', 'r', 'g', 0 ), 0 );
530 /* Simple copying test with offset */
531 DNS_COPY ( copy_offset
,
532 DATA ( 4, 'i', 'p', 'x', 'e', 3, 'o', 'r', 'g', 0 ), 0,
533 DATA ( 'f', 'o', 'o', 0, 4, 'i', 'p', 'x', 'e',
534 3, 'o', 'r', 'g', 0 ), 4 );
536 /* Compression pointer copying test */
538 DATA ( 3, 'o', 'r', 'g', 0, 3, 'g', 'i', 't', 4, 'i', 'p', 'x', 'e',
540 DATA ( 3, 'g', 'i', 't', 4, 'i', 'p', 'x', 'e', 3, 'o', 'r', 'g',
543 /* Infinite loop copying test */
544 DNS_COPY ( copy_infinite
,
545 DATA ( 4, 'l', 'o', 'o', 'p', 7, 'f', 'o', 'r', 'e', 'v', 'e', 'r',
549 /* DNS search list test */
551 DATA ( 4, 'i', 'p', 'x', 'e', 3, 'o', 'r', 'g', 0,
552 4, 'b', 'o', 'o', 't', 0xc0, 0x00,
553 3, 'd', 'e', 'v', 0xc0, 0x0a,
554 11, 'n', 'e', 't', 'w', 'o', 'r', 'k', 'b', 'o', 'o', 't',
556 DATA ( "ipxe.org", "boot.ipxe.org", "dev.boot.ipxe.org",
557 "networkboot.org" ) );
560 * Perform DNS self-test
563 static void dns_test_exec ( void ) {
566 dns_encode_ok ( &encode_simple
);
567 dns_encode_ok ( &encode_single
);
568 dns_encode_ok ( &encode_absolute
);
569 dns_encode_ok ( &encode_empty
);
570 dns_encode_ok ( &encode_root
);
571 dns_encode_fail_ok ( &encode_initial_dot
);
572 dns_encode_fail_ok ( &encode_double_dot
);
573 dns_encode_fail_ok ( &encode_solo_double_dot
);
574 dns_encode_fail_ok ( &encode_trailing_double_dot
);
575 dns_encode_fail_ok ( &encode_overlength
);
578 dns_decode_ok ( &decode_simple
);
579 dns_decode_ok ( &decode_ptr
);
580 dns_decode_ok ( &decode_root
);
581 dns_decode_fail_ok ( &decode_incomplete_name
);
582 dns_decode_fail_ok ( &decode_incomplete_label
);
583 dns_decode_fail_ok ( &decode_incomplete_ptr
);
584 dns_decode_fail_ok ( &decode_forward
);
585 dns_decode_fail_ok ( &decode_infinite
);
586 dns_decode_fail_ok ( &decode_empty
);
588 /* Comparison tests */
589 dns_compare_ok ( &compare_simple
);
590 dns_compare_ok ( &compare_ptr
);
591 dns_compare_ok ( &compare_case
);
592 dns_compare_fail_ok ( &compare_mismatch
);
593 dns_compare_fail_ok ( &compare_infinite
);
596 dns_copy_ok ( ©_simple
);
597 dns_copy_ok ( ©_offset
);
598 dns_copy_ok ( ©_ptr
);
599 dns_copy_fail_ok ( ©_infinite
);
601 /* Search list tets */
602 dns_list_ok ( &search
);
606 struct self_test dns_test __self_test
= {
608 .exec
= dns_test_exec
,