]> git.ipfire.org Git - thirdparty/openvpn.git/commitdiff
dco: support float notifications on FreeBSD
authorKristof Provost <kp@FreeBSD.org>
Wed, 23 Jul 2025 08:36:49 +0000 (10:36 +0200)
committerGert Doering <gert@greenie.muc.de>
Mon, 28 Jul 2025 07:56:06 +0000 (09:56 +0200)
Signed-off-by: Kristof Provost <kprovost@netgate.com>
Acked-by: Gert Doering <gert@greenie.muc.de>
Message-Id: <20250723083816.71604-2-kprovost@netgate.com>
URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg32282.html
Signed-off-by: Gert Doering <gert@greenie.muc.de>
configure.ac
src/openvpn/dco_freebsd.c
src/openvpn/dco_freebsd.h
src/openvpn/multi.c
src/openvpn/ovpn_dco_freebsd.h

index 66cb79b157e8932ed224c85d332f8c3fe8811519..50697b8ec0e6dcdc91610794d9738e35e7c28a29 100644 (file)
@@ -848,6 +848,15 @@ if test "$enable_dco" != "no"; then
                                else
                                        AC_MSG_ERROR([DCO support can't be enabled])
                                fi
+                       else
+                               AC_CHECK_DECLS(
+                                       [OVPN_NOTIF_FLOAT],
+                                       [AC_DEFINE([ENABLE_DCO_FLOAT_FREEBSD], [1], [We have DCO float notifications on FreeBSD])],
+                                       ,
+                                       [[
+                                               #include <net/if_ovpn.h>
+                                       ]]
+                               )
                        fi
                        ;;
                *-mingw*)
index 78ee9a1f758fb6b1b75b09aeb93d96f74579ed59..8add41af8545029c68f52e02367c472c67286018 100644 (file)
@@ -72,6 +72,63 @@ sockaddr_to_nvlist(const struct sockaddr *sa)
     return (nvl);
 }
 
+#ifdef ENABLE_DCO_FLOAT_FREEBSD
+static bool
+nvlist_to_sockaddr(const nvlist_t *nvl, struct sockaddr_storage *ss)
+{
+    if (!nvlist_exists_number(nvl, "af"))
+    {
+        return (false);
+    }
+    if (!nvlist_exists_binary(nvl, "address"))
+    {
+        return (false);
+    }
+    if (!nvlist_exists_number(nvl, "port"))
+    {
+        return (false);
+    }
+
+    ss->ss_family = nvlist_get_number(nvl, "af");
+
+    switch (ss->ss_family)
+    {
+        case AF_INET:
+        {
+            struct sockaddr_in *in = (struct sockaddr_in *)ss;
+            const void *data;
+            size_t len;
+
+            in->sin_len = sizeof(*in);
+            data = nvlist_get_binary(nvl, "address", &len);
+            assert(len == sizeof(in->sin_addr));
+            memcpy(&in->sin_addr, data, sizeof(in->sin_addr));
+            in->sin_port = nvlist_get_number(nvl, "port");
+            break;
+        }
+
+        case AF_INET6:
+        {
+            struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)ss;
+            const void *data;
+            size_t len;
+
+            in6->sin6_len = sizeof(*in6);
+            data = nvlist_get_binary(nvl, "address", &len);
+            assert(len == sizeof(in6->sin6_addr));
+            memcpy(&in6->sin6_addr, data, sizeof(in6->sin6_addr));
+            in6->sin6_port = nvlist_get_number(nvl, "port");
+            break;
+        }
+
+        default:
+            return (false);
+    }
+
+    return (true);
+}
+#endif /* ifdef ENABLE_DCO_FLOAT_FREEBSD */
+
 int
 dco_new_peer(dco_context_t *dco, unsigned int peerid, int sd,
              struct sockaddr *localaddr, struct sockaddr *remoteaddr,
@@ -573,6 +630,27 @@ dco_do_read(dco_context_t *dco)
             dco->dco_message_type = OVPN_CMD_SWAP_KEYS;
             break;
 
+#ifdef ENABLE_DCO_FLOAT_FREEBSD
+        case OVPN_NOTIF_FLOAT: {
+            const nvlist_t *address;
+
+            if (!nvlist_exists_nvlist(nvl, "address"))
+            {
+                msg(M_WARN, "Float notification without address");
+                break;
+            }
+
+            address = nvlist_get_nvlist(nvl, "address");
+            if (!nvlist_to_sockaddr(address, &dco->dco_float_peer_ss))
+            {
+                msg(M_WARN, "Failed to parse float notification");
+                break;
+            }
+            dco->dco_message_type = OVPN_CMD_FLOAT_PEER;
+            break;
+        }
+#endif
+
         default:
             msg(M_WARN, "Unknown kernel notification %d", type);
             break;
index e926af50ac08c7ff031a36753595048ed0e357fb..69c2d054d1921864271c58c9ec08907cd016de32 100644 (file)
@@ -36,6 +36,7 @@ enum ovpn_message_type_t {
     OVPN_CMD_DEL_PEER,
     OVPN_CMD_PACKET,
     OVPN_CMD_SWAP_KEYS,
+    OVPN_CMD_FLOAT_PEER,
 };
 
 enum ovpn_del_reason_t {
@@ -55,6 +56,7 @@ typedef struct dco_context {
     int dco_message_type;
     int dco_message_peer_id;
     int dco_del_peer_reason;
+    struct sockaddr_storage dco_float_peer_ss;
     uint64_t dco_read_bytes;
     uint64_t dco_write_bytes;
 
index c90ed5ba4e92a5e143c096ea541b16825f72b7d2..49f5320114d7ea919b60bd29f863cf511efb03a0 100644 (file)
@@ -3409,7 +3409,7 @@ multi_process_incoming_dco(struct multi_context *m)
         {
             process_incoming_del_peer(m, mi, dco);
         }
-#if defined(TARGET_LINUX) || defined(TARGET_WIN32)
+#if defined(TARGET_LINUX) || defined(TARGET_WIN32) || defined(TARGET_FREEBSD)
         else if (dco->dco_message_type == OVPN_CMD_FLOAT_PEER)
         {
             ASSERT(mi->context.c2.link_sockets[0]);
index 53f94dfdba88b81b2494109d75de25479836287b..7eb643b447a1196515106c13093bb09b567d15a6 100644 (file)
@@ -37,6 +37,7 @@
 enum ovpn_notif_type {
     OVPN_NOTIF_DEL_PEER,
     OVPN_NOTIF_ROTATE_KEY,
+    OVPN_NOTIF_FLOAT,
 };
 
 enum ovpn_del_reason {