bool
dco_check_startup_option(int msglevel, const struct options *o)
{
- /* check if DCO was already disabled by the user or if no dev name was
- * specified at all. In the latter case, later logic will most likely stop
- * OpenVPN, so no need to print any message here.
+ /* check if no dev name was specified at all. In the case,
+ * later logic will most likely stop OpenVPN, so no need to
+ * print any message here.
*/
- if (!dco_enabled(o) || !o->dev)
+ if (!o->dev)
{
return false;
}
#if defined(_WIN32)
if (o->mode == MODE_SERVER)
{
- msg(msglevel, "Only client and p2p data channel offload is supported "
- "with ovpn-dco.");
+ msg(msglevel, "--mode server is set. Disabling Data Channel Offload");
+ return false;
+ }
+
+ if ((o->windows_driver == WINDOWS_DRIVER_WINTUN)
+ || (o->windows_driver == WINDOWS_DRIVER_TAP_WINDOWS6))
+ {
+ msg(msglevel, "--windows-driver is set to '%s'. Disabling Data Channel Offload",
+ print_windows_driver(o->windows_driver));
return false;
}
bool
dco_available(int msglevel)
{
- return true;
+ /* try to open device by symbolic name */
+ HANDLE h = CreateFile("\\\\.\\ovpn-dco", GENERIC_READ | GENERIC_WRITE,
+ 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, NULL);
+
+ if (h != INVALID_HANDLE_VALUE)
+ {
+ CloseHandle(h);
+ return true;
+ }
+
+ DWORD err = GetLastError();
+ if (err == ERROR_ACCESS_DENIED)
+ {
+ /* this likely means that device exists but is already in use,
+ * don't bail out since later we try to open all existing dco
+ * devices and then bail out if all devices are in use
+ */
+ return true;
+ }
+
+ msg(msglevel, "Note: ovpn-dco-win driver is missing, disabling data channel offload.");
+ return false;
}
int
" does not begin with \"tun\" or \"tap\".\n"
"--dev-node node : Explicitly set the device node rather than using\n"
" /dev/net/tun, /dev/tun, /dev/tap, etc.\n"
-#if defined(ENABLE_DCO) && (defined(TARGET_LINUX) || defined(TARGET_FREEBSD))
+#if defined(ENABLE_DCO)
"--disable-dco : Do not attempt using Data Channel Offload.\n"
#endif
"--lladdr hw : Set the link layer address of the tap device.\n"
o->tuntap_options.dhcp_masq_offset = 0; /* use network address as internal DHCP server address */
o->route_method = ROUTE_METHOD_ADAPTIVE;
o->block_outside_dns = false;
- o->windows_driver = WINDOWS_DRIVER_TAP_WINDOWS6;
+ o->windows_driver = WINDOWS_DRIVER_UNSPECIFIED;
#endif
o->vlan_accept = VLAN_ALL;
o->vlan_pvid = 1;
}
#endif /* _WIN32 */
o->allow_recursive_routing = false;
+
+#ifndef ENABLE_DCO
+ o->tuntap_options.disable_dco = true;
+#endif /* ENABLE_DCO */
}
void
SHOW_STR(dev);
SHOW_STR(dev_type);
SHOW_STR(dev_node);
-#if defined(ENABLE_DCO) && (defined(TARGET_LINUX) || defined(TARGET_FREEBSD))
+#if defined(ENABLE_DCO)
SHOW_BOOL(tuntap_options.disable_dco);
#endif
SHOW_STR(lladdr);
options_set_backwards_compatible_options(o);
options_postprocess_cipher(o);
- options_postprocess_mutate_invariant(o);
-
o->ncp_ciphers = mutate_ncp_cipher_list(o->ncp_ciphers, &o->gc);
if (o->ncp_ciphers == NULL)
{
"incompatible with each other.");
}
-#if defined(TARGET_LINUX) || defined(TARGET_FREEBSD)
- /* check if any option should force disabling DCO */
- o->tuntap_options.disable_dco = !dco_check_option(D_DCO, o)
- || !dco_check_startup_option(D_DCO, o);
-#elif defined(_WIN32)
- /* in Windows we have no 'fallback to non-DCO' strategy, so if a conflicting
- * option is found, we simply bail out by means of M_USAGE
- */
if (dco_enabled(o))
{
- dco_check_option(M_USAGE, o);
- dco_check_startup_option(M_USAGE, o);
+ /* check if any option should force disabling DCO */
+ o->tuntap_options.disable_dco = !dco_check_option(D_DCO, o)
+ || !dco_check_startup_option(D_DCO, o);
+ }
+
+#ifdef _WIN32
+ if (dco_enabled(o))
+ {
+ o->windows_driver = WINDOWS_DRIVER_DCO;
+ }
+ else
+ {
+ if (o->windows_driver == WINDOWS_DRIVER_DCO)
+ {
+ msg(M_WARN, "Option --windows-driver ovpn-dco is ignored because Data Channel Offload is disabled");
+ o->windows_driver = WINDOWS_DRIVER_TAP_WINDOWS6;
+ }
+ else if (o->windows_driver == WINDOWS_DRIVER_UNSPECIFIED)
+ {
+ o->windows_driver = WINDOWS_DRIVER_TAP_WINDOWS6;
+ }
}
#endif
o->dev_node = NULL;
}
+ /* this depends on o->windows_driver, which is set above */
+ options_postprocess_mutate_invariant(o);
+
/*
* Save certain parms before modifying options during connect, especially
* when using --pull
#endif
else if (streq(p[0], "disable-dco"))
{
-#if defined(TARGET_LINUX) || defined(TARGET_FREEBSD)
options->tuntap_options.disable_dco = true;
-#endif
}
else if (streq(p[0], "dev-node") && p[1] && !p[2])
{