From 57e9594d4a43e1c8e43749eae9ea8795bfbafbac Mon Sep 17 00:00:00 2001 From: Joel Low Date: Fri, 31 Jan 2025 22:31:54 +0800 Subject: [PATCH] strongswan: DHCP on lo fixes backport Fixes #25801. Adds the following commits to fix DHCP behaviour on Strongswan 5.9.14: - https://github.com/strongswan/strongswan/commit/abbf9d28b0032cf80b79bcacea3146a60800a6dd - https://github.com/strongswan/strongswan/commit/00d8c36d6fdf9e8ee99b9f92a64e7e81dbfa4432 - https://github.com/strongswan/strongswan/commit/a50ed3006e8152eb2cf20e9f92f088ecc18081b0 Signed-off-by: Joel Low --- ...t-loopback-interfaces-as-packet-sour.patch | 28 ++++++++ ...ctly-bind-packet-socket-to-an-interf.patch | 63 ++++++++++++++++++ ...to-bind-the-receive-socket-to-a-diff.patch | 66 +++++++++++++++++++ 3 files changed, 157 insertions(+) create mode 100644 net/strongswan/patches/0005-pf-handler-Accept-loopback-interfaces-as-packet-sour.patch create mode 100644 net/strongswan/patches/0006-pf-handler-Correctly-bind-packet-socket-to-an-interf.patch create mode 100644 net/strongswan/patches/0007-dhcp-Add-option-to-bind-the-receive-socket-to-a-diff.patch diff --git a/net/strongswan/patches/0005-pf-handler-Accept-loopback-interfaces-as-packet-sour.patch b/net/strongswan/patches/0005-pf-handler-Accept-loopback-interfaces-as-packet-sour.patch new file mode 100644 index 0000000000000..5c8731d862648 --- /dev/null +++ b/net/strongswan/patches/0005-pf-handler-Accept-loopback-interfaces-as-packet-sour.patch @@ -0,0 +1,28 @@ +From abbf9d28b0032cf80b79bcacea3146a60800a6dd Mon Sep 17 00:00:00 2001 +From: Tobias Brunner +Date: Mon, 27 Jan 2025 09:40:56 +0100 +Subject: [PATCH 1/3] pf-handler: Accept loopback interfaces as packet source + +In some setups the responses from the DHCP server are sent via lo, which +does not have an address of type `ARPHRD_ETHER` (the address length is +the same, though, just all zeros, by default). Note that the dhcp plugin +doesn't actually care for the MAC address or interface details, that's +only used by the farp plugin. + +Fixes: 187c72d1afdc ("dhcp: Port the plugin to FreeBSD/macOS") +--- + src/libcharon/network/pf_handler.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/src/libcharon/network/pf_handler.c ++++ b/src/libcharon/network/pf_handler.c +@@ -176,7 +176,8 @@ static cached_iface_t *find_interface(pr + + if (ioctl(fd, SIOCGIFNAME, &req) == 0 && + ioctl(fd, SIOCGIFHWADDR, &req) == 0 && +- req.ifr_hwaddr.sa_family == ARPHRD_ETHER) ++ (req.ifr_hwaddr.sa_family == ARPHRD_ETHER || ++ req.ifr_hwaddr.sa_family == ARPHRD_LOOPBACK)) + { + idx = find_least_used_cache_entry(this); + diff --git a/net/strongswan/patches/0006-pf-handler-Correctly-bind-packet-socket-to-an-interf.patch b/net/strongswan/patches/0006-pf-handler-Correctly-bind-packet-socket-to-an-interf.patch new file mode 100644 index 0000000000000..89f6a68b2eeb9 --- /dev/null +++ b/net/strongswan/patches/0006-pf-handler-Correctly-bind-packet-socket-to-an-interf.patch @@ -0,0 +1,63 @@ +From 00d8c36d6fdf9e8ee99b9f92a64e7e81dbfa4432 Mon Sep 17 00:00:00 2001 +From: Tobias Brunner +Date: Thu, 30 Jan 2025 14:40:33 +0100 +Subject: [PATCH 2/3] pf-handler: Correctly bind packet socket to an interface + +Binding such sockets via SO_BINDTODEVICE does not work at all. Instead, +bind() has to be used, as described in the packet(7) man page. +--- + src/libcharon/network/pf_handler.c | 31 +++++++++++++++++++++++++++--- + 1 file changed, 28 insertions(+), 3 deletions(-) + +--- a/src/libcharon/network/pf_handler.c ++++ b/src/libcharon/network/pf_handler.c +@@ -227,6 +227,30 @@ METHOD(pf_handler_t, destroy, void, + } + + /** ++ * Bind the given packet socket to the a named device ++ */ ++static bool bind_packet_socket_to_device(int fd, char *iface) ++{ ++ struct sockaddr_ll addr = { ++ .sll_family = AF_PACKET, ++ .sll_ifindex = if_nametoindex(iface), ++ }; ++ ++ if (!addr.sll_ifindex) ++ { ++ DBG1(DBG_CFG, "unable to bind socket to '%s': not found", iface); ++ return FALSE; ++ } ++ if (bind(fd, (struct sockaddr*)&addr, sizeof(addr)) == -1) ++ { ++ DBG1(DBG_CFG, "binding socket to '%s' failed: %s", ++ iface, strerror(errno)); ++ return FALSE; ++ } ++ return TRUE; ++} ++ ++/** + * Setup capturing via AF_PACKET socket + */ + static bool setup_internal(private_pf_handler_t *this, char *iface, +@@ -248,14 +272,15 @@ static bool setup_internal(private_pf_ha + this->name, strerror(errno)); + return FALSE; + } +- if (iface && !bind_to_device(this->receive, iface)) ++ if (iface && iface[0] && !bind_packet_socket_to_device(this->receive, iface)) + { + return FALSE; + } + lib->watcher->add(lib->watcher, this->receive, WATCHER_READ, + receive_packet, this); +- DBG2(DBG_NET, "listening for %s (protocol=0x%04x) requests on fd=%d", +- this->name, protocol, this->receive); ++ DBG2(DBG_NET, "listening for %s (protocol=0x%04x) requests on fd=%d bound " ++ "to %s", this->name, protocol, this->receive, ++ iface && iface[0] ? iface : "no interface"); + return TRUE; + } + diff --git a/net/strongswan/patches/0007-dhcp-Add-option-to-bind-the-receive-socket-to-a-diff.patch b/net/strongswan/patches/0007-dhcp-Add-option-to-bind-the-receive-socket-to-a-diff.patch new file mode 100644 index 0000000000000..bb3319ac5033a --- /dev/null +++ b/net/strongswan/patches/0007-dhcp-Add-option-to-bind-the-receive-socket-to-a-diff.patch @@ -0,0 +1,66 @@ +From a50ed3006e8152eb2cf20e9f92f088ecc18081b0 Mon Sep 17 00:00:00 2001 +From: Tobias Brunner +Date: Wed, 29 Jan 2025 17:23:31 +0100 +Subject: [PATCH 3/3] dhcp: Add option to bind the receive socket to a + different interface + +This can be useful if the DHCP server runs on the same server. On Linux, +the response is then sent via `lo`, so packets won't be received if both +sockets are bound to e.g. a bridge interface. +--- + conf/plugins/dhcp.opt | 10 ++++++++++ + src/libcharon/plugins/dhcp/dhcp_socket.c | 13 ++++++++----- + 2 files changed, 18 insertions(+), 5 deletions(-) + +--- a/conf/plugins/dhcp.opt ++++ b/conf/plugins/dhcp.opt +@@ -36,3 +36,13 @@ charon.plugins.dhcp.interface + Interface name the plugin uses for address allocation. The default is to + bind to any (0.0.0.0) and let the system decide which way to route the + packets to the DHCP server. ++ ++charon.plugins.dhcp.interface_receive = charon.plugins.dhcp.interface ++ Interface name the plugin uses to bind its receive socket. ++ ++ Interface name the plugin uses to bind its receive socket. The default is ++ to use the same interface as the send socket. Set it to the empty string ++ to avoid binding the receive socket to any interface while the send socket ++ is bound to one. If the server runs on the same host and the send socket is ++ bound to an interface, it might be necessary to set this to `lo` or the ++ empty string. +--- a/src/libcharon/plugins/dhcp/dhcp_socket.c ++++ b/src/libcharon/plugins/dhcp/dhcp_socket.c +@@ -716,7 +716,7 @@ dhcp_socket_t *dhcp_socket_create() + }, + }; + socklen_t addr_len; +- char *iface; ++ char *iface, *iface_receive; + int on = 1, rcvbuf = 0; + + #if !defined(__APPLE__) && !defined(__FreeBSD__) +@@ -809,8 +809,11 @@ dhcp_socket_t *dhcp_socket_create() + this->dst = host_create_from_string(lib->settings->get_str(lib->settings, + "%s.plugins.dhcp.server", "255.255.255.255", + lib->ns), DHCP_SERVER_PORT); +- iface = lib->settings->get_str(lib->settings, "%s.plugins.dhcp.interface", +- NULL, lib->ns); ++ iface = lib->settings->get_str(lib->settings, ++ "%s.plugins.dhcp.interface", NULL, lib->ns); ++ iface_receive = lib->settings->get_str(lib->settings, ++ "%s.plugins.dhcp.interface_receive", NULL, ++ lib->ns) ?: iface; + if (!this->dst) + { + DBG1(DBG_CFG, "configured DHCP server address invalid"); +@@ -873,8 +876,8 @@ dhcp_socket_t *dhcp_socket_create() + return NULL; + } + +- this->pf_handler = pf_handler_create("DHCP", iface, receive_dhcp, this, +- &dhcp_filter); ++ this->pf_handler = pf_handler_create("DHCP", iface_receive, receive_dhcp, ++ this, &dhcp_filter); + if (!this->pf_handler) + { + destroy(this);