From 1ad12fe5b75e5cedd9e758b0a1342e10baea293b Mon Sep 17 00:00:00 2001 From: Samuel Mendoza-Jonas Date: Tue, 12 Dec 2017 14:05:40 +1100 Subject: [PATCH] discover/pxe-parser: Fix relative parsing for manual config files 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 (cherry picked from commit a2d5a3e3cb55fe3583acaae44fabc7c3d7f8df50) --- discover/device-handler.c | 2 +- discover/pxe-parser.c | 16 ++++++- test/parser/Makefile.am | 1 + .../test-pxe-discover-bootfile-async-file.c | 42 +++++++++++++++++++ 4 files changed, 58 insertions(+), 3 deletions(-) create mode 100644 test/parser/test-pxe-discover-bootfile-async-file.c diff --git a/discover/device-handler.c b/discover/device-handler.c index 8ad885f..8223015 100644 --- a/discover/device-handler.c +++ b/discover/device-handler.c @@ -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); diff --git a/discover/pxe-parser.c b/discover/pxe-parser.c index aef43b8..29d9c33 100644 --- a/discover/pxe-parser.c +++ b/discover/pxe-parser.c @@ -356,7 +356,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); @@ -385,13 +385,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", diff --git a/test/parser/Makefile.am b/test/parser/Makefile.am index fa644fe..eb71a07 100644 --- a/test/parser/Makefile.am +++ b/test/parser/Makefile.am @@ -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 index 0000000..af61659 --- /dev/null +++ b/test/parser/test-pxe-discover-bootfile-async-file.c @@ -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"); +} -- 2.39.2