Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / ipxe / src / tests / dns_test.c
1 /*
2  * Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
3  *
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.
8  *
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.
13  *
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
17  * 02110-1301, USA.
18  */
19
20 FILE_LICENCE ( GPL2_OR_LATER );
21
22 /** @file
23  *
24  * DNS self-tests
25  *
26  */
27
28 /* Forcibly enable assertions */
29 #undef NDEBUG
30
31 #include <string.h>
32 #include <assert.h>
33 #include <ipxe/dns.h>
34 #include <ipxe/test.h>
35
36 /** Define inline data */
37 #define DATA(...) { __VA_ARGS__ }
38
39 /** A DNS encoding test */
40 struct dns_encode_test {
41         /** String */
42         const char *string;
43         /** Encoded string */
44         const void *data;
45         /** Length of encoded string */
46         int len;
47 };
48
49 /**
50  * Define a DNS encoding test
51  *
52  * @v _name             Test name
53  * @v _string           Test string
54  * @v _data             Expected encoded data
55  * @ret test            DNS encoding test
56  */
57 #define DNS_ENCODE( _name, _string, _data )                             \
58         static const uint8_t _name ## __data[] = _data;                 \
59         static struct dns_encode_test _name = {                         \
60                 .string = _string,                                      \
61                 .data = _name ## __data,                                \
62                 .len = sizeof ( _name ## __data ),                      \
63         }
64
65 /**
66  * Report DNS encoding test result
67  *
68  * @v test              DNS encoding test
69  * @v file              Test code file
70  * @v line              Test code line
71  */
72 static void dns_encode_okx ( struct dns_encode_test *test, const char *file,
73                              unsigned int line ) {
74         uint8_t data[ test->len ];
75         struct dns_name name;
76         int len;
77
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 );
83
84         /* Check encoded name */
85         name.data = data;
86         name.len = sizeof ( data );
87         len = dns_encode ( test->string, &name );
88         okx ( len >= 0, file, line );
89         if ( len >= 0 ) {
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 );
94         }
95 }
96 #define dns_encode_ok( test ) dns_encode_okx ( test, __FILE__, __LINE__ )
97
98 /**
99  * Report DNS encoding failure test result
100  *
101  * @v test              DNS encoding test
102  * @v file              Test code file
103  * @v line              Test code line
104  */
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 };
108         int len;
109
110         len = dns_encode ( test->string, &name );
111         okx ( len < 0, file, line );
112 }
113 #define dns_encode_fail_ok( test ) \
114         dns_encode_fail_okx ( test, __FILE__, __LINE__ )
115
116 /** A DNS decoding test */
117 struct dns_decode_test {
118         /** Name */
119         struct dns_name name;
120         /** Expected string */
121         const char *string;
122 };
123
124 /**
125  * Define a DNS decoding test
126  *
127  * @v _name             Test name
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
132  */
133 #define DNS_DECODE( _name, _data, _offset, _string )                    \
134         static uint8_t _name ## __data[] = _data;                       \
135         static struct dns_decode_test _name = {                         \
136                 .name = {                                               \
137                         .data = _name ## __data,                        \
138                         .offset = _offset,                              \
139                         .len = sizeof ( _name ## __data ),              \
140                 },                                                      \
141                 .string = _string,                                      \
142         }
143
144 /**
145  * Report DNS decoding test result
146  *
147  * @v test              DNS decoding test
148  * @v file              Test code file
149  * @v line              Test code line
150  */
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 */ ];
154         int len;
155
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 );
160
161         /* Check decoded string */
162         len = dns_decode ( &test->name, string, sizeof ( string ) );
163         okx ( len >= 0, file, line );
164         if ( len >= 0 ) {
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 );
169         }
170 }
171 #define dns_decode_ok( test ) dns_decode_okx ( test, __FILE__, __LINE__ )
172
173 /**
174  * Report DNS decoding failure test result
175  *
176  * @v test              DNS decoding test
177  * @v file              Test code file
178  * @v line              Test code line
179  */
180 static void dns_decode_fail_okx ( struct dns_decode_test *test,
181                                   const char *file, unsigned int line ) {
182         int len;
183
184         len = dns_decode ( &test->name, NULL, 0 );
185         okx ( len < 0, file, line );
186 }
187 #define dns_decode_fail_ok( test ) \
188         dns_decode_fail_okx ( test, __FILE__, __LINE__ )
189
190 /** A DNS comparison test */
191 struct dns_compare_test {
192         /** First name */
193         struct dns_name first;
194         /** Second name */
195         struct dns_name second;
196 };
197
198 /**
199  * Define a DNS comparison test
200  *
201  * @v _name             Test name
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
207  */
208 #define DNS_COMPARE( _name, _first_data, _first_offset, _second_data,   \
209                      _second_offset )                                   \
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 = {                        \
213                 .first = {                                              \
214                         .data = _name ## __first_data,                  \
215                         .offset = _first_offset,                        \
216                         .len = sizeof ( _name ## __first_data ),        \
217                 },                                                      \
218                 .second = {                                             \
219                         .data = _name ## __second_data,                 \
220                         .offset = _second_offset,                       \
221                         .len = sizeof ( _name ## __second_data ),       \
222                 },                                                      \
223         }
224
225 /**
226  * Report DNS comparison test result
227  *
228  * @v test              DNS comparison test
229  * @v file              Test code file
230  * @v line              Test code line
231  */
232 static void dns_compare_okx ( struct dns_compare_test *test, const char *file,
233                               unsigned int line ) {
234
235         okx ( dns_compare ( &test->first, &test->second ) == 0, file, line );
236 }
237 #define dns_compare_ok( test ) dns_compare_okx ( test, __FILE__, __LINE__ )
238
239 /**
240  * Report DNS comparison test failure result
241  *
242  * @v test              DNS comparison test
243  * @v file              Test code file
244  * @v line              Test code line
245  */
246 static void dns_compare_fail_okx ( struct dns_compare_test *test,
247                                    const char *file, unsigned int line ) {
248
249         okx ( dns_compare ( &test->first, &test->second ) != 0, file, line );
250 }
251 #define dns_compare_fail_ok( test ) \
252         dns_compare_fail_okx ( test, __FILE__, __LINE__ )
253
254 /** A DNS copying test */
255 struct dns_copy_test {
256         /** Source name */
257         struct dns_name src;
258         /** Expected copied name */
259         struct dns_name dst;
260 };
261
262 /**
263  * Define a DNS copying test
264  *
265  * @v _name             Test name
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
271  */
272 #define DNS_COPY( _name, _src_data, _src_offset, _dst_data,             \
273                   _dst_offset )                                         \
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 = {                           \
277                 .src = {                                                \
278                         .data = _name ## __src_data,                    \
279                         .offset = _src_offset,                          \
280                         .len = sizeof ( _name ## __src_data ),          \
281                 },                                                      \
282                 .dst = {                                                \
283                         .data = _name ## __dst_data,                    \
284                         .offset = _dst_offset,                          \
285                         .len = sizeof ( _name ## __dst_data ),          \
286                 },                                                      \
287         }
288
289 /**
290  * Report a DNS copying test result
291  *
292  * @v test              DNS copying test
293  * @v file              Test code file
294  * @v line              Test code line
295  */
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 ];
299         struct dns_name dst;
300         int len;
301
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 ) ),
307               file, line );
308
309         /* Check copied name */
310         dst.data = data;
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 ) ),
317               file, line );
318         okx ( memcmp ( data, test->dst.data, sizeof ( data ) ) == 0,
319               file, line );
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 ) );
323 }
324 #define dns_copy_ok( test ) dns_copy_okx ( test, __FILE__, __LINE__ )
325
326 /**
327  * Report a DNS copying failure test result
328  *
329  * @v test              DNS copying test
330  * @v file              Test code file
331  * @v line              Test code line
332  */
333 static void dns_copy_fail_okx ( struct dns_copy_test *test,
334                                 const char *file, unsigned int line ) {
335         struct dns_name dst;
336         int len;
337
338         memset ( &dst, 0, sizeof ( dst ) );
339         len = dns_copy ( &test->src, &dst );
340         okx ( len < 0, file, line );
341 }
342 #define dns_copy_fail_ok( test ) dns_copy_fail_okx ( test, __FILE__, __LINE__ )
343
344 /** A DNS search list test */
345 struct dns_list_test {
346         /** Search list */
347         struct dns_name list;
348         /** Expected decoded search list */
349         const char **strings;
350         /** Number of expected decoded string */
351         unsigned int count;
352 };
353
354 /**
355  * Define a DNS search list test
356  *
357  * @v _name             Test name
358  * @v _list             RFC1035-encoded data
359  * @v _strings          Expected decoded strings
360  * @ret test            DNS search list test
361  */
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 = {                           \
366                 .list = {                                               \
367                         .data = _name ## __list,                        \
368                         .offset = 0,                                    \
369                         .len = sizeof ( _name ## __list ),              \
370                 },                                                      \
371                 .strings = _name ## __strings,                          \
372                 .count = ( sizeof ( _name ## __strings ) /              \
373                            sizeof ( _name ## __strings[0] ) ),          \
374         }
375
376 /**
377  * Report DNS search list test result
378  *
379  * @v test              DNS search list test
380  * @v file              Test code file
381  * @v line              Test code line
382  */
383 static void dns_list_okx ( struct dns_list_test *test, const char *file,
384                            unsigned int line ) {
385         struct dns_name name;
386         unsigned int i;
387
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 */ ];
393                 int len;
394                 int offset;
395
396                 /* Decode this name */
397                 len = dns_decode ( &name, buf, sizeof ( buf ) );
398                 okx ( len >= 0, file, line );
399                 if ( len >= 0 ) {
400                         okx ( len == ( ( int ) strlen ( test->strings[i] ) ),
401                               file, line );
402                         okx ( strcmp ( buf, test->strings[i] ) == 0,
403                               file, line );
404                         DBGC ( test, "DNS search list found \"%s\" at offset "
405                                "%#zx\n", buf, name.offset );
406                 }
407
408                 /* Skip to next name */
409                 offset = dns_skip ( &name );
410                 okx ( offset >= 0, file, line );
411                 name.offset = offset;
412         }
413
414         /* Check that we have consumed the whole search list */
415         okx ( name.offset == name.len, file, line );
416 }
417 #define dns_list_ok( test ) dns_list_okx ( test, __FILE__, __LINE__ )
418
419 /* Simple encoding test */
420 DNS_ENCODE ( encode_simple, "ipxe.org",
421              DATA ( 4, 'i', 'p', 'x', 'e', 3, 'o', 'r', 'g', 0 ) );
422
423 /* Single-word encoding test */
424 DNS_ENCODE ( encode_single, "foo", DATA ( 3, 'f', 'o', 'o', 0 ) );
425
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',
429                     0 ) );
430
431 /* Empty string encoding test */
432 DNS_ENCODE ( encode_empty, "", DATA ( 0 ) );
433
434 /* Root domain encoding test */
435 DNS_ENCODE ( encode_root, ".", DATA ( 0 ) );
436
437 /* Invalid initial dot encoding test */
438 DNS_ENCODE ( encode_initial_dot, ".foo", DATA() );
439
440 /* Invalid double dot encoding test */
441 DNS_ENCODE ( encode_double_dot, "ipxe..org", DATA() );
442
443 /* Invalid solo double dot encoding test */
444 DNS_ENCODE ( encode_solo_double_dot, "..", DATA() );
445
446 /* Invalid trailing double dot encoding test */
447 DNS_ENCODE ( encode_trailing_double_dot, "ipxe.org..", DATA() );
448
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() );
454
455 /* Simple decoding test */
456 DNS_DECODE ( decode_simple,
457              DATA ( 4, 'i', 'p', 'x', 'e', 3, 'o', 'r', 'g', 0 ), 0,
458              "ipxe.org" );
459
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,
464              "git.ipxe.org" );
465
466 /* Root decoding test */
467 DNS_DECODE ( decode_root,
468              DATA ( 0 ), 0, "" );
469
470 /* Incomplete name decoding test */
471 DNS_DECODE ( decode_incomplete_name,
472              DATA ( 4, 'i', 'p', 'x', 'e' ), 0, NULL );
473
474 /* Incomplete label decoding test */
475 DNS_DECODE ( decode_incomplete_label,
476              DATA ( 4, 'i', 'p', 'x' ), 0, NULL );
477
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,
481              NULL );
482
483 /* Forward reference decoding test */
484 DNS_DECODE ( decode_forward,
485              DATA ( 0xc0, 0x02, 3, 'f', 'o', 'o', 0 ), 0, NULL );
486
487 /* Infinite loop decoding test */
488 DNS_DECODE ( decode_infinite,
489              DATA ( 4, 'i', 'p', 'x', 'e', 0xc0, 0x00 ), 0, NULL );
490
491 /* Empty decoding test */
492 DNS_DECODE ( decode_empty,
493              DATA (), 0, NULL );
494
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 );
499
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',
504                      0xc0, 0x00 ), 5 );
505
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 );
510
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 );
515
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 );
520
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 );
525
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 );
531
532 /* Compression pointer copying test */
533 DNS_COPY ( copy_ptr,
534            DATA ( 3, 'o', 'r', 'g', 0, 3, 'g', 'i', 't', 4, 'i', 'p', 'x', 'e',
535                   0xc0, 0x00 ), 5,
536            DATA ( 3, 'g', 'i', 't', 4, 'i', 'p', 'x', 'e', 3, 'o', 'r', 'g',
537                   0 ), 0 );
538
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',
542                   0xc0, 0x05 ), 0,
543            DATA (), 0 );
544
545 /* DNS search list test */
546 DNS_LIST ( search,
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',
551                   0xc0, 0x05 ),
552            DATA ( "ipxe.org", "boot.ipxe.org", "dev.boot.ipxe.org",
553                   "networkboot.org" ) );
554
555 /**
556  * Perform DNS self-test
557  *
558  */
559 static void dns_test_exec ( void ) {
560
561         /* Encoding tests */
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 );
572
573         /* Decoding tests */
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 );
583
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 );
590
591         /* Copying tests */
592         dns_copy_ok ( &copy_simple );
593         dns_copy_ok ( &copy_offset );
594         dns_copy_ok ( &copy_ptr );
595         dns_copy_fail_ok ( &copy_infinite );
596
597         /* Search list tets */
598         dns_list_ok ( &search );
599 }
600
601 /** DNS self-test */
602 struct self_test dns_test __self_test = {
603         .name = "dns",
604         .exec = dns_test_exec,
605 };