Files
OpenVPNAdapter/openvpn/tun/tunio.hpp
T
Sergey Abramchuk 84ad2a289f Squashed 'OpenVPN Adapter/Vendors/openvpn/' changes from 098fd412a..e6d68831a
e6d68831a deps: update mbedTLS to 2.7.0
59de63fa6 cli.cpp: added OPENVPN_REMOTE_OVERRIDE
caf9cf6c1 RedirectPipe: added additional flags for flexibility
68595de4d ClientAPI::RemoteOverride: added error status
37d848ca2 Log lines from C++ exceptions should contain the text "exception"
f05802cf9 Increase server validation of password size to 16KB to support bundling SAML messages.
52e4d4a5f Increase client validation of password/response size to 16KB to support bundling SAML messages.
a0416ed92 [OVPN3-209] win: add dependencies checksum verification
f6eadbc4d [OVPN3-206] Refactor Windows build system
7b30c2f12 [OVPN3-220] proto.hpp: send initial options set on rekeying
33dd2f29e mbedtls: backport fixes for CVE-2018-0487
0912a9b62 [OVPN3-213] build system: mbedtls timing tests
98fa55576 deps: update asio to 1.12.0
620531101 [OVPN3-215] asio: apply external patches
f4a73bde5 [OVPN3-215] asio: rebase external patches on top of our current commit ID
a61cac928 mbedtls: Patches from 2.7 to fix timing test failures
c892f41fb win: tune dependencies build
8a394a37d [OVPN3-213] build system: mbedtls timing tests
0a3dd67da [OVPN3-190] tun linux: add to/from_json methods
44c6cdfdc [OVPN3-206] readme: update Windows build instructions
0edec4a09 [OVPN3-206] win: update directories in VS projects
3d6fd62cb mac build: improve unittest stability
758ae98c6 [OVPN3-209] win: add dependencies checksum verification
a7642ee82 [OVPN3-205] win: apply mbedTLS patches
ac94b6eb7 [OVPN3-206] Refactor Windows build system
c5bc3859e mbedTLS: don't set endpoint twice in conf object
3d5dd9ee3 [OVPN3-199] mac build: do not overwrite DEP_DIR
b713762ba mbedtls: Patches from 2.7 to fix timing test failures
37ab79fa6 tun linux: apply changes from 362acf0
6a7aee2c9 [OVPN3-190] tun: implement persistence
1d2ebb07f [OVPN3-190] tun: move tun creation to separate class
53e33d634 [OVPN3-190] tun: move content of tun to tuncli
85d3377c2 [OVPN3-190] tun: move tun setup methods to separate file
735b985eb i/o layer:  wrap raw pointers embedded in closures
322ae24b5 OptionList: support variadic template parameter pack in constructors
8a012b454 lz4: added namespace and improved error handling
34998e94a zlib: removed verbose parameter
846ed217d OpenSSL: set SSL_MODE_RELEASE_BUFFERS to conserve memory by releasing unneeded buffers
32e3ea117 OptionList: added show_unused_options() method
fe38233a8 Buffer: added typedefs for thread-safe refcounts
b34b6271e compression: added compress_lz4() and decompress_lz4()
755e1a181 linux/core.hpp: added exclude_from_core() function
a7f6fe64f ManClientInstance::Send: added userprop_local_update() virtual method
94526ac19 BufferAllocated: fixed regression in buffer copy
33c16812e [OVPN3-144] mbedTLS: fix support for 4096bit encrypted keys
f249ab4bd [OVPN3-144] build-mbedtls: run make check before compiling
5040aef4c [OVPN3-144] build-mbedtls: apply patches using git-apply instead of patch
8a5e838ab [OVPN3-144] mbedTLS: fix incompatibility with PKI created by OpenSSL 1.1
e7badefd7 proto.hpp/tls-crypt: fix access to ACK IDs during packet validation
73fa974db proto.hpp: print buffer exception in case of packet access error
79ad5eded Estblishing a stable branch
1c5f20ab0 Hide the @ sign in logs if username is empty
01ee1f5a4 Added ClientAPI::Config::retryOnAuthFailed parameter
05880b136 Added ProfileParseLimits::MAX_SERVER_LIST_SIZE and raise limit to 4096
eedee4fa6 cli.cpp: allow -s server override to reference a friendly name
6e350e9f9 Linux tun setup: use LinuxGW46 to obtain gateway info
3e044c6c7 top-level .gitignore was missing a trailing newline
a27355ac7 Use C++11 push_back(std::move(...))) for pushing objects onto vectors
8c3af2704 HostPort::split_host_port: support unix socket filename as an alternative kind of host
14b588c86 asio: added asio_resolver_results_to_string()
fd6e8e9bf AsioPolySock: minor changes to remote_endpoint_str()
06f5e4d71 AsioBoundSocket::Socket: added to_string() method
8fd968532 RemoteList: minor cleanup in set_endpoint_range()
f9fc2f54e BufferAllocated: improve movability
8cb8d52cd string: added first_line() method
a26b1646b AsioPolySock: extend AltRouting support
ef3a40c27 Listen::Item: added AltRouting mode
02e786bc9 write_binary_atomic: support ConstBuffer
6745799c9 fileunix: added read_binary_unix_fast()
5689c2d9c write_binary_unix(): added ConstBuffer variant
2b0e76453 enum_dir: refactor to allow enumeration via lambda
116a5bd5e bufstr: added const_buf_from_string() method
f8ec81413 Buffer: added const_buffer_ref() variant accepting a const argument
ae98aa8b6 AsioPolySock: support AltRouting
8f81479f1 AsioBoundSocket::Socket: support inheritance
9598918e9 ServerProto: added schedule_disconnect() method.
4516cf67b ServerProto: reset CoarseTime object when AsioTimer is canceled
0ffc76a0b Route: implement operator< so Route objects can be used as map/set keys.
c4af9f68b event_loop_wait_barrier: raise default timeout to 30 seconds
d7fe87540 appversion.hpp: rename VERSION -> BUILD_VERSION

git-subtree-dir: OpenVPN Adapter/Vendors/openvpn
git-subtree-split: e6d68831a71131b7d92fbea93d3b9cbe10ba2068
2018-04-04 12:34:20 +03:00

276 lines
6.9 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/>.
// Low level tun device I/O class for all platforms (Unix and Windows)
#ifndef OPENVPN_TUN_TUNIO_H
#define OPENVPN_TUN_TUNIO_H
#include <openvpn/io/io.hpp>
#include <openvpn/common/size.hpp>
#include <openvpn/common/rc.hpp>
#include <openvpn/frame/frame.hpp>
#include <openvpn/ip/ip.hpp>
#include <openvpn/common/socktypes.hpp>
#include <openvpn/log/sessionstats.hpp>
#include <openvpn/tun/tunlog.hpp>
namespace openvpn {
template <typename ReadHandler, typename PacketFrom, typename STREAM>
class TunIO : public RC<thread_unsafe_refcount>
{
public:
typedef RCPtr<TunIO> Ptr;
TunIO(ReadHandler read_handler_arg,
const Frame::Ptr& frame_arg,
const SessionStats::Ptr& stats_arg)
: stream(nullptr),
retain_stream(false),
tun_prefix(false),
halt(false),
read_handler(read_handler_arg),
frame(frame_arg),
frame_context((*frame_arg)[Frame::READ_TUN]),
stats(stats_arg)
{
}
virtual ~TunIO()
{
//OPENVPN_LOG("**** TUNIO destruct");
stop();
delete stream;
}
bool write(Buffer& buf)
{
if (!halt)
{
try {
// handle tun packet prefix, if enabled
if (tun_prefix)
{
if (buf.offset() >= 4 && buf.size() >= 1)
{
switch (IPHeader::version(buf[0]))
{
case 4:
prepend_pf_inet(buf, PF_INET);
break;
case 6:
prepend_pf_inet(buf, PF_INET6);
break;
default:
OPENVPN_LOG_TUN_ERROR("TUN write error: cannot identify IP version for prefix");
tun_error(Error::TUN_FRAMING_ERROR, nullptr);
return false;
}
}
else
{
OPENVPN_LOG_TUN_ERROR("TUN write error: cannot write prefix");
tun_error(Error::TUN_FRAMING_ERROR, nullptr);
return false;
}
}
// write data to tun device
const size_t wrote = stream->write_some(buf.const_buffer());
if (stats)
{
stats->inc_stat(SessionStats::TUN_BYTES_OUT, wrote);
stats->inc_stat(SessionStats::TUN_PACKETS_OUT, 1);
}
if (wrote == buf.size())
return true;
else
{
OPENVPN_LOG_TUN_ERROR("TUN partial write error");
tun_error(Error::TUN_WRITE_ERROR, nullptr);
return false;
}
}
catch (openvpn_io::system_error& e)
{
OPENVPN_LOG_TUN_ERROR("TUN write exception: " << e.what());
tun_error(Error::TUN_WRITE_ERROR, &e.code());
return false;
}
}
else
return false;
}
template <class BUFSEQ>
bool write_seq(const BUFSEQ& bs)
{
if (!halt)
{
try {
// write data to tun device
const size_t wrote = stream->write_some(bs);
if (stats)
{
stats->inc_stat(SessionStats::TUN_BYTES_OUT, wrote);
stats->inc_stat(SessionStats::TUN_PACKETS_OUT, 1);
}
if (wrote == bs.size())
return true;
else
{
OPENVPN_LOG_TUN_ERROR("TUN partial write error");
tun_error(Error::TUN_WRITE_ERROR, nullptr);
return false;
}
}
catch (openvpn_io::system_error& e)
{
OPENVPN_LOG_TUN_ERROR("TUN write exception: " << e.what());
tun_error(Error::TUN_WRITE_ERROR, &e.code());
return false;
}
}
else
return false;
}
void start(const int n_parallel)
{
if (!halt)
{
for (int i = 0; i < n_parallel; i++)
queue_read(nullptr);
}
}
// must be called by derived class destructor
void stop()
{
if (!halt)
{
halt = true;
if (stream)
{
stream->cancel();
if (!retain_stream)
{
//OPENVPN_LOG("**** TUNIO close");
stream->close();
}
else
stream->release();
}
}
}
std::string name() const
{
return name_;
}
private:
void prepend_pf_inet(Buffer& buf, const std::uint32_t value)
{
const std::uint32_t net_value = htonl(value);
buf.prepend((unsigned char *)&net_value, sizeof(net_value));
}
protected:
void queue_read(PacketFrom *tunfrom)
{
OPENVPN_LOG_TUN_VERBOSE("TunIO::queue_read");
if (!tunfrom)
tunfrom = new PacketFrom();
frame_context.prepare(tunfrom->buf);
// queue read on tun device
stream->async_read_some(frame_context.mutable_buffer(tunfrom->buf),
[self=Ptr(this), tunfrom=typename PacketFrom::SPtr(tunfrom)](const openvpn_io::error_code& error, const size_t bytes_recvd) mutable
{
self->handle_read(std::move(tunfrom), error, bytes_recvd);
});
}
void handle_read(typename PacketFrom::SPtr pfp, const openvpn_io::error_code& error, const size_t bytes_recvd)
{
OPENVPN_LOG_TUN_VERBOSE("TunIO::handle_read: " << error.message());
if (!halt)
{
if (!error)
{
pfp->buf.set_size(bytes_recvd);
if (stats)
{
stats->inc_stat(SessionStats::TUN_BYTES_IN, bytes_recvd);
stats->inc_stat(SessionStats::TUN_PACKETS_IN, 1);
}
if (!tun_prefix)
{
read_handler->tun_read_handler(pfp);
}
else if (pfp->buf.size() >= 4)
{
// handle tun packet prefix, if enabled
pfp->buf.advance(4);
read_handler->tun_read_handler(pfp);
}
else
{
OPENVPN_LOG_TUN_ERROR("TUN Read Error: cannot read prefix");
tun_error(Error::TUN_READ_ERROR, nullptr);
}
}
else
{
OPENVPN_LOG_TUN_ERROR("TUN Read Error: " << error.message());
tun_error(Error::TUN_READ_ERROR, &error);
}
if (!halt)
queue_read(pfp.release()); // reuse buffer if still available
}
}
void tun_error(const Error::Type errtype, const openvpn_io::error_code* error)
{
if (stats)
stats->error(errtype);
read_handler->tun_error_handler(errtype, error);
}
// should be set by derived class constructor
std::string name_;
STREAM *stream;
bool retain_stream; // don't close tun stream
bool tun_prefix;
bool halt;
ReadHandler read_handler;
const Frame::Ptr frame;
const Frame::Context& frame_context;
SessionStats::Ptr stats;
};
}
#endif