Browse code

Bugfix: Set broadcast address on interface.

This fixes a problem that was introduced in OpenVPN 2.5. Previously,
the ifconfig utility was used for adding the local address to an
interface. This utility automatically sets the correct broadcast address
based on the given unicast address and netmask.

Due to switching to iproute and Netlink, this does not happen
automatically any longer, which means that applications that rely on
broadcasts do not work correctly.

This patch fixes this issue both when using iproute (by telling iproute
to set the broadcast address based on the local address and prefix) and
when using Netlink (by calculating the correct broadcast address and
setting it).

Signed-off-by: Sebastian Marsching <sebastian-git-2016@marsching.com>
Acked-by: Antonio Quartulli <antonio@openvpn.net>
Message-Id: <20250915110507.20557-1-sebastian-git-2016@marsching.com>
URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg33131.html
Signed-off-by: Gert Doering <gert@greenie.muc.de>
(cherry picked from commit 0df0edc49ce4acb96c8e16bdf0fcee1eedfd91f0)

Sebastian Marsching authored on 2025/09/15 20:05:07
Showing 2 changed files
... ...
@@ -159,7 +159,7 @@ net_addr_v4_add(openvpn_net_ctx_t *ctx, const char *iface,
159 159
 
160 160
     const char *addr_str = print_in_addr_t(*addr, 0, &ctx->gc);
161 161
 
162
-    argv_printf(&argv, "%s addr add dev %s %s/%d", iproute_path, iface,
162
+    argv_printf(&argv, "%s addr add dev %s %s/%d broadcast +", iproute_path, iface,
163 163
                 addr_str, prefixlen);
164 164
     argv_msg(M_INFO, &argv);
165 165
     openvpn_execve_check(&argv, ctx->es, S_FATAL, "Linux ip addr add failed");
... ...
@@ -32,6 +32,7 @@
32 32
 #include "misc.h"
33 33
 #include "networking.h"
34 34
 #include "proto.h"
35
+#include "route.h"
35 36
 
36 37
 #include <errno.h>
37 38
 #include <string.h>
... ...
@@ -800,6 +801,13 @@ sitnl_addr_set(int cmd, uint32_t flags, int ifindex, sa_family_t af_family,
800 800
         SITNL_ADDATTR(&req.n, sizeof(req), IFA_LOCAL, local, size);
801 801
     }
802 802
 
803
+    if (af_family == AF_INET && local && !remote && prefixlen <= 30)
804
+    {
805
+        inet_address_t broadcast = *local;
806
+        broadcast.ipv4 |= htonl(~netbits_to_netmask(prefixlen));
807
+        SITNL_ADDATTR(&req.n, sizeof(req), IFA_BROADCAST, &broadcast, size);
808
+    }
809
+
803 810
     ret = sitnl_send(&req.n, 0, 0, NULL, NULL);
804 811
     if (ret == -EEXIST)
805 812
     {