These changes are the raw update to qemu-2.6.
[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  * 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.
22  */
23
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25
26 /** @file
27  *
28  * DNS self-tests
29  *
30  */
31
32 /* Forcibly enable assertions */
33 #undef NDEBUG
34
35 #include <string.h>
36 #include <assert.h>
37 #include <ipxe/dns.h>
38 #include <ipxe/test.h>
39
40 /** Define inline data */
41 #define DATA(...) { __VA_ARGS__ }
42
43 /** A DNS encoding test */
44 struct dns_encode_test {
45         /** String */
46         const char *string;
47         /** Encoded string */
48         const void *data;
49         /** Length of encoded string */
50         int len;
51 };
52
53 /**
54  * Define a DNS encoding test
55  *
56  * @v _name             Test name
57  * @v _string           Test string
58  * @v _data             Expected encoded data
59  * @ret test            DNS encoding test
60  */
61 #define DNS_ENCODE( _name, _string, _data )                             \
62         static const uint8_t _name ## __data[] = _data;                 \
63         static struct dns_encode_test _name = {                         \
64                 .string = _string,                                      \
65                 .data = _name ## __data,                                \
66                 .len = sizeof ( _name ## __data ),                      \
67         }
68
69 /**
70  * Report DNS encoding test result
71  *
72  * @v test              DNS encoding test
73  * @v file              Test code file
74  * @v line              Test code line
75  */
76 static void dns_encode_okx ( struct dns_encode_test *test, const char *file,
77                              unsigned int line ) {
78         uint8_t data[ test->len ];
79         struct dns_name name;
80         int len;
81
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 );
87
88         /* Check encoded name */
89         name.data = data;
90         name.len = sizeof ( data );
91         len = dns_encode ( test->string, &name );
92         okx ( len >= 0, file, line );
93         if ( len >= 0 ) {
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 );
98         }
99 }
100 #define dns_encode_ok( test ) dns_encode_okx ( test, __FILE__, __LINE__ )
101
102 /**
103  * Report DNS encoding failure test result
104  *
105  * @v test              DNS encoding test
106  * @v file              Test code file
107  * @v line              Test code line
108  */
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 };
112         int len;
113
114         len = dns_encode ( test->string, &name );
115         okx ( len < 0, file, line );
116 }
117 #define dns_encode_fail_ok( test ) \
118         dns_encode_fail_okx ( test, __FILE__, __LINE__ )
119
120 /** A DNS decoding test */
121 struct dns_decode_test {
122         /** Name */
123         struct dns_name name;
124         /** Expected string */
125         const char *string;
126 };
127
128 /**
129  * Define a DNS decoding test
130  *
131  * @v _name             Test name
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
136  */
137 #define DNS_DECODE( _name, _data, _offset, _string )                    \
138         static uint8_t _name ## __data[] = _data;                       \
139         static struct dns_decode_test _name = {                         \
140                 .name = {                                               \
141                         .data = _name ## __data,                        \
142                         .offset = _offset,                              \
143                         .len = sizeof ( _name ## __data ),              \
144                 },                                                      \
145                 .string = _string,                                      \
146         }
147
148 /**
149  * Report DNS decoding test result
150  *
151  * @v test              DNS decoding test
152  * @v file              Test code file
153  * @v line              Test code line
154  */
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 */ ];
158         int len;
159
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 );
164
165         /* Check decoded string */
166         len = dns_decode ( &test->name, string, sizeof ( string ) );
167         okx ( len >= 0, file, line );
168         if ( len >= 0 ) {
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 );
173         }
174 }
175 #define dns_decode_ok( test ) dns_decode_okx ( test, __FILE__, __LINE__ )
176
177 /**
178  * Report DNS decoding failure test result
179  *
180  * @v test              DNS decoding test
181  * @v file              Test code file
182  * @v line              Test code line
183  */
184 static void dns_decode_fail_okx ( struct dns_decode_test *test,
185                                   const char *file, unsigned int line ) {
186         int len;
187
188         len = dns_decode ( &test->name, NULL, 0 );
189         okx ( len < 0, file, line );
190 }
191 #define dns_decode_fail_ok( test ) \
192         dns_decode_fail_okx ( test, __FILE__, __LINE__ )
193
194 /** A DNS comparison test */
195 struct dns_compare_test {
196         /** First name */
197         struct dns_name first;
198         /** Second name */
199         struct dns_name second;
200 };
201
202 /**
203  * Define a DNS comparison test
204  *
205  * @v _name             Test name
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
211  */
212 #define DNS_COMPARE( _name, _first_data, _first_offset, _second_data,   \
213                      _second_offset )                                   \
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 = {                        \
217                 .first = {                                              \
218                         .data = _name ## __first_data,                  \
219                         .offset = _first_offset,                        \
220                         .len = sizeof ( _name ## __first_data ),        \
221                 },                                                      \
222                 .second = {                                             \
223                         .data = _name ## __second_data,                 \
224                         .offset = _second_offset,                       \
225                         .len = sizeof ( _name ## __second_data ),       \
226                 },                                                      \
227         }
228
229 /**
230  * Report DNS comparison test result
231  *
232  * @v test              DNS comparison test
233  * @v file              Test code file
234  * @v line              Test code line
235  */
236 static void dns_compare_okx ( struct dns_compare_test *test, const char *file,
237                               unsigned int line ) {
238
239         okx ( dns_compare ( &test->first, &test->second ) == 0, file, line );
240 }
241 #define dns_compare_ok( test ) dns_compare_okx ( test, __FILE__, __LINE__ )
242
243 /**
244  * Report DNS comparison test failure result
245  *
246  * @v test              DNS comparison test
247  * @v file              Test code file
248  * @v line              Test code line
249  */
250 static void dns_compare_fail_okx ( struct dns_compare_test *test,
251                                    const char *file, unsigned int line ) {
252
253         okx ( dns_compare ( &test->first, &test->second ) != 0, file, line );
254 }
255 #define dns_compare_fail_ok( test ) \
256         dns_compare_fail_okx ( test, __FILE__, __LINE__ )
257
258 /** A DNS copying test */
259 struct dns_copy_test {
260         /** Source name */
261         struct dns_name src;
262         /** Expected copied name */
263         struct dns_name dst;
264 };
265
266 /**
267  * Define a DNS copying test
268  *
269  * @v _name             Test name
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
275  */
276 #define DNS_COPY( _name, _src_data, _src_offset, _dst_data,             \
277                   _dst_offset )                                         \
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 = {                           \
281                 .src = {                                                \
282                         .data = _name ## __src_data,                    \
283                         .offset = _src_offset,                          \
284                         .len = sizeof ( _name ## __src_data ),          \
285                 },                                                      \
286                 .dst = {                                                \
287                         .data = _name ## __dst_data,                    \
288                         .offset = _dst_offset,                          \
289                         .len = sizeof ( _name ## __dst_data ),          \
290                 },                                                      \
291         }
292
293 /**
294  * Report a DNS copying test result
295  *
296  * @v test              DNS copying test
297  * @v file              Test code file
298  * @v line              Test code line
299  */
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 ];
303         struct dns_name dst;
304         int len;
305
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 ) ),
311               file, line );
312
313         /* Check copied name */
314         dst.data = data;
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 ) ),
321               file, line );
322         okx ( memcmp ( data, test->dst.data, sizeof ( data ) ) == 0,
323               file, line );
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 ) );
327 }
328 #define dns_copy_ok( test ) dns_copy_okx ( test, __FILE__, __LINE__ )
329
330 /**
331  * Report a DNS copying failure test result
332  *
333  * @v test              DNS copying test
334  * @v file              Test code file
335  * @v line              Test code line
336  */
337 static void dns_copy_fail_okx ( struct dns_copy_test *test,
338                                 const char *file, unsigned int line ) {
339         struct dns_name dst;
340         int len;
341
342         memset ( &dst, 0, sizeof ( dst ) );
343         len = dns_copy ( &test->src, &dst );
344         okx ( len < 0, file, line );
345 }
346 #define dns_copy_fail_ok( test ) dns_copy_fail_okx ( test, __FILE__, __LINE__ )
347
348 /** A DNS search list test */
349 struct dns_list_test {
350         /** Search list */
351         struct dns_name list;
352         /** Expected decoded search list */
353         const char **strings;
354         /** Number of expected decoded string */
355         unsigned int count;
356 };
357
358 /**
359  * Define a DNS search list test
360  *
361  * @v _name             Test name
362  * @v _list             RFC1035-encoded data
363  * @v _strings          Expected decoded strings
364  * @ret test            DNS search list test
365  */
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 = {                           \
370                 .list = {                                               \
371                         .data = _name ## __list,                        \
372                         .offset = 0,                                    \
373                         .len = sizeof ( _name ## __list ),              \
374                 },                                                      \
375                 .strings = _name ## __strings,                          \
376                 .count = ( sizeof ( _name ## __strings ) /              \
377                            sizeof ( _name ## __strings[0] ) ),          \
378         }
379
380 /**
381  * Report DNS search list test result
382  *
383  * @v test              DNS search list test
384  * @v file              Test code file
385  * @v line              Test code line
386  */
387 static void dns_list_okx ( struct dns_list_test *test, const char *file,
388                            unsigned int line ) {
389         struct dns_name name;
390         unsigned int i;
391
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 */ ];
397                 int len;
398                 int offset;
399
400                 /* Decode this name */
401                 len = dns_decode ( &name, buf, sizeof ( buf ) );
402                 okx ( len >= 0, file, line );
403                 if ( len >= 0 ) {
404                         okx ( len == ( ( int ) strlen ( test->strings[i] ) ),
405                               file, line );
406                         okx ( strcmp ( buf, test->strings[i] ) == 0,
407                               file, line );
408                         DBGC ( test, "DNS search list found \"%s\" at offset "
409                                "%#zx\n", buf, name.offset );
410                 }
411
412                 /* Skip to next name */
413                 offset = dns_skip ( &name );
414                 okx ( offset >= 0, file, line );
415                 name.offset = offset;
416         }
417
418         /* Check that we have consumed the whole search list */
419         okx ( name.offset == name.len, file, line );
420 }
421 #define dns_list_ok( test ) dns_list_okx ( test, __FILE__, __LINE__ )
422
423 /* Simple encoding test */
424 DNS_ENCODE ( encode_simple, "ipxe.org",
425              DATA ( 4, 'i', 'p', 'x', 'e', 3, 'o', 'r', 'g', 0 ) );
426
427 /* Single-word encoding test */
428 DNS_ENCODE ( encode_single, "foo", DATA ( 3, 'f', 'o', 'o', 0 ) );
429
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',
433                     0 ) );
434
435 /* Empty string encoding test */
436 DNS_ENCODE ( encode_empty, "", DATA ( 0 ) );
437
438 /* Root domain encoding test */
439 DNS_ENCODE ( encode_root, ".", DATA ( 0 ) );
440
441 /* Invalid initial dot encoding test */
442 DNS_ENCODE ( encode_initial_dot, ".foo", DATA() );
443
444 /* Invalid double dot encoding test */
445 DNS_ENCODE ( encode_double_dot, "ipxe..org", DATA() );
446
447 /* Invalid solo double dot encoding test */
448 DNS_ENCODE ( encode_solo_double_dot, "..", DATA() );
449
450 /* Invalid trailing double dot encoding test */
451 DNS_ENCODE ( encode_trailing_double_dot, "ipxe.org..", DATA() );
452
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() );
458
459 /* Simple decoding test */
460 DNS_DECODE ( decode_simple,
461              DATA ( 4, 'i', 'p', 'x', 'e', 3, 'o', 'r', 'g', 0 ), 0,
462              "ipxe.org" );
463
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,
468              "git.ipxe.org" );
469
470 /* Root decoding test */
471 DNS_DECODE ( decode_root,
472              DATA ( 0 ), 0, "" );
473
474 /* Incomplete name decoding test */
475 DNS_DECODE ( decode_incomplete_name,
476              DATA ( 4, 'i', 'p', 'x', 'e' ), 0, NULL );
477
478 /* Incomplete label decoding test */
479 DNS_DECODE ( decode_incomplete_label,
480              DATA ( 4, 'i', 'p', 'x' ), 0, NULL );
481
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,
485              NULL );
486
487 /* Forward reference decoding test */
488 DNS_DECODE ( decode_forward,
489              DATA ( 0xc0, 0x02, 3, 'f', 'o', 'o', 0 ), 0, NULL );
490
491 /* Infinite loop decoding test */
492 DNS_DECODE ( decode_infinite,
493              DATA ( 4, 'i', 'p', 'x', 'e', 0xc0, 0x00 ), 0, NULL );
494
495 /* Empty decoding test */
496 DNS_DECODE ( decode_empty,
497              DATA (), 0, NULL );
498
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 );
503
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',
508                      0xc0, 0x00 ), 5 );
509
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 );
514
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 );
519
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 );
524
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 );
529
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 );
535
536 /* Compression pointer copying test */
537 DNS_COPY ( copy_ptr,
538            DATA ( 3, 'o', 'r', 'g', 0, 3, 'g', 'i', 't', 4, 'i', 'p', 'x', 'e',
539                   0xc0, 0x00 ), 5,
540            DATA ( 3, 'g', 'i', 't', 4, 'i', 'p', 'x', 'e', 3, 'o', 'r', 'g',
541                   0 ), 0 );
542
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',
546                   0xc0, 0x05 ), 0,
547            DATA (), 0 );
548
549 /* DNS search list test */
550 DNS_LIST ( search,
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',
555                   0xc0, 0x05 ),
556            DATA ( "ipxe.org", "boot.ipxe.org", "dev.boot.ipxe.org",
557                   "networkboot.org" ) );
558
559 /**
560  * Perform DNS self-test
561  *
562  */
563 static void dns_test_exec ( void ) {
564
565         /* Encoding tests */
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 );
576
577         /* Decoding tests */
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 );
587
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 );
594
595         /* Copying tests */
596         dns_copy_ok ( &copy_simple );
597         dns_copy_ok ( &copy_offset );
598         dns_copy_ok ( &copy_ptr );
599         dns_copy_fail_ok ( &copy_infinite );
600
601         /* Search list tets */
602         dns_list_ok ( &search );
603 }
604
605 /** DNS self-test */
606 struct self_test dns_test __self_test = {
607         .name = "dns",
608         .exec = dns_test_exec,
609 };