diff options
author | Antonio Quartulli | 2022-07-19 00:17:57 +0200 |
---|---|---|
committer | Gert Doering | 2022-07-19 10:53:15 +0200 |
commit | 8989b0f2833d25c97654c25fa6a49d8fc0ef903d (patch) | |
tree | a6e862e9a18b383c43194184d386ae48e90951c1 /src/openvpn/dco.c | |
parent | dd98c38b31c02cbca7f88ed0a709e68f24361195 (diff) | |
download | openvpn-8989b0f2833d25c97654c25fa6a49d8fc0ef903d.zip openvpn-8989b0f2833d25c97654c25fa6a49d8fc0ef903d.tar.gz |
dco: add option check - disable DCO if conflict is detected
Signed-off-by: Antonio Quartulli <a@unstable.cc>
Acked-by: Gert Doering <gert@greenie.muc.de>
Message-Id: <20220718221757.545-1-a@unstable.cc>
URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg24701.html
Signed-off-by: Gert Doering <gert@greenie.muc.de>
Diffstat (limited to 'src/openvpn/dco.c')
-rw-r--r-- | src/openvpn/dco.c | 190 |
1 files changed, 190 insertions, 0 deletions
diff --git a/src/openvpn/dco.c b/src/openvpn/dco.c new file mode 100644 index 0000000..b3fd135 --- /dev/null +++ b/src/openvpn/dco.c @@ -0,0 +1,190 @@ +/* + * OpenVPN -- An application to securely tunnel IP networks + * over a single TCP/UDP port, with support for SSL/TLS-based + * session authentication and key exchange, + * packet encryption, packet authentication, and + * packet compression. + * + * Copyright (C) 2021-2022 Arne Schwabe <arne@rfc2549.org> + * Copyright (C) 2021-2022 Antonio Quartulli <a@unstable.cc> + * Copyright (C) 2021-2022 OpenVPN Inc <sales@openvpn.net> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program (see the file COPYING included with this + * distribution); if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#elif defined(_MSC_VER) +#include "config-msvc.h" +#endif + +#if defined(ENABLE_DCO) + +#include "syshead.h" +#include "dco.h" +#include "networking.h" +#include "options.h" +#include "ssl_ncp.h" +#include "tun.h" + +static bool +dco_check_option_conflict_platform(int msglevel, const struct options *o) +{ +#if defined(TARGET_LINUX) + /* if the device name is fixed, we need to check if an interface with this + * name already exists. IF it does, it must be a DCO interface, otherwise + * DCO has to be disabled in order to continue. + */ + if (tun_name_is_fixed(o->dev)) + { + char iftype[IFACE_TYPE_LEN_MAX]; + /* we pass NULL as net_ctx because using DCO on Linux implies that we + * are using SITNL and the latter does not need any context. This way we + * don't need to have the net_ctx percolate all the way here + */ + int ret = net_iface_type(NULL, o->dev, iftype); + if ((ret == 0) && (strcmp(iftype, "ovpn-dco") != 0)) + { + msg(msglevel, "Interface %s exists and is non-DCO. Disabling data channel offload", + o->dev); + return false; + } + else if ((ret < 0) && (ret != -ENODEV)) + { + msg(msglevel, "Cannot retrieve type of device %s: %s (%d)", o->dev, + strerror(-ret), ret); + } + } +#endif /* if defined(TARGET_LINUX) */ + return true; +} + +static bool +dco_check_option_conflict_ce(const struct connection_entry *ce, int msglevel) +{ + if (ce->fragment) + { + msg(msglevel, "Note: --fragment disables data channel offload."); + return false; + } + + if (ce->http_proxy_options) + { + msg(msglevel, "Note: --http-proxy disables data channel offload."); + return false; + } + + if (ce->socks_proxy_server) + { + msg(msglevel, "Note: --socks-proxy disables data channel offload."); + return false; + } + + return true; +} + +bool +dco_check_option_conflict(int msglevel, const struct options *o) +{ + if (o->tuntap_options.disable_dco) + { + /* already disabled by --disable-dco, no need to print warnings */ + return false; + } + + if (!dco_available(msglevel)) + { + return false; + } + + if (!dco_check_option_conflict_platform(msglevel, o)) + { + return false; + } + + if (dev_type_enum(o->dev, o->dev_type) != DEV_TYPE_TUN) + { + msg(msglevel, "Note: dev-type not tun, disabling data channel offload."); + return false; + } + + /* At this point the ciphers have already been normalised */ + if (o->enable_ncp_fallback + && !tls_item_in_cipher_list(o->ciphername, DCO_SUPPORTED_CIPHERS)) + { + msg(msglevel, "Note: --data-cipher-fallback with cipher '%s' " + "disables data channel offload.", o->ciphername); + return false; + } + + if (o->connection_list) + { + const struct connection_list *l = o->connection_list; + for (int i = 0; i < l->len; ++i) + { + if (!dco_check_option_conflict_ce(l->array[i], msglevel)) + { + return false; + } + } + } + else + { + if (!dco_check_option_conflict_ce(&o->ce, msglevel)) + { + return false; + } + } + + if (o->mode == MODE_SERVER && o->topology != TOP_SUBNET) + { + msg(msglevel, "Note: NOT using '--topology subnet' disables data channel offload."); + return false; + } + +#if defined(USE_COMP) + if (o->comp.alg != COMP_ALG_UNDEF) + { + msg(msglevel, "Note: Using compression disables data channel offload."); + + if (o->mode == MODE_SERVER && !(o->comp.flags & COMP_F_MIGRATE)) + { + /* We can end up here from the multi.c call, only print the + * note if it is not already enabled */ + msg(msglevel, "Consider using the '--compress migrate' option."); + } + return false; + } +#endif + + struct gc_arena gc = gc_new(); + char *tmp_ciphers = string_alloc(o->ncp_ciphers, &gc); + const char *token; + while ((token = strsep(&tmp_ciphers, ":"))) + { + if (!tls_item_in_cipher_list(token, DCO_SUPPORTED_CIPHERS)) + { + msg(msglevel, "Note: cipher '%s' in --data-ciphers is not supported " + "by ovpn-dco, disabling data channel offload.", token); + gc_free(&gc); + return false; + } + } + gc_free(&gc); + + return true; +} + +#endif /* defined(ENABLE_DCO) */ |