discover/pxe-parser: Fix relative parsing for manual config files
authorSamuel Mendoza-Jonas <sam@mendozajonas.com>
Tue, 12 Dec 2017 03:05:40 +0000 (14:05 +1100)
committerSamuel Mendoza-Jonas <sam@mendozajonas.com>
Tue, 12 Dec 2017 05:15:59 +0000 (16:15 +1100)
Manually specified config files are asynchronously downloaded by
device_handler_process_url() before being parsed. This overwrites the
'pxeconffile' parameter, causing the parser to create relative paths
relative to the downloaded file's path, not the original remote path.

Work around this by setting 'pxeconffile-local' instead to differentiate
between the original config file's location and the local copy.

Signed-off-by: Samuel Mendoza-Jonas <sam@mendozajonas.com>
discover/device-handler.c
discover/pxe-parser.c
test/parser/Makefile.am
test/parser/test-pxe-discover-bootfile-async-file.c [new file with mode: 0644]

index 8ad885f68225c031efc6de9b0b9f570776a53662..82230154ba77d9a314f50d3a41fe184837197d40 100644 (file)
@@ -1356,7 +1356,7 @@ static void process_url_cb(struct load_url_result *result, void *data)
 
        mac = event_get_param(event, "mac");
        char *url = talloc_asprintf(event, "file://%s", result->local);
-       event_set_param(event, "pxeconffile", url);
+       event_set_param(event, "pxeconffile-local", url);
 
        dev = discover_device_create(handler, mac, event->device);
        ctx = device_handler_discover_context_create(handler, dev);
index 7183ecff2dca169251999be12c3f592a441b1bce..2f099e3ec17717031d9ad555285a878c4e3e6e90 100644 (file)
@@ -368,7 +368,7 @@ static struct conf_context *copy_context(void *ctx, struct discover_context *dc)
 
 static int pxe_parse(struct discover_context *dc)
 {
-       struct pb_url *pxe_base_url;
+       struct pb_url *pxe_base_url, *file_url;
        struct conf_context *conf = NULL;
        struct load_url_result *result;
        void *ctx = talloc_parent(dc);
@@ -397,13 +397,25 @@ static int pxe_parse(struct discover_context *dc)
                return -1;
 
        if (complete_url) {
+               /* Check if this file has already been downloaded */
+               if (event_get_param(dc->event, "pxeconffile-local"))
+                       file_url = pb_url_parse(dc, event_get_param(dc->event,
+                                               "pxeconffile-local"));
+               else
+                       file_url = dc->conf_url;
+
+               if (!file_url) {
+                       pb_log("%s: Failed to parse conf url!\n", __func__);
+                       goto out_conf;
+               }
+
                device_handler_status_dev_info(conf->dc->handler,
                        dc->device,
                        _("Requesting config %s"),
                        pb_url_to_string(conf->dc->conf_url));
 
                /* we have a complete URL; use this and we're done. */
-               result = load_url_async(conf->dc, conf->dc->conf_url,
+               result = load_url_async(conf->dc, file_url,
                                        pxe_conf_parse_cb, conf, NULL, ctx);
                if (!result) {
                        pb_log("load_url_async fails for %s\n",
index fa644fe3f98daa417cc49289e0eb0791965dd754..eb71a07dd1b76cafb3df7f361c4e296695a433e5 100644 (file)
@@ -71,6 +71,7 @@ parser_TESTS = \
        test/parser/test-pxe-discover-bootfile-pathprefix \
        test/parser/test-pxe-discover-bootfile-relative-conffile \
        test/parser/test-pxe-discover-bootfile-absolute-conffile \
+       test/parser/test-pxe-discover-bootfile-async-file \
        test/parser/test-unresolved-remove
 
 TESTS += $(parser_TESTS)
diff --git a/test/parser/test-pxe-discover-bootfile-async-file.c b/test/parser/test-pxe-discover-bootfile-async-file.c
new file mode 100644 (file)
index 0000000..af61659
--- /dev/null
@@ -0,0 +1,42 @@
+
+#include "parser-test.h"
+
+#if 0 /* PARSER_EMBEDDED_CONFIG */
+label linux
+kernel vmlinux
+initrd initrd
+#endif
+
+/**
+ * Manually specified conf files will be downloaded locally before being passed
+ * to the parser. Check that the parser correctly resolves relative paths to the
+ * actual source, rather than the local file path.
+ */
+
+void run_test(struct parser_test *test)
+{
+       struct discover_boot_option *opt;
+       struct discover_context *ctx;
+
+       test_read_conf_embedded_url(test, "file://tmp/conf.txt");
+
+       test_set_event_source(test);
+       test_set_event_param(test->ctx->event, "pxeconffile",
+                       "tftp://host/dir/fail.txt");
+       test_set_event_param(test->ctx->event, "pxeconffile-local",
+                       "file://tmp/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");
+
+       check_resolved_url_resource(opt->boot_image,
+                       "tftp://host/dir/vmlinux");
+       check_resolved_url_resource(opt->initrd,
+                       "tftp://host/dir/initrd");
+}