diff options
-rw-r--r-- | discover/device-handler.c | 34 | ||||
-rw-r--r-- | discover/device-handler.h | 18 | ||||
-rw-r--r-- | discover/event.c | 2 | ||||
-rw-r--r-- | discover/event.h | 1 | ||||
-rw-r--r-- | discover/grub2/grub2.c | 24 | ||||
-rw-r--r-- | discover/kboot-parser.c | 26 | ||||
-rw-r--r-- | discover/parser.c | 83 | ||||
-rw-r--r-- | discover/parser.h | 9 | ||||
-rw-r--r-- | discover/pxe-parser.c | 62 | ||||
-rw-r--r-- | discover/udev.c | 2 | ||||
-rw-r--r-- | discover/user-event.c | 274 | ||||
-rw-r--r-- | discover/user-event.h | 4 | ||||
-rw-r--r-- | discover/yaboot-parser.c | 26 | ||||
-rw-r--r-- | test/parser/handler.c | 3 | ||||
-rw-r--r-- | utils/pb-udhcpc | 103 |
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 () { |