discover/pxe: pxe parser should only treat "::" paths as absolute
authorJeremy Kerr <jk@ozlabs.org>
Thu, 27 Feb 2014 05:54:32 +0000 (13:54 +0800)
committerJeremy Kerr <jk@ozlabs.org>
Thu, 27 Feb 2014 05:54:32 +0000 (13:54 +0800)
PXELinux treats all paths as relative, requiring a "::/path" syntax for
truly absolute URLs.

This change implements the same behaviour in petitboot, and updates the
testcases to suit.

Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
discover/pxe-parser.c
test/parser/Makefile.am
test/parser/test-pxe-non-url-pathprefix-with-conf.c
test/parser/test-pxe-path-resolve-absolute.c [new file with mode: 0644]
test/parser/test-pxe-path-resolve-relative.c [new file with mode: 0644]
test/parser/test-pxe-pathprefix-discover-mac.c
test/parser/test-pxe-pathprefix-discover.c
test/parser/test-pxe-pathprefix-with-conf.c

index 17ae55e6a3dc0c5665be7e7678a308dddf6ecf0d..98e160373a90f25c68fe22434d60d84ee9dfda19 100644 (file)
@@ -28,6 +28,44 @@ static void pxe_finish(struct conf_context *conf)
                discover_context_add_boot_option(conf->dc, info->opt);
 }
 
+/* We need a slightly modified version of pb_url_join, to allow for the
+ * pxelinux "::filename" syntax for absolute URLs
+ */
+static struct pb_url *pxe_url_join(void *ctx, const struct pb_url *url,
+               const char *s)
+{
+       struct pb_url *new_url;
+       int len;
+
+       len = strlen(s);
+
+       if (len > 2 && s[0] == ':' && s[1] == ':') {
+               char *tmp;
+
+               if (s[2] == '/') {
+                       /* ::/path -> /path */
+                       tmp = talloc_strdup(ctx, s+2);
+               } else {
+                       /* ::path -> /path */
+                       tmp = talloc_strdup(ctx, s+1);
+                       tmp[0] = '/';
+               }
+
+               new_url = pb_url_join(ctx, url, tmp);
+
+               talloc_free(tmp);
+
+       } else {
+               const char *tmp;
+               /* strip leading slashes */
+               for (tmp = s; *tmp == '/'; tmp++);
+                       ;
+               new_url = pb_url_join(ctx, url, tmp);
+       }
+
+       return new_url;
+}
+
 static void pxe_process_pair(struct conf_context *ctx,
                const char *name, char *value)
 {
@@ -72,11 +110,11 @@ static void pxe_process_pair(struct conf_context *ctx,
                return;
 
        if (streq(name, "KERNEL")) {
-               url = pb_url_join(ctx->dc, ctx->dc->conf_url, value);
+               url = pxe_url_join(ctx->dc, ctx->dc->conf_url, value);
                opt->boot_image = create_url_resource(opt, url);
 
        } else if (streq(name, "INITRD")) {
-               url = pb_url_join(ctx->dc, ctx->dc->conf_url, value);
+               url = pxe_url_join(ctx->dc, ctx->dc->conf_url, value);
                opt->initrd = create_url_resource(opt, url);
 
        } else if (streq(name, "APPEND")) {
@@ -90,7 +128,7 @@ static void pxe_process_pair(struct conf_context *ctx,
                        end = strchrnul(str, ' ');
                        *end = '\0';
 
-                       url = pb_url_join(ctx->dc, ctx->dc->conf_url, str);
+                       url = pxe_url_join(ctx->dc, ctx->dc->conf_url, str);
                        opt->initrd = create_url_resource(opt, url);
                }
        }
index aeb16d8adcab209b05d7f77bf30894f92d627ab7..62770d2c950e05aa9ca915e21f2acefdc76eb3ab 100644 (file)
@@ -67,6 +67,8 @@ TESTS = \
        test-pxe-non-url-pathprefix-with-conf \
        test-pxe-pathprefix-discover \
        test-pxe-pathprefix-discover-mac \
+       test-pxe-path-resolve-relative \
+       test-pxe-path-resolve-absolute \
        test-unresolved-remove
 
 $(TESTS): %: %.embedded-config.o
index 36d472699bd408b3ca0872281023a39fb3c67e8e..b8cc2c27cde52bb27f0edea6a18407f1b1e1f7ea 100644 (file)
@@ -34,5 +34,6 @@ void run_test(struct parser_test *test)
 
        check_resolved_url_resource(opt->boot_image,
                        "tftp://host/path/to/./kernel");
-       check_resolved_url_resource(opt->initrd, "tftp://host/initrd");
+       check_resolved_url_resource(opt->initrd,
+                       "tftp://host/path/to/initrd");
 }
diff --git a/test/parser/test-pxe-path-resolve-absolute.c b/test/parser/test-pxe-path-resolve-absolute.c
new file mode 100644 (file)
index 0000000..04502fc
--- /dev/null
@@ -0,0 +1,36 @@
+
+#include "parser-test.h"
+
+#if 0 /* PARSER_EMBEDDED_CONFIG */
+label linux
+kernel ::vmlinux
+initrd ::/initrd
+#endif
+
+void run_test(struct parser_test *test)
+{
+       struct discover_boot_option *opt;
+       struct discover_context *ctx;
+
+       test_read_conf_embedded_url(test, "tftp://host/path/conf.txt");
+
+       test_set_event_source(test);
+       test_set_event_param(test->ctx->event, "siaddr", "host");
+       test_set_event_param(test->ctx->event, "pxeconffile", "path/conf.txt");
+
+       test_run_parser(test, "pxe");
+
+       ctx = test->ctx;
+
+       check_boot_option_count(ctx, 1);
+       opt = get_boot_option(ctx, 0);
+
+       check_name(opt, "linux");
+
+       /* even though the initrd is specifed as /initrd, pxelinux treats
+        * this as relative. */
+       check_resolved_url_resource(opt->boot_image,
+                       "tftp://host/vmlinux");
+       check_resolved_url_resource(opt->initrd,
+                       "tftp://host/initrd");
+}
diff --git a/test/parser/test-pxe-path-resolve-relative.c b/test/parser/test-pxe-path-resolve-relative.c
new file mode 100644 (file)
index 0000000..920c139
--- /dev/null
@@ -0,0 +1,36 @@
+
+#include "parser-test.h"
+
+#if 0 /* PARSER_EMBEDDED_CONFIG */
+label linux
+kernel vmlinux
+initrd /initrd
+#endif
+
+void run_test(struct parser_test *test)
+{
+       struct discover_boot_option *opt;
+       struct discover_context *ctx;
+
+       test_read_conf_embedded_url(test, "tftp://host/path/conf.txt");
+
+       test_set_event_source(test);
+       test_set_event_param(test->ctx->event, "siaddr", "host");
+       test_set_event_param(test->ctx->event, "pxeconffile", "path/conf.txt");
+
+       test_run_parser(test, "pxe");
+
+       ctx = test->ctx;
+
+       check_boot_option_count(ctx, 1);
+       opt = get_boot_option(ctx, 0);
+
+       check_name(opt, "linux");
+
+       /* even though the initrd is specifed as /initrd, pxelinux treats
+        * this as relative. */
+       check_resolved_url_resource(opt->boot_image,
+                       "tftp://host/path/vmlinux");
+       check_resolved_url_resource(opt->initrd,
+                       "tftp://host/path/initrd");
+}
index 1e5fa71e5c8eec377cc375c09931bdfd73cee2a9..3c003fab258d5e5d75febdf535309d96ae47b7dd 100644 (file)
@@ -37,5 +37,5 @@ void run_test(struct parser_test *test)
        check_resolved_url_resource(opt->boot_image,
                        "tftp://host/path/to/./kernel");
        check_resolved_url_resource(opt->initrd,
-                       "tftp://host/initrd");
+                       "tftp://host/path/to/initrd");
 }
index 9cb44c8764b7a954a0c3c6b549408c7f8864cff2..8048961824a7a7b6cd632354b856aa8f9fb73ac0 100644 (file)
@@ -36,5 +36,5 @@ void run_test(struct parser_test *test)
        check_resolved_url_resource(opt->boot_image,
                        "tftp://host/path/to/./kernel");
        check_resolved_url_resource(opt->initrd,
-                       "tftp://host/initrd");
+                       "tftp://host/path/to/initrd");
 }
index 57f942dd8cad99bd273ef5b9d70f28a865b0766e..ce1d600dbea3ddb9e84d0377addedde8bac4e243 100644 (file)
@@ -34,5 +34,6 @@ void run_test(struct parser_test *test)
 
        check_resolved_url_resource(opt->boot_image,
                        "tftp://host/path/to/./kernel");
-       check_resolved_url_resource(opt->initrd, "tftp://host/initrd");
+       check_resolved_url_resource(opt->initrd,
+                       "tftp://host/path/to/initrd");
 }