summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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