summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeelesh Gupta <neelegup@linux.vnet.ibm.com>2013-10-28 12:45:21 +0530
committerJeremy Kerr <jk@ozlabs.org>2013-11-06 16:34:26 +0800
commitb8e53cb4b96eb17dc7fa0ffc505dfebae37e6cbf (patch)
tree2049ee274a9a7872366da8b95dbecaffc215df3a
parentf385e8cacbc574e213b0805a8d383373f29a8058 (diff)
downloadtalos-petitboot-b8e53cb4b96eb17dc7fa0ffc505dfebae37e6cbf.zip
talos-petitboot-b8e53cb4b96eb17dc7fa0ffc505dfebae37e6cbf.tar.gz
discover: Change parsers to explicitly request configuration files
Add a new function parser_request_url() to read the data from configuration files present remotely. We deprecate iterate_parser_files() and download_config() functions along with the 'filenames' and 'method' members of the 'parser' structure so that individual parsers would now require to request the configuration files data from the parser code and doesn't necessarily export the list of configuration files. Add the support to handle incoming DHCP event, done by passing all the relevant environment variables of the udhcpc to the discover code. Also, update the pxe parser code to populate the list of configuration file names as per PXELINUX convention of fallback names using mac and ip addresses of the booting machine. Signed-off-by: Neelesh Gupta <neelegup@linux.vnet.ibm.com> Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
-rw-r--r--discover/device-handler.c34
-rw-r--r--discover/device-handler.h18
-rw-r--r--discover/event.c2
-rw-r--r--discover/event.h1
-rw-r--r--discover/grub2/grub2.c24
-rw-r--r--discover/kboot-parser.c26
-rw-r--r--discover/parser.c83
-rw-r--r--discover/parser.h9
-rw-r--r--discover/pxe-parser.c62
-rw-r--r--discover/udev.c2
-rw-r--r--discover/user-event.c274
-rw-r--r--discover/user-event.h4
-rw-r--r--discover/yaboot-parser.c26
-rw-r--r--test/parser/handler.c3
-rw-r--r--utils/pb-udhcpc103
15 files changed, 428 insertions, 243 deletions
diff --git a/discover/device-handler.c b/discover/device-handler.c
index a497147..cfd0c7b 100644
--- a/discover/device-handler.c
+++ b/discover/device-handler.c
@@ -589,7 +589,7 @@ void device_handler_add_device(struct device_handler *handler,
* array, but has only just been initialised by the hotplug source.
*/
int device_handler_discover(struct device_handler *handler,
- struct discover_device *dev, enum conf_method method)
+ struct discover_device *dev)
{
struct discover_context *ctx;
int rc;
@@ -604,7 +604,7 @@ int device_handler_discover(struct device_handler *handler,
goto out;
/* run the parsers. This will populate the ctx's boot_option list. */
- iterate_parsers(ctx, method);
+ iterate_parsers(ctx);
/* add discovered stuff to the handler */
device_handler_discover_context_commit(handler, ctx);
@@ -615,18 +615,17 @@ out:
return 0;
}
-/* incoming conf event */
-int device_handler_conf(struct device_handler *handler,
- struct discover_device *dev, struct pb_url *url,
- enum conf_method method)
+/* Incoming dhcp event */
+int device_handler_dhcp(struct device_handler *handler,
+ struct discover_device *dev, struct event *event)
{
struct discover_context *ctx;
/* create our context */
ctx = device_handler_discover_context_create(handler, dev);
- ctx->conf_url = url;
+ ctx->event = event;
- iterate_parsers(ctx, method);
+ iterate_parsers(ctx);
device_handler_discover_context_commit(handler, ctx);
@@ -635,6 +634,25 @@ int device_handler_conf(struct device_handler *handler,
return 0;
}
+/* incoming conf event */
+int device_handler_conf(struct device_handler *handler,
+ struct discover_device *dev, struct pb_url *url)
+{
+ struct discover_context *ctx;
+
+ /* create our context */
+ ctx = device_handler_discover_context_create(handler, dev);
+ ctx->conf_url = url;
+
+ iterate_parsers(ctx);
+
+ device_handler_discover_context_commit(handler, ctx);
+
+ talloc_free(ctx);
+
+ return 0;
+}
+
static struct discover_boot_option *find_boot_option_by_id(
struct device_handler *handler, const char *id)
{
diff --git a/discover/device-handler.h b/discover/device-handler.h
index 6b36e07..56d585a 100644
--- a/discover/device-handler.h
+++ b/discover/device-handler.h
@@ -14,16 +14,6 @@ struct event;
struct device;
struct waitset;
-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 device *device;
@@ -64,7 +54,6 @@ struct discover_context {
struct discover_device *device;
struct list boot_options;
struct pb_url *conf_url;
- enum conf_method method;
void *test_data;
};
@@ -82,10 +71,11 @@ struct discover_device *discover_device_create(struct device_handler *handler,
void device_handler_add_device(struct device_handler *handler,
struct discover_device *device);
int device_handler_discover(struct device_handler *handler,
- struct discover_device *dev, enum conf_method method);
+ struct discover_device *dev);
+int device_handler_dhcp(struct device_handler *handler,
+ struct discover_device *dev, struct event *event);
int device_handler_conf(struct device_handler *handler,
- struct discover_device *dev, struct pb_url *url,
- enum conf_method method);
+ struct discover_device *dev, struct pb_url *url);
void device_handler_remove(struct device_handler *handler,
struct discover_device *device);
diff --git a/discover/event.c b/discover/event.c
index 0ccd391..d4bb2c5 100644
--- a/discover/event.c
+++ b/discover/event.c
@@ -50,6 +50,8 @@ static int event_parse_ad_header(char *buf, int len, enum event_action *action,
*action = EVENT_ACTION_REMOVE;
else if (streq(buf, "conf"))
*action = EVENT_ACTION_CONF;
+ else if (streq(buf, "dhcp"))
+ *action = EVENT_ACTION_DHCP;
else {
pb_log("%s: unknown action: %s\n", __func__, buf);
return -1;
diff --git a/discover/event.h b/discover/event.h
index adba336..98ece11 100644
--- a/discover/event.h
+++ b/discover/event.h
@@ -11,6 +11,7 @@ enum event_action {
EVENT_ACTION_ADD = 20,
EVENT_ACTION_REMOVE,
EVENT_ACTION_CONF,
+ EVENT_ACTION_DHCP,
EVENT_ACTION_MAX,
};
diff --git a/discover/grub2/grub2.c b/discover/grub2/grub2.c
index 22d42df..9a46127 100644
--- a/discover/grub2/grub2.c
+++ b/discover/grub2/grub2.c
@@ -86,24 +86,36 @@ bool resolve_grub2_resource(struct device_handler *handler,
return true;
}
-static int grub2_parse(struct discover_context *dc, char *buf, int len)
-{
+static int grub2_parse(struct discover_context *dc)
+ {
+ const char * const *filename;
struct grub2_parser *parser;
+ int len, rc;
+ char *buf;
+
+ /* Support block device boot only at present */
+ if (dc->event)
+ return -1;
parser = grub2_parser_create(dc);
- grub2_parser_parse(parser, buf, len);
+ for (filename = grub2_conf_files; *filename; filename++) {
+ rc = parser_request_file(dc, dc->device, *filename, &buf, &len);
+ if (rc)
+ continue;
+
+ grub2_parser_parse(parser, buf, len);
+ talloc_free(buf);
+ }
talloc_free(parser);
- return 1;
+ return 0;
}
static struct parser grub2_parser = {
.name = "grub2",
- .method = CONF_METHOD_LOCAL_FILE,
.parse = grub2_parse,
- .filenames = grub2_conf_files,
.resolve_resource = resolve_grub2_resource,
};
diff --git a/discover/kboot-parser.c b/discover/kboot-parser.c
index 9d0322d..8572674 100644
--- a/discover/kboot-parser.c
+++ b/discover/kboot-parser.c
@@ -151,33 +151,45 @@ static const char *const kboot_ignored_names[] = {
NULL
};
-static int kboot_parse(struct discover_context *dc, char *buf, int len)
+static int kboot_parse(struct discover_context *dc)
{
struct conf_context *conf;
+ const char * const *filename;
+ char *buf;
+ int len, rc;
+
+ /* Support block device boot only at present */
+ if (dc->event)
+ return -1;
conf = talloc_zero(dc, struct conf_context);
if (!conf)
- return 0;
+ return -1;
conf->dc = dc;
conf->global_options = kboot_global_options,
conf_init_global_options(conf);
conf->get_pair = conf_get_pair_equal;
conf->process_pair = kboot_process_pair;
- conf->parser_info = (void *)kboot_ignored_names,
+ conf->parser_info = (void *)kboot_ignored_names;
+
+ for (filename = kboot_conf_files; *filename; filename++) {
+ rc = parser_request_file(dc, dc->device, *filename, &buf, &len);
+ if (rc)
+ continue;
- conf_parse_buf(conf, buf, len);
+ conf_parse_buf(conf, buf, len);
+ talloc_free(buf);
+ }
talloc_free(conf);
- return 1;
+ return 0;
}
static struct parser kboot_parser = {
.name = "kboot",
- .method = CONF_METHOD_LOCAL_FILE,
.parse = kboot_parse,
- .filenames = kboot_conf_files,
.resolve_resource = resolve_devpath_resource,
};
diff --git a/discover/parser.c b/discover/parser.c
index 7b70118..21b48de 100644
--- a/discover/parser.c
+++ b/discover/parser.c
@@ -78,97 +78,44 @@ int parser_replace_file(struct discover_context *ctx,
return rc;
}
-static int download_config(struct discover_context *ctx, char **buf, int *len)
+int parser_request_url(struct discover_context *ctx, struct pb_url *url,
+ char **buf, int *len)
{
struct load_url_result *result;
int rc;
- result = load_url(ctx, ctx->conf_url);
+ result = load_url(ctx, url);
if (!result)
- return -1;
+ goto out;
rc = read_file(ctx, result->local, buf, len);
- if (rc)
+ if (rc) {
+ pb_log("Read failed for the parser %s on file %s\n",
+ ctx->parser->name, result->local);
goto out_clean;
+ }
return 0;
out_clean:
if (result->cleanup_local)
unlink(result->local);
+out:
return -1;
}
-static void iterate_parser_files(struct discover_context *ctx,
- const struct parser *parser)
-{
- const char * const *filename;
- const char *path;
-
- if (!parser->filenames)
- return;
-
- for (filename = parser->filenames; *filename; filename++) {
- int rc, len;
- char *buf;
-
- path = local_path(ctx, ctx->device, *filename);
- if (!path)
- continue;
-
- rc = read_file(ctx, path, &buf, &len);
- if (!rc) {
- pb_log("Running parser %s on file %s\n",
- parser->name, *filename);
- parser->parse(ctx, buf, len);
- talloc_free(buf);
- }
- }
-}
-
-void iterate_parsers(struct discover_context *ctx, enum conf_method method)
+void iterate_parsers(struct discover_context *ctx)
{
struct p_item* i;
- int rc, len;
- char *buf;
pb_log("trying parsers for %s\n", ctx->device->device->id);
- switch (method) {
- case CONF_METHOD_LOCAL_FILE:
- list_for_each_entry(&parsers, i, list) {
- if (i->parser->method != CONF_METHOD_LOCAL_FILE)
- continue;
-
- pb_debug("\ttrying parser '%s'\n", i->parser->name);
- ctx->parser = i->parser;
- iterate_parser_files(ctx, ctx->parser);
- }
- ctx->parser = NULL;
- break;
-
- case CONF_METHOD_DHCP:
- rc = download_config(ctx, &buf, &len);
- if (rc) {
- pb_log("\tdownload failed, aborting\n");
- return;
- }
-
- list_for_each_entry(&parsers, i, list) {
- if (i->parser->method != method)
- continue;
-
- pb_debug("\ttrying parser '%s'\n", i->parser->name);
- ctx->parser = i->parser;
- i->parser->parse(ctx, buf, len);
- }
-
- break;
-
- case CONF_METHOD_UNKNOWN:
- break;
-
+ list_for_each_entry(&parsers, i, list) {
+ pb_debug("\ttrying parser '%s'\n", i->parser->name);
+ ctx->parser = i->parser;
+ i->parser->parse(ctx);
}
+ ctx->parser = NULL;
}
static void *parsers_ctx;
diff --git a/discover/parser.h b/discover/parser.h
index 2aaa077..970d72c 100644
--- a/discover/parser.h
+++ b/discover/parser.h
@@ -27,10 +27,7 @@ struct resource;
*/
struct parser {
char *name;
- enum conf_method method;
- const char * const *filenames;
- int (*parse)(struct discover_context *ctx,
- char *buf, int len);
+ int (*parse)(struct discover_context *ctx);
bool (*resolve_resource)(
struct device_handler *handler,
struct resource *res);
@@ -48,7 +45,7 @@ enum generic_icon_type {
void parser_init(void);
-void iterate_parsers(struct discover_context *ctx, enum conf_method method);
+void iterate_parsers(struct discover_context *ctx);
int parse_user_event(struct discover_context *ctx, struct event *event);
/* File IO functions for parsers; these should be the only interface that
@@ -63,5 +60,7 @@ int parser_request_file(struct discover_context *ctx,
int parser_replace_file(struct discover_context *ctx,
struct discover_device *dev, const char *filename,
char *buf, int len);
+int parser_request_url(struct discover_context *ctx, struct pb_url *url,
+ char **buf, int *len);
#endif /* _PARSER_H */
diff --git a/discover/pxe-parser.c b/discover/pxe-parser.c
index 368d5c7..bc07a13 100644
--- a/discover/pxe-parser.c
+++ b/discover/pxe-parser.c
@@ -9,6 +9,8 @@
#include "parser-conf.h"
#include "parser-utils.h"
#include "resource.h"
+#include "paths.h"
+#include "user-event.h"
struct pxe_parser_info {
struct discover_boot_option *opt;
@@ -91,15 +93,23 @@ static void pxe_process_pair(struct conf_context *ctx,
}
-static int pxe_parse(struct discover_context *dc, char *buf, int len)
+static int pxe_parse(struct discover_context *dc)
{
struct pxe_parser_info *parser_info;
+ char **pxe_conf_files, **filename;
+ struct pb_url *conf_url, *url;
struct conf_context *conf;
+ int len, rc;
+ char *buf;
+
+ /* Expects dhcp event parameters to support network boot */
+ if (!dc->event)
+ return -1;
conf = talloc_zero(dc, struct conf_context);
if (!conf)
- return 0;
+ goto out;
conf->dc = dc;
conf->get_pair = conf_get_pair_space;
@@ -109,16 +119,60 @@ static int pxe_parse(struct discover_context *dc, char *buf, int len)
parser_info = talloc_zero(conf, struct pxe_parser_info);
conf->parser_info = parser_info;
+ conf_url = user_event_parse_conf_url(dc, dc->event);
+ if (!conf_url)
+ goto out_conf;
+
+ if (dc->conf_url) {
+ rc = parser_request_url(dc, dc->conf_url, &buf, &len);
+ if (rc)
+ goto out_conf;
+ } else {
+ pxe_conf_files = user_event_parse_conf_filenames(dc, dc->event);
+ if (!pxe_conf_files)
+ goto out_conf;
+
+ for (filename = pxe_conf_files; *filename; filename++) {
+ url = pb_url_join(dc, conf_url, *filename);
+ if (!url)
+ goto out_pxe_conf;
+
+ rc = parser_request_url(dc, url, &buf, &len);
+ if (!rc) /* found one, just break */
+ break;
+
+ talloc_free(url);
+ }
+
+ /* No configuration file found on the boot server */
+ if (rc)
+ goto out_pxe_conf;
+
+ dc->conf_url = url;
+
+ talloc_free(conf_url);
+ talloc_free(pxe_conf_files);
+ }
+
+ /* Call the config file parser with the data read from the file */
conf_parse_buf(conf, buf, len);
+ talloc_free(buf);
+ talloc_free(conf);
+
+ return 0;
+
+out_pxe_conf:
+ talloc_free(pxe_conf_files);
+out_conf:
talloc_free(conf);
- return 1;
+out:
+ return -1;
}
static struct parser pxe_parser = {
.name = "pxe",
.parse = pxe_parse,
- .method = CONF_METHOD_DHCP,
};
register_parser(pxe_parser);
diff --git a/discover/udev.c b/discover/udev.c
index 0c656f3..48ab745 100644
--- a/discover/udev.c
+++ b/discover/udev.c
@@ -116,7 +116,7 @@ static int udev_handle_dev_add(struct pb_udev *udev, struct udev_device *dev)
udev_setup_device_params(dev, ddev);
- device_handler_discover(udev->handler, ddev, CONF_METHOD_LOCAL_FILE);
+ device_handler_discover(udev->handler, ddev);
return 0;
}
diff --git a/discover/user-event.c b/discover/user-event.c
index 4b56de4..61008c1 100644
--- a/discover/user-event.c
+++ b/discover/user-event.c
@@ -40,6 +40,9 @@
#include "user-event.h"
+#define MAC_ADDR_SIZE 6
+#define IP_ADDR_SIZE 4
+
struct user_event {
struct device_handler *handler;
int socket;
@@ -52,8 +55,8 @@ static const char *event_action_name(enum event_action action)
return "add";
case EVENT_ACTION_REMOVE:
return "remove";
- case EVENT_ACTION_CONF:
- return "conf";
+ case EVENT_ACTION_DHCP:
+ return "dhcp";
default:
break;
}
@@ -73,27 +76,30 @@ static void user_event_print_event(struct event __attribute__((unused)) *event)
event->params[i].name, event->params[i].value);
}
-static enum conf_method parse_conf_method(const char *str)
-{
-
- if (!strcasecmp(str, "dhcp")) {
- return CONF_METHOD_DHCP;
- }
- return CONF_METHOD_UNKNOWN;
-}
-
static struct resource *user_event_resource(struct discover_boot_option *opt,
- struct event *event, const char *param_name)
+ struct event *event)
{
+ const char *siaddr, *boot_file;
struct resource *res;
struct pb_url *url;
- const char *val;
+ char *url_str;
- val = event_get_param(event, param_name);
- if (!val)
+ siaddr = event_get_param(event, "siaddr");
+ if (!siaddr) {
+ pb_log("%s: next server option not found\n", __func__);
+ return NULL;
+ }
+
+ boot_file = event_get_param(event, "boot_file");
+ if (!boot_file) {
+ pb_log("%s: boot_file not found\n", __func__);
return NULL;
+ }
+
+ url_str = talloc_asprintf(opt, "%s%s/%s", "tftp://", siaddr, boot_file);
+ url = pb_url_parse(opt, url_str);
+ talloc_free(url_str);
- url = pb_url_parse(opt, val);
if (!url)
return NULL;
@@ -109,41 +115,55 @@ static struct resource *user_event_resource(struct discover_boot_option *opt,
static int parse_user_event(struct discover_context *ctx, struct event *event)
{
struct discover_boot_option *d_opt;
+ char *server_ip, *root_dir, *p;
struct boot_option *opt;
struct device *dev;
- const char *p;
+ const char *val;
dev = ctx->device->device;
d_opt = discover_boot_option_create(ctx, ctx->device);
- opt = d_opt->option;
-
if (!d_opt)
goto fail;
- p = event_get_param(event, "name");
+ opt = d_opt->option;
+
+ val = event_get_param(event, "name");
- if (!p) {
+ if (!val) {
pb_log("%s: no name found\n", __func__);
- goto fail;
+ goto fail_opt;
}
- opt->id = talloc_asprintf(opt, "%s#%s", dev->id, p);
- opt->name = talloc_strdup(opt, p);
+ opt->id = talloc_asprintf(opt, "%s#%s", dev->id, val);
+ opt->name = talloc_strdup(opt, val);
- d_opt->boot_image = user_event_resource(d_opt, event, "image");
+ d_opt->boot_image = user_event_resource(d_opt, event);
if (!d_opt->boot_image) {
pb_log("%s: no boot image found for %s!\n", __func__,
opt->name);
- goto fail;
+ goto fail_opt;
}
- d_opt->initrd = user_event_resource(d_opt, event, "initrd");
-
- p = event_get_param(event, "args");
-
- if (p)
- opt->boot_args = talloc_strdup(opt, p);
+ val = event_get_param(event, "rootpath");
+ if (val) {
+ server_ip = talloc_strdup(opt, val);
+ p = strchr(server_ip, ':');
+ if (p) {
+ root_dir = talloc_strdup(opt, p + 1);
+ *p = '\0';
+ opt->boot_args = talloc_asprintf(opt, "%s%s:%s",
+ "root=/dev/nfs ip=any nfsroot=",
+ server_ip, root_dir);
+
+ talloc_free(root_dir);
+ } else {
+ opt->boot_args = talloc_asprintf(opt, "%s",
+ "root=/dev/nfs ip=any nfsroot=");
+ }
+
+ talloc_free(server_ip);
+ }
opt->description = talloc_asprintf(opt, "%s %s", opt->boot_image_file,
opt->boot_args ? : "");
@@ -155,16 +175,189 @@ static int parse_user_event(struct discover_context *ctx, struct event *event)
return 0;
-fail:
+fail_opt:
talloc_free(d_opt);
+fail:
return -1;
}
+static const char *parse_host_addr(struct event *event)
+{
+ const char *val;
+
+ val = event_get_param(event, "tftp");
+ if (val)
+ return val;
+
+ val = event_get_param(event, "siaddr");
+ if (val)
+ return val;
+
+ val = event_get_param(event, "serverid");
+ if (val)
+ return val;
+
+ return NULL;
+}
+
+static char *parse_mac_addr(struct discover_context *ctx, const char *mac)
+{
+ unsigned int mac_addr_arr[MAC_ADDR_SIZE];
+ char *mac_addr;
+
+ sscanf(mac, "%X:%X:%X:%X:%X:%X", mac_addr_arr, mac_addr_arr + 1,
+ mac_addr_arr + 2, mac_addr_arr + 3, mac_addr_arr + 4,
+ mac_addr_arr + 5);
+
+ mac_addr = talloc_asprintf(ctx, "01-%02X-%02X-%02X-%02X-%02X-%02X",
+ mac_addr_arr[0], mac_addr_arr[1], mac_addr_arr[2],
+ mac_addr_arr[3], mac_addr_arr[4], mac_addr_arr[5]);
+
+ return mac_addr;
+}
+
+static char *parse_ip_addr(struct discover_context *ctx, const char *ip)
+{
+ unsigned int ip_addr_arr[IP_ADDR_SIZE];
+ char *ip_hex;
+
+ sscanf(ip, "%u.%u.%u.%u", ip_addr_arr, ip_addr_arr + 1,
+ ip_addr_arr + 2, ip_addr_arr + 3);
+
+ ip_hex = talloc_asprintf(ctx, "%02X%02X%02X%02X", ip_addr_arr[0],
+ ip_addr_arr[1], ip_addr_arr[2], ip_addr_arr[3]);
+
+ return ip_hex;
+}
+
+struct pb_url *user_event_parse_conf_url(struct discover_context *ctx,
+ struct event *event)
+{
+ const char *conffile, *host, *bootfile;
+ char *p, *basedir, *url_str;
+ struct pb_url *url;
+
+ conffile = event_get_param(event, "conffile");
+ if (conffile) {
+ if (is_url(conffile)) {
+ url = pb_url_parse(ctx, conffile);
+ } else {
+ host = parse_host_addr(event);
+ if (!host) {
+ pb_log("%s: host address not found\n",
+ __func__);
+ return NULL;
+ }
+
+ url_str = talloc_asprintf(ctx, "%s%s/%s", "tftp://",
+ host, conffile);
+ url = pb_url_parse(ctx, url_str);
+
+ talloc_free(url_str);
+ }
+
+ ctx->conf_url = url;
+ } else {
+ host = parse_host_addr(event);
+ if (!host) {
+ pb_log("%s: host address not found\n", __func__);
+ return NULL;
+ }
+
+ bootfile = event_get_param(event, "bootfile");
+ if (!bootfile) {
+ pb_log("%s: bootfile param not found\n", __func__);
+ return NULL;
+ }
+
+ basedir = talloc_strdup(ctx, bootfile);
+ p = strchr(basedir, '/');
+ if (p)
+ *p = '\0';
+
+ if (!strcmp(basedir,"") || !strcmp(basedir, "."))
+ url_str = talloc_asprintf(ctx, "%s%s/", "tftp://",host);
+ else
+ url_str = talloc_asprintf(ctx, "%s%s/%s/", "tftp://",host,
+ basedir);
+
+ url = pb_url_parse(ctx, url_str);
+
+ talloc_free(url_str);
+ talloc_free(basedir);
+ }
+
+ return url;
+}
+
+char **user_event_parse_conf_filenames(
+ struct discover_context *ctx, struct event *event)
+{
+ char *mac_addr, *ip_hex;
+ const char *mac, *ip;
+ char **filenames;
+ int index, len;
+
+ mac = event_get_param(event, "mac");
+ if (mac)
+ mac_addr = parse_mac_addr(ctx, mac);
+ else
+ mac_addr = NULL;
+
+ ip = event_get_param(event, "ip");
+ if (ip) {
+ ip_hex = parse_ip_addr(ctx, ip);
+ len = strlen(ip_hex);
+ } else {
+ ip_hex = NULL;
+ len = 0;
+ }
+
+ if (!mac_addr && !ip_hex) {
+ pb_log("%s: neither mac nor ip parameter found\n", __func__);
+ return NULL;
+ }
+
+ /* Filenames as fallback IP's + mac + default */
+ filenames = talloc_array(ctx, char *, len + 3);
+
+ index = 0;
+ if (mac_addr)
+ filenames[index++] = talloc_strdup(filenames, mac_addr);
+
+ while (len) {
+ filenames[index++] = talloc_strdup(filenames, ip_hex);
+ ip_hex[--len] = '\0';
+ }
+
+ filenames[index++] = talloc_strdup(filenames, "default");
+ filenames[index++] = NULL;
+
+ if (mac_addr)
+ talloc_free(mac_addr);
+
+ if (ip_hex)
+ talloc_free(ip_hex);
+
+ return filenames;
+}
+
+static int user_event_dhcp(struct user_event *uev, struct event *event)
+{
+ struct device_handler *handler = uev->handler;
+ struct discover_device *dev;
+
+ dev = discover_device_create(handler, event->device);
+
+ device_handler_dhcp(handler, dev, event);
+
+ return 0;
+}
+
static int user_event_conf(struct user_event *uev, struct event *event)
{
struct device_handler *handler = uev->handler;
struct discover_device *dev;
- enum conf_method method;
struct pb_url *url;
const char *val;
@@ -176,17 +369,9 @@ static int user_event_conf(struct user_event *uev, struct event *event)
if (!url)
return 0;
- val = event_get_param(event, "method");
- if (!val)
- return 0;
-
- method = parse_conf_method(val);
- if (method == CONF_METHOD_UNKNOWN)
- return 0;
-
dev = discover_device_create(handler, event->device);
- device_handler_conf(handler, dev, url, method);
+ device_handler_conf(handler, dev, url);
return 0;
}
@@ -249,6 +434,9 @@ static void user_event_handle_message(struct user_event *uev, char *buf,
case EVENT_ACTION_CONF:
result = user_event_conf(uev, event);
break;
+ case EVENT_ACTION_DHCP:
+ result = user_event_dhcp(uev, event);
+ break;
default:
break;
}
diff --git a/discover/user-event.h b/discover/user-event.h
index 488f04a..976c257 100644
--- a/discover/user-event.h
+++ b/discover/user-event.h
@@ -27,6 +27,10 @@
struct user_event;
struct waitset;
+struct pb_url *user_event_parse_conf_url(struct discover_context *ctx,
+ struct event *event);
+char **user_event_parse_conf_filenames(
+ struct discover_context *ctx, struct event *event);
struct user_event *user_event_init(struct waitset *waitset,
struct device_handler *handler);
void user_event_destroy(struct user_event *uev);
diff --git a/discover/yaboot-parser.c b/discover/yaboot-parser.c
index 22792d4..e52187f 100644
--- a/discover/yaboot-parser.c
+++ b/discover/yaboot-parser.c
@@ -356,15 +356,22 @@ static const char *yaboot_known_names[] = {
NULL
};
-static int yaboot_parse(struct discover_context *dc, char *buf, int len)
+static int yaboot_parse(struct discover_context *dc)
{
- struct conf_context *conf;
+ const char * const *filename;
struct yaboot_state *state;
+ struct conf_context *conf;
+ int len, rc;
+ char *buf;
+
+ /* Support block device boot only at present */
+ if (dc->event)
+ return -1;
conf = talloc_zero(dc, struct conf_context);
if (!conf)
- return 0;
+ return -1;
conf->dc = dc;
conf->global_options = yaboot_global_options,
@@ -378,17 +385,22 @@ static int yaboot_parse(struct discover_context *dc, char *buf, int len)
state->opt = NULL;
- conf_parse_buf(conf, buf, len);
+ for (filename = yaboot_conf_files; *filename; filename++) {
+ rc = parser_request_file(dc, dc->device, *filename, &buf, &len);
+ if (rc)
+ continue;
+
+ conf_parse_buf(conf, buf, len);
+ talloc_free(buf);
+ }
talloc_free(conf);
- return 1;
+ return 0;
}
static struct parser yaboot_parser = {
.name = "yaboot",
- .method = CONF_METHOD_LOCAL_FILE,
.parse = yaboot_parse,
- .filenames = yaboot_conf_files,
.resolve_resource = resolve_devpath_resource,
};
diff --git a/test/parser/handler.c b/test/parser/handler.c
index 64978da..d9057eb 100644
--- a/test/parser/handler.c
+++ b/test/parser/handler.c
@@ -40,10 +40,9 @@ void parser_init(void)
{
}
-void iterate_parsers(struct discover_context *ctx, enum conf_method method)
+void iterate_parsers(struct discover_context *ctx)
{
(void)ctx;
- (void)method;
assert(false);
}
diff --git a/utils/pb-udhcpc b/utils/pb-udhcpc
index dd291b9..3494985 100644
--- a/utils/pb-udhcpc
+++ b/utils/pb-udhcpc
@@ -9,97 +9,44 @@
PBOOT_USER_EVENT_SOCKET="/tmp/petitboot.ev"
log="/var/log/petitboot/pb-udhcpc.log"
-resolve_url() {
- file="$1"
-
- # URL? use as-is.
- tmp=${file%://*}
- if [ "$tmp" != "$file" ]
- then
- echo "$file"
- return
- fi
-
- # Otherwise, TFTP using an appropriate host. Start with the
- # DHCP 'tftp' option:
- host=${tftp}
-
- # next, try the DHCP next-server-address
- [ -z "$host" ] && host=${siaddr}
-
- # finally, use the DHCP server we got this lease from:
- [ -z "$host" ] && host=${serverid}
-
- echo "tftp://$host/$file"
-}
-
-do_pxe() {
- basedir=$1
-
- params="conf@${interface} method=dhcp"
+pb_add () {
+ # Looks like udhcpc will give us different names, depending if the
+ # parameter was in the header, or specified by options
+ [ -z "$bootfile" ] && bootfile=${boot_file}
- # first, try by MAC
- mac=$(tr ':' '-' < /sys/class/$interface/address)
- pb-event $params url=$basedir/01-$mac
+ mac=$(< /sys/class/net/$interface/address)
+ paramstr=''
- # try decreasing fragments of IP lease
- ip_hex=$(printf '%02X%02X%02X%02X' $(echo $ip | tr '.' ' '))
- for i in $(seq 8 -1 1)
+ # Collect relevant DHCP response parameters into $paramstr
+ for name in conffile bootfile mac ip siaddr serverid tftp
do
- frag=${ip_hex:0:$i}
- pb-event $params url=$basedir/$frag
- done
+ value=$(eval "echo \${$name}")
+ [ -n "$value" ] || continue;
- # last, use default
- pb-event $params url=$basedir/default
-}
+ paramstr="$paramstr $name=$value"
+ done
-pb_add () {
+ pb-event dhcp@{interface} $paramstr
- # Look for an explicit config file location in the DHCP config-file
- # parameter
+ # Check if an explicit config file present
if [ -n "${conffile}" ]
then
- url=$(resolve_url ${conffile})
- pb-event conf@${interface} url=$url method=dhcp
- return
- fi
-
- # Otherwise, we'll need the boot-file parameter. Looks like udhcpc
- # will give us different names, depending if the parameter was in
- # the header, or specified by options
- [ -z "$bootfile" ] && bootfile=${boot_file}
-
- if [ -z "$bootfile" ]
- then
- return
+ return;
fi
- # PXE behaviour is to download the config file based on a file
- # structure relative to the pxelinux binary
- file=${bootfile}
- [ -z "$file" ] && file=${boot_file}
- if [ -n "$file" ]
- then
- basedir=${file%%/*}
- do_pxe $basedir
- fi
+ # Finally, add an option for the boot_file parameter
+ paramstr='name=netboot'
- # Finally, add an option for the boot_file parameter
- k_server_ip=${rootpath%%:*}
- k_root_dir=${rootpath#*:}
+ # Collect relevant parameters to add an option to the boot_file parameter
+ for name in rootpath siaddr boot_file
+ do
+ value=$(eval "echo \${$name}")
+ [ -n "$value" ] || continue;
- args=
- if [ -n "$rootpath" ]
- then
- [ ${k_server_ip} != ${rootpath} ] || k_server_ip=${serverid}
- args="root=/dev/nfs ip=any nfsroot=${k_server_ip}:${k_root_dir}"
- fi
+ paramstr="$paramstr $name=$value"
+ done
- pb-event add@${interface} \
- name=netboot \
- image=tftp://${siaddr}/${boot_file} \
- args="$args"
+ pb-event add@{interface} $paramstr
}
pb_remove () {
OpenPOWER on IntegriCloud