mirror of
https://github.com/OpenVPN/openvpn3.git
synced 2024-09-20 04:02:15 +02:00
dco: implement new ovpn-dco logic
With the recent changes in ovpn-dco, aimed at accommodating the new multi-peer logic, userspace has to adapt as well in order to follow the expected flow. In particular we require userspace to act as following: 1) create TCP/UDP transport socket towards peer/server; 2) perform initial handshare over TCP/UDP socket 3) when handshake is complete, add peer/server to ovpn-dco kernel module via CMD_NEW_PEER by passing peer address, port and socket fd; 4) handle further control channel communication over netlink. To implement the logic above, the OvpnDcoClient has lost its "Protowrapper" template and now it basically implemente the TransportClient and TransportParent at the same time. This way, it can instantiate a TCP/UDP TransportClient internally and use it for point 1 and 2. This change greatly simplify the OvpnDcoClient itself as several operations are directly handled by the TCP/UDP TransportClient. Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
This commit is contained in:
parent
2c2fdaa7c5
commit
e30146bfb6
@ -52,12 +52,14 @@
|
||||
#endif
|
||||
|
||||
#include <openvpn/dco/korekey.hpp>
|
||||
#include <openvpn/dco/protowrapper.hpp>
|
||||
|
||||
// client-side DCO (Data Channel Offload) module for Linux/kovpn
|
||||
|
||||
namespace openvpn {
|
||||
namespace DCOTransport {
|
||||
enum {
|
||||
OVPN_PEER_ID_UNDEF = 0x00FFFFFF,
|
||||
};
|
||||
|
||||
OPENVPN_EXCEPTION(dco_error);
|
||||
|
||||
@ -165,27 +167,6 @@ namespace openvpn {
|
||||
ip_addr = addr.to_string();
|
||||
}
|
||||
|
||||
virtual IP::Addr server_endpoint_addr() const override
|
||||
{
|
||||
if (proto)
|
||||
return proto->server_endpoint_addr();
|
||||
else
|
||||
return IP::Addr();
|
||||
}
|
||||
|
||||
virtual Protocol transport_protocol() const override
|
||||
{
|
||||
switch (server_endpoint_addr().version())
|
||||
{
|
||||
case IP::Addr::V4:
|
||||
return Protocol(Protocol::UDPv4);
|
||||
case IP::Addr::V6:
|
||||
return Protocol(Protocol::UDPv6);
|
||||
default:
|
||||
return Protocol();
|
||||
}
|
||||
}
|
||||
|
||||
virtual void stop() override
|
||||
{
|
||||
stop_();
|
||||
@ -245,7 +226,7 @@ namespace openvpn {
|
||||
config(config_arg),
|
||||
transport_parent(parent_arg),
|
||||
tun_parent(nullptr),
|
||||
peer_id(-1)
|
||||
peer_id(OVPN_PEER_ID_UNDEF)
|
||||
{
|
||||
}
|
||||
|
||||
@ -254,86 +235,6 @@ namespace openvpn {
|
||||
transport_parent = parent_arg;
|
||||
}
|
||||
|
||||
void transport_start_udp()
|
||||
{
|
||||
transport_start_impl(false);
|
||||
}
|
||||
|
||||
void transport_start_tcp()
|
||||
{
|
||||
transport_start_impl(true);
|
||||
}
|
||||
|
||||
void transport_start_impl(bool tcp)
|
||||
{
|
||||
if (tcp)
|
||||
proto.reset(new TCP(io_context));
|
||||
else
|
||||
proto.reset(new UDP(io_context));
|
||||
|
||||
if (config->transport.remote_list->endpoint_available(&server_host, &server_port, nullptr))
|
||||
{
|
||||
start_connect();
|
||||
}
|
||||
else
|
||||
{
|
||||
transport_parent->transport_pre_resolve();
|
||||
async_resolve_name(server_host, server_port);
|
||||
}
|
||||
}
|
||||
|
||||
// called after DNS resolution has succeeded or failed
|
||||
void resolve_callback(const openvpn_io::error_code& error,
|
||||
openvpn_io::ip::udp::resolver::results_type results) override
|
||||
{
|
||||
if (!halt)
|
||||
{
|
||||
if (!error)
|
||||
{
|
||||
// save resolved endpoint list in remote_list
|
||||
config->transport.remote_list->set_endpoint_range(results);
|
||||
start_connect();
|
||||
}
|
||||
else
|
||||
{
|
||||
std::ostringstream os;
|
||||
os << "DNS resolve error on '" << server_host << "' for session: " << error.message();
|
||||
config->transport.stats->error(Error::RESOLVE_ERROR);
|
||||
stop_();
|
||||
transport_parent->transport_error(Error::UNDEF, os.str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void start_connect()
|
||||
{
|
||||
proto->get_endpoint(config->transport.remote_list);
|
||||
OPENVPN_LOG("Contacting " << proto->server_endpoint_addr() << " via " << proto->proto());
|
||||
transport_parent->transport_wait();
|
||||
proto->open();
|
||||
|
||||
if (config->transport.socket_protect)
|
||||
{
|
||||
if (!config->transport.socket_protect->socket_protect(proto->native_handle(), server_endpoint_addr()))
|
||||
{
|
||||
stop();
|
||||
std::ostringstream os;
|
||||
os << "socket_protect error (";
|
||||
os << proto->proto();
|
||||
os << ")";
|
||||
transport_parent->transport_error(Error::UNDEF, os.str());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
proto->async_connect([self=Ptr(this)](const openvpn_io::error_code &error) {
|
||||
self->start_impl_udp(error);
|
||||
});
|
||||
}
|
||||
|
||||
// start I/O on UDP socket
|
||||
virtual void start_impl_udp(const openvpn_io::error_code& error) = 0;
|
||||
|
||||
virtual void stop_() = 0;
|
||||
|
||||
openvpn_io::io_context& io_context;
|
||||
@ -345,14 +246,12 @@ namespace openvpn {
|
||||
TransportClientParent* transport_parent;
|
||||
TunClientParent* tun_parent;
|
||||
|
||||
ProtoBase::Ptr proto;
|
||||
|
||||
ActionList::Ptr remove_cmds;
|
||||
|
||||
std::string server_host;
|
||||
std::string server_port;
|
||||
|
||||
int peer_id;
|
||||
uint32_t peer_id;
|
||||
};
|
||||
|
||||
#ifdef ENABLE_KOVPN
|
||||
|
@ -22,10 +22,14 @@
|
||||
|
||||
// tun/transport client for ovpn-dco
|
||||
|
||||
class OvpnDcoClient : public Client, public KoRekey::Receiver {
|
||||
#include <openvpn/dco/dcocli.hpp>
|
||||
|
||||
class OvpnDcoClient : public Client, public KoRekey::Receiver, public TransportClientParent {
|
||||
friend class ClientConfig;
|
||||
friend class GeNL;
|
||||
|
||||
OPENVPN_EXCEPTION(dcocli_error);
|
||||
|
||||
typedef RCPtr<OvpnDcoClient> Ptr;
|
||||
typedef GeNL<OvpnDcoClient *> GeNLImpl;
|
||||
|
||||
@ -37,6 +41,26 @@ class OvpnDcoClient : public Client, public KoRekey::Receiver {
|
||||
public:
|
||||
virtual void tun_start(const OptionList &opt, TransportClient &transcli,
|
||||
CryptoDCSettings &dc_settings) override {
|
||||
// extract peer ID from pushed options
|
||||
try {
|
||||
const Option *o = opt.get_ptr("peer-id");
|
||||
if (o)
|
||||
{
|
||||
bool status = parse_number_validate<uint32_t>(o->get(1, 16), 16, 0, OVPN_PEER_ID_UNDEF - 1,
|
||||
&peer_id);
|
||||
if (!status)
|
||||
OPENVPN_THROW(dcocli_error, "Parse/range issue with pushed peer-id");
|
||||
}
|
||||
else
|
||||
{
|
||||
OPENVPN_THROW(dcocli_error, "No peer-id pushed by server");
|
||||
}
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
OPENVPN_THROW(dcocli_error, "Cannot extract peer-id: " << e.what());
|
||||
}
|
||||
|
||||
// notify parent
|
||||
tun_parent->tun_pre_tun_config();
|
||||
|
||||
@ -78,111 +102,135 @@ public:
|
||||
dc_settings.set_factory(CryptoDCFactory::Ptr(new KoRekey::Factory(
|
||||
dc_settings.factory(), this, config->transport.frame)));
|
||||
|
||||
// add peer in ovpn-dco
|
||||
add_peer(peer_id, state->vpn_ip4_gw.to_ipv4_zero(), state->vpn_ip6_gw.to_ipv6_zero());
|
||||
// signal that we are connected
|
||||
tun_parent->tun_connected();
|
||||
}
|
||||
|
||||
virtual std::string tun_name() const override { return "ovpn-dco"; }
|
||||
|
||||
virtual IP::Addr server_endpoint_addr() const override
|
||||
{
|
||||
if (transport)
|
||||
return transport->server_endpoint_addr();
|
||||
else
|
||||
return IP::Addr();
|
||||
}
|
||||
|
||||
virtual unsigned short server_endpoint_port() const override
|
||||
{
|
||||
if (transport)
|
||||
return transport->server_endpoint_port();
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual Protocol transport_protocol() const override
|
||||
{
|
||||
return transport->transport_protocol();
|
||||
}
|
||||
|
||||
virtual void transport_start() override {
|
||||
if (config->transport.protocol.is_udp())
|
||||
transport_start_udp();
|
||||
else if (config->transport.protocol.is_tcp())
|
||||
transport_start_tcp();
|
||||
else {
|
||||
stop();
|
||||
std::ostringstream os;
|
||||
os << "unsupported protocol: " << config->transport.protocol.str();
|
||||
transport_parent->transport_error(Error::UNDEF, os.str());
|
||||
TransportClientFactory::Ptr transport_factory;
|
||||
|
||||
if (!config->transport.protocol.is_tcp())
|
||||
{
|
||||
UDPTransport::ClientConfig::Ptr udpconf = UDPTransport::ClientConfig::new_obj();
|
||||
udpconf->remote_list = config->transport.remote_list;
|
||||
udpconf->frame = config->transport.frame;
|
||||
udpconf->stats = config->transport.stats;
|
||||
udpconf->socket_protect = config->transport.socket_protect;
|
||||
udpconf->server_addr_float = config->transport.server_addr_float;
|
||||
transport_factory = udpconf;
|
||||
}
|
||||
else
|
||||
{
|
||||
TCPTransport::ClientConfig::Ptr tcpconf = TCPTransport::ClientConfig::new_obj();
|
||||
tcpconf->remote_list = config->transport.remote_list;
|
||||
tcpconf->frame = config->transport.frame;
|
||||
tcpconf->stats = config->transport.stats;
|
||||
tcpconf->socket_protect = config->transport.socket_protect;
|
||||
transport_factory = tcpconf;
|
||||
}
|
||||
|
||||
transport = transport_factory->new_transport_client_obj(io_context, this);
|
||||
transport->transport_start();
|
||||
}
|
||||
|
||||
virtual bool transport_send_const(const Buffer &buf) override {
|
||||
if (peer_id == OVPN_PEER_ID_UNDEF)
|
||||
return transport->transport_send_const(buf);
|
||||
|
||||
return send(buf);
|
||||
}
|
||||
|
||||
virtual bool transport_send(BufferAllocated &buf) override {
|
||||
if (peer_id == OVPN_PEER_ID_UNDEF)
|
||||
return transport->transport_send(buf);
|
||||
|
||||
return send(buf);
|
||||
}
|
||||
|
||||
bool send(const Buffer &buf) {
|
||||
if (config->builder) {
|
||||
if (config->builder)
|
||||
pipe->write_some(buf.const_buffer());
|
||||
} else {
|
||||
genl->send_data(buf.c_data(), buf.size());
|
||||
}
|
||||
else
|
||||
genl->send_data(peer_id, buf.c_data(), buf.size());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void start_impl_udp(const openvpn_io::error_code &error) override {
|
||||
start_impl(error);
|
||||
void get_remote_sockaddr(struct sockaddr_storage &sa, socklen_t &salen)
|
||||
{
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
|
||||
struct sockaddr_in *sa4 = (struct sockaddr_in *)&sa;
|
||||
struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)&sa;
|
||||
|
||||
IP::Addr remote_addr = transport->server_endpoint_addr();
|
||||
if (remote_addr.version() == IP::Addr::V4) {
|
||||
salen = sizeof(*sa4);
|
||||
*sa4 = remote_addr.to_ipv4().to_sockaddr(transport->server_endpoint_port());
|
||||
} else {
|
||||
salen = sizeof(*sa6);
|
||||
*sa6 = remote_addr.to_ipv6().to_sockaddr(transport->server_endpoint_port());
|
||||
}
|
||||
}
|
||||
|
||||
void start_impl(const openvpn_io::error_code &error) {
|
||||
if (halt)
|
||||
void del_peer(uint32_t peer_id)
|
||||
{
|
||||
TunBuilderBase *tb = config->builder;
|
||||
if (tb) {
|
||||
tb->tun_builder_dco_del_peer(peer_id);
|
||||
return;
|
||||
|
||||
if (!error) {
|
||||
openvpn_io::ip::address local_addr = proto->local_address();
|
||||
openvpn_io::ip::address remote_addr = proto->remote_address();
|
||||
unsigned short local_port = proto->local_port();
|
||||
unsigned short remote_port = proto->remote_port();
|
||||
|
||||
auto conf_proto = config->transport.protocol;
|
||||
ovpn_proto p = OVPN_PROTO_UNDEF;
|
||||
if (conf_proto.is_tcp()) {
|
||||
p = conf_proto.is_ipv6() ? OVPN_PROTO_TCP6 : OVPN_PROTO_TCP4;
|
||||
} else {
|
||||
p = conf_proto.is_ipv6() ? OVPN_PROTO_UDP6 : OVPN_PROTO_UDP4;
|
||||
}
|
||||
|
||||
TunBuilderBase *tb = config->builder;
|
||||
if (tb) {
|
||||
tb->tun_builder_new();
|
||||
// pipe fd which is used to communicate to kernel
|
||||
int fd = tb->tun_builder_dco_enable(proto->native_handle(), p,
|
||||
config->dev_name);
|
||||
if (fd == -1) {
|
||||
stop_();
|
||||
transport_parent->transport_error(Error::TUN_IFACE_CREATE,
|
||||
"error creating ovpn-dco device");
|
||||
return;
|
||||
}
|
||||
pipe.reset(new openvpn_io::posix::stream_descriptor(io_context, fd));
|
||||
tb->tun_builder_dco_new_peer(local_addr.to_string(), local_port,
|
||||
remote_addr.to_string(), remote_port);
|
||||
|
||||
queue_read_pipe(nullptr);
|
||||
|
||||
transport_parent->transport_connecting();
|
||||
} else {
|
||||
std::ostringstream os;
|
||||
int res = TunNetlink::iface_new(os, config->dev_name, "ovpn-dco");
|
||||
if (res != 0) {
|
||||
stop_();
|
||||
transport_parent->transport_error(Error::TUN_IFACE_CREATE, os.str());
|
||||
} else {
|
||||
genl.reset(new GeNLImpl(
|
||||
io_context, if_nametoindex(config->dev_name.c_str()), this));
|
||||
|
||||
genl->start_vpn(proto->native_handle(), p);
|
||||
genl->register_packet();
|
||||
genl->new_peer(local_addr, local_port, remote_addr, remote_port);
|
||||
|
||||
transport_parent->transport_connecting();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
std::ostringstream os;
|
||||
os << proto->proto();
|
||||
os << " connect error on '" << server_host << ':' << server_port << "' ("
|
||||
<< proto->server_endpoint_addr() << "): " << error.message();
|
||||
config->transport.stats->error(config->transport.protocol.is_tcp()
|
||||
? Error::TCP_CONNECT_ERROR
|
||||
: Error::UDP_CONNECT_ERROR);
|
||||
stop_();
|
||||
transport_parent->transport_error(Error::UNDEF, os.str());
|
||||
}
|
||||
|
||||
genl->del_peer(peer_id);
|
||||
}
|
||||
|
||||
void add_peer(uint32_t peer_id, IPv4::Addr ipv4, IPv6::Addr ipv6)
|
||||
{
|
||||
struct sockaddr_storage sa;
|
||||
socklen_t salen;
|
||||
|
||||
get_remote_sockaddr(sa, salen);
|
||||
|
||||
TunBuilderBase *tb = config->builder;
|
||||
if (tb) {
|
||||
tb->tun_builder_dco_new_peer(peer_id, transport->native_handle(), (struct sockaddr *)&sa, salen,
|
||||
ipv4, ipv6);
|
||||
|
||||
queue_read_pipe(nullptr);
|
||||
return;
|
||||
}
|
||||
|
||||
genl->new_peer(peer_id, transport->native_handle(), (struct sockaddr *)&sa, salen, ipv4, ipv6);
|
||||
}
|
||||
|
||||
virtual void resolve_callback(const openvpn_io::error_code& error,
|
||||
openvpn_io::ip::udp::resolver::results_type results) override
|
||||
{
|
||||
}
|
||||
|
||||
virtual void stop_() override {
|
||||
@ -197,11 +245,15 @@ public:
|
||||
std::ostringstream os;
|
||||
if (genl)
|
||||
genl->stop();
|
||||
|
||||
int res = TunNetlink::iface_del(os, config->dev_name);
|
||||
if (res != 0) {
|
||||
OPENVPN_LOG("ovpndcocli: error deleting iface ovpn:" << os.str());
|
||||
}
|
||||
}
|
||||
|
||||
if (transport)
|
||||
transport->stop();
|
||||
}
|
||||
}
|
||||
|
||||
@ -229,15 +281,18 @@ public:
|
||||
break;
|
||||
|
||||
case CryptoDCInstance::NEW_SECONDARY:
|
||||
|
||||
genl->new_key(OVPN_KEY_SLOT_SECONDARY, kc);
|
||||
break;
|
||||
|
||||
case CryptoDCInstance::PRIMARY_SECONDARY_SWAP:
|
||||
genl->swap_keys();
|
||||
|
||||
genl->swap_keys(peer_id);
|
||||
break;
|
||||
|
||||
case CryptoDCInstance::DEACTIVATE_SECONDARY:
|
||||
genl->del_key(OVPN_KEY_SLOT_SECONDARY);
|
||||
|
||||
genl->del_key(peer_id, OVPN_KEY_SLOT_SECONDARY);
|
||||
break;
|
||||
|
||||
case CryptoDCInstance::DEACTIVATE_ALL:
|
||||
@ -270,11 +325,11 @@ public:
|
||||
break;
|
||||
|
||||
case CryptoDCInstance::PRIMARY_SECONDARY_SWAP:
|
||||
tb->tun_builder_dco_swap_keys();
|
||||
tb->tun_builder_dco_swap_keys(peer_id);
|
||||
break;
|
||||
|
||||
case CryptoDCInstance::DEACTIVATE_SECONDARY:
|
||||
tb->tun_builder_dco_del_key(OVPN_KEY_SLOT_SECONDARY);
|
||||
tb->tun_builder_dco_del_key(peer_id, OVPN_KEY_SLOT_SECONDARY);
|
||||
break;
|
||||
|
||||
case CryptoDCInstance::DEACTIVATE_ALL:
|
||||
@ -288,6 +343,10 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
virtual void transport_recv(BufferAllocated& buf) override {
|
||||
transport_parent->transport_recv(buf);
|
||||
}
|
||||
|
||||
bool tun_read_handler(BufferAllocated &buf) {
|
||||
if (halt)
|
||||
return false;
|
||||
@ -301,26 +360,44 @@ public:
|
||||
break;
|
||||
|
||||
case OVPN_CMD_DEL_PEER: {
|
||||
stop_();
|
||||
int8_t reason = -1;
|
||||
uint32_t peer_id;
|
||||
buf.read(&peer_id, sizeof(peer_id));
|
||||
uint8_t reason;
|
||||
buf.read(&reason, sizeof(reason));
|
||||
|
||||
std::ostringstream os;
|
||||
Error::Type err;
|
||||
|
||||
switch (reason) {
|
||||
case OVPN_DEL_PEER_REASON_EXPIRED:
|
||||
transport_parent->transport_error(Error::TRANSPORT_ERROR,
|
||||
"keepalive timeout");
|
||||
break;
|
||||
err = Error::TRANSPORT_ERROR;
|
||||
os << "keepalive timeout";
|
||||
break;
|
||||
|
||||
case OVPN_DEL_PEER_REASON_TRANSPORT_ERROR:
|
||||
transport_parent->transport_error(Error::TRANSPORT_ERROR,
|
||||
"transport error");
|
||||
break;
|
||||
err = Error::TRANSPORT_ERROR;
|
||||
os << "transport error";
|
||||
break;
|
||||
|
||||
case OVPN_DEL_PEER_REASON_TEARDOWN:
|
||||
err = Error::TRANSPORT_ERROR;
|
||||
os << "peer deleted, id=" << peer_id << ", teardown";
|
||||
break;
|
||||
|
||||
case OVPN_DEL_PEER_REASON_USERSPACE:
|
||||
// volountary delete - do not stop client
|
||||
OPENVPN_LOG("peer deleted, id=" << peer_id << ", requested by userspace");
|
||||
peer_id = OVPN_PEER_ID_UNDEF;
|
||||
return true;
|
||||
|
||||
default:
|
||||
std::ostringstream os;
|
||||
os << "peer deleted, reason " << reason;
|
||||
transport_parent->transport_error(Error::TUN_HALT, os.str());
|
||||
break;
|
||||
err = Error::TUN_HALT;
|
||||
os << "peer deleted, id=" << peer_id << ", reason=" << reason;
|
||||
break;
|
||||
}
|
||||
|
||||
stop_();
|
||||
transport_parent->transport_error(err, os.str());
|
||||
break;
|
||||
}
|
||||
|
||||
@ -339,10 +416,80 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
virtual void transport_needs_send() override {
|
||||
transport_parent->transport_needs_send();
|
||||
}
|
||||
|
||||
virtual void transport_error(const Error::Type fatal_err, const std::string& err_text) override {
|
||||
transport_parent->transport_error(fatal_err, err_text);
|
||||
}
|
||||
|
||||
virtual void proxy_error(const Error::Type fatal_err, const std::string& err_text) override {
|
||||
transport_parent->proxy_error(fatal_err, err_text);
|
||||
}
|
||||
|
||||
virtual bool transport_is_openvpn_protocol() override {
|
||||
return transport_parent->transport_is_openvpn_protocol();
|
||||
}
|
||||
|
||||
virtual void transport_pre_resolve() override {
|
||||
transport_parent->transport_pre_resolve();
|
||||
}
|
||||
|
||||
virtual void transport_wait_proxy() override {
|
||||
transport_parent->transport_wait_proxy();
|
||||
}
|
||||
|
||||
virtual void transport_wait() override {
|
||||
transport_parent->transport_wait();
|
||||
}
|
||||
|
||||
virtual void transport_connecting() override {
|
||||
transport_parent->transport_connecting();
|
||||
}
|
||||
|
||||
virtual bool is_keepalive_enabled() const override {
|
||||
return transport_parent->is_keepalive_enabled();
|
||||
}
|
||||
|
||||
virtual void disable_keepalive(unsigned int& keepalive_ping,
|
||||
unsigned int &keepalive_timeout) override {
|
||||
transport_parent->disable_keepalive(keepalive_ping, keepalive_timeout);
|
||||
}
|
||||
|
||||
private:
|
||||
OvpnDcoClient(openvpn_io::io_context &io_context_arg,
|
||||
ClientConfig *config_arg, TransportClientParent *parent_arg)
|
||||
: Client(io_context_arg, config_arg, parent_arg) {}
|
||||
: Client(io_context_arg, config_arg, parent_arg)
|
||||
{
|
||||
TunBuilderBase *tb = config->builder;
|
||||
if (tb) {
|
||||
tb->tun_builder_new();
|
||||
// pipe fd which is used to communicate to kernel
|
||||
int fd = tb->tun_builder_dco_enable(config->dev_name);
|
||||
if (fd == -1) {
|
||||
stop_();
|
||||
transport_parent->transport_error(Error::TUN_IFACE_CREATE,
|
||||
"error creating ovpn-dco device");
|
||||
return;
|
||||
}
|
||||
|
||||
pipe.reset(new openvpn_io::posix::stream_descriptor(io_context, fd));
|
||||
return;
|
||||
}
|
||||
|
||||
std::ostringstream os;
|
||||
int res = TunNetlink::iface_new(os, config->dev_name, "ovpn-dco");
|
||||
if (res != 0) {
|
||||
stop_();
|
||||
transport_parent->transport_error(Error::TUN_IFACE_CREATE, os.str());
|
||||
return;
|
||||
}
|
||||
|
||||
genl.reset(new GeNLImpl(io_context_arg, if_nametoindex(config_arg->dev_name.c_str()), this));
|
||||
genl->register_packet();
|
||||
}
|
||||
|
||||
void handle_keepalive() {
|
||||
// since userspace doesn't know anything about presense or
|
||||
@ -363,11 +510,11 @@ private:
|
||||
keepalive_timeout = config->ping_restart_override;
|
||||
|
||||
if (config->builder) {
|
||||
config->builder->tun_builder_dco_set_peer(keepalive_interval,
|
||||
config->builder->tun_builder_dco_set_peer(peer_id, keepalive_interval,
|
||||
keepalive_timeout);
|
||||
} else {
|
||||
// enable keepalive in kernel
|
||||
genl->set_peer(keepalive_interval, keepalive_timeout);
|
||||
genl->set_peer(peer_id, keepalive_interval, keepalive_timeout);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -404,4 +551,5 @@ private:
|
||||
std::unique_ptr<openvpn_io::posix::stream_descriptor> pipe;
|
||||
|
||||
GeNLImpl::Ptr genl;
|
||||
};
|
||||
TransportClient::Ptr transport;
|
||||
};
|
||||
|
@ -1,106 +0,0 @@
|
||||
// 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.
|
||||
//
|
||||
// Copyright (C) 2012-2020 OpenVPN Inc.
|
||||
//
|
||||
// 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/>.
|
||||
|
||||
namespace openvpn {
|
||||
namespace DCOTransport {
|
||||
class ProtoBase : public virtual RC<thread_unsafe_refcount> {
|
||||
public:
|
||||
typedef RCPtr<ProtoBase> Ptr;
|
||||
|
||||
virtual IP::Addr server_endpoint_addr() const = 0;
|
||||
virtual void close() = 0;
|
||||
virtual void get_endpoint(RemoteList::Ptr remote_list) = 0;
|
||||
virtual void open() = 0;
|
||||
virtual const char *proto() = 0;
|
||||
virtual int native_handle() = 0;
|
||||
virtual void
|
||||
async_connect(std::function<void(const openvpn_io::error_code &)>&&) = 0;
|
||||
virtual openvpn_io::ip::address local_address() = 0;
|
||||
virtual openvpn_io::ip::address remote_address() = 0;
|
||||
virtual unsigned short local_port() = 0;
|
||||
virtual unsigned short remote_port() = 0;
|
||||
};
|
||||
|
||||
template <class ENDPOINT, class SOCKET> class ProtoImpl : public ProtoBase {
|
||||
public:
|
||||
explicit ProtoImpl(openvpn_io::io_context &io_context)
|
||||
: resolver(io_context), socket(io_context) {}
|
||||
|
||||
virtual IP::Addr server_endpoint_addr() const override {
|
||||
return IP::Addr::from_asio(server_endpoint.address());
|
||||
}
|
||||
|
||||
virtual void close() override {
|
||||
socket.close();
|
||||
resolver.cancel();
|
||||
}
|
||||
|
||||
virtual void get_endpoint(RemoteList::Ptr remote_list) override {
|
||||
remote_list->get_endpoint(server_endpoint);
|
||||
}
|
||||
|
||||
virtual void open() override { socket.open(server_endpoint.protocol()); }
|
||||
|
||||
virtual const char *proto() override { return "UDP"; }
|
||||
|
||||
virtual int native_handle() override { return socket.native_handle(); }
|
||||
|
||||
virtual void async_connect(
|
||||
std::function<void(const openvpn_io::error_code &)>&& func) override {
|
||||
socket.async_connect(server_endpoint, func);
|
||||
}
|
||||
|
||||
virtual openvpn_io::ip::address local_address() override {
|
||||
return socket.local_endpoint().address();
|
||||
}
|
||||
|
||||
virtual openvpn_io::ip::address remote_address() override {
|
||||
return socket.remote_endpoint().address();
|
||||
}
|
||||
|
||||
virtual unsigned short local_port() override {
|
||||
return socket.local_endpoint().port();
|
||||
}
|
||||
|
||||
virtual unsigned short remote_port() override {
|
||||
return socket.remote_endpoint().port();
|
||||
}
|
||||
|
||||
protected:
|
||||
openvpn_io::ip::udp::resolver resolver;
|
||||
SOCKET socket;
|
||||
ENDPOINT server_endpoint;
|
||||
};
|
||||
|
||||
class UDP : public ProtoImpl<UDPTransport::AsioEndpoint,
|
||||
openvpn_io::ip::udp::socket> {
|
||||
public:
|
||||
explicit UDP(openvpn_io::io_context &io_context) : ProtoImpl(io_context) {}
|
||||
};
|
||||
|
||||
class TCP : public ProtoImpl<openvpn_io::ip::tcp::endpoint,
|
||||
openvpn_io::ip::tcp::socket> {
|
||||
public:
|
||||
explicit TCP(openvpn_io::io_context &io_context) : ProtoImpl(io_context) {}
|
||||
};
|
||||
|
||||
} // namespace DCOTransport
|
||||
} // namespace openvpn
|
Loading…
Reference in New Issue
Block a user