discover: Add configuration events & DHCP handler
authorJeremy Kerr <jk@ozlabs.org>
Tue, 19 Mar 2013 06:24:57 +0000 (14:24 +0800)
committerJeremy Kerr <jk@ozlabs.org>
Mon, 29 Apr 2013 04:48:01 +0000 (14:48 +1000)
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 <jk@ozlabs.org>
discover/device-handler.c
discover/device-handler.h
discover/event.c
discover/event.h
discover/parser.c

index 6ff70c14b6e2faf0265667ce2749245deb3b8c74..594a7c3c80a87b2c142cd17730cf09f46b50b149 100644 (file)
@@ -451,6 +451,61 @@ static int handle_remove_user_event(struct device_handler *handler,
        return 0;
 }
 
        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] = {
 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_TYPE_USER] = {
                [EVENT_ACTION_ADD]      = handle_add_user_event,
                [EVENT_ACTION_REMOVE]   = handle_remove_user_event,
+               [EVENT_ACTION_CONF]     = handle_conf_user_event,
        }
 };
 
        }
 };
 
index ad9f50a43b041003048753591e22c176527b1594..f4c911e08892cf64df67dcb84f91f2908b243164 100644 (file)
@@ -14,6 +14,10 @@ struct device;
 enum conf_method {
        CONF_METHOD_LOCAL_FILE, /* discover by looking at local files on this
                                   block 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 {
 };
 
 struct discover_device {
@@ -48,6 +52,7 @@ struct discover_context {
        struct event            *event;
        struct discover_device  *device;
        struct list             boot_options;
        struct event            *event;
        struct discover_device  *device;
        struct list             boot_options;
+       struct pb_url           *conf_url;
        enum conf_method        method;
 };
 
        enum conf_method        method;
 };
 
index 1314561c9eda23e19cfc016604ae71d207d9ae09..a05ce2752f42325fb9efd7c52bfeb44c092e9bae 100644 (file)
@@ -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;
                *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;
        else {
                pb_log("%s: unknown action: %s\n", __func__, buf);
                return -1;
index 900ced892d11738939dad4381fd4241c4c7208ca..70cc8fc3c15d3da7e39436e0c527696de7d1eced 100644 (file)
@@ -10,6 +10,7 @@ enum event_type {
 enum event_action {
        EVENT_ACTION_ADD = 20,
        EVENT_ACTION_REMOVE,
 enum event_action {
        EVENT_ACTION_ADD = 20,
        EVENT_ACTION_REMOVE,
+       EVENT_ACTION_CONF,
        EVENT_ACTION_MAX,
 };
 
        EVENT_ACTION_MAX,
 };
 
index c04a0afca610b31bfb07468824770445cfc94d92..42ee2e55c9a0f352949e26551abc5c344bd1d84a 100644 (file)
@@ -73,6 +73,28 @@ static char *local_path(struct discover_context *ctx,
        return join_paths(ctx, ctx->device->mount_path, filename);
 }
 
        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)
 {
 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)
 {
 
 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);
 
 
        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;
                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;
                        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;
+
        }
 }
 
        }
 }