mirror of
https://github.com/deneraraujo/OpenVPNAdapter.git
synced 2026-04-24 00:00:05 +08:00
Merge commit '86cc97e55fe346502462284d2e636a2b3708163e' as 'Sources/OpenVPN3'
This commit is contained in:
@@ -0,0 +1,172 @@
|
||||
// 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/>.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
#include <openvpn/buffer/bufhex.hpp>
|
||||
#include <openvpn/common/rc.hpp>
|
||||
#include <openvpn/win/scoped_handle.hpp>
|
||||
#include <openvpn/win/event.hpp>
|
||||
|
||||
#define TUN_IOCTL_REGISTER_RINGS CTL_CODE(51820U, 0x970U, METHOD_BUFFERED, FILE_READ_DATA | FILE_WRITE_DATA)
|
||||
#define TUN_IOCTL_FORCE_CLOSE_HANDLES CTL_CODE(51820U, 0x971U, METHOD_NEITHER, FILE_READ_DATA | FILE_WRITE_DATA)
|
||||
|
||||
#define WINTUN_RING_CAPACITY 0x800000
|
||||
#define WINTUN_RING_TRAILING_BYTES 0x10000
|
||||
#define WINTUN_RING_FRAMING_SIZE 12
|
||||
#define WINTUN_MAX_PACKET_SIZE 0xffff
|
||||
#define WINTUN_PACKET_ALIGN 4
|
||||
|
||||
namespace openvpn
|
||||
{
|
||||
namespace TunWin
|
||||
{
|
||||
struct TUN_RING {
|
||||
std::atomic_ulong head;
|
||||
std::atomic_ulong tail;
|
||||
std::atomic_long alertable;
|
||||
UCHAR data[WINTUN_RING_CAPACITY + WINTUN_RING_TRAILING_BYTES + WINTUN_RING_FRAMING_SIZE];
|
||||
};
|
||||
|
||||
struct TUN_REGISTER_RINGS
|
||||
{
|
||||
struct
|
||||
{
|
||||
ULONG ring_size;
|
||||
TUN_RING* ring;
|
||||
HANDLE tail_moved;
|
||||
} send, receive;
|
||||
};
|
||||
|
||||
typedef openvpn_io::windows::object_handle AsioEvent;
|
||||
|
||||
class RingBuffer : public RC<thread_unsafe_refcount>
|
||||
{
|
||||
public:
|
||||
typedef RCPtr<RingBuffer> Ptr;
|
||||
|
||||
RingBuffer(openvpn_io::io_context& io_context)
|
||||
: send_ring_hmem(CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(TUN_RING), NULL)),
|
||||
receive_ring_hmem(CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(TUN_RING), NULL)),
|
||||
send_tail_moved_asio_event_(io_context)
|
||||
{
|
||||
// sanity checks
|
||||
static_assert((sizeof(TUN_RING) - sizeof(TUN_RING::data)) == 12, "sizeof(TUN_RING) is expected to be 12");
|
||||
#if !defined(ATOMIC_LONG_LOCK_FREE) || (ATOMIC_LONG_LOCK_FREE != 2)
|
||||
#error Atomic long is expected to be always lock-free
|
||||
#endif
|
||||
|
||||
send_ring_ = (TUN_RING*)MapViewOfFile(send_ring_hmem(), FILE_MAP_ALL_ACCESS, 0, 0, sizeof(TUN_RING));
|
||||
receive_ring_ = (TUN_RING*)MapViewOfFile(receive_ring_hmem(), FILE_MAP_ALL_ACCESS, 0, 0, sizeof(TUN_RING));
|
||||
send_tail_moved_asio_event_.assign(send_ring_tail_moved_());
|
||||
}
|
||||
|
||||
RingBuffer(openvpn_io::io_context& io_context,
|
||||
HANDLE client_process,
|
||||
const std::string& send_ring_hmem_hex,
|
||||
const std::string& receive_ring_hmem_hex,
|
||||
const std::string& send_ring_tail_moved_hex,
|
||||
const std::string& receive_ring_tail_moved_hex)
|
||||
: send_tail_moved_asio_event_(io_context)
|
||||
{
|
||||
HANDLE remote_handle = BufHex::parse<HANDLE>(send_ring_hmem_hex, "send_ring_hmem");
|
||||
HANDLE handle;
|
||||
DuplicateHandle(client_process, remote_handle, GetCurrentProcess(), &handle, 0, FALSE, DUPLICATE_SAME_ACCESS);
|
||||
send_ring_hmem.reset(handle);
|
||||
|
||||
remote_handle = BufHex::parse<HANDLE>(receive_ring_hmem_hex, "receive_ring_hmem");
|
||||
DuplicateHandle(client_process, remote_handle, GetCurrentProcess(), &handle, 0, FALSE, DUPLICATE_SAME_ACCESS);
|
||||
receive_ring_hmem.reset(handle);
|
||||
|
||||
remote_handle = BufHex::parse<HANDLE>(send_ring_tail_moved_hex, "send_ring_tail_moved");
|
||||
DuplicateHandle(client_process, remote_handle, GetCurrentProcess(), &handle, 0, FALSE, DUPLICATE_SAME_ACCESS);
|
||||
send_ring_tail_moved_.reset(handle);
|
||||
|
||||
remote_handle = BufHex::parse<HANDLE>(receive_ring_tail_moved_hex, "receive_ring_tail_moved");
|
||||
DuplicateHandle(client_process, remote_handle, GetCurrentProcess(), &handle, 0, FALSE, DUPLICATE_SAME_ACCESS);
|
||||
receive_ring_tail_moved_.reset(handle);
|
||||
|
||||
send_ring_ = (TUN_RING*)MapViewOfFile(send_ring_hmem(), FILE_MAP_ALL_ACCESS, 0, 0, sizeof(TUN_RING));
|
||||
receive_ring_ = (TUN_RING*)MapViewOfFile(receive_ring_hmem(), FILE_MAP_ALL_ACCESS, 0, 0, sizeof(TUN_RING));
|
||||
}
|
||||
|
||||
RingBuffer(RingBuffer const&) = delete;
|
||||
RingBuffer& operator=(RingBuffer const&) = delete;
|
||||
|
||||
~RingBuffer()
|
||||
{
|
||||
UnmapViewOfFile(send_ring_);
|
||||
UnmapViewOfFile(receive_ring_);
|
||||
}
|
||||
|
||||
HANDLE send_ring_tail_moved()
|
||||
{
|
||||
return send_ring_tail_moved_();
|
||||
}
|
||||
|
||||
HANDLE receive_ring_tail_moved()
|
||||
{
|
||||
return receive_ring_tail_moved_();
|
||||
}
|
||||
|
||||
TUN_RING* send_ring()
|
||||
{
|
||||
return send_ring_;
|
||||
}
|
||||
|
||||
TUN_RING* receive_ring()
|
||||
{
|
||||
return receive_ring_;
|
||||
}
|
||||
|
||||
AsioEvent& send_tail_moved_asio_event()
|
||||
{
|
||||
return send_tail_moved_asio_event_;
|
||||
}
|
||||
|
||||
#ifdef HAVE_JSON
|
||||
void serialize(Json::Value& json)
|
||||
{
|
||||
json["send_ring_hmem"] = BufHex::render(send_ring_hmem());
|
||||
json["receive_ring_hmem"] = BufHex::render(receive_ring_hmem());
|
||||
json["send_ring_tail_moved"] = BufHex::render(send_ring_tail_moved());
|
||||
json["receive_ring_tail_moved"] = BufHex::render(receive_ring_tail_moved());
|
||||
}
|
||||
#endif
|
||||
|
||||
protected:
|
||||
Win::ScopedHANDLE send_ring_hmem;
|
||||
Win::ScopedHANDLE receive_ring_hmem;
|
||||
Win::Event send_ring_tail_moved_{FALSE};
|
||||
Win::Event receive_ring_tail_moved_{FALSE};
|
||||
AsioEvent send_tail_moved_asio_event_;
|
||||
|
||||
TUN_RING* send_ring_ = nullptr;
|
||||
TUN_RING* receive_ring_ = nullptr;
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user