From 19dab336ae13f0476bfbf0db34f1329a802eeb8e Mon Sep 17 00:00:00 2001 From: Jeremy Kerr Date: Tue, 19 Mar 2013 14:24:57 +0800 Subject: [PATCH] discover: Add configuration events & DHCP handler This change adds a new event type, EVENT_ACTION_CONF. These events supply a new configuration URL that petitiboot should download and parse. With this in place, we can receive DHCP configuration events. Signed-off-by: Jeremy Kerr --- discover/device-handler.c | 56 +++++++++++++++++++++++++++++++++++++++ discover/device-handler.h | 5 ++++ discover/event.c | 2 ++ discover/event.h | 1 + discover/parser.c | 49 ++++++++++++++++++++++++++++++++-- 5 files changed, 111 insertions(+), 2 deletions(-) diff --git a/discover/device-handler.c b/discover/device-handler.c index 6ff70c1..594a7c3 100644 --- a/discover/device-handler.c +++ b/discover/device-handler.c @@ -451,6 +451,61 @@ static int handle_remove_user_event(struct device_handler *handler, return 0; } +static enum conf_method parse_conf_method(const char *str) +{ + + if (!strcasecmp(str, "dhcp")) { + return CONF_METHOD_DHCP; + } + return CONF_METHOD_UNKNOWN; +} + +static int handle_conf_user_event(struct device_handler *handler, + struct event *event) +{ + struct discover_context *ctx; + struct discover_device *dev; + enum conf_method method; + const char *val; + + ctx = talloc(handler, struct discover_context); + ctx->event = event; + list_init(&ctx->boot_options); + + val = event_get_param(event, "url"); + if (!val) { + talloc_free(ctx); + return 0; + } + + ctx->conf_url = pb_url_parse(ctx, val); + if (!ctx->conf_url) { + talloc_free(ctx); + return 0; + } + + val = event_get_param(event, "method"); + if (!val) { + talloc_free(ctx); + return 0; + } + + method = parse_conf_method(val); + if (method == CONF_METHOD_UNKNOWN) { + talloc_free(ctx); + return 0; + } + + dev = discover_device_create(handler, ctx, event); + ctx->device = dev; + + iterate_parsers(ctx, method); + + context_commit(handler, ctx); + + return 0; +} + typedef int (*event_handler)(struct device_handler *, struct event *); static event_handler handlers[EVENT_TYPE_MAX][EVENT_ACTION_MAX] = { @@ -461,6 +516,7 @@ static event_handler handlers[EVENT_TYPE_MAX][EVENT_ACTION_MAX] = { [EVENT_TYPE_USER] = { [EVENT_ACTION_ADD] = handle_add_user_event, [EVENT_ACTION_REMOVE] = handle_remove_user_event, + [EVENT_ACTION_CONF] = handle_conf_user_event, } }; diff --git a/discover/device-handler.h b/discover/device-handler.h index ad9f50a..f4c911e 100644 --- a/discover/device-handler.h +++ b/discover/device-handler.h @@ -14,6 +14,10 @@ struct device; enum conf_method { CONF_METHOD_LOCAL_FILE, /* discover by looking at local files on this block device */ + + CONF_METHOD_DHCP, /* configuration from a DHCP response */ + + CONF_METHOD_UNKNOWN = -1, }; struct discover_device { @@ -48,6 +52,7 @@ struct discover_context { struct event *event; struct discover_device *device; struct list boot_options; + struct pb_url *conf_url; enum conf_method method; }; diff --git a/discover/event.c b/discover/event.c index 1314561..a05ce27 100644 --- a/discover/event.c +++ b/discover/event.c @@ -42,6 +42,8 @@ static int event_parse_ad_header(char *buf, int len, enum event_action *action, *action = EVENT_ACTION_ADD; else if (streq(buf, "remove")) *action = EVENT_ACTION_REMOVE; + else if (streq(buf, "conf")) + *action = EVENT_ACTION_CONF; else { pb_log("%s: unknown action: %s\n", __func__, buf); return -1; diff --git a/discover/event.h b/discover/event.h index 900ced8..70cc8fc 100644 --- a/discover/event.h +++ b/discover/event.h @@ -10,6 +10,7 @@ enum event_type { enum event_action { EVENT_ACTION_ADD = 20, EVENT_ACTION_REMOVE, + EVENT_ACTION_CONF, EVENT_ACTION_MAX, }; diff --git a/discover/parser.c b/discover/parser.c index c04a0af..42ee2e5 100644 --- a/discover/parser.c +++ b/discover/parser.c @@ -73,6 +73,28 @@ static char *local_path(struct discover_context *ctx, return join_paths(ctx, ctx->device->mount_path, filename); } +static int download_config(struct discover_context *ctx, char **buf, int *len) +{ + unsigned tempfile; + const char *file; + int rc; + + file = load_url(ctx, ctx->conf_url, &tempfile); + if (!file) + return -1; + + rc = read_file(ctx, file, buf, len); + if (rc) + goto out_clean; + + return 0; + +out_clean: + if (tempfile) + unlink(file); + return -1; +} + static void iterate_parser_files(struct discover_context *ctx, const struct parser *parser) { @@ -100,11 +122,13 @@ static void iterate_parser_files(struct discover_context *ctx, void iterate_parsers(struct discover_context *ctx, enum conf_method method) { - int i; + int rc, i, len; + char *buf; pb_log("trying parsers for %s\n", ctx->device->device->id); - if (method == CONF_METHOD_LOCAL_FILE) { + switch (method) { + case CONF_METHOD_LOCAL_FILE: for (i = 0; i < n_parsers; i++) { if (parsers[i]->method != CONF_METHOD_LOCAL_FILE) continue; @@ -114,6 +138,27 @@ void iterate_parsers(struct discover_context *ctx, enum conf_method method) iterate_parser_files(ctx, ctx->parser); } ctx->parser = NULL; + break; + + case CONF_METHOD_DHCP: + rc = download_config(ctx, &buf, &len); + if (rc) + return; + + for (i = 0; i < n_parsers; i++) { + if (parsers[i]->method != method) + continue; + + pb_log("\ttrying parser '%s'\n", parsers[i]->name); + ctx->parser = parsers[i]; + parsers[i]->parse(ctx, buf, len); + } + + break; + + case CONF_METHOD_UNKNOWN: + break; + } } -- 2.39.2