2018-05-21 11:16:56 +02:00
|
|
|
// OpenVPN -- An application to securely tunnel IP networks
|
|
|
|
// over a single port, with support for SSL/TLS-based
|
|
|
|
// session authentication and key exchange,
|
|
|
|
// packet encryption, packet authentication, and
|
|
|
|
// packet compression.
|
|
|
|
//
|
2022-09-29 11:41:13 +02:00
|
|
|
// Copyright (C) 2012-2022 OpenVPN Inc.
|
2018-05-21 11:16:56 +02:00
|
|
|
//
|
|
|
|
// This program is free software: you can redistribute it and/or modify
|
|
|
|
// it under the terms of the GNU Affero General Public License Version 3
|
|
|
|
// 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 Affero General Public License for more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU Affero General Public License
|
|
|
|
// along with this program in the COPYING file.
|
|
|
|
// If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
2020-08-21 12:07:25 +02:00
|
|
|
#pragma once
|
2018-05-21 11:16:56 +02:00
|
|
|
|
|
|
|
#include <memory>
|
|
|
|
#include <sstream>
|
2021-02-23 01:10:17 +01:00
|
|
|
#include <vector>
|
2018-05-21 11:16:56 +02:00
|
|
|
|
2021-02-23 01:10:17 +01:00
|
|
|
#include <openvpn/buffer/asiobuf.hpp>
|
2018-05-21 11:16:56 +02:00
|
|
|
#include <openvpn/common/exception.hpp>
|
2021-02-23 01:10:17 +01:00
|
|
|
#include <openvpn/common/size.hpp>
|
2018-05-21 11:16:56 +02:00
|
|
|
#include <openvpn/common/to_string.hpp>
|
|
|
|
#include <openvpn/time/time.hpp>
|
|
|
|
#include <openvpn/transport/client/transbase.hpp>
|
2021-02-23 01:10:17 +01:00
|
|
|
#include <openvpn/transport/dco.hpp>
|
2022-04-28 15:18:03 +02:00
|
|
|
#include <openvpn/tun/tunmtu.hpp>
|
2018-05-21 11:16:56 +02:00
|
|
|
#include <openvpn/tun/builder/capture.hpp>
|
2021-02-23 01:10:17 +01:00
|
|
|
#include <openvpn/tun/client/tunbase.hpp>
|
2021-03-24 05:05:40 +01:00
|
|
|
|
|
|
|
#ifndef ENABLE_OVPNDCOWIN
|
2019-09-23 14:16:30 +02:00
|
|
|
#include <openvpn/tun/linux/client/tunmethods.hpp>
|
2021-03-24 05:05:40 +01:00
|
|
|
#endif
|
2020-08-21 12:07:25 +02:00
|
|
|
|
2020-08-21 13:15:48 +02:00
|
|
|
#ifdef ENABLE_KOVPN
|
2021-02-23 01:10:17 +01:00
|
|
|
#include <openvpn/kovpn/kodevtun.hpp>
|
2018-05-21 11:16:56 +02:00
|
|
|
#include <openvpn/kovpn/kostats.hpp>
|
2021-02-23 01:10:17 +01:00
|
|
|
#include <openvpn/kovpn/kovpn.hpp>
|
2020-09-29 14:18:43 +02:00
|
|
|
#include <openvpn/kovpn/rps_xps.hpp>
|
2020-08-21 13:15:48 +02:00
|
|
|
#elif ENABLE_OVPNDCO
|
2021-02-23 01:10:17 +01:00
|
|
|
#include <openvpn/buffer/buffer.hpp>
|
2020-08-21 15:06:51 +02:00
|
|
|
#include <openvpn/common/uniqueptr.hpp>
|
2021-02-23 01:10:17 +01:00
|
|
|
#include <openvpn/dco/key.hpp>
|
2020-08-21 15:06:51 +02:00
|
|
|
#include <openvpn/tun/linux/client/genl.hpp>
|
2021-02-23 01:10:17 +01:00
|
|
|
#include <openvpn/tun/linux/client/sitnl.hpp>
|
2021-03-24 05:05:40 +01:00
|
|
|
#elif ENABLE_OVPNDCOWIN
|
2022-05-02 11:37:15 +02:00
|
|
|
#include <bcrypt.h>
|
2021-03-24 05:05:40 +01:00
|
|
|
#include <openvpn/dco/key.hpp>
|
2022-04-21 17:21:30 +02:00
|
|
|
#include <openvpn/dco/ovpn-dco.h>
|
2023-04-21 15:12:12 +02:00
|
|
|
#include <openvpn/win/modname.hpp>
|
2020-08-21 13:15:48 +02:00
|
|
|
#else
|
2021-03-24 05:05:40 +01:00
|
|
|
#error either ENABLE_KOVPN, ENABLE_OVPNDCO or ENABLE_OVPNDCOWIN must be defined
|
2020-08-21 13:15:48 +02:00
|
|
|
#endif
|
2018-05-21 11:16:56 +02:00
|
|
|
|
2020-09-29 14:18:43 +02:00
|
|
|
#include <openvpn/dco/korekey.hpp>
|
2020-08-21 13:15:48 +02:00
|
|
|
|
2018-05-21 11:16:56 +02:00
|
|
|
// client-side DCO (Data Channel Offload) module for Linux/kovpn
|
|
|
|
|
|
|
|
namespace openvpn {
|
2021-02-23 01:10:17 +01:00
|
|
|
namespace DCOTransport {
|
|
|
|
enum
|
|
|
|
{
|
|
|
|
OVPN_PEER_ID_UNDEF = 0x00FFFFFF,
|
|
|
|
};
|
|
|
|
|
|
|
|
class ClientConfig : public DCO,
|
|
|
|
public TransportClientFactory,
|
|
|
|
public TunClientFactory
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
typedef RCPtr<ClientConfig> Ptr;
|
|
|
|
|
|
|
|
std::string dev_name;
|
2018-05-21 11:16:56 +02:00
|
|
|
|
2021-02-23 01:10:17 +01:00
|
|
|
DCO::TransportConfig transport;
|
|
|
|
DCO::TunConfig tun;
|
2018-05-21 11:16:56 +02:00
|
|
|
|
2021-02-23 01:10:17 +01:00
|
|
|
unsigned int ping_restart_override = 0;
|
|
|
|
|
2021-09-15 13:39:02 +02:00
|
|
|
void process_push(const OptionList &opt) override
|
|
|
|
{
|
|
|
|
transport.remote_list->process_push(opt);
|
|
|
|
}
|
|
|
|
|
tun: add persis-tun support for dco-win
Add DcoTunPersist object to DCO::TunConfig.
DcoTunPersist stores:
- device handle
- tun settings
- adapter index/name
- pointer to TunSetup object, which itself
stores commands to undo tun settings
When intializing client options, instantiate DcoTunPersist
object within the scope of ClientConfig, which serves as
transport and tun factory for dco. Indicate that "sock" object
(device handle) should be preserved - not replaced when persisting
tun settings.
When establishing dco-win connection in OvpnDcoWinClient,
either use tun_persist created above (if persistance is enabled)
or instantiate it in-place (no persistance).
If nothing is stored in tun_persist (means this is first
connection or reconnect without persistance), acquire device
handle from tun_setup, wrap it into ASIO's basic_stream_handle
and store it in OvpnDcoWinClient - no need to persist it yet.
When starting tun, check if persisted tun session matches
to-be-created session. If no - clear previous tun settings,
set up tun and persist tun state. If device handle is already
stored in tun_persist, it won't be replaced.
On tun stop, send DEL_PEER command, which deletes peer
from the driver but keeps adapter in connected state. Then
close locally stored ASIO handle and reset tun_persist.
In case of "short term persistance" this will undo tun settings
and close device handle. For long term persistence, tun_persist
is also stored in ClientConfig and handle won't be closed yet.
In case of disconnect, ClientConfig::finalize(disconnect=true)
is called, which resets tun_persist, which in turn
undoes tun settings and closes device handle.
Signed-off-by: Lev Stipakov <lev@openvpn.net>
2022-10-04 10:27:19 +02:00
|
|
|
virtual void finalize(const bool disconnected) override
|
|
|
|
{
|
|
|
|
#ifdef ENABLE_OVPNDCOWIN
|
|
|
|
if (disconnected)
|
|
|
|
tun.tun_persist.reset();
|
|
|
|
#endif
|
|
|
|
}
|
2023-01-11 20:43:22 +01:00
|
|
|
|
2021-02-23 01:10:17 +01:00
|
|
|
virtual TunClientFactory::Ptr
|
|
|
|
new_tun_factory(const DCO::TunConfig &conf, const OptionList &opt) override
|
2023-01-11 20:43:22 +01:00
|
|
|
{
|
2021-02-23 01:10:17 +01:00
|
|
|
tun = conf;
|
2023-01-11 20:43:22 +01:00
|
|
|
|
2021-02-23 01:10:17 +01:00
|
|
|
// set a default MTU
|
|
|
|
if (!tun.tun_prop.mtu)
|
2022-04-28 15:18:03 +02:00
|
|
|
tun.tun_prop.mtu = TUN_MTU_DEFAULT;
|
2023-01-11 20:43:22 +01:00
|
|
|
|
2021-02-23 01:10:17 +01:00
|
|
|
// parse "dev" option
|
2023-01-11 20:43:22 +01:00
|
|
|
{
|
2021-02-23 01:10:17 +01:00
|
|
|
const Option *dev = opt.get_ptr("dev");
|
2023-01-11 20:43:22 +01:00
|
|
|
if (dev)
|
2021-02-23 01:10:17 +01:00
|
|
|
dev_name = dev->get(1, 64);
|
2023-01-11 20:43:22 +01:00
|
|
|
else
|
2021-02-23 01:10:17 +01:00
|
|
|
dev_name = "ovpnc";
|
2023-01-11 20:43:22 +01:00
|
|
|
}
|
|
|
|
|
2021-02-23 01:10:17 +01:00
|
|
|
// parse ping-restart-override
|
|
|
|
ping_restart_override = opt.get_num<decltype(ping_restart_override)>(
|
|
|
|
"ping-restart-override", 1, ping_restart_override, 0, 3600);
|
2023-01-11 20:43:22 +01:00
|
|
|
|
2021-02-23 01:10:17 +01:00
|
|
|
return TunClientFactory::Ptr(this);
|
2023-01-11 20:43:22 +01:00
|
|
|
}
|
|
|
|
|
2021-02-23 01:10:17 +01:00
|
|
|
virtual TransportClientFactory::Ptr
|
|
|
|
new_transport_factory(const DCO::TransportConfig &conf) override
|
2023-01-11 20:43:22 +01:00
|
|
|
{
|
2021-02-23 01:10:17 +01:00
|
|
|
transport = conf;
|
|
|
|
return TransportClientFactory::Ptr(this);
|
2023-01-11 20:43:22 +01:00
|
|
|
}
|
tun: add persis-tun support for dco-win
Add DcoTunPersist object to DCO::TunConfig.
DcoTunPersist stores:
- device handle
- tun settings
- adapter index/name
- pointer to TunSetup object, which itself
stores commands to undo tun settings
When intializing client options, instantiate DcoTunPersist
object within the scope of ClientConfig, which serves as
transport and tun factory for dco. Indicate that "sock" object
(device handle) should be preserved - not replaced when persisting
tun settings.
When establishing dco-win connection in OvpnDcoWinClient,
either use tun_persist created above (if persistance is enabled)
or instantiate it in-place (no persistance).
If nothing is stored in tun_persist (means this is first
connection or reconnect without persistance), acquire device
handle from tun_setup, wrap it into ASIO's basic_stream_handle
and store it in OvpnDcoWinClient - no need to persist it yet.
When starting tun, check if persisted tun session matches
to-be-created session. If no - clear previous tun settings,
set up tun and persist tun state. If device handle is already
stored in tun_persist, it won't be replaced.
On tun stop, send DEL_PEER command, which deletes peer
from the driver but keeps adapter in connected state. Then
close locally stored ASIO handle and reset tun_persist.
In case of "short term persistance" this will undo tun settings
and close device handle. For long term persistence, tun_persist
is also stored in ClientConfig and handle won't be closed yet.
In case of disconnect, ClientConfig::finalize(disconnect=true)
is called, which resets tun_persist, which in turn
undoes tun settings and closes device handle.
Signed-off-by: Lev Stipakov <lev@openvpn.net>
2022-10-04 10:27:19 +02:00
|
|
|
|
2021-02-23 01:10:17 +01:00
|
|
|
virtual TunClient::Ptr new_tun_client_obj(openvpn_io::io_context &io_context,
|
|
|
|
TunClientParent &parent,
|
|
|
|
TransportClient *transcli) override;
|
|
|
|
|
2022-04-28 15:18:03 +02:00
|
|
|
virtual TransportClient::Ptr
|
|
|
|
new_transport_client_obj(openvpn_io::io_context &io_context,
|
|
|
|
TransportClientParent *parent) override;
|
2021-02-23 01:10:17 +01:00
|
|
|
|
|
|
|
static DCO::Ptr new_controller(TunBuilderBase *tb)
|
2018-05-21 11:16:56 +02:00
|
|
|
{
|
2021-02-23 01:10:17 +01:00
|
|
|
auto ctrl = new ClientConfig();
|
|
|
|
if (ctrl)
|
|
|
|
ctrl->builder = tb;
|
|
|
|
return ctrl;
|
|
|
|
}
|
2018-05-21 11:16:56 +02:00
|
|
|
|
2021-02-23 01:10:17 +01:00
|
|
|
protected:
|
|
|
|
ClientConfig() = default;
|
|
|
|
};
|
2018-05-21 11:16:56 +02:00
|
|
|
|
2021-02-23 01:10:17 +01:00
|
|
|
class Client : public TransportClient,
|
|
|
|
public TunClient,
|
|
|
|
public AsyncResolvableUDP
|
|
|
|
{
|
|
|
|
friend class ClientConfig;
|
2019-07-03 16:18:35 +02:00
|
|
|
|
2021-02-23 01:10:17 +01:00
|
|
|
typedef RCPtr<Client> Ptr;
|
2018-05-21 11:16:56 +02:00
|
|
|
|
2021-02-23 01:10:17 +01:00
|
|
|
public:
|
|
|
|
// transport methods
|
2018-05-21 11:16:56 +02:00
|
|
|
|
2021-02-23 01:10:17 +01:00
|
|
|
virtual bool transport_send_queue_empty() override
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2018-05-21 11:16:56 +02:00
|
|
|
|
2021-02-23 01:10:17 +01:00
|
|
|
virtual bool transport_has_send_queue() override
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2018-05-21 11:16:56 +02:00
|
|
|
|
2023-08-21 15:51:50 +02:00
|
|
|
virtual size_t transport_send_queue_size() override
|
2021-02-23 01:10:17 +01:00
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
2018-05-21 11:16:56 +02:00
|
|
|
|
2021-02-23 01:10:17 +01:00
|
|
|
virtual void reset_align_adjust(const size_t align_adjust) override
|
|
|
|
{
|
|
|
|
}
|
2018-05-21 11:16:56 +02:00
|
|
|
|
2021-02-23 01:10:17 +01:00
|
|
|
virtual void transport_stop_requeueing() override
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void server_endpoint_info(std::string &host,
|
|
|
|
std::string &port,
|
|
|
|
std::string &proto,
|
|
|
|
std::string &ip_addr) const override
|
|
|
|
{
|
|
|
|
host = server_host;
|
|
|
|
port = server_port;
|
|
|
|
const IP::Addr addr = server_endpoint_addr();
|
2023-05-10 15:26:47 +02:00
|
|
|
proto = std::string(transport_protocol().str());
|
2021-02-23 01:10:17 +01:00
|
|
|
proto += "-DCO";
|
|
|
|
ip_addr = addr.to_string();
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void stop() override
|
|
|
|
{
|
|
|
|
stop_();
|
|
|
|
}
|
|
|
|
|
|
|
|
// tun methods
|
|
|
|
|
|
|
|
virtual void set_disconnect() override
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual bool
|
|
|
|
tun_send(BufferAllocated &buf) override // return true if send succeeded
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual std::string vpn_ip4() const override
|
|
|
|
{
|
|
|
|
if (state->vpn_ip4_addr.specified())
|
|
|
|
return state->vpn_ip4_addr.to_string();
|
|
|
|
else
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual std::string vpn_ip6() const override
|
|
|
|
{
|
|
|
|
if (state->vpn_ip6_addr.specified())
|
|
|
|
return state->vpn_ip6_addr.to_string();
|
|
|
|
else
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual std::string vpn_gw4() const override
|
|
|
|
{
|
|
|
|
if (state->vpn_ip4_gw.specified())
|
|
|
|
return state->vpn_ip4_gw.to_string();
|
|
|
|
else
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual std::string vpn_gw6() const override
|
|
|
|
{
|
|
|
|
if (state->vpn_ip6_gw.specified())
|
|
|
|
return state->vpn_ip6_gw.to_string();
|
|
|
|
else
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
|
2022-06-24 16:23:17 +02:00
|
|
|
int vpn_mtu() const override
|
|
|
|
{
|
|
|
|
return state->mtu;
|
|
|
|
}
|
|
|
|
|
2021-02-23 01:10:17 +01:00
|
|
|
protected:
|
|
|
|
Client(openvpn_io::io_context &io_context_arg,
|
|
|
|
ClientConfig *config_arg,
|
|
|
|
TransportClientParent *parent_arg)
|
|
|
|
: AsyncResolvableUDP(io_context_arg), io_context(io_context_arg),
|
|
|
|
halt(false), state(new TunProp::State()), config(config_arg),
|
|
|
|
transport_parent(parent_arg), tun_parent(nullptr),
|
|
|
|
peer_id(OVPN_PEER_ID_UNDEF)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void transport_reparent(TransportClientParent *parent_arg) override
|
|
|
|
{
|
|
|
|
transport_parent = parent_arg;
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void stop_() = 0;
|
|
|
|
|
|
|
|
openvpn_io::io_context &io_context;
|
|
|
|
bool halt;
|
|
|
|
|
|
|
|
TunProp::State::Ptr state;
|
|
|
|
|
|
|
|
ClientConfig::Ptr config;
|
|
|
|
TransportClientParent *transport_parent;
|
|
|
|
TunClientParent *tun_parent;
|
|
|
|
|
|
|
|
ActionList::Ptr remove_cmds;
|
|
|
|
|
|
|
|
std::string server_host;
|
|
|
|
std::string server_port;
|
|
|
|
|
|
|
|
uint32_t peer_id;
|
|
|
|
};
|
2018-05-21 11:16:56 +02:00
|
|
|
|
2020-09-29 14:18:43 +02:00
|
|
|
#ifdef ENABLE_KOVPN
|
2021-02-23 01:10:17 +01:00
|
|
|
#include <openvpn/kovpn/kovpncli.hpp>
|
2021-09-22 00:08:16 +02:00
|
|
|
inline DCO::Ptr new_controller(TunBuilderBase *)
|
|
|
|
{
|
|
|
|
return KovpnClientConfig::new_controller();
|
|
|
|
}
|
2021-02-23 01:10:17 +01:00
|
|
|
inline TransportClient::Ptr
|
|
|
|
ClientConfig::new_transport_client_obj(openvpn_io::io_context &io_context,
|
|
|
|
TransportClientParent *parent)
|
|
|
|
{
|
|
|
|
return TransportClient::Ptr(new KovpnClient(io_context, this, parent));
|
|
|
|
}
|
2020-08-21 13:15:48 +02:00
|
|
|
#elif ENABLE_OVPNDCO
|
2021-02-23 01:10:17 +01:00
|
|
|
#include <openvpn/dco/ovpndcocli.hpp>
|
2021-09-22 00:08:16 +02:00
|
|
|
inline DCO::Ptr new_controller(TunBuilderBase *tb)
|
|
|
|
{
|
|
|
|
if (!OvpnDcoClient::available(tb))
|
2021-06-17 20:42:39 +02:00
|
|
|
return nullptr;
|
2023-01-11 20:43:22 +01:00
|
|
|
|
2021-06-17 20:42:39 +02:00
|
|
|
CryptoAlgs::allow_dc_algs({CryptoAlgs::CHACHA20_POLY1305,
|
|
|
|
CryptoAlgs::AES_128_GCM,
|
|
|
|
CryptoAlgs::AES_192_GCM,
|
|
|
|
CryptoAlgs::AES_256_GCM});
|
2021-09-22 00:08:16 +02:00
|
|
|
return ClientConfig::new_controller(tb);
|
2021-05-25 05:47:32 +02:00
|
|
|
}
|
2021-02-23 01:10:17 +01:00
|
|
|
inline TransportClient::Ptr
|
|
|
|
ClientConfig::new_transport_client_obj(openvpn_io::io_context &io_context,
|
|
|
|
TransportClientParent *parent)
|
|
|
|
{
|
|
|
|
return TransportClient::Ptr(new OvpnDcoClient(io_context, this, parent));
|
|
|
|
}
|
2021-03-24 05:05:40 +01:00
|
|
|
#elif ENABLE_OVPNDCOWIN
|
|
|
|
#include <openvpn/dco/ovpndcowincli.hpp>
|
2021-09-22 00:08:16 +02:00
|
|
|
inline DCO::Ptr new_controller(TunBuilderBase *tb)
|
|
|
|
{
|
2021-06-17 20:42:39 +02:00
|
|
|
if (!OvpnDcoWinClient::available())
|
|
|
|
return nullptr;
|
2023-01-11 20:43:22 +01:00
|
|
|
|
2022-05-02 11:37:15 +02:00
|
|
|
std::list<CryptoAlgs::Type> algs{CryptoAlgs::AES_128_GCM, CryptoAlgs::AES_192_GCM, CryptoAlgs::AES_256_GCM};
|
|
|
|
BCRYPT_ALG_HANDLE h;
|
|
|
|
NTSTATUS status = BCryptOpenAlgorithmProvider(&h, L"CHACHA20_POLY1305", NULL, 0);
|
|
|
|
if (BCRYPT_SUCCESS(status))
|
|
|
|
{
|
|
|
|
BCryptCloseAlgorithmProvider(h, 0);
|
|
|
|
algs.push_back(CryptoAlgs::CHACHA20_POLY1305);
|
|
|
|
}
|
2023-01-11 20:43:22 +01:00
|
|
|
|
2022-05-02 11:37:15 +02:00
|
|
|
CryptoAlgs::allow_dc_algs(algs);
|
2021-09-22 00:08:16 +02:00
|
|
|
return ClientConfig::new_controller(nullptr);
|
2021-05-25 05:47:32 +02:00
|
|
|
}
|
2021-03-24 05:05:40 +01:00
|
|
|
inline TransportClient::Ptr
|
|
|
|
ClientConfig::new_transport_client_obj(openvpn_io::io_context &io_context,
|
|
|
|
TransportClientParent *parent)
|
|
|
|
{
|
|
|
|
return TransportClient::Ptr(new OvpnDcoWinClient(io_context, this, parent));
|
|
|
|
}
|
2020-08-21 13:15:48 +02:00
|
|
|
#endif
|
2018-05-21 11:16:56 +02:00
|
|
|
|
2021-02-23 01:10:17 +01:00
|
|
|
inline TunClient::Ptr
|
|
|
|
ClientConfig::new_tun_client_obj(openvpn_io::io_context &io_context,
|
|
|
|
TunClientParent &parent,
|
|
|
|
TransportClient *transcli)
|
|
|
|
{
|
|
|
|
Client *cli = static_cast<Client *>(transcli);
|
|
|
|
cli->tun_parent = &parent;
|
|
|
|
return TunClient::Ptr(cli);
|
2020-08-21 12:07:25 +02:00
|
|
|
}
|
2021-02-23 01:10:17 +01:00
|
|
|
} // namespace DCOTransport
|
|
|
|
} // namespace openvpn
|