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