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,