Hi,

On Fri, Oct 07, 2022 at 11:56:52AM +0200, Gert Doering wrote:
> I'll dig into the POINTTOPOINT issue... configure a real MULTIPOINT
> interface for --topology subnet (which is something I've always avoided
> so far, because "we know the other stuff works")

This is... an interesting problem.

Changing the tun(4) stuff to do IFF_BROADCAST for "topology subnet"
is straightforward, and makes the whole code much simpler actually
(and you can do "ifconfig tun7 1.2.3.4/24" and have it actually do
what you expect "here is a subnet, with 255 different next-hop IPs
available for routing").  Patch is attached so you can see what
I'm talking about :-)

Butbut... ovpn(4) does not support the TUNSIFMODE ioctl() to set
something that is not IFF_POINTOPOINT, so we fail with

    2022-10-11 20:58:28 ioctl(TUNSIFMODE): Can't assign requested address 
(errno=49)
    2022-10-11 20:58:28 DCO device tun14 opened
    2022-10-11 20:58:28 /sbin/ifconfig tun14 10.194.3.56/24 mtu 1500 up
    ifconfig: ioctl (SIOCAIFADDR): Destination address required
    2022-10-11 20:58:28 FreeBSD ifconfig failed: external program exited with 
error status: 1
    2022-10-11 20:58:28 Exiting due to fatal error


@kp, not sure how to move forward.  What we need is a "true on-link
subnet", so installation of iroutes to "peer #4" works (which it
doesn't today), and I think that means "ovpn(4) needs to learn 
IFF_BROADCAST".


OTOH, in "not peer2peer mode", we only support topology subnet anyway,
so maybe it should autoconfigure that, depending on the mode OpenVPN
requests (p2p mode -> IFF_POINTOPOINT, p2mp mode -> IFF_BROADCAST),
so we don't even need TUNSIFMODE.

Looking into if_ovpn.c, this is a bit beyond my understanding of the
code, though...

gert
-- 
"If was one thing all people took for granted, was conviction that if you 
 feed honest figures into a computer, honest figures come out. Never doubted 
 it myself till I met a computer with a sense of humor."
                             Robert A. Heinlein, The Moon is a Harsh Mistress

Gert Doering - Munich, Germany                             g...@greenie.muc.de
From 02f74941b29532f977be58205202eb2ccb21b12e Mon Sep 17 00:00:00 2001
From: Gert Doering <g...@greenie.muc.de>
Date: Tue, 11 Oct 2022 19:54:23 +0200
Subject: [PATCH] FreeBSD: for topology subnet, put tun interface into
 IFF_BROADCAST mode

For reasons unknown, OpenVPN has always put FreeBSD tun(4) interfaces
into point-to-point mode (IFF_POINTOPOINT), which means "local and
remote address, no on-link subnet".

"--topology subnet" was emulated by adding a subnet-route to the "remote"
(which was just picking a free address from the subnet).

This works well enough for classic tun(4) interfaces that have no
next-hop resolution, and routes pointing to "that fake remote" only
(because all routing is done inside OpenVPN and it does not matter how
packets get there) - but for ovpn(4) interfaces, it breaks iroute setup,
where the route next-hop must be an on-link address.

Thus, change interface to IFF_BROADCAST mode, and get rid of all the
special code needed to "fake" subnet mode.

Tested with tun(4) and ovpn(4) on FreeBSD 14, client and server, and
with tun(4) on FreeBSD 12 and 7.4

Signed-off-by: Gert Doering <g...@greenie.muc.de>
---
 Changes.rst       |  5 +++++
 src/openvpn/tun.c | 28 ++++++++++------------------
 2 files changed, 15 insertions(+), 18 deletions(-)

diff --git a/Changes.rst b/Changes.rst
index df56f76a..0397cb94 100644
--- a/Changes.rst
+++ b/Changes.rst
@@ -163,6 +163,11 @@ User-visible Changes
 - :code:`link_mtu` parameter is removed from environment or replaced with 0 when scripts are
   called with parameters. This parameter is unreliable and no longer internally calculated.
 
+- FreeBSD tun interfaces with ``--topology subnet`` are now put into real
+  subnet mode (IFF_BROADCAST instead of IFF_POINTOPOINT) - this might upset
+  software that enumerates interfaces, looking for "broadcast capable?" and
+  expecting certain results.  Normal uses should not see any difference.
+
 Overview of changes in 2.5
 ==========================
 
diff --git a/src/openvpn/tun.c b/src/openvpn/tun.c
index ddee49f9..ede65cbe 100644
--- a/src/openvpn/tun.c
+++ b/src/openvpn/tun.c
@@ -1479,8 +1479,6 @@ do_ifconfig_ipv4(struct tuntap *tt, const char *ifname, int tun_mtu,
 
 #elif defined(TARGET_FREEBSD) || defined(TARGET_DRAGONFLY)
 
-    in_addr_t remote_end;           /* for "virtual" subnet topology */
-
     /* example: ifconfig tun2 10.2.0.2 10.2.0.1 mtu 1450 netmask 255.255.255.255 up */
     if (tun)
     {
@@ -1490,10 +1488,9 @@ do_ifconfig_ipv4(struct tuntap *tt, const char *ifname, int tun_mtu,
     }
     else if (tt->type == DEV_TYPE_TUN && tt->topology == TOP_SUBNET)
     {
-        remote_end = create_arbitrary_remote( tt );
-        argv_printf(&argv, "%s %s %s %s mtu %d netmask %s up", IFCONFIG_PATH,
-                    ifname, ifconfig_local, print_in_addr_t(remote_end, 0, &gc),
-                    tun_mtu, ifconfig_remote_netmask);
+        int netbits = netmask_to_netbits2(tt->remote_netmask);
+        argv_printf(&argv, "%s %s %s/%d mtu %d up", IFCONFIG_PATH,
+                    ifname, ifconfig_local, netbits, tun_mtu );
     }
     else
     {
@@ -1504,18 +1501,6 @@ do_ifconfig_ipv4(struct tuntap *tt, const char *ifname, int tun_mtu,
     argv_msg(M_INFO, &argv);
     openvpn_execve_check(&argv, es, S_FATAL, "FreeBSD ifconfig failed");
 
-    /* Add a network route for the local tun interface */
-    if (!tun && tt->type == DEV_TYPE_TUN && tt->topology == TOP_SUBNET)
-    {
-        struct route_ipv4 r;
-        CLEAR(r);
-        r.flags = RT_DEFINED;
-        r.network = tt->local & tt->remote_netmask;
-        r.netmask = tt->remote_netmask;
-        r.gateway = remote_end;
-        add_route(&r, tt, 0, NULL, es, NULL);
-    }
-
 #elif defined(TARGET_AIX)
     {
         /* AIX ifconfig will complain if it can't find ODM path in env */
@@ -2949,12 +2934,19 @@ open_tun(const char *dev, const char *dev_type, const char *dev_node, struct tun
 
         if (tt->fd >= 0 && tt->type == DEV_TYPE_TUN)
         {
+            /* see "Interface Flags" in ifnet(9) */
             int i = IFF_POINTOPOINT | IFF_MULTICAST;
+            if (tt->topology == TOP_SUBNET)
+            {
+                i = IFF_BROADCAST | IFF_MULTICAST;
+            }
 
             if (ioctl(tt->fd, TUNSIFMODE, &i) < 0)
             {
                 msg(M_WARN | M_ERRNO, "ioctl(TUNSIFMODE)");
             }
+
+            /* multi_af mode for v4+v6, see "tun(4)" */
             i = 1;
             if (ioctl(tt->fd, TUNSIFHEAD, &i) < 0)
             {
-- 
2.37.3

Attachment: signature.asc
Description: PGP signature

_______________________________________________
Openvpn-devel mailing list
Openvpn-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/openvpn-devel

Reply via email to