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
20 FILE_LICENCE ( GPL2_OR_LATER );
28 /* Forcibly enable assertions */
34 #include <ipxe/test.h>
36 /** Define inline data */
37 #define DATA(...) { __VA_ARGS__ }
39 /** A DNS encoding test */
40 struct dns_encode_test {
45 /** Length of encoded string */
50 * Define a DNS encoding test
53 * @v _string Test string
54 * @v _data Expected encoded data
55 * @ret test DNS encoding test
57 #define DNS_ENCODE( _name, _string, _data ) \
58 static const uint8_t _name ## __data[] = _data; \
59 static struct dns_encode_test _name = { \
61 .data = _name ## __data, \
62 .len = sizeof ( _name ## __data ), \
66 * Report DNS encoding test result
68 * @v test DNS encoding test
69 * @v file Test code file
70 * @v line Test code line
72 static void dns_encode_okx ( struct dns_encode_test *test, const char *file,
74 uint8_t data[ test->len ];
78 /* Check ability to determine length with no buffer */
79 memset ( &name, 0, sizeof ( name ) );
80 len = dns_encode ( test->string, &name );
81 okx ( len >= 0, file, line );
82 okx ( len == test->len, file, line );
84 /* Check encoded name */
86 name.len = sizeof ( data );
87 len = dns_encode ( test->string, &name );
88 okx ( len >= 0, file, line );
90 okx ( len == test->len, file, line );
91 okx ( memcmp ( data, test->data, test->len ) == 0, file, line );
92 DBGC ( test, "DNS encoded \"%s\" to:\n", test->string );
93 DBGC_HDA ( test, 0, data, len );
96 #define dns_encode_ok( test ) dns_encode_okx ( test, __FILE__, __LINE__ )
99 * Report DNS encoding failure test result
101 * @v test DNS encoding test
102 * @v file Test code file
103 * @v line Test code line
105 static void dns_encode_fail_okx ( struct dns_encode_test *test,
106 const char *file, unsigned int line ) {
107 struct dns_name name = { .data = NULL, .len = 0 };
110 len = dns_encode ( test->string, &name );
111 okx ( len < 0, file, line );
113 #define dns_encode_fail_ok( test ) \
114 dns_encode_fail_okx ( test, __FILE__, __LINE__ )
116 /** A DNS decoding test */
117 struct dns_decode_test {
119 struct dns_name name;
120 /** Expected string */
125 * Define a DNS decoding test
128 * @v _data RFC1035-encoded data
129 * @v _offset Starting offset within encoded data
130 * @v _string Expected decoded string
131 * @ret test DNS decoding test
133 #define DNS_DECODE( _name, _data, _offset, _string ) \
134 static uint8_t _name ## __data[] = _data; \
135 static struct dns_decode_test _name = { \
137 .data = _name ## __data, \
139 .len = sizeof ( _name ## __data ), \
145 * Report DNS decoding test result
147 * @v test DNS decoding test
148 * @v file Test code file
149 * @v line Test code line
151 static void dns_decode_okx ( struct dns_decode_test *test, const char *file,
152 unsigned int line ) {
153 char string[ strlen ( test->string ) + 1 /* NUL */ ];
156 /* Check ability to determine length with no buffer */
157 len = dns_decode ( &test->name, NULL, 0 );
158 okx ( len >= 0, file, line );
159 okx ( len == ( ( int ) strlen ( test->string ) ), file, line );
161 /* Check decoded string */
162 len = dns_decode ( &test->name, string, sizeof ( string ) );
163 okx ( len >= 0, file, line );
165 okx ( strcmp ( string, test->string ) == 0, file, line );
166 DBGC ( test, "DNS decoded \"%s\" from offset %#zx in:\n",
167 string, test->name.offset );
168 DBGC_HDA ( test, 0, test->name.data, test->name.len );
171 #define dns_decode_ok( test ) dns_decode_okx ( test, __FILE__, __LINE__ )
174 * Report DNS decoding failure test result
176 * @v test DNS decoding test
177 * @v file Test code file
178 * @v line Test code line
180 static void dns_decode_fail_okx ( struct dns_decode_test *test,
181 const char *file, unsigned int line ) {
184 len = dns_decode ( &test->name, NULL, 0 );
185 okx ( len < 0, file, line );
187 #define dns_decode_fail_ok( test ) \
188 dns_decode_fail_okx ( test, __FILE__, __LINE__ )
190 /** A DNS comparison test */
191 struct dns_compare_test {
193 struct dns_name first;
195 struct dns_name second;
199 * Define a DNS comparison test
202 * @v _first_data First RFC1035-encoded data
203 * @v _first_offset Starting offset within first encoded data
204 * @v _second_data Second RFC1035-encoded data
205 * @v _second_offset Starting offset within second encoded data
206 * @ret test DNS comparison test
208 #define DNS_COMPARE( _name, _first_data, _first_offset, _second_data, \
210 static uint8_t _name ## __first_data[] = _first_data; \
211 static uint8_t _name ## __second_data[] = _second_data; \
212 static struct dns_compare_test _name = { \
214 .data = _name ## __first_data, \
215 .offset = _first_offset, \
216 .len = sizeof ( _name ## __first_data ), \
219 .data = _name ## __second_data, \
220 .offset = _second_offset, \
221 .len = sizeof ( _name ## __second_data ), \
226 * Report DNS comparison test result
228 * @v test DNS comparison test
229 * @v file Test code file
230 * @v line Test code line
232 static void dns_compare_okx ( struct dns_compare_test *test, const char *file,
233 unsigned int line ) {
235 okx ( dns_compare ( &test->first, &test->second ) == 0, file, line );
237 #define dns_compare_ok( test ) dns_compare_okx ( test, __FILE__, __LINE__ )
240 * Report DNS comparison test failure result
242 * @v test DNS comparison test
243 * @v file Test code file
244 * @v line Test code line
246 static void dns_compare_fail_okx ( struct dns_compare_test *test,
247 const char *file, unsigned int line ) {
249 okx ( dns_compare ( &test->first, &test->second ) != 0, file, line );
251 #define dns_compare_fail_ok( test ) \
252 dns_compare_fail_okx ( test, __FILE__, __LINE__ )
254 /** A DNS copying test */
255 struct dns_copy_test {
258 /** Expected copied name */
263 * Define a DNS copying test
266 * @v _src_data Source RFC1035-encoded data
267 * @v _src_offset Starting offset within source encoded data
268 * @v _dst_data Expected copied RFC1035-encoded data
269 * @v _dst_offset Starting offset withint copied encoded data
270 * @ret test DNS copying test
272 #define DNS_COPY( _name, _src_data, _src_offset, _dst_data, \
274 static uint8_t _name ## __src_data[] = _src_data; \
275 static uint8_t _name ## __dst_data[] = _dst_data; \
276 static struct dns_copy_test _name = { \
278 .data = _name ## __src_data, \
279 .offset = _src_offset, \
280 .len = sizeof ( _name ## __src_data ), \
283 .data = _name ## __dst_data, \
284 .offset = _dst_offset, \
285 .len = sizeof ( _name ## __dst_data ), \
290 * Report a DNS copying test result
292 * @v test DNS copying test
293 * @v file Test code file
294 * @v line Test code line
296 static void dns_copy_okx ( struct dns_copy_test *test,
297 const char *file, unsigned int line ) {
298 uint8_t data[ test->dst.len ];
302 /* Check ability to determine length with no buffer */
303 memset ( &dst, 0, sizeof ( dst ) );
304 len = dns_copy ( &test->src, &dst );
305 okx ( len >= 0, file, line );
306 okx ( len == ( ( int ) ( test->dst.len - test->dst.offset ) ),
309 /* Check copied name */
311 dst.offset = test->dst.offset;
312 dst.len = sizeof ( data );
313 memcpy ( dst.data, test->dst.data, test->dst.offset );
314 len = dns_copy ( &test->src, &dst );
315 okx ( len >= 0, file, line );
316 okx ( len == ( ( int ) ( test->dst.len - test->dst.offset ) ),
318 okx ( memcmp ( data, test->dst.data, sizeof ( data ) ) == 0,
320 DBGC ( test, "DNS copied:\n" );
321 DBGC_HDA ( test, 0, test->src.data, test->src.len );
322 DBGC_HDA ( test, 0, data, ( test->dst.offset + len ) );
324 #define dns_copy_ok( test ) dns_copy_okx ( test, __FILE__, __LINE__ )
327 * Report a DNS copying failure test result
329 * @v test DNS copying test
330 * @v file Test code file
331 * @v line Test code line
333 static void dns_copy_fail_okx ( struct dns_copy_test *test,
334 const char *file, unsigned int line ) {
338 memset ( &dst, 0, sizeof ( dst ) );
339 len = dns_copy ( &test->src, &dst );
340 okx ( len < 0, file, line );
342 #define dns_copy_fail_ok( test ) dns_copy_fail_okx ( test, __FILE__, __LINE__ )
344 /** A DNS search list test */
345 struct dns_list_test {
347 struct dns_name list;
348 /** Expected decoded search list */
349 const char **strings;
350 /** Number of expected decoded string */
355 * Define a DNS search list test
358 * @v _list RFC1035-encoded data
359 * @v _strings Expected decoded strings
360 * @ret test DNS search list test
362 #define DNS_LIST( _name, _list, _strings ) \
363 static uint8_t _name ## __list[] = _list; \
364 static const char * _name ## __strings[] = _strings; \
365 static struct dns_list_test _name = { \
367 .data = _name ## __list, \
369 .len = sizeof ( _name ## __list ), \
371 .strings = _name ## __strings, \
372 .count = ( sizeof ( _name ## __strings ) / \
373 sizeof ( _name ## __strings[0] ) ), \
377 * Report DNS search list test result
379 * @v test DNS search list test
380 * @v file Test code file
381 * @v line Test code line
383 static void dns_list_okx ( struct dns_list_test *test, const char *file,
384 unsigned int line ) {
385 struct dns_name name;
388 DBGC ( test, "DNS search list:\n" );
389 DBGC_HDA ( test, 0, test->list.data, test->list.len );
390 memcpy ( &name, &test->list, sizeof ( name ) );
391 for ( i = 0 ; i < test->count ; i++ ) {
392 char buf[ strlen ( test->strings[i] ) + 1 /* NUL */ ];
396 /* Decode this name */
397 len = dns_decode ( &name, buf, sizeof ( buf ) );
398 okx ( len >= 0, file, line );
400 okx ( len == ( ( int ) strlen ( test->strings[i] ) ),
402 okx ( strcmp ( buf, test->strings[i] ) == 0,
404 DBGC ( test, "DNS search list found \"%s\" at offset "
405 "%#zx\n", buf, name.offset );
408 /* Skip to next name */
409 offset = dns_skip ( &name );
410 okx ( offset >= 0, file, line );
411 name.offset = offset;
414 /* Check that we have consumed the whole search list */
415 okx ( name.offset == name.len, file, line );
417 #define dns_list_ok( test ) dns_list_okx ( test, __FILE__, __LINE__ )
419 /* Simple encoding test */
420 DNS_ENCODE ( encode_simple, "ipxe.org",
421 DATA ( 4, 'i', 'p', 'x', 'e', 3, 'o', 'r', 'g', 0 ) );
423 /* Single-word encoding test */
424 DNS_ENCODE ( encode_single, "foo", DATA ( 3, 'f', 'o', 'o', 0 ) );
426 /* Absolute encoding test */
427 DNS_ENCODE ( encode_absolute, "git.ipxe.org.",
428 DATA ( 3, 'g', 'i', 't', 4, 'i', 'p', 'x', 'e', 3, 'o', 'r', 'g',
431 /* Empty string encoding test */
432 DNS_ENCODE ( encode_empty, "", DATA ( 0 ) );
434 /* Root domain encoding test */
435 DNS_ENCODE ( encode_root, ".", DATA ( 0 ) );
437 /* Invalid initial dot encoding test */
438 DNS_ENCODE ( encode_initial_dot, ".foo", DATA() );
440 /* Invalid double dot encoding test */
441 DNS_ENCODE ( encode_double_dot, "ipxe..org", DATA() );
443 /* Invalid solo double dot encoding test */
444 DNS_ENCODE ( encode_solo_double_dot, "..", DATA() );
446 /* Invalid trailing double dot encoding test */
447 DNS_ENCODE ( encode_trailing_double_dot, "ipxe.org..", DATA() );
449 /* Invalid overlength label encoding test */
450 DNS_ENCODE ( encode_overlength,
451 "this-label-is-maliciously-long-in-an-attempt-to-overflow-the-"
452 "length-field-and-generate-a-length-which-looks-like-a-"
453 "compression-pointer", DATA() );
455 /* Simple decoding test */
456 DNS_DECODE ( decode_simple,
457 DATA ( 4, 'i', 'p', 'x', 'e', 3, 'o', 'r', 'g', 0 ), 0,
460 /* Compression pointer decoding test */
461 DNS_DECODE ( decode_ptr,
462 DATA ( 3, 'o', 'r', 'g', 0, 3, 'g', 'i', 't', 4, 'i', 'p', 'x',
463 'e', 0xc0, 0x00 ), 5,
466 /* Root decoding test */
467 DNS_DECODE ( decode_root,
470 /* Incomplete name decoding test */
471 DNS_DECODE ( decode_incomplete_name,
472 DATA ( 4, 'i', 'p', 'x', 'e' ), 0, NULL );
474 /* Incomplete label decoding test */
475 DNS_DECODE ( decode_incomplete_label,
476 DATA ( 4, 'i', 'p', 'x' ), 0, NULL );
478 /* Incomplete compression pointer decoding test */
479 DNS_DECODE ( decode_incomplete_ptr,
480 DATA ( 3, 'o', 'r', 'g', 0, 4, 'i', 'p', 'x', 'e', 0xc0 ), 5,
483 /* Forward reference decoding test */
484 DNS_DECODE ( decode_forward,
485 DATA ( 0xc0, 0x02, 3, 'f', 'o', 'o', 0 ), 0, NULL );
487 /* Infinite loop decoding test */
488 DNS_DECODE ( decode_infinite,
489 DATA ( 4, 'i', 'p', 'x', 'e', 0xc0, 0x00 ), 0, NULL );
491 /* Empty decoding test */
492 DNS_DECODE ( decode_empty,
495 /* Simple comparison test */
496 DNS_COMPARE ( compare_simple,
497 DATA ( 4, 'i', 'p', 'x', 'e', 3, 'o', 'r', 'g', 0 ), 0,
498 DATA ( 4, 'i', 'p', 'x', 'e', 3, 'o', 'r', 'g', 0 ), 0 );
500 /* Compression pointer comparison test */
501 DNS_COMPARE ( compare_ptr,
502 DATA ( 4, 'i', 'p', 'x', 'e', 3, 'o', 'r', 'g', 0 ), 0,
503 DATA ( 3, 'o', 'r', 'g', 0, 4, 'i', 'p', 'x', 'e',
506 /* Case insensitive comparison test */
507 DNS_COMPARE ( compare_case,
508 DATA ( 4, 'i', 'p', 'x', 'e', 3, 'o', 'r', 'g', 0 ), 0,
509 DATA ( 4, 'i', 'p', 'x', 'e', 3, 'O', 'R', 'G', 0 ), 0 );
511 /* Mismatch comparison test */
512 DNS_COMPARE ( compare_mismatch,
513 DATA ( 4, 'i', 'p', 'x', 'e', 3, 'o', 'r', 'g', 0 ), 0,
514 DATA ( 4, 'g', 'p', 'x', 'e', 3, 'o', 'r', 'g', 0 ), 0 );
516 /* Infinite loop comparison test */
517 DNS_COMPARE ( compare_infinite,
518 DATA ( 3, 'f', 'o', 'o', 0xc0, 0x00 ), 0,
519 DATA ( 3, 'f', 'o', 'o', 0xc0, 0x00 ), 0 );
521 /* Simple copying test */
522 DNS_COPY ( copy_simple,
523 DATA ( 4, 'i', 'p', 'x', 'e', 3, 'o', 'r', 'g', 0 ), 0,
524 DATA ( 4, 'i', 'p', 'x', 'e', 3, 'o', 'r', 'g', 0 ), 0 );
526 /* Simple copying test with offset */
527 DNS_COPY ( copy_offset,
528 DATA ( 4, 'i', 'p', 'x', 'e', 3, 'o', 'r', 'g', 0 ), 0,
529 DATA ( 'f', 'o', 'o', 0, 4, 'i', 'p', 'x', 'e',
530 3, 'o', 'r', 'g', 0 ), 4 );
532 /* Compression pointer copying test */
534 DATA ( 3, 'o', 'r', 'g', 0, 3, 'g', 'i', 't', 4, 'i', 'p', 'x', 'e',
536 DATA ( 3, 'g', 'i', 't', 4, 'i', 'p', 'x', 'e', 3, 'o', 'r', 'g',
539 /* Infinite loop copying test */
540 DNS_COPY ( copy_infinite,
541 DATA ( 4, 'l', 'o', 'o', 'p', 7, 'f', 'o', 'r', 'e', 'v', 'e', 'r',
545 /* DNS search list test */
547 DATA ( 4, 'i', 'p', 'x', 'e', 3, 'o', 'r', 'g', 0,
548 4, 'b', 'o', 'o', 't', 0xc0, 0x00,
549 3, 'd', 'e', 'v', 0xc0, 0x0a,
550 11, 'n', 'e', 't', 'w', 'o', 'r', 'k', 'b', 'o', 'o', 't',
552 DATA ( "ipxe.org", "boot.ipxe.org", "dev.boot.ipxe.org",
553 "networkboot.org" ) );
556 * Perform DNS self-test
559 static void dns_test_exec ( void ) {
562 dns_encode_ok ( &encode_simple );
563 dns_encode_ok ( &encode_single );
564 dns_encode_ok ( &encode_absolute );
565 dns_encode_ok ( &encode_empty );
566 dns_encode_ok ( &encode_root );
567 dns_encode_fail_ok ( &encode_initial_dot );
568 dns_encode_fail_ok ( &encode_double_dot );
569 dns_encode_fail_ok ( &encode_solo_double_dot );
570 dns_encode_fail_ok ( &encode_trailing_double_dot );
571 dns_encode_fail_ok ( &encode_overlength );
574 dns_decode_ok ( &decode_simple );
575 dns_decode_ok ( &decode_ptr );
576 dns_decode_ok ( &decode_root );
577 dns_decode_fail_ok ( &decode_incomplete_name );
578 dns_decode_fail_ok ( &decode_incomplete_label );
579 dns_decode_fail_ok ( &decode_incomplete_ptr );
580 dns_decode_fail_ok ( &decode_forward );
581 dns_decode_fail_ok ( &decode_infinite );
582 dns_decode_fail_ok ( &decode_empty );
584 /* Comparison tests */
585 dns_compare_ok ( &compare_simple );
586 dns_compare_ok ( &compare_ptr );
587 dns_compare_ok ( &compare_case );
588 dns_compare_fail_ok ( &compare_mismatch );
589 dns_compare_fail_ok ( &compare_infinite );
592 dns_copy_ok ( ©_simple );
593 dns_copy_ok ( ©_offset );
594 dns_copy_ok ( ©_ptr );
595 dns_copy_fail_ok ( ©_infinite );
597 /* Search list tets */
598 dns_list_ok ( &search );
602 struct self_test dns_test __self_test = {
604 .exec = dns_test_exec,