Message ID | AE20A784-506C-488B-9302-2D3AE775B168@opnsense.org |
---|---|
State | Accepted |
Headers | show |
Series | [Openvpn-devel,1/1] Allow to set ifmode for existing DCO interfaces in FreeBSD | expand |
Acked-by: Gert Doering <gert@greenie.muc.de> Thanks for the patch, and the explanation on IRC. This is FreeBSD/DCO specific, and makes the case ifconfig ovpn3 create openvpn --dev ovpn3 --dev-type tun --topology subnet ... work correctly (without it, p2p ifconfig claims to work but ipv6 route addition fails as well). I have stared at the code (looks good) and tested on my FreeBSD 14/DCO test VM with and without the patch, adding relevant test cases to the t_client.rc setup. With the patch, nothing breaks ;-) and the newly considered cases work. There is a slight catch - if the interface (ovpn3) has already been brought "up", the dco_set_ifmode() call fails with 2024-06-02 14:54:06 dco_set_ifmode: failed to set ifmode=00008002: Device busy (errno=16) .. so it will not work properly in all cases. (Also, t_client.sh is not really suited for this sort of test today, as the "compare pre/post ifconfig state" check fails on interface flags - need to think more how to make this work) The patch got badly whitespace mangled in transit (empty lines got turned into extra indent in the following line, and thus). As I said on IRC, I'm happy to fix that for occasional submitters, but generally recommend "git send-email" or pushing to gerrit to avoid outlook induced garbage. Your patch has been applied to the master and release/2.6 branch (highly localized, and arguably a bugfix). commit 82036c17c45d45c3fe8725f64b33720cb9c94dad (master) commit 2f2ff186564c3999efaf48d734df95471ac22d84 (release/2.6) Author: Franco Fichtner Date: Tue May 28 17:42:52 2024 +0000 Allow to set ifmode for existing DCO interfaces in FreeBSD Signed-off-by: Franco Fichtner <franco@opnsense.org> Acked-by: Gert Doering <gert@greenie.muc.de> Message-Id: <AE20A784-506C-488B-9302-2D3AE775B168@opnsense.org> URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg28688.html Signed-off-by: Gert Doering <gert@greenie.muc.de> -- kind regards, Gert Doering
Hi Gert, > On 2. Jun 2024, at 17:50, Gert Doering <gert@greenie.muc.de> wrote: > > work correctly (without it, p2p ifconfig claims to work but ipv6 route > addition fails as well). I did not notice but all the better. > There is a slight catch - if the interface (ovpn3) has already been > brought "up", the dco_set_ifmode() call fails with > > 2024-06-02 14:54:06 dco_set_ifmode: failed to set ifmode=00008002: Device busy (errno=16) > > .. so it will not work properly in all cases. I mentioned this in the original work patch on our end: https://github.com/opnsense/ports/commit/2dc9273a03577 However, I believe something on the OpenVPN end changed in 2.6 for DCO related changes prior as we ran into these integration bugs: https://github.com/opnsense/core/commit/c22f74a786 Which indicate the daemon stops working properly in these cases anyway. This appeared to be a general problem, not directly related to DCO as we weren't using it / lacked support on FreeBSD 13 at the time. Did not dive too much into the OpenVPN code but it did verify the suspicion and this needs to be addressed from the user side now which is more than reasonable. > The patch got badly whitespace mangled in transit (empty lines got > turned into extra indent in the following line, and thus). As I said > on IRC, I'm happy to fix that for occasional submitters, but generally > recommend "git send-email" or pushing to gerrit to avoid outlook induced > garbage. I'll improve my process for the next one. Thanks! Cheers, Franco
diff --git a/src/openvpn/dco_freebsd.c b/src/openvpn/dco_freebsd.c index 577c65f8..7c8b29c9 100644 --- a/src/openvpn/dco_freebsd.c +++ b/src/openvpn/dco_freebsd.c @@ -219,6 +219,9 @@ create_interface(struct tuntap *tt, const char *dev) { ifr.ifr_data = (char *)dev; } + + snprintf(tt->dco.ifname, IFNAMSIZ, "%s", ifr.ifr_data); + ret = ioctl(tt->dco.fd, SIOCSIFNAME, &ifr); if (ret) { @@ -229,16 +232,6 @@ create_interface(struct tuntap *tt, const char *dev) return ret; } - snprintf(tt->dco.ifname, IFNAMSIZ, "%s", ifr.ifr_data); - - /* see "Interface Flags" in ifnet(9) */ - int i = IFF_POINTOPOINT | IFF_MULTICAST; - if (tt->topology == TOP_SUBNET) - { - i = IFF_BROADCAST | IFF_MULTICAST; - } - dco_set_ifmode(&tt->dco, i); - return 0; } @@ -265,7 +258,20 @@ remove_interface(struct tuntap *tt) int
While prexisting devices work well TUN/TAP the DCO interfaces require setting the ifmode which cannot be done by FreeBSD base tooling. In peer-to-peer mode this is not a problem because that is the default mode. Subnet mode, however, will fail to be set and the resulting connection does not start: Failed to create interface ovpns2 (SIOCSIFNAME): File exists (errno=17) DCO device ovpns2 already exists, won't be destroyed at shutdown /sbin/ifconfig ovpns2 10.1.8.1/24 mtu 1500 up ifconfig: in_exec_nl(): Empty IFA_LOCAL/IFA_ADDRESS ifconfig: ioctl (SIOCAIFADDR): Invalid argument FreeBSD ifconfig failed: external program exited with error status: 1 Exiting due to fatal error Slightly restructure the code to catch the specific error condition and execute dco_set_ifmode() in this case as well. Signed-off-by: Franco Fichtner <franco@opnsense.org> --- src/openvpn/dco_freebsd.c | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) open_tun_dco(struct tuntap *tt, openvpn_net_ctx_t *ctx, const char *dev) { - return create_interface(tt, dev); + int ret = create_interface(tt, dev); + + if (ret >= 0 || ret == -EEXIST) + { + /* see "Interface Flags" in ifnet(9) */ + int i = IFF_POINTOPOINT | IFF_MULTICAST; + if (tt->topology == TOP_SUBNET) + { + i = IFF_BROADCAST | IFF_MULTICAST; + } + dco_set_ifmode(&tt->dco, i); + } + + return ret; } void