From: Samuel Mendoza-Jonas Date: Thu, 24 Jul 2014 05:05:36 +0000 (+1000) Subject: discover: Enable 'url' pb-events X-Git-Tag: v1.0.0~139 X-Git-Url: http://git.ozlabs.org/?p=petitboot;a=commitdiff_plain;h=e1f6ffb9ca9e35738385a3524ba46896a0b519e6;ds=sidebyside discover: Enable 'url' pb-events Adds a new option to pb-event; ./pb-event url@dev url=scheme://path/to/petitboot.conf Specifies a remote conf file to parse for boot options Signed-off-by: Samuel Mendoza-Jonas Signed-off-by: Jeremy Kerr --- diff --git a/discover/device-handler.c b/discover/device-handler.c index 5a5210e..191ec33 100644 --- a/discover/device-handler.c +++ b/discover/device-handler.c @@ -18,6 +18,11 @@ #include #include +#include +#include +#include +#include + #include "device-handler.h" #include "discover-server.h" #include "user-event.h" @@ -831,6 +836,135 @@ void device_handler_update_config(struct device_handler *handler, device_handler_reinit(handler); } +static char *device_from_addr(void *ctx, struct pb_url *url) +{ + char *ipaddr, *buf, *tok, *dev = NULL; + const char *delim = " "; + struct sockaddr_in *ip; + struct sockaddr_in si; + struct addrinfo *res; + struct process *p; + int rc; + + /* Note: IPv4 only */ + rc = inet_pton(AF_INET, url->host, &(si.sin_addr)); + if (rc > 0) { + ipaddr = url->host; + } else { + /* need to turn hostname into a valid IP */ + rc = getaddrinfo(url->host, NULL, NULL, &res); + if (rc) { + pb_debug("%s: Invalid URL\n",__func__); + return NULL; + } + ipaddr = talloc_array(ctx,char,INET_ADDRSTRLEN); + ip = (struct sockaddr_in *) res->ai_addr; + inet_ntop(AF_INET, &(ip->sin_addr), ipaddr, INET_ADDRSTRLEN); + freeaddrinfo(res); + } + + const char *argv[] = { + pb_system_apps.ip, + "route", "show", "to", "match", + ipaddr, + NULL + }; + + p = process_create(ctx); + + p->path = pb_system_apps.ip; + p->argv = argv; + p->keep_stdout = true; + + rc = process_run_sync(p); + + if (rc) { + /* ip has complained for some reason; most likely + * there is no route to the host - bail out */ + pb_debug("%s: No route to %s\n",__func__,url->host); + return NULL; + } + + buf = p->stdout_buf; + /* If a route is found, ip-route output will be of the form + * "... dev DEVNAME ... " */ + tok = strtok(buf, delim); + while (tok) { + if (!strcmp(tok, "dev")) { + tok = strtok(NULL, delim); + dev = talloc_strdup(ctx, tok); + break; + } + tok = strtok(NULL, delim); + } + + process_release(p); + if (dev) + pb_debug("%s: Found interface '%s'\n", __func__,dev); + return dev; +} + + +void device_handler_process_url(struct device_handler *handler, + const char *url) +{ + struct discover_context *ctx; + struct discover_device *dev; + struct boot_status *status; + struct pb_url *pb_url; + struct event *event; + struct param *param; + + status = talloc(handler, struct boot_status); + + status->type = BOOT_STATUS_ERROR; + status->progress = 0; + status->detail = talloc_asprintf(status, + _("Received config URL %s"), url); + + event = talloc(handler, struct event); + event->type = EVENT_TYPE_USER; + event->action = EVENT_ACTION_CONF; + + event->params = talloc_array(event, struct param, 1); + param = &event->params[0]; + param->name = talloc_strdup(event, "pxeconffile"); + param->value = talloc_strdup(event, url); + event->n_params = 1; + + pb_url = pb_url_parse(event, event->params->value); + if (!pb_url || !pb_url->host) { + status->message = talloc_asprintf(handler, + _("Invalid config URL!")); + goto msg; + } + + event->device = device_from_addr(event, pb_url); + if (!event->device) { + status->message = talloc_asprintf(status, + _("Unable to route to host %s"), + pb_url->host); + goto msg; + } + + dev = discover_device_create(handler, event->device); + ctx = device_handler_discover_context_create(handler, dev); + ctx->event = event; + + iterate_parsers(ctx); + + device_handler_discover_context_commit(handler, ctx); + + talloc_free(ctx); + + status->type = BOOT_STATUS_INFO; + status->message = talloc_asprintf(status, _("Config file %s parsed"), + pb_url->file); +msg: + boot_status(handler, status); + talloc_free(status); +} + #ifndef PETITBOOT_TEST static void device_handler_update_lang(const char *lang) diff --git a/discover/device-handler.h b/discover/device-handler.h index 246abf9..e8e71ad 100644 --- a/discover/device-handler.h +++ b/discover/device-handler.h @@ -117,6 +117,8 @@ void device_handler_boot(struct device_handler *handler, void device_handler_cancel_default(struct device_handler *handler); void device_handler_update_config(struct device_handler *handler, struct config *config); +void device_handler_process_url(struct device_handler *handler, + const char *url); void device_handler_reinit(struct device_handler *handler); int device_request_write(struct discover_device *dev, bool *release); diff --git a/discover/event.c b/discover/event.c index 6434b40..7932378 100644 --- a/discover/event.c +++ b/discover/event.c @@ -47,6 +47,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, "url")) + *action = EVENT_ACTION_URL; else if (streq(buf, "conf")) *action = EVENT_ACTION_CONF; else if (streq(buf, "dhcp")) diff --git a/discover/event.h b/discover/event.h index 98ece11..8dee13b 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_URL, EVENT_ACTION_CONF, EVENT_ACTION_DHCP, EVENT_ACTION_MAX, diff --git a/discover/user-event.c b/discover/user-event.c index 1f70045..69defa3 100644 --- a/discover/user-event.c +++ b/discover/user-event.c @@ -54,6 +54,8 @@ static const char *event_action_name(enum event_action action) return "add"; case EVENT_ACTION_REMOVE: return "remove"; + case EVENT_ACTION_URL: + return "url"; case EVENT_ACTION_DHCP: return "dhcp"; default: @@ -430,6 +432,18 @@ static int user_event_remove(struct user_event *uev, struct event *event) return 0; } +static int user_event_url(struct user_event *uev, struct event *event) +{ + struct device_handler *handler = uev->handler; + const char *url; + + url = event_get_param(event, "url"); + if (url) + device_handler_process_url(handler, url); + + return 0; +} + static void user_event_handle_message(struct user_event *uev, char *buf, int len) { @@ -453,6 +467,9 @@ static void user_event_handle_message(struct user_event *uev, char *buf, case EVENT_ACTION_REMOVE: result = user_event_remove(uev, event); break; + case EVENT_ACTION_URL: + result = user_event_url(uev, event); + break; case EVENT_ACTION_CONF: result = user_event_conf(uev, event); break;