Files

166 lines
5.5 KiB
C++

// 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-2017 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/>.
// Create a special transport factory that persists an existing
// transport client. This is used to preserve the transport
// socket when other client components are restarted after
// a RELAY message is received from the server.
#ifndef OPENVPN_TRANSPORT_CLIENT_RELAY_H
#define OPENVPN_TRANSPORT_CLIENT_RELAY_H
#include <memory>
#include <openvpn/transport/client/transbase.hpp>
namespace openvpn {
class TransportRelayFactory : public TransportClientFactory
{
public:
TransportRelayFactory(openvpn_io::io_context& io_context,
TransportClient::Ptr transport,
TransportClientParent* old_parent)
: io_context_(io_context),
transport_(std::move(transport)),
null_parent_(new NullParent(old_parent))
{
// Temporarily point transport to our null parent
transport_->transport_reparent(null_parent_.get());
}
class TransportClientNull : public TransportClient
{
public:
TransportClientNull(TransportClient* old)
: endpoint_(old->server_endpoint_addr()),
protocol_(old->transport_protocol())
{
old->server_endpoint_info(host_, port_, proto_, ip_addr_);
}
private:
virtual void transport_start() {}
virtual void stop() {}
virtual bool transport_send_const(const Buffer& buf) { return false; }
virtual bool transport_send(BufferAllocated& buf) { return false; }
virtual bool transport_send_queue_empty() { return false; }
virtual bool transport_has_send_queue() { return false; }
virtual unsigned int transport_send_queue_size() { return 0; }
virtual void transport_stop_requeueing() { }
virtual void reset_align_adjust(const size_t align_adjust) {}
virtual void transport_reparent(TransportClientParent* parent) {}
virtual IP::Addr server_endpoint_addr() const
{
return endpoint_;
}
virtual Protocol transport_protocol() const
{
return protocol_;
}
virtual void server_endpoint_info(std::string& host, std::string& port, std::string& proto, std::string& ip_addr) const
{
host = host_;
port = port_;
proto = proto_;
ip_addr = ip_addr_;
}
IP::Addr endpoint_;
Protocol protocol_;
std::string host_;
std::string port_;
std::string proto_;
std::string ip_addr_;
};
private:
class NullParent : public TransportClientParent
{
public:
NullParent(TransportClientParent* old_parent)
: is_openvpn_protocol(old_parent->transport_is_openvpn_protocol())
{
}
private:
virtual void transport_recv(BufferAllocated& buf) {}
virtual void transport_needs_send() {}
virtual void transport_error(const Error::Type fatal_err, const std::string& err_text)
{
OPENVPN_LOG("TransportRelayFactory: Transport Error in null parent: " << Error::name(fatal_err) << " : " << err_text);
}
virtual void proxy_error(const Error::Type fatal_err, const std::string& err_text)
{
OPENVPN_LOG("TransportRelayFactory: Proxy Error in null parent: " << Error::name(fatal_err) << " : " << err_text);
}
// Return true if we are transporting OpenVPN protocol
virtual bool transport_is_openvpn_protocol() { return is_openvpn_protocol; }
// progress notifications
virtual void transport_pre_resolve() {}
virtual void transport_wait_proxy() {}
virtual void transport_wait() {}
virtual void transport_connecting() {}
// Return true if keepalive parameter(s) are enabled.
virtual bool is_keepalive_enabled() const { return false; }
// Disable keepalive for rest of session, but fetch
// the keepalive parameters (in seconds).
virtual void disable_keepalive(unsigned int& keepalive_ping, unsigned int& keepalive_timeout)
{
keepalive_ping = 0;
keepalive_timeout = 0;
}
bool is_openvpn_protocol;
};
virtual TransportClient::Ptr new_transport_client_obj(openvpn_io::io_context& io_context,
TransportClientParent* parent) override
{
// io_context MUST stay consistent
if (&io_context != &io_context_)
throw Exception("TransportRelayFactory: inconsistent io_context");
transport_->transport_reparent(parent);
return transport_;
}
virtual bool is_relay() override
{
return true;
}
openvpn_io::io_context& io_context_; // only used to verify consistency
TransportClient::Ptr transport_; // the persisted transport
std::unique_ptr<TransportClientParent> null_parent_; // placeholder for TransportClient parent before reparenting
};
}
#endif