[PATCH v2 5/9] discover: Support IPv6 addresses
Samuel Mendoza-Jonas
sam at mendozajonas.com
Thu May 24 14:47:38 AEST 2018
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 at mendozajonas.com>
---
discover/device-handler.c | 51 +++++++++++++++--------
discover/network.c | 86 ++++++++++++++++++++++++++++++---------
discover/user-event.c | 8 +++-
3 files changed, 106 insertions(+), 39 deletions(-)
diff --git a/discover/device-handler.c b/discover/device-handler.c
index 569e652..4164409 100644
--- a/discover/device-handler.c
+++ b/discover/device-handler.c
@@ -1167,10 +1167,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();
@@ -1265,32 +1270,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 e2cae91..7a9ae21 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",
@@ -333,7 +349,21 @@ static void configure_interface_dhcp(struct network *network,
"-O", "pxepathprefix",
"-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,
};
@@ -344,24 +374,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 77d28c1..59e0717 100644
--- a/discover/user-event.c
+++ b/discover/user-event.c
@@ -395,8 +395,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);
--
2.17.0
More information about the Petitboot
mailing list