summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSamuel Mendoza-Jonas <sam@mendozajonas.com>2018-05-09 11:18:57 +1000
committerSamuel Mendoza-Jonas <sam@mendozajonas.com>2018-07-10 14:42:56 +1000
commitf5fb1751ec92110669a039bb0de209bffe74538a (patch)
tree9862dd312e22e8a4214736eeedc5c047afdc2c5a
parent02a66447edbc43e6baf4c1a1221a251b5f2536b8 (diff)
downloadtalos-petitboot-f5fb1751ec92110669a039bb0de209bffe74538a.zip
talos-petitboot-f5fb1751ec92110669a039bb0de209bffe74538a.tar.gz
discover: Support IPv6 addresses
Support handling IPv6 addresses from user events and call the udhcpc6 client in addition to the udhcpc client. Signed-off-by: Samuel Mendoza-Jonas <sam@mendozajonas.com>
-rw-r--r--discover/device-handler.c51
-rw-r--r--discover/network.c86
-rw-r--r--discover/user-event.c12
3 files changed, 109 insertions, 40 deletions
diff --git a/discover/device-handler.c b/discover/device-handler.c
index 72dda75..69bc050 100644
--- a/discover/device-handler.c
+++ b/discover/device-handler.c
@@ -1374,10 +1374,15 @@ int device_handler_dhcp(struct device_handler *handler,
struct discover_device *dev, struct event *event)
{
struct discover_context *ctx;
+ const char *ip;
+
+ if (event_get_param(event, "ipv6"))
+ ip = event_get_param(event, "ipv6");
+ else
+ ip = event_get_param(event, "ip");
device_handler_status_dev_info(handler, dev,
- _("Processing DHCP lease response (ip: %s)"),
- event_get_param(event, "ip"));
+ _("Processing DHCP lease response (ip: %s)"), ip);
pending_network_jobs_start();
@@ -1475,32 +1480,44 @@ void device_handler_update_config(struct device_handler *handler,
static char *device_from_addr(void *ctx, struct pb_url *url)
{
char *ipaddr, *buf, *tok, *dev = NULL;
+ bool ipv6_route;
const char *delim = " ";
- struct sockaddr_in *ip;
- struct sockaddr_in si;
+ struct sockaddr_in *ipv4;
+ struct sockaddr_in6 *ipv6;
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;
- }
+ /* Confirm url->host is either a valid hostname, or a
+ * valid IPv4 or IPv6 address */
+ rc = getaddrinfo(url->host, NULL, NULL, &res);
+ if (rc) {
+ pb_debug("%s: Invalid URL\n",__func__);
+ return NULL;
+ }
+
+ switch (res->ai_family) {
+ case AF_INET: /* ipv4 */
ipaddr = talloc_array(ctx,char,INET_ADDRSTRLEN);
- ip = (struct sockaddr_in *) res->ai_addr;
- inet_ntop(AF_INET, &(ip->sin_addr), ipaddr, INET_ADDRSTRLEN);
+ ipv4 = (struct sockaddr_in *) res->ai_addr;
+ inet_ntop(AF_INET, &(ipv4->sin_addr), ipaddr, INET_ADDRSTRLEN);
+ ipv6_route = false;
+ break;
+ case AF_INET6: /* ipv6 */
+ ipaddr = talloc_array(ctx,char,INET6_ADDRSTRLEN);
+ ipv6 = (struct sockaddr_in6 *) res->ai_addr;
+ inet_ntop(AF_INET6, &(ipv6->sin6_addr), ipaddr, INET6_ADDRSTRLEN);
+ ipv6_route = true;
+ break;
+ default: /* error */
freeaddrinfo(res);
+ return NULL;
}
+ freeaddrinfo(res);
const char *argv[] = {
pb_system_apps.ip,
+ ipv6_route ? "-6" : "-4",
"route", "show", "to", "match",
ipaddr,
NULL
diff --git a/discover/network.c b/discover/network.c
index 5a3b0b4..2057525 100644
--- a/discover/network.c
+++ b/discover/network.c
@@ -53,6 +53,7 @@ struct interface {
struct list_item list;
struct process *udhcpc_process;
+ struct process *udhcpc6_process;
struct discover_device *dev;
bool ready;
};
@@ -279,6 +280,13 @@ static int interface_change(struct interface *interface, bool up)
process_stop_async(interface->udhcpc_process);
process_release(interface->udhcpc_process);
}
+ if (!up && interface->udhcpc6_process) {
+ /* we don't care about the callback from here */
+ interface->udhcpc6_process->exit_cb = NULL;
+ interface->udhcpc6_process->data = NULL;
+ process_stop_async(interface->udhcpc6_process);
+ process_release(interface->udhcpc6_process);
+ }
if (!up) {
rc = process_run_simple(interface, pb_system_apps.ip,
@@ -312,9 +320,17 @@ static int interface_down(struct interface *interface)
static void udhcpc_process_exit(struct process *process)
{
struct interface *interface = process->data;
- pb_debug("udhcp client [pid %d] for interface %s exited, rc %d\n",
- process->pid, interface->name, process->exit_status);
- interface->udhcpc_process = NULL;
+
+ if (process == interface->udhcpc_process) {
+ pb_debug("udhcpc client [pid %d] for interface %s exited, rc %d\n",
+ process->pid, interface->name, process->exit_status);
+ interface->udhcpc_process = NULL;
+ } else {
+ pb_debug("udhcpc6 client [pid %d] for interface %s exited, rc %d\n",
+ process->pid, interface->name, process->exit_status);
+ interface->udhcpc6_process = NULL;
+ }
+
process_release(process);
}
@@ -322,10 +338,10 @@ static void configure_interface_dhcp(struct network *network,
struct interface *interface)
{
const struct platform *platform;
- char pidfile[256], id[10];
- struct process *process;
+ char pidfile[256], idv4[10], idv6[10];
+ struct process *p_v4, *p_v6;
int rc;
- const char *argv[] = {
+ const char *argv_ipv4[] = {
pb_system_apps.udhcpc,
"-R",
"-f",
@@ -334,7 +350,21 @@ static void configure_interface_dhcp(struct network *network,
"-O", "reboottime",
"-p", pidfile,
"-i", interface->name,
- "-x", id, /* [11,12] - dhcp client identifier */
+ "-x", idv4, /* [11,12] - dhcp client identifier */
+ NULL,
+ };
+
+ const char *argv_ipv6[] = {
+ pb_system_apps.udhcpc6,
+ "-R",
+ "-f",
+ "-O", "bootfile_url",
+ "-O", "bootfile_param",
+ "-O", "pxeconffile",
+ "-O", "pxepathprefix",
+ "-p", pidfile,
+ "-i", interface->name,
+ "-x", idv6, /* [15,16] - dhcp client identifier */
NULL,
};
@@ -345,24 +375,40 @@ static void configure_interface_dhcp(struct network *network,
PIDFILE_BASE, interface->name);
platform = platform_get();
- if (platform && platform->dhcp_arch_id != 0xffff)
- snprintf(id, sizeof(id), "0x5d:%04x", platform->dhcp_arch_id);
+ if (platform && platform->dhcp_arch_id != 0xffff) {
+ snprintf(idv6, sizeof(idv6), "0x3d:%04x",
+ platform->dhcp_arch_id);
+ snprintf(idv4, sizeof(idv4), "0x5d:%04x",
+ platform->dhcp_arch_id);
+ } else {
+ argv_ipv4[11] = argv_ipv6[15] = NULL;
+ }
+
+ p_v4 = process_create(interface);
+ p_v4->path = pb_system_apps.udhcpc;
+ p_v4->argv = argv_ipv4;
+ p_v4->exit_cb = udhcpc_process_exit;
+ p_v4->data = interface;
+
+ pb_log("Running DHCPv4 client\n");
+ rc = process_run_async(p_v4);
+ if (rc)
+ process_release(p_v4);
else
- argv[11] = NULL;
-
- process = process_create(interface);
-
- process->path = pb_system_apps.udhcpc;
- process->argv = argv;
- process->exit_cb = udhcpc_process_exit;
- process->data = interface;
+ interface->udhcpc_process = p_v4;
- rc = process_run_async(process);
+ pb_log("Running DHCPv6 client\n");
+ p_v6 = process_create(interface);
+ p_v6->path = pb_system_apps.udhcpc6;
+ p_v6->argv = argv_ipv6;
+ p_v6->exit_cb = udhcpc_process_exit;
+ p_v6->data = interface;
+ rc = process_run_async(p_v6);
if (rc)
- process_release(process);
+ process_release(p_v6);
else
- interface->udhcpc_process = process;
+ interface->udhcpc6_process = p_v6;
return;
}
diff --git a/discover/user-event.c b/discover/user-event.c
index 7f63d43..ee282bb 100644
--- a/discover/user-event.c
+++ b/discover/user-event.c
@@ -390,7 +390,9 @@ static int user_event_dhcp(struct user_event *uev, struct event *event)
uint8_t hwaddr[MAC_ADDR_SIZE];
- if (!event_get_param(event, "mac") || !event_get_param(event, "ip"))
+ if (!event_get_param(event, "mac"))
+ return -1;
+ if (!event_get_param(event, "ip") && !event_get_param(event, "ipv6"))
return -1;
sscanf(event_get_param(event, "mac"),
@@ -398,8 +400,12 @@ static int user_event_dhcp(struct user_event *uev, struct event *event)
hwaddr, hwaddr + 1, hwaddr + 2,
hwaddr + 3, hwaddr + 4, hwaddr + 5);
- system_info_set_interface_address(sizeof(hwaddr), hwaddr,
- event_get_param(event, "ip"));
+ if (event_get_param(event, "ipv6"))
+ system_info_set_interface_address(sizeof(hwaddr), hwaddr,
+ event_get_param(event, "ipv6"));
+ else
+ system_info_set_interface_address(sizeof(hwaddr), hwaddr,
+ event_get_param(event, "ip"));
dev = discover_device_create(handler, event_get_param(event, "mac"),
event->device);
OpenPOWER on IntegriCloud