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 * URI self-tests
29 *
30 */
31
32 /* Forcibly enable assertions */
33 #undef NDEBUG
34
35 #include <string.h>
36 #include <byteswap.h>
37 #include <ipxe/uri.h>
38 #include <ipxe/tcpip.h>
39 #include <ipxe/params.h>
40 #include <ipxe/test.h>
41
42 /** A URI parsing/formatting test */
43 struct uri_test {
44 /** URI string */
45 const char *string;
46 /** URI */
47 struct uri uri;
48 };
49
50 /** A URI port number test */
51 struct uri_port_test {
52 /** URI string */
53 const char *string;
54 /** Default port number */
55 unsigned int default_port;
56 /** Expected port number */
57 unsigned int port;
58 };
59
60 /** A URI or path resolution test */
61 struct uri_resolve_test {
62 /** Base path or URI */
63 const char *base;
64 /** Relative path or URI */
65 const char *relative;
66 /** Expected resolved path or URI */
67 const char *resolved;
68 };
69
70 /** A PXE URI test */
71 struct uri_pxe_test {
72 /** Server address */
73 union {
74 struct sockaddr sa;
75 struct sockaddr_in sin;
76 struct sockaddr_in6 sin6;
77 struct sockaddr_tcpip st;
78 } server;
79 /** Filename */
80 const char *filename;
81 /** URI */
82 struct uri uri;
83 /** URI string (for display only; cannot be reparsed) */
84 const char *string;
85 };
86
87 /** A current working URI test */
88 struct uri_churi_test {
89 /** Relative URI */
90 const char *relative;
91 /** Expected new working URI */
92 const char *expected;
93 };
94
95 /** A form parameter URI test list */
96 struct uri_params_test_list {
97 /** Key */
98 const char *key;
99 /** Value */
100 const char *value;
101 };
102
103 /** A form parameter URI test */
104 struct uri_params_test {
105 /** URI string */
106 const char *string;
107 /** URI */
108 struct uri uri;
109 /** Parameter list name */
110 const char *name;
111 /** Parameter list */
112 struct uri_params_test_list *list;
113 };
114
115 /**
116 * Compare two URI component strings
117 *
118 * @v first First string, or NULL
119 * @v second Second string, or NULL
120 * @v difference Difference
121 */
uristrcmp(const char * first,const char * second)122 static int uristrcmp ( const char *first, const char *second ) {
123
124 /* Compare strings, allowing for either to be NULL */
125 if ( first == second ) {
126 return 0;
127 } else if ( ( first == NULL ) || ( second == NULL ) ) {
128 return -1;
129 } else {
130 return strcmp ( first, second );
131 }
132 }
133
134 /**
135 * Report URI equality test result
136 *
137 * @v uri URI
138 * @v expected Expected URI
139 * @v file Test code file
140 * @v line Test code line
141 */
uri_okx(struct uri * uri,struct uri * expected,const char * file,unsigned int line)142 static void uri_okx ( struct uri *uri, struct uri *expected, const char *file,
143 unsigned int line ) {
144
145 okx ( uristrcmp ( uri->scheme, expected->scheme ) == 0, file, line );
146 okx ( uristrcmp ( uri->opaque, expected->opaque ) == 0, file, line );
147 okx ( uristrcmp ( uri->user, expected->user ) == 0, file, line );
148 okx ( uristrcmp ( uri->password, expected->password ) == 0, file, line);
149 okx ( uristrcmp ( uri->host, expected->host ) == 0, file, line );
150 okx ( uristrcmp ( uri->port, expected->port ) == 0, file, line );
151 okx ( uristrcmp ( uri->path, expected->path ) == 0, file, line );
152 okx ( uristrcmp ( uri->query, expected->query ) == 0, file, line );
153 okx ( uristrcmp ( uri->fragment, expected->fragment ) == 0, file, line);
154 okx ( uri->params == expected->params, file, line );
155 }
156 #define uri_ok( uri, expected ) uri_okx ( uri, expected, __FILE__, __LINE__ )
157
158 /**
159 * Report URI parsing test result
160 *
161 * @v test URI test
162 * @v file Test code file
163 * @v line Test code line
164 */
uri_parse_okx(struct uri_test * test,const char * file,unsigned int line)165 static void uri_parse_okx ( struct uri_test *test, const char *file,
166 unsigned int line ) {
167 struct uri *uri;
168
169 /* Parse URI */
170 uri = parse_uri ( test->string );
171 okx ( uri != NULL, file, line );
172 if ( uri )
173 uri_okx ( uri, &test->uri, file, line );
174 uri_put ( uri );
175 }
176 #define uri_parse_ok( test ) uri_parse_okx ( test, __FILE__, __LINE__ )
177
178 /**
179 * Report URI formatting test result
180 *
181 * @v test URI test
182 * @v file Test code file
183 * @v line Test code line
184 */
uri_format_okx(struct uri_test * test,const char * file,unsigned int line)185 static void uri_format_okx ( struct uri_test *test, const char *file,
186 unsigned int line ) {
187 char buf[ strlen ( test->string ) + 1 /* NUL */ ];
188 char *tmp;
189 size_t len;
190
191 /* Format into fixed-size buffer */
192 len = format_uri ( &test->uri, buf, sizeof ( buf ) );
193 okx ( len == ( sizeof ( buf ) - 1 /* NUL */ ), file, line );
194 okx ( strcmp ( buf, test->string ) == 0, file, line );
195
196 /* Format into temporarily allocated buffer */
197 tmp = format_uri_alloc ( &test->uri );
198 okx ( tmp != NULL, file, line );
199 if ( tmp )
200 okx ( strcmp ( tmp, test->string ) == 0, file, line );
201 free ( tmp );
202 }
203 #define uri_format_ok( test ) uri_format_okx ( test, __FILE__, __LINE__ )
204
205 /**
206 * Report URI duplication test result
207 *
208 * @v test URI
209 * @v file Test code file
210 * @v line Test code line
211 */
uri_dup_okx(struct uri * uri,const char * file,unsigned int line)212 static void uri_dup_okx ( struct uri *uri, const char *file,
213 unsigned int line ) {
214 struct uri *dup;
215
216 dup = uri_dup ( uri );
217 okx ( dup != NULL, file, line );
218 if ( dup )
219 uri_okx ( dup, uri, file, line );
220 uri_put ( dup );
221 }
222 #define uri_dup_ok( test ) uri_dup_okx ( test, __FILE__, __LINE__ )
223
224 /**
225 * Report URI combined parsing and formatting test result
226 *
227 * @v test URI test
228 * @v file Test code file
229 * @v line Test code line
230 */
uri_parse_format_dup_okx(struct uri_test * test,const char * file,unsigned int line)231 static void uri_parse_format_dup_okx ( struct uri_test *test, const char *file,
232 unsigned int line ) {
233
234 uri_parse_okx ( test, file, line );
235 uri_format_okx ( test, file, line );
236 uri_dup_okx ( &test->uri, file, line );
237 }
238 #define uri_parse_format_dup_ok( test ) \
239 uri_parse_format_dup_okx ( test, __FILE__, __LINE__ )
240
241 /**
242 * Report URI port number test result
243 *
244 * @v test URI port number test
245 * @v file Test code file
246 * @v line Test code line
247 */
uri_port_okx(struct uri_port_test * test,const char * file,unsigned int line)248 static void uri_port_okx ( struct uri_port_test *test, const char *file,
249 unsigned int line ) {
250 struct uri *uri;
251 unsigned int port;
252
253 /* Parse URI */
254 uri = parse_uri ( test->string );
255 okx ( uri != NULL, file, line );
256 if ( uri ) {
257 port = uri_port ( uri, test->default_port );
258 okx ( port == test->port, file, line );
259 }
260 uri_put ( uri );
261 }
262 #define uri_port_ok( test ) uri_port_okx ( test, __FILE__, __LINE__ )
263
264 /**
265 * Report URI resolution test result
266 *
267 * @v test Path resolution test
268 * @v file Test code file
269 * @v line Test code line
270 */
uri_resolve_okx(struct uri_resolve_test * test,const char * file,unsigned int line)271 static void uri_resolve_okx ( struct uri_resolve_test *test,
272 const char *file, unsigned int line ) {
273 struct uri *base;
274 struct uri *relative;
275 struct uri *resolved = NULL;
276 char *formatted;
277
278 /* Parse URIs */
279 base = parse_uri ( test->base );
280 okx ( base != NULL, file, line );
281 relative = parse_uri ( test->relative );
282 okx ( relative != NULL, file, line );
283
284 /* Resolve URI */
285 if ( base && relative ) {
286 resolved = resolve_uri ( base, relative );
287 okx ( resolved != NULL, file, line );
288 }
289
290 /* Format resolved URI */
291 formatted = format_uri_alloc ( resolved );
292 okx ( formatted != NULL, file, line );
293
294 /* Check resolved URI */
295 if ( formatted )
296 okx ( strcmp ( formatted, test->resolved ) == 0, file, line );
297
298 free ( formatted );
299 uri_put ( resolved );
300 uri_put ( relative );
301 uri_put ( base );
302 }
303 #define uri_resolve_ok( test ) uri_resolve_okx ( test, __FILE__, __LINE__ )
304
305 /**
306 * Report path resolution test result
307 *
308 * @v test Path resolution test
309 * @v file Test code file
310 * @v line Test code line
311 */
uri_resolve_path_okx(struct uri_resolve_test * test,const char * file,unsigned int line)312 static void uri_resolve_path_okx ( struct uri_resolve_test *test,
313 const char *file, unsigned int line ) {
314 char *resolved;
315
316 /* Resolve paths using resolve_path() directly */
317 resolved = resolve_path ( test->base, test->relative );
318 okx ( resolved != NULL, file, line );
319 if ( resolved )
320 okx ( strcmp ( resolved, test->resolved ) == 0, file, line );
321 free ( resolved );
322
323 /* Resolve paths as URIs (since all paths are valid URIs) */
324 uri_resolve_okx ( test, file, line );
325 }
326 #define uri_resolve_path_ok( test ) \
327 uri_resolve_path_okx ( test, __FILE__, __LINE__ )
328
329 /**
330 * Report URI PXE test result
331 *
332 * @v test URI PXE test
333 * @v file Test code file
334 * @v line Test code line
335 */
uri_pxe_okx(struct uri_pxe_test * test,const char * file,unsigned int line)336 static void uri_pxe_okx ( struct uri_pxe_test *test, const char *file,
337 unsigned int line ) {
338 char buf[ strlen ( test->string ) + 1 /* NUL */ ];
339 struct uri *uri;
340 size_t len;
341
342 /* Construct URI */
343 uri = pxe_uri ( &test->server.sa, test->filename );
344 okx ( uri != NULL, file, line );
345 if ( uri ) {
346 uri_okx ( uri, &test->uri, file, line );
347 len = format_uri ( uri, buf, sizeof ( buf ) );
348 okx ( len == ( sizeof ( buf ) - 1 /* NUL */ ), file, line );
349 okx ( strcmp ( buf, test->string ) == 0, file, line );
350 }
351 uri_put ( uri );
352 }
353 #define uri_pxe_ok( test ) uri_pxe_okx ( test, __FILE__, __LINE__ )
354
355 /**
356 * Report current working URI test result
357 *
358 * @v tests List of current working URI tests
359 * @v file Test code file
360 * @v line Test code line
361 */
uri_churi_okx(struct uri_churi_test * test,const char * file,unsigned int line)362 static void uri_churi_okx ( struct uri_churi_test *test, const char *file,
363 unsigned int line ) {
364 struct uri *old_cwuri;
365 struct uri *uri;
366 char *formatted;
367
368 /* Preserve original current working URI */
369 old_cwuri = uri_get ( cwuri );
370
371 /* Perform sequence of current working URI changes */
372 do {
373 /* Parse relative URI */
374 uri = parse_uri ( test->relative );
375 okx ( uri != NULL, file, line );
376
377 /* Move to this URI */
378 churi ( uri );
379
380 /* Format new current working URI */
381 formatted = format_uri_alloc ( cwuri );
382 okx ( formatted != NULL, file, line );
383 if ( formatted ) {
384 okx ( strcmp ( formatted, test->expected ) == 0,
385 file, line );
386 }
387
388 /* Free temporary storage */
389 free ( formatted );
390 uri_put ( uri );
391
392 /* Move to next current working URI test */
393 test++;
394
395 } while ( test->relative != NULL );
396
397 /* Restore original current working URI */
398 churi ( old_cwuri );
399 uri_put ( old_cwuri );
400 }
401 #define uri_churi_ok( test ) uri_churi_okx ( test, __FILE__, __LINE__ )
402
403 /**
404 * Report form parameter URI test list result
405 *
406 * @v test Form parameter URI test
407 * @v uri URI
408 * @v file Test code file
409 * @v line Test code line
410 */
uri_params_list_okx(struct uri_params_test * test,struct uri * uri,const char * file,unsigned int line)411 static void uri_params_list_okx ( struct uri_params_test *test,
412 struct uri *uri, const char *file,
413 unsigned int line ) {
414 struct uri_params_test_list *list;
415 struct parameter *param;
416
417 /* Check URI */
418 uri_okx ( uri, &test->uri, file, line );
419
420 /* Check URI parameters */
421 okx ( uri->params != NULL, file, line );
422 if ( uri->params ) {
423 list = test->list;
424 for_each_param ( param, uri->params ) {
425 okx ( strcmp ( param->key, list->key ) == 0,
426 file, line );
427 okx ( strcmp ( param->value, list->value ) == 0,
428 file, line );
429 list++;
430 }
431 okx ( list->key == NULL, file, line );
432 }
433 }
434 #define uri_params_list_ok( test ) \
435 uri_params_list_okx ( test, __FILE__, __LINE__ )
436
437 /**
438 * Report form parameter URI test result
439 *
440 * @v test Form parameter URI test
441 * @v file Test code file
442 * @v line Test code line
443 */
uri_params_okx(struct uri_params_test * test,const char * file,unsigned int line)444 static void uri_params_okx ( struct uri_params_test *test, const char *file,
445 unsigned int line ) {
446 struct uri_params_test_list *list;
447 struct parameters *params;
448 struct parameter *param;
449 struct uri *uri;
450 struct uri *dup;
451
452 /* Create parameter list */
453 params = create_parameters ( test->name );
454 okx ( params != NULL, file, line );
455 if ( params ) {
456 for ( list = test->list ; list->key ; list++ ) {
457 param = add_parameter ( params, list->key, list->value);
458 okx ( param != NULL, file, line );
459 }
460 }
461
462 /* Record parameter list as part of expected URI */
463 test->uri.params = params;
464
465 /* Parse URI */
466 uri = parse_uri ( test->string );
467 okx ( uri != NULL, file, line );
468 if ( uri )
469 uri_params_list_okx ( test, uri, file, line );
470
471 /* Duplicate URI */
472 dup = uri_dup ( uri );
473 okx ( dup != NULL, file, line );
474 if ( dup )
475 uri_params_list_okx ( test, dup, file, line );
476
477 /* Clear parameter list in expected URI */
478 test->uri.params = NULL;
479
480 uri_put ( uri );
481 uri_put ( dup );
482 }
483 #define uri_params_ok( test ) uri_params_okx ( test, __FILE__, __LINE__ )
484
485 /** Empty URI */
486 static struct uri_test uri_empty = {
487 .string = "",
488 };
489
490 /** Basic HTTP URI */
491 static struct uri_test uri_boot_ipxe_org = {
492 "http://boot.ipxe.org/demo/boot.php",
493 { .scheme = "http", .host = "boot.ipxe.org", .path = "/demo/boot.php" }
494 };
495
496 /** Basic opaque URI */
497 static struct uri_test uri_mailto = {
498 "mailto:ipxe-devel@lists.ipxe.org",
499 { .scheme = "mailto", .opaque = "ipxe-devel@lists.ipxe.org" }
500 };
501
502 /** Basic path-only URI */
503 static struct uri_test uri_path = {
504 "/var/lib/tftpboot/pxelinux.0",
505 { .path = "/var/lib/tftpboot/pxelinux.0" },
506 };
507
508 /** Path-only URI with escaped characters */
509 static struct uri_test uri_path_escaped = {
510 "/hello%20world%3F",
511 { .path = "/hello world?" },
512 };
513
514 /** HTTP URI with all the trimmings */
515 static struct uri_test uri_http_all = {
516 "http://anon:password@example.com:3001/~foo/cgi-bin/foo.pl?a=b&c=d#bit",
517 {
518 .scheme = "http",
519 .user = "anon",
520 .password = "password",
521 .host = "example.com",
522 .port = "3001",
523 .path = "/~foo/cgi-bin/foo.pl",
524 .query = "a=b&c=d",
525 .fragment = "bit",
526 },
527 };
528
529 /** HTTP URI with escaped characters */
530 static struct uri_test uri_http_escaped = {
531 "https://test.ipxe.org/wtf%3F%0A?kind%23of/uri%20is#this%3F",
532 {
533 .scheme = "https",
534 .host = "test.ipxe.org",
535 .path = "/wtf?\n",
536 .query = "kind#of/uri is",
537 .fragment = "this?",
538 },
539 };
540
541 /** HTTP URI with improperly escaped characters */
542 static struct uri_test uri_http_escaped_improper = {
543 /* We accept for parsing improperly escaped characters.
544 * (Formatting the parsed URI would produce the properly
545 * encoded form, and so would not exactly match the original
546 * URI string.)
547 */
548 "https://test%2eipxe.org/wt%66%3f\n?kind%23of/uri is#this?",
549 {
550 .scheme = "https",
551 .host = "test.ipxe.org",
552 .path = "/wtf?\n",
553 .query = "kind#of/uri is",
554 .fragment = "this?",
555 },
556 };
557
558 /** IPv6 URI */
559 static struct uri_test uri_ipv6 = {
560 "http://[2001:ba8:0:1d4::6950:5845]/",
561 {
562 .scheme = "http",
563 .host = "[2001:ba8:0:1d4::6950:5845]",
564 .path = "/",
565 },
566 };
567
568 /** IPv6 URI with port */
569 static struct uri_test uri_ipv6_port = {
570 "http://[2001:ba8:0:1d4::6950:5845]:8001/boot",
571 {
572 .scheme = "http",
573 .host = "[2001:ba8:0:1d4::6950:5845]",
574 .port = "8001",
575 .path = "/boot",
576 },
577 };
578
579 /** IPv6 URI with link-local address */
580 static struct uri_test uri_ipv6_local = {
581 "http://[fe80::69ff:fe50:5845%25net0]/ipxe",
582 {
583 .scheme = "http",
584 .host = "[fe80::69ff:fe50:5845%net0]",
585 .path = "/ipxe",
586 },
587 };
588
589 /** IPv6 URI with link-local address not conforming to RFC 6874 */
590 static struct uri_test uri_ipv6_local_non_conforming = {
591 /* We accept for parsing a single "%" in "%net0" (rather than
592 * the properly encoded form "%25net0"). (Formatting the
593 * parsed URI would produce the properly encoded form, and so
594 * would not exactly match the original URI string.)
595 */
596 "http://[fe80::69ff:fe50:5845%net0]/ipxe",
597 {
598 .scheme = "http",
599 .host = "[fe80::69ff:fe50:5845%net0]",
600 .path = "/ipxe",
601 },
602 };
603
604 /** iSCSI URI */
605 static struct uri_test uri_iscsi = {
606 "iscsi:10.253.253.1::::iqn.2010-04.org.ipxe:rabbit",
607 {
608 .scheme = "iscsi",
609 .opaque = "10.253.253.1::::iqn.2010-04.org.ipxe:rabbit",
610 },
611 };
612
613 /** File URI with relative (opaque) path */
614 static struct uri_test uri_file_relative = {
615 "file:boot/script.ipxe",
616 {
617 .scheme = "file",
618 .opaque = "boot/script.ipxe",
619 },
620 };
621
622 /** File URI with absolute path */
623 static struct uri_test uri_file_absolute = {
624 "file:/boot/script.ipxe",
625 {
626 .scheme = "file",
627 .path = "/boot/script.ipxe",
628 },
629 };
630
631 /** File URI with volume name */
632 static struct uri_test uri_file_volume = {
633 "file://hpilo/boot/script.ipxe",
634 {
635 .scheme = "file",
636 .host = "hpilo",
637 .path = "/boot/script.ipxe",
638 },
639 };
640
641 /** URI with port number */
642 static struct uri_port_test uri_explicit_port = {
643 "http://192.168.0.1:8080/boot.php",
644 80,
645 8080,
646 };
647
648 /** URI without port number */
649 static struct uri_port_test uri_default_port = {
650 "http://192.168.0.1/boot.php",
651 80,
652 80,
653 };
654
655 /** Simple path resolution test */
656 static struct uri_resolve_test uri_simple_path = {
657 "/etc/passwd",
658 "group",
659 "/etc/group",
660 };
661
662 /** Path resolution test with "." and ".." elements */
663 static struct uri_resolve_test uri_relative_path = {
664 "/var/lib/tftpboot/pxe/pxelinux.0",
665 "./../ipxe/undionly.kpxe",
666 "/var/lib/tftpboot/ipxe/undionly.kpxe",
667 };
668
669 /** Path resolution test terminating with directory */
670 static struct uri_resolve_test uri_directory_path = {
671 "/test/cgi-bin.pl/boot.ipxe",
672 "..",
673 "/test/",
674 };
675
676 /** Path resolution test with excessive ".." elements */
677 static struct uri_resolve_test uri_excessive_path = {
678 "/var/lib/tftpboot/ipxe.pxe",
679 "../../../../../../../foo",
680 "/foo",
681 };
682
683 /** Path resolution test with absolute path */
684 static struct uri_resolve_test uri_absolute_path = {
685 "/var/lib/tftpboot",
686 "/etc/hostname",
687 "/etc/hostname",
688 };
689
690 /** Relative URI resolution test */
691 static struct uri_resolve_test uri_relative = {
692 "http://boot.ipxe.org/demo/boot.php?vendor=10ec&device=8139",
693 "initrd.img",
694 "http://boot.ipxe.org/demo/initrd.img",
695 };
696
697 /** Absolute URI resolution test */
698 static struct uri_resolve_test uri_absolute = {
699 "http://boot.ipxe.org/demo/boot.php",
700 "ftp://192.168.0.1/boot.ipxe",
701 "ftp://192.168.0.1/boot.ipxe",
702 };
703
704 /** Absolute path URI resolution test */
705 static struct uri_resolve_test uri_absolute_uri_path = {
706 "http://boot.ipxe.org/demo/boot.php#test",
707 "/demo/vmlinuz",
708 "http://boot.ipxe.org/demo/vmlinuz",
709 };
710
711 /** Query URI resolution test */
712 static struct uri_resolve_test uri_query = {
713 "http://10.253.253.1/test.pl?mac=02-00-69-50-58-45",
714 "?mac=00-1f-16-bc-fe-2f",
715 "http://10.253.253.1/test.pl?mac=00-1f-16-bc-fe-2f",
716 };
717
718 /** Fragment URI resolution test */
719 static struct uri_resolve_test uri_fragment = {
720 "http://192.168.0.254/test#foo",
721 "#bar",
722 "http://192.168.0.254/test#bar",
723 };
724
725 /** PXE URI with absolute URI */
726 static struct uri_pxe_test uri_pxe_absolute = {
727 {
728 /* 192.168.0.3 */
729 .sin = {
730 .sin_family = AF_INET,
731 .sin_addr = { .s_addr = htonl ( 0xc0a80003 ) },
732 },
733 },
734 "http://not.a.tftp/uri",
735 {
736 .scheme = "http",
737 .host = "not.a.tftp",
738 .path = "/uri",
739 },
740 "http://not.a.tftp/uri",
741 };
742
743 /** PXE URI with absolute path */
744 static struct uri_pxe_test uri_pxe_absolute_path = {
745 {
746 /* 192.168.0.2 */
747 .sin = {
748 .sin_family = AF_INET,
749 .sin_addr = { .s_addr = htonl ( 0xc0a80002 ) },
750 },
751 },
752 "/absolute/path",
753 {
754 .scheme = "tftp",
755 .host = "192.168.0.2",
756 .path = "//absolute/path",
757 },
758 "tftp://192.168.0.2//absolute/path",
759 };
760
761 /** PXE URI with relative path */
762 static struct uri_pxe_test uri_pxe_relative_path = {
763 {
764 /* 192.168.0.3 */
765 .sin = {
766 .sin_family = AF_INET,
767 .sin_addr = { .s_addr = htonl ( 0xc0a80003 ) },
768 },
769 },
770 "relative/path",
771 {
772 .scheme = "tftp",
773 .host = "192.168.0.3",
774 .path = "/relative/path",
775 },
776 "tftp://192.168.0.3/relative/path",
777 };
778
779 /** PXE URI with path containing special characters */
780 static struct uri_pxe_test uri_pxe_icky = {
781 {
782 /* 10.0.0.6 */
783 .sin = {
784 .sin_family = AF_INET,
785 .sin_addr = { .s_addr = htonl ( 0x0a000006 ) },
786 },
787 },
788 "C:\\tftpboot\\icky#path",
789 {
790 .scheme = "tftp",
791 .host = "10.0.0.6",
792 .path = "/C:\\tftpboot\\icky#path",
793 },
794 "tftp://10.0.0.6/C%3A\\tftpboot\\icky%23path",
795 };
796
797 /** PXE URI with custom port */
798 static struct uri_pxe_test uri_pxe_port = {
799 {
800 /* 192.168.0.1:4069 */
801 .sin = {
802 .sin_family = AF_INET,
803 .sin_addr = { .s_addr = htonl ( 0xc0a80001 ) },
804 .sin_port = htons ( 4069 ),
805 },
806 },
807 "/another/path",
808 {
809 .scheme = "tftp",
810 .host = "192.168.0.1",
811 .port = "4069",
812 .path = "//another/path",
813 },
814 "tftp://192.168.0.1:4069//another/path",
815 };
816
817 /** Current working URI test */
818 static struct uri_churi_test uri_churi[] = {
819 {
820 "http://boot.ipxe.org/demo/boot.php",
821 "http://boot.ipxe.org/demo/boot.php",
822 },
823 {
824 "?vendor=10ec&device=8139",
825 "http://boot.ipxe.org/demo/boot.php?vendor=10ec&device=8139",
826 },
827 {
828 "fedora/fedora.ipxe",
829 "http://boot.ipxe.org/demo/fedora/fedora.ipxe",
830 },
831 {
832 "vmlinuz",
833 "http://boot.ipxe.org/demo/fedora/vmlinuz",
834 },
835 {
836 "http://local/boot/initrd.img",
837 "http://local/boot/initrd.img",
838 },
839 {
840 "modules/8139too.ko",
841 "http://local/boot/modules/8139too.ko",
842 },
843 {
844 NULL,
845 NULL,
846 }
847 };
848
849 /** Form parameter URI test list */
850 static struct uri_params_test_list uri_params_list[] = {
851 {
852 "vendor",
853 "10ec",
854 },
855 {
856 "device",
857 "8139",
858 },
859 {
860 "uuid",
861 "f59fac00-758f-498f-9fe5-87d790045d94",
862 },
863 {
864 NULL,
865 NULL,
866 }
867 };
868
869 /** Form parameter URI test */
870 static struct uri_params_test uri_params = {
871 "http://boot.ipxe.org/demo/boot.php##params",
872 {
873 .scheme = "http",
874 .host = "boot.ipxe.org",
875 .path = "/demo/boot.php",
876 },
877 NULL,
878 uri_params_list,
879 };
880
881 /** Named form parameter URI test list */
882 static struct uri_params_test_list uri_named_params_list[] = {
883 {
884 "mac",
885 "00:1e:65:80:d3:b6",
886 },
887 {
888 "serial",
889 "LXTQ20Z1139322762F2000",
890 },
891 {
892 NULL,
893 NULL,
894 }
895 };
896
897 /** Named form parameter URI test */
898 static struct uri_params_test uri_named_params = {
899 "http://192.168.100.4:3001/register##params=foo",
900 {
901 .scheme = "http",
902 .host = "192.168.100.4",
903 .port = "3001",
904 .path = "/register",
905 },
906 "foo",
907 uri_named_params_list,
908 };
909
910 /**
911 * Perform URI self-test
912 *
913 */
uri_test_exec(void)914 static void uri_test_exec ( void ) {
915
916 /* URI parsing, formatting, and duplication tests */
917 uri_parse_format_dup_ok ( &uri_empty );
918 uri_parse_format_dup_ok ( &uri_boot_ipxe_org );
919 uri_parse_format_dup_ok ( &uri_mailto );
920 uri_parse_format_dup_ok ( &uri_path );
921 uri_parse_format_dup_ok ( &uri_path_escaped );
922 uri_parse_format_dup_ok ( &uri_http_all );
923 uri_parse_format_dup_ok ( &uri_http_escaped );
924 uri_parse_ok ( &uri_http_escaped_improper ); /* Parse only */
925 uri_parse_format_dup_ok ( &uri_ipv6 );
926 uri_parse_format_dup_ok ( &uri_ipv6_port );
927 uri_parse_format_dup_ok ( &uri_ipv6_local );
928 uri_parse_ok ( &uri_ipv6_local_non_conforming ); /* Parse only */
929 uri_parse_format_dup_ok ( &uri_iscsi );
930 uri_parse_format_dup_ok ( &uri_file_relative );
931 uri_parse_format_dup_ok ( &uri_file_absolute );
932 uri_parse_format_dup_ok ( &uri_file_volume );
933
934 /** URI port number tests */
935 uri_port_ok ( &uri_explicit_port );
936 uri_port_ok ( &uri_default_port );
937
938 /** Path resolution tests */
939 uri_resolve_path_ok ( &uri_simple_path );
940 uri_resolve_path_ok ( &uri_relative_path );
941 uri_resolve_path_ok ( &uri_directory_path );
942 uri_resolve_path_ok ( &uri_excessive_path );
943 uri_resolve_path_ok ( &uri_absolute_path );
944
945 /** URI resolution tests */
946 uri_resolve_ok ( &uri_relative );
947 uri_resolve_ok ( &uri_absolute );
948 uri_resolve_ok ( &uri_absolute_uri_path );
949 uri_resolve_ok ( &uri_query );
950 uri_resolve_ok ( &uri_fragment );
951
952 /* PXE URI construction tests */
953 uri_pxe_ok ( &uri_pxe_absolute );
954 uri_pxe_ok ( &uri_pxe_absolute_path );
955 uri_pxe_ok ( &uri_pxe_relative_path );
956 uri_pxe_ok ( &uri_pxe_icky );
957 uri_pxe_ok ( &uri_pxe_port );
958
959 /* Current working URI tests */
960 uri_churi_ok ( uri_churi );
961
962 /* Form parameter URI tests */
963 uri_params_ok ( &uri_params );
964 uri_params_ok ( &uri_named_params );
965 }
966
967 /** URI self-test */
968 struct self_test uri_test __self_test = {
969 .name = "uri",
970 .exec = uri_test_exec,
971 };
972