]> git.ipfire.org Git - thirdparty/openvpn.git/commitdiff
Allowing installing FreeBSD routes with interface instead of next-hop
authorArne Schwabe <arne@rfc2549.org>
Mon, 6 Oct 2025 14:58:37 +0000 (16:58 +0200)
committerGert Doering <gert@greenie.muc.de>
Mon, 6 Oct 2025 16:27:27 +0000 (18:27 +0200)
This matches the Linux behaviour of the net_route add/delete commands

Change-Id: I88e16e15fad065cb310d38f09924053efc3a6ce5
Signed-off-by: Arne Schwabe <arne@rfc2549.org>
Gerrit URL: https://gerrit.openvpn.net/c/openvpn/+/1193
Message-Id: <20251006145844.27794-1-gert@greenie.muc.de>
URL: https://sourceforge.net/p/openvpn/mailman/message/59242876/
Signed-off-by: Gert Doering <gert@greenie.muc.de>
src/openvpn/networking_freebsd.c

index b47444cc763185d1d7cb8a3eb1f4c3d5a314a05b..04051a6ee55650e2196b4857964bdbb8bced71f1 100644 (file)
@@ -15,17 +15,31 @@ net_route_v4(const char *op, const in_addr_t *dst, int prefixlen, const in_addr_
     char buf1[INET_ADDRSTRLEN], buf2[INET_ADDRSTRLEN];
     in_addr_t _dst, _gw;
     struct argv argv = argv_new();
-    bool status;
+
+    ASSERT(gw || iface);
 
     _dst = ntohl(*dst);
-    _gw = ntohl(*gw);
 
-    argv_printf(&argv, "%s %s -net %s/%d %s -fib %d", ROUTE_PATH, op,
-                inet_ntop(AF_INET, &_dst, buf1, sizeof(buf1)), prefixlen,
-                inet_ntop(AF_INET, &_gw, buf2, sizeof(buf2)), table);
+    /* if we have a gateway (GW != NULL) install route to gateway IP
+     * if not, install "connected" route to interface
+     * (needed to make 'ifconfig-push IPs outside server subnet' work)
+     */
+    if (gw)
+    {
+        _gw = ntohl(*gw);
+        argv_printf(&argv, "%s %s -net %s/%d %s -fib %d", ROUTE_PATH, op,
+                    inet_ntop(AF_INET, &_dst, buf1, sizeof(buf1)), prefixlen,
+                    inet_ntop(AF_INET, &_gw, buf2, sizeof(buf2)), table);
+    }
+    else
+    {
+        argv_printf(&argv, "%s %s -net %s/%d -iface %s -fib %d", ROUTE_PATH, op,
+                    inet_ntop(AF_INET, &_dst, buf1, sizeof(buf1)), prefixlen,
+                    iface, table);
+    }
 
     argv_msg(M_INFO, &argv);
-    status = openvpn_execve_check(&argv, NULL, 0, "ERROR: FreeBSD route command failed");
+    bool status = openvpn_execve_check(&argv, NULL, 0, "ERROR: FreeBSD route command failed");
 
     argv_free(&argv);
 
@@ -38,14 +52,29 @@ net_route_v6(const char *op, const struct in6_addr *dst, int prefixlen, const st
 {
     char buf1[INET6_ADDRSTRLEN], buf2[INET6_ADDRSTRLEN];
     struct argv argv = argv_new();
-    bool status;
 
-    argv_printf(&argv, "%s -6 %s -net %s/%d %s -fib %d", ROUTE_PATH, op,
-                inet_ntop(AF_INET6, dst, buf1, sizeof(buf1)), prefixlen,
-                inet_ntop(AF_INET6, gw, buf2, sizeof(buf2)), table);
+    ASSERT(gw || iface);
+
+    /* if we have a gateway (GW != NULL) install route to gateway IP
+     * if not, install "connected" route to interface
+     * (needed to make 'ifconfig-push IPs outside server subnet' work)
+     */
+    if (gw)
+    {
+        argv_printf(&argv, "%s -6 %s -net %s/%d %s -fib %d", ROUTE_PATH, op,
+                    inet_ntop(AF_INET6, dst, buf1, sizeof(buf1)), prefixlen,
+                    inet_ntop(AF_INET6, gw, buf2, sizeof(buf2)), table);
+    }
+    else
+    {
+        argv_printf(&argv, "%s -6 %s -net %s/%d -iface %s -fib %d", ROUTE_PATH, op,
+                    inet_ntop(AF_INET6, dst, buf1, sizeof(buf1)), prefixlen,
+                    iface, table);
+    }
+
 
     argv_msg(M_INFO, &argv);
-    status = openvpn_execve_check(&argv, NULL, 0, "ERROR: FreeBSD route command failed");
+    bool status = openvpn_execve_check(&argv, NULL, 0, "ERROR: FreeBSD route command failed");
 
     argv_free(&argv);