Merge commit '9b95600d069b5477fb0a091ffb9a51500c73c87d' into feature/update-dependencies

This commit is contained in:
Sergey Abramchuk
2017-04-15 11:59:39 +03:00
39 changed files with 773 additions and 223 deletions
@@ -26,13 +26,11 @@
#include <iostream>
#include <sstream>
#include <algorithm>
#include <utility>
#include <exception>
#include <CoreFoundation/CoreFoundation.h>
#include <openvpn/common/size.hpp>
#include <openvpn/common/exception.hpp>
#include <openvpn/buffer/buffer.hpp>
// Wrapper classes for Apple Core Foundation objects.
#define OPENVPN_CF_WRAP(cls, castmeth, cftype, idmeth) \
@@ -52,7 +50,7 @@
{ \
CFTypeRef o = Type<cftype>::cast(obj); \
if (o) \
return cls(cftype(o), BORROW); \
return cls(cftype(o), GET); \
else \
return cls(); \
}
@@ -60,9 +58,9 @@
namespace openvpn {
namespace CF
{
enum Own {
OWN,
BORROW
enum Rule {
CREATE, // create rule
GET // get rule
};
template <typename T> struct Type {};
@@ -73,10 +71,9 @@ namespace openvpn {
public:
Wrap() : obj_(nullptr) {}
// Set own=BORROW if we don't currently own the object
explicit Wrap(T obj, const Own own=OWN)
explicit Wrap(T obj, const Rule rule=CREATE)
{
if (own == BORROW && obj)
if (rule == GET && obj)
CFRetain(obj);
obj_ = obj;
}
@@ -118,9 +115,9 @@ namespace openvpn {
std::swap(obj_, other.obj_);
}
void reset(T obj=nullptr, const Own own=OWN)
void reset(T obj=nullptr, const Rule rule=CREATE)
{
if (own == BORROW && obj)
if (rule == GET && obj)
CFRetain(obj);
if (obj_)
CFRelease(obj_);
@@ -129,15 +126,20 @@ namespace openvpn {
bool defined() const { return obj_ != nullptr; }
explicit operator bool() const noexcept
{
return defined();
}
T operator()() const { return obj_; }
CFTypeRef generic() const { return (CFTypeRef)obj_; }
static T cast(CFTypeRef obj) { return T(Type<T>::cast(obj)); }
static Wrap from_generic(CFTypeRef obj, const Own own=OWN)
static Wrap from_generic(CFTypeRef obj, const Rule rule=CREATE)
{
return Wrap(cast(obj), own);
return Wrap(cast(obj), rule);
}
T release()
@@ -155,7 +157,7 @@ namespace openvpn {
}
// Intended for use with Core Foundation methods that require
// a T* for saving a (non-borrowed) return value
// a T* for saving a create-rule return value
T* mod_ref()
{
if (obj_)
@@ -181,14 +183,11 @@ namespace openvpn {
}
private:
Wrap& operator=(T obj); // prevent use because no way to pass ownership parameter
Wrap& operator=(T obj) = delete; // prevent use because no way to pass rule parameter
T obj_;
};
// essentially a vector of void *, used as source for array and dictionary constructors
typedef BufferAllocatedType<CFTypeRef> SrcList;
// common CF types
OPENVPN_CF_WRAP(String, string_cast, CFStringRef, CFStringGetTypeID)
@@ -207,7 +206,7 @@ namespace openvpn {
inline Generic generic_cast(CFTypeRef obj)
{
return Generic(obj, BORROW);
return Generic(obj, GET);
}
// constructors
@@ -219,7 +218,7 @@ namespace openvpn {
inline String string(CFStringRef str)
{
return String(str, BORROW);
return String(str, GET);
}
inline String string(const String& str)
@@ -267,11 +266,6 @@ namespace openvpn {
return Array(CFArrayCreate(kCFAllocatorDefault, values, numValues, &kCFTypeArrayCallBacks));
}
inline Array array(const SrcList& values)
{
return array((const void **)values.c_data(), values.size());
}
inline Dict dict(const void **keys, const void **values, CFIndex numValues)
{
return Dict(CFDictionaryCreate(kCFAllocatorDefault,
@@ -282,19 +276,14 @@ namespace openvpn {
&kCFTypeDictionaryValueCallBacks));
}
inline Dict dict(const SrcList& keys, const SrcList& values)
{
return dict((const void **)keys.c_data(), (const void **)values.c_data(), std::min(keys.size(), values.size()));
}
inline Dict const_dict(MutableDict& mdict)
{
return Dict(mdict(), CF::BORROW);
return Dict(mdict(), CF::GET);
}
inline Array const_array(MutableArray& marray)
{
return Array(marray(), CF::BORROW);
return Array(marray(), CF::GET);
}
inline Dict empty_dict()
@@ -374,7 +363,13 @@ namespace openvpn {
// string methods
OPENVPN_SIMPLE_EXCEPTION(cppstring_error);
struct cppstring_error : public std::exception
{
virtual const char* what() const throw()
{
return "cppstring_error";
}
};
inline std::string cppstring(CFStringRef str)
{
@@ -22,7 +22,8 @@
#ifndef OPENVPN_APPLECRYPTO_CF_CFHELPER_H
#define OPENVPN_APPLECRYPTO_CF_CFHELPER_H
#include <openvpn/applecrypto/cf/cf.hpp>
#include <openvpn/buffer/buffer.hpp>
#include <openvpn/apple/cf/cf.hpp>
// These methods build on the Wrapper classes for Apple Core Foundation objects
// defined in cf.hpp. They add additional convenience methods, such as dictionary
@@ -31,6 +32,19 @@
namespace openvpn {
namespace CF {
// essentially a vector of void *, used as source for array and dictionary constructors
typedef BufferAllocatedType<CFTypeRef> SrcList;
inline Array array(const SrcList& values)
{
return array((const void **)values.c_data(), values.size());
}
inline Dict dict(const SrcList& keys, const SrcList& values)
{
return dict((const void **)keys.c_data(), (const void **)values.c_data(), std::min(keys.size(), values.size()));
}
inline CFTypeRef mutable_dict_new()
{
return CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
@@ -0,0 +1,33 @@
// 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 Technologies, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program in the COPYING file.
// If not, see <http://www.gnu.org/licenses/>.
#ifndef OPENVPN_APPLECRYPTO_CF_CFHOST_H
#define OPENVPN_APPLECRYPTO_CF_CFHOST_H
#include <openvpn/apple/cf/cf.hpp>
namespace openvpn {
namespace CF {
OPENVPN_CF_WRAP(Host, host_cast, CFHostRef, CFHostGetTypeID)
}
}
#endif
@@ -19,14 +19,14 @@
// along with this program in the COPYING file.
// If not, see <http://www.gnu.org/licenses/>.
#ifndef OPENVPN_APPLE_RUNLOOP_H
#define OPENVPN_APPLE_RUNLOOP_H
#ifndef OPENVPN_APPLECRYPTO_CF_CFRUNLOOP_H
#define OPENVPN_APPLECRYPTO_CF_CFRUNLOOP_H
#include <openvpn/applecrypto/cf/cf.hpp>
#include <openvpn/apple/cf/cf.hpp>
namespace openvpn {
namespace CF {
OPENVPN_CF_WRAP(RunLoop, runloop_cast, CFRunLoopRef, CFRunLoopGetTypeID);
OPENVPN_CF_WRAP(RunLoop, runloop_cast, CFRunLoopRef, CFRunLoopGetTypeID)
OPENVPN_CF_WRAP(RunLoopSource, runloop_source_cast, CFRunLoopSourceRef, CFRunLoopSourceGetTypeID);
}
}
@@ -36,7 +36,7 @@
#include <openvpn/common/size.hpp>
#include <openvpn/common/exception.hpp>
#include <openvpn/applecrypto/cf/cf.hpp>
#include <openvpn/apple/cf/cf.hpp>
// Define C++ wrappings for Apple security-related objects.
@@ -0,0 +1,33 @@
// 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 Technologies, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program in the COPYING file.
// If not, see <http://www.gnu.org/licenses/>.
#ifndef OPENVPN_APPLECRYPTO_CF_CFSTREAM_H
#define OPENVPN_APPLECRYPTO_CF_CFSTREAM_H
#include <openvpn/apple/cf/cf.hpp>
namespace openvpn {
namespace CF {
OPENVPN_CF_WRAP(Socket, socket_cast, CFSocketRef, CFSocketGetTypeID)
}
}
#endif
@@ -0,0 +1,34 @@
// 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 Technologies, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program in the COPYING file.
// If not, see <http://www.gnu.org/licenses/>.
#ifndef OPENVPN_APPLECRYPTO_CF_CFSTREAM_H
#define OPENVPN_APPLECRYPTO_CF_CFSTREAM_H
#include <openvpn/apple/cf/cf.hpp>
namespace openvpn {
namespace CF {
OPENVPN_CF_WRAP(ReadStream, read_stream_cast, CFReadStreamRef, CFReadStreamGetTypeID)
OPENVPN_CF_WRAP(WriteStream, write_stream_cast, CFWriteStreamRef, CFWriteStreamGetTypeID)
}
}
#endif
@@ -22,7 +22,7 @@
#ifndef OPENVPN_APPLECRYPTO_CF_CFTIMER_H
#define OPENVPN_APPLECRYPTO_CF_CFTIMER_H
#include <openvpn/applecrypto/cf/cf.hpp>
#include <openvpn/apple/cf/cf.hpp>
namespace openvpn {
namespace CF {
@@ -21,7 +21,7 @@
#include <string>
#include <openvpn/applecrypto/util/reach.hpp>
#include <openvpn/apple/reach.hpp>
#include <openvpn/netconf/enumiface.hpp>
#ifndef OPENVPN_APPLECRYPTO_UTIL_IOSACTIVEIFACE_H
@@ -28,11 +28,11 @@
#include <thread>
#include <openvpn/log/logthread.hpp>
#include <openvpn/applecrypto/cf/cftimer.hpp>
#include <openvpn/applecrypto/cf/cfhelper.hpp>
#include <openvpn/applecrypto/util/reachable.hpp>
#include <openvpn/apple/cf/cftimer.hpp>
#include <openvpn/apple/cf/cfhelper.hpp>
#include <openvpn/apple/cf/cfrunloop.hpp>
#include <openvpn/apple/reachable.hpp>
#include <openvpn/client/clilife.hpp>
#include <openvpn/apple/runloop.hpp>
#include <openvpn/apple/macsleep.hpp>
#include <openvpn/apple/scdynstore.hpp>
@@ -126,7 +126,7 @@ namespace openvpn {
void thread_func()
{
runloop.reset(CFRunLoopGetCurrent(), CF::BORROW);
runloop.reset(CFRunLoopGetCurrent(), CF::GET);
Log::Context logctx(logwrap);
try {
// set up dynamic store query object
@@ -77,8 +77,8 @@
#include <memory>
#include <openvpn/common/socktypes.hpp>
#include <openvpn/applecrypto/cf/cf.hpp>
#include <openvpn/applecrypto/util/reach.hpp>
#include <openvpn/apple/cf/cf.hpp>
#include <openvpn/apple/reach.hpp>
namespace openvpn {
namespace CF {
@@ -24,7 +24,7 @@
#include <SystemConfiguration/SCDynamicStore.h>
#include <openvpn/applecrypto/cf/cf.hpp>
#include <openvpn/apple/cf/cf.hpp>
namespace openvpn {
namespace CF {
@@ -36,7 +36,7 @@
#include <openvpn/common/string.hpp>
#include <openvpn/crypto/static_key.hpp>
#include <openvpn/crypto/cryptoalgs.hpp>
#include <openvpn/applecrypto/cf/error.hpp>
#include <openvpn/apple/cf/error.hpp>
namespace openvpn {
namespace AppleCrypto {
@@ -34,7 +34,7 @@
#include <openvpn/common/exception.hpp>
#include <openvpn/common/string.hpp>
#include <openvpn/crypto/cryptoalgs.hpp>
#include <openvpn/applecrypto/cf/error.hpp>
#include <openvpn/apple/cf/error.hpp>
#define OPENVPN_DIGEST_CONTEXT(TYPE) CC_##TYPE##_CTX TYPE##_ctx
@@ -47,8 +47,8 @@
#include <openvpn/frame/frame.hpp>
#include <openvpn/frame/memq_stream.hpp>
#include <openvpn/pki/epkibase.hpp>
#include <openvpn/applecrypto/cf/cfsec.hpp>
#include <openvpn/applecrypto/cf/error.hpp>
#include <openvpn/apple/cf/cfsec.hpp>
#include <openvpn/apple/cf/error.hpp>
#include <openvpn/ssl/tlsver.hpp>
#include <openvpn/ssl/sslconsts.hpp>
#include <openvpn/ssl/sslapi.hpp>
@@ -139,7 +139,9 @@ namespace openvpn {
#if !defined(OPENVPN_PLATFORM_WIN)
virtual void set_cloexec() override
{
SockOpt::set_cloexec(socket.native_handle());
const int fd = socket.native_handle();
if (fd >= 0)
SockOpt::set_cloexec(fd);
}
#endif
@@ -207,7 +209,9 @@ namespace openvpn {
virtual void set_cloexec() override
{
SockOpt::set_cloexec(socket.native_handle());
const int fd = socket.native_handle();
if (fd >= 0)
SockOpt::set_cloexec(fd);
}
virtual void close() override
@@ -156,6 +156,9 @@ namespace openvpn {
ClientEvent::Base::Ptr ev = new ClientEvent::Disconnected();
client_options->events().add_event(std::move(ev));
#ifdef OPENVPN_IO_REQUIRES_STOP
io_context.stop();
#endif
}
}
@@ -214,7 +217,7 @@ namespace openvpn {
OPENVPN_LOG("Client terminated, reconnecting in " << seconds << "...");
server_poll_timer.cancel();
client_options->remote_reset_cache_item();
restart_wait_timer.expires_at(Time::now() + Time::Duration::seconds(seconds));
restart_wait_timer.expires_after(Time::Duration::seconds(seconds));
restart_wait_timer.async_wait([self=Ptr(this), gen=generation](const openvpn_io::error_code& error)
{
self->restart_wait_callback(gen, error);
@@ -345,7 +348,7 @@ namespace openvpn {
{
if (!conn_timer_pending && conn_timeout > 0)
{
conn_timer.expires_at(Time::now() + Time::Duration::seconds(conn_timeout));
conn_timer.expires_after(Time::Duration::seconds(conn_timeout));
conn_timer.async_wait([self=Ptr(this), gen=generation](const openvpn_io::error_code& error)
{
self->conn_timer_callback(gen, error);
@@ -393,7 +396,7 @@ namespace openvpn {
server_poll_timer.cancel();
interim_finalize();
client_options->remote_reset_cache_item();
restart_wait_timer.expires_at(Time::now() + Time::Duration::milliseconds(delay_ms));
restart_wait_timer.expires_after(Time::Duration::milliseconds(delay_ms));
restart_wait_timer.async_wait([self=Ptr(this), gen=generation](const openvpn_io::error_code& error)
{
self->restart_wait_callback(gen, error);
@@ -589,7 +592,7 @@ namespace openvpn {
restart_wait_timer.cancel();
if (client_options->server_poll_timeout_enabled())
{
server_poll_timer.expires_at(Time::now() + client_options->server_poll_timeout());
server_poll_timer.expires_after(client_options->server_poll_timeout());
server_poll_timer.async_wait([self=Ptr(this), gen=generation](const openvpn_io::error_code& error)
{
self->server_poll_callback(gen, error);
@@ -66,8 +66,9 @@
#include <openvpn/client/cliemuexr.hpp>
#endif
#if defined(OPENVPN_CUSTOM_TUN_FACTORY)
// includer of this file must define OPENVPN_CUSTOM_TUN_FACTORY class
#if defined(OPENVPN_EXTERNAL_TUN_FACTORY)
// requires that client implements ExternalTun::Factory::new_tun_factory
#include <openvpn/tun/extern/config.hpp>
#elif defined(USE_TUN_BUILDER)
#include <openvpn/tun/builder/client.hpp>
#elif defined(OPENVPN_PLATFORM_LINUX) && !defined(OPENVPN_FORCE_TUN_NULL)
@@ -151,6 +152,10 @@ namespace openvpn {
#if defined(USE_TUN_BUILDER)
TunBuilderBase* builder = nullptr;
#endif
#if defined(OPENVPN_EXTERNAL_TUN_FACTORY)
ExternalTun::Factory* extern_tun_factory = nullptr;
#endif
};
ClientOptions(const OptionList& opt, // only needs to remain in scope for duration of constructor call
@@ -191,7 +196,7 @@ namespace openvpn {
rng.reset(new SSLLib::RandomAPI(false));
prng.reset(new SSLLib::RandomAPI(true));
#if defined(ENABLE_DCO) && !defined(OPENVPN_FORCE_TUN_NULL) && !defined(OPENVPN_CUSTOM_TUN_FACTORY)
#if defined(ENABLE_DCO) && !defined(OPENVPN_FORCE_TUN_NULL) && !defined(OPENVPN_EXTERNAL_TUN_FACTORY)
if (config.dco)
dco = DCOTransport::new_controller();
#else
@@ -292,17 +297,22 @@ namespace openvpn {
}
else
{
#if defined(OPENVPN_CUSTOM_TUN_FACTORY)
#if defined(OPENVPN_EXTERNAL_TUN_FACTORY)
{
OPENVPN_CUSTOM_TUN_FACTORY::Ptr tunconf = OPENVPN_CUSTOM_TUN_FACTORY::new_obj();
tunconf->tun_prop.session_name = session_name;
tunconf->tun_prop.google_dns_fallback = config.google_dns_fallback;
ExternalTun::Config tunconf;
tunconf.tun_prop.layer = layer;
tunconf.tun_prop.session_name = session_name;
tunconf.tun_prop.google_dns_fallback = config.google_dns_fallback;
if (tun_mtu)
tunconf->tun_prop.mtu = tun_mtu;
tunconf->frame = frame;
tunconf->stats = cli_stats;
tunconf->tun_prop.remote_list = remote_list;
tun_factory = tunconf;
tunconf.tun_prop.mtu = tun_mtu;
tunconf.frame = frame;
tunconf.stats = cli_stats;
tunconf.tun_prop.remote_list = remote_list;
tunconf.tun_persist = config.tun_persist;
tunconf.stop = config.stop;
tun_factory.reset(config.extern_tun_factory->new_tun_factory(tunconf, opt));
if (!tun_factory)
throw option_error("OPENVPN_EXTERNAL_TUN_FACTORY: no tun factory");
}
#elif defined(USE_TUN_BUILDER)
{
@@ -448,7 +458,7 @@ namespace openvpn {
// IPv6
{
const unsigned int n = push_base->singleton.extend(opt, "block-ipv6");
if (!n && config.ipv6() == IPv6Setting::NO)
if (!n && config.ipv6() == IPv6Setting::No)
push_base->singleton.emplace_back("block-ipv6");
}
}
@@ -463,9 +473,9 @@ namespace openvpn {
PeerInfo::Set::Ptr pi(new PeerInfo::Set);
// IPv6
if (config.ipv6() == IPv6Setting::NO)
if (config.ipv6() == IPv6Setting::No)
pi->emplace_back("IV_IPv6", "0");
else if (config.ipv6() == IPv6Setting::YES)
else if (config.ipv6() == IPv6Setting::Yes)
pi->emplace_back("IV_IPv6", "1");
// autologin sessions
@@ -777,7 +777,7 @@ namespace openvpn {
{
if (!received_options.partial())
{
push_request_timer.expires_at(now() + dur);
push_request_timer.expires_after(dur);
push_request_timer.async_wait([self=Ptr(this), dur](const openvpn_io::error_code& error)
{
self->send_push_request_callback(dur, error);
@@ -865,7 +865,7 @@ namespace openvpn {
void schedule_inactive_timer()
{
inactive_timer.expires_at(now() + inactive_duration);
inactive_timer.expires_after(inactive_duration);
inactive_timer.async_wait([self=Ptr(this)](const openvpn_io::error_code& error)
{
self->inactive_callback(error);
@@ -955,7 +955,7 @@ namespace openvpn {
void schedule_info_hold_callback()
{
Base::update_now();
info_hold_timer.expires_at(now() + Time::Duration::seconds(1));
info_hold_timer.expires_after(Time::Duration::seconds(1));
info_hold_timer.async_wait([self=Ptr(this)](const openvpn_io::error_code& error)
{
self->info_hold_callback(error);
@@ -24,36 +24,72 @@
#ifndef OPENVPN_COMMON_FUNCTION_H
#define OPENVPN_COMMON_FUNCTION_H
#include <cstddef> // for std::size_t
#include <utility> // for std::move
#include <new>
#include <utility>
namespace openvpn {
template <typename F>
// F -- function type (usually a lambda expression)
// N (default=3) -- max size of functor in void* machine words before we overflow to dynamic allocation
// INTERN_ONLY (default=false) -- if true, throw a static assertion if functor cannot be stored internally
template <typename F, std::size_t N=3, bool INTERN_ONLY=false>
class Function;
template <typename R, typename ... A>
class Function<R(A...)>
template <typename R, typename ... A, std::size_t N, bool INTERN_ONLY>
class Function<R(A...), N, INTERN_ONLY>
{
public:
static constexpr size_t N = 3; // max size of functor in machine words
Function() noexcept
{
methods = nullptr;
}
template <typename T>
Function(T&& functor) noexcept
{
static_assert(sizeof(Intern<T>) <= sizeof(data), "Functor too large");
setup_methods<T>();
new (data) Intern<T>(std::move(functor));
construct(std::move(functor));
}
Function(Function&& f) noexcept
Function(Function&& other) noexcept
{
methods = f.methods;
methods->move(data, f.data);
methods = other.methods;
other.methods = nullptr;
if (methods)
methods->move(data, other.data);
}
Function& operator=(Function&& other) noexcept
{
if (methods)
methods->destruct(data);
methods = other.methods;
other.methods = nullptr;
if (methods)
methods->move(data, other.data);
return *this;
}
~Function()
{
methods->destruct(data);
if (methods)
methods->destruct(data);
}
template <typename T>
void reset(T&& functor) noexcept
{
if (methods)
methods->destruct(data);
construct(std::move(functor));
}
void reset() noexcept
{
if (methods)
{
methods->destruct(data);
methods = nullptr;
}
}
R operator()(A... args)
@@ -61,7 +97,33 @@ namespace openvpn {
return methods->invoke(data, args...);
}
explicit operator bool() const noexcept
{
return methods != nullptr;
}
private:
template <typename T>
void construct(T&& functor) noexcept
{
constexpr bool is_intern = (sizeof(Intern<T>) <= sizeof(data));
static_assert(!INTERN_ONLY || is_intern, "Function: Intern<T> doesn't fit in data[] and INTERN_ONLY=true");
static_assert(sizeof(Extern<T>) <= sizeof(data), "Function: Extern<T> doesn't fit in data[]");
if (is_intern)
{
// store functor internally (in data)
setup_methods_intern<T>();
new (data) Intern<T>(std::move(functor));
}
else
{
// store functor externally (using new)
setup_methods_extern<T>();
new (data) Extern<T>(std::move(functor));
}
}
struct Methods
{
R (*invoke)(void *, A...);
@@ -70,7 +132,7 @@ namespace openvpn {
};
template <typename T>
void setup_methods()
void setup_methods_intern()
{
static const struct Methods m = {
&Intern<T>::invoke,
@@ -80,15 +142,22 @@ namespace openvpn {
methods = &m;
}
template <typename T>
void setup_methods_extern()
{
static const struct Methods m = {
&Extern<T>::invoke,
&Extern<T>::move,
&Extern<T>::destruct,
};
methods = &m;
}
// store functor internally (in data)
template <typename T>
class Intern
{
public:
Intern(Intern&& obj) noexcept
: functor_(std::move(obj.functor_))
{
}
Intern(T&& functor) noexcept
: functor_(std::move(functor))
{
@@ -116,6 +185,40 @@ namespace openvpn {
T functor_;
};
// store functor externally (using new)
template <typename T>
class Extern
{
public:
Extern(T&& functor) noexcept
: functor_(new T(std::move(functor)))
{
}
static R invoke(void *ptr, A... args)
{
Extern* self = reinterpret_cast<Extern<T>*>(ptr);
return (*self->functor_)(args...);
}
static void move(void *dest, void *src)
{
Extern* d = reinterpret_cast<Extern<T>*>(dest);
Extern* s = reinterpret_cast<Extern<T>*>(src);
d->functor_ = s->functor_;
// no need to set s->functor_=nullptr because parent will not destruct src after move
}
static void destruct(void *ptr)
{
Extern* self = reinterpret_cast<Extern<T>*>(ptr);
delete self->functor_;
}
private:
T* functor_;
};
const Methods* methods;
void* data[N];
};
@@ -152,12 +152,18 @@ namespace openvpn {
{
if (!argv.empty())
{
RedirectPipe::InOut inout;
os << to_string() << std::endl;
#ifdef OPENVPN_PROCESS_AVOID_PIPES
const int status = system_cmd(argv[0], argv);
if (status < 0)
os << "Error: command failed to execute" << std::endl;
#else
RedirectPipe::InOut inout;
const int status = system_cmd(argv[0], argv, nullptr, inout, true);
if (status < 0)
os << "Error: command failed to execute" << std::endl;
os << inout.out;
#endif
}
else
os << "Error: command called with empty argv" << std::endl;
@@ -123,7 +123,7 @@ namespace openvpn {
signal_rearm();
#ifdef OPENVPN_EXIT_IN
exit_timer.expires_at(Time::now() + Time::Duration::seconds(OPENVPN_EXIT_IN));
exit_timer.expires_after(Time::Duration::seconds(OPENVPN_EXIT_IN));
exit_timer.async_wait([self=Ptr(this)](const openvpn_io::error_code& error)
{
if (!error)
@@ -54,6 +54,11 @@ namespace openvpn {
{
return time_point(duration(t.raw()));
}
static duration to_duration(const Time::Duration& d)
{
return duration(d.raw());
}
};
class AsioTimer : public openvpn_io::basic_waitable_timer<AsioClock>
@@ -67,7 +72,12 @@ namespace openvpn {
std::size_t expires_at(const Time& t)
{
return openvpn_io::basic_waitable_timer<AsioClock>::expires_at(AsioClock::to_time_point(t));
}
}
std::size_t expires_after(const Time::Duration& d)
{
return openvpn_io::basic_waitable_timer<AsioClock>::expires_after(AsioClock::to_duration(d));
}
};
}
@@ -0,0 +1,45 @@
// 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 Technologies, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program in the COPYING file.
// If not, see <http://www.gnu.org/licenses/>.
#ifndef OPENVPN_TUN_EXTERN_CONFIG_H
#define OPENVPN_TUN_EXTERN_CONFIG_H
// These includes are also intended to resolve forward references in fw.hpp
#include <openvpn/common/options.hpp>
#include <openvpn/tun/client/tunbase.hpp>
#include <openvpn/tun/client/tunprop.hpp>
#include <openvpn/frame/frame.hpp>
#include <openvpn/log/sessionstats.hpp>
#include <openvpn/common/stop.hpp>
namespace openvpn {
namespace ExternalTun {
struct Config
{
TunProp::Config tun_prop;
Frame::Ptr frame;
SessionStats::Ptr stats;
Stop* stop = nullptr;
bool tun_persist = false;
};
}
}
#endif
@@ -0,0 +1,49 @@
// 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 Technologies, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program in the COPYING file.
// If not, see <http://www.gnu.org/licenses/>.
#ifndef OPENVPN_TUN_EXTERN_FW_H
#define OPENVPN_TUN_EXTERN_FW_H
namespace openvpn {
#if defined(OPENVPN_EXTERNAL_TUN_FACTORY)
struct TunClientFactory;
class OptionList;
namespace ExternalTun {
struct Config; // defined in config.hpp
struct Factory
{
virtual TunClientFactory* new_tun_factory(const Config& conf, const OptionList& opt) = 0;
virtual ~Factory() {}
};
}
#else
namespace ExternalTun {
struct Factory {};
}
#endif
}
#endif
@@ -29,9 +29,9 @@ namespace openvpn {
{
public:
enum Type {
NO,
YES,
DEFAULT,
No,
Yes,
Default,
};
IPv6Setting()
@@ -49,11 +49,11 @@ namespace openvpn {
{
switch (type_)
{
case NO:
case No:
return "no";
case YES:
case Yes:
return "yes";
case DEFAULT:
case Default:
default:
return "default";
}
@@ -62,11 +62,11 @@ namespace openvpn {
static IPv6Setting parse(const std::string& str)
{
if (str == "no")
return IPv6Setting(NO);
return IPv6Setting(No);
else if (str == "yes")
return IPv6Setting(YES);
return IPv6Setting(Yes);
else if (str == "default")
return IPv6Setting(DEFAULT);
return IPv6Setting(Default);
else
throw Exception("IPv6Setting: unrecognized setting: '" + str + '\'');
}
@@ -82,7 +82,7 @@ namespace openvpn {
}
private:
Type type_ = DEFAULT;
Type type_ = Default;
};
}
@@ -26,8 +26,10 @@
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <net/route.h>
#include <net/if.h>
#include <net/if_dl.h>
#include <cstring>
@@ -34,7 +34,7 @@
#include <openvpn/common/process.hpp>
#include <openvpn/apple/macver.hpp>
#include <openvpn/apple/scdynstore.hpp>
#include <openvpn/applecrypto/cf/cfhelper.hpp>
#include <openvpn/apple/cf/cfhelper.hpp>
#include <openvpn/tun/builder/capture.hpp>
namespace openvpn {
@@ -29,8 +29,8 @@
#include <openvpn/log/logthread.hpp>
#include <openvpn/common/action.hpp>
#include <openvpn/applecrypto/cf/cftimer.hpp>
#include <openvpn/apple/runloop.hpp>
#include <openvpn/apple/cf/cftimer.hpp>
#include <openvpn/apple/cf/cfrunloop.hpp>
#include <openvpn/tun/mac/macdns.hpp>
namespace openvpn {
@@ -183,7 +183,7 @@ namespace openvpn {
// as well.
void thread_func()
{
runloop.reset(CFRunLoopGetCurrent(), CF::BORROW);
runloop.reset(CFRunLoopGetCurrent(), CF::GET);
Log::Context logctx(logwrap);
try {
@@ -28,7 +28,7 @@
#include <openvpn/common/exception.hpp>
#include <openvpn/addr/ip.hpp>
#include <openvpn/apple/scdynstore.hpp>
#include <openvpn/applecrypto/cf/cfhelper.hpp>
#include <openvpn/apple/cf/cfhelper.hpp>
namespace openvpn {
struct MacGWInfo
@@ -22,6 +22,8 @@
#ifndef OPENVPN_TUN_PERSIST_TUNWRAPASIO_H
#define OPENVPN_TUN_PERSIST_TUNWRAPASIO_H
#include <utility>
namespace openvpn {
// This object supports that subset of the Asio stream
@@ -48,17 +50,14 @@ namespace openvpn {
// subset of methods used by TunIO).
// Prototypes from asio/windows/basic_stream_handle.hpp
template <typename MutableBufferSequence, typename ReadHandler>
ASIO_INITFN_RESULT_TYPE(ReadHandler,
void (openvpn_io::error_code, std::size_t))
async_read_some(const MutableBufferSequence& buffers,
ASIO_MOVE_ARG(ReadHandler) handler)
template <typename MUTABLE_BUFFER, typename HANDLER>
void async_read_some(const MUTABLE_BUFFER& buffers, HANDLER&& handler)
{
return tun_wrap->obj()->async_read_some(buffers, handler);
return tun_wrap->obj()->async_read_some(buffers, std::move(handler));
}
template <typename ConstBufferSequence>
std::size_t write_some(const ConstBufferSequence& buffers)
template <typename CONST_BUFFER>
std::size_t write_some(const CONST_BUFFER& buffers)
{
return tun_wrap->obj()->write_some(buffers);
}
@@ -388,7 +388,7 @@ namespace openvpn {
void layer_2_schedule_timer(const unsigned int seconds)
{
l2_timer.expires_at(Time::now() + Time::Duration::seconds(seconds));
l2_timer.expires_after(Time::Duration::seconds(seconds));
l2_timer.async_wait([self=Ptr(this)](const openvpn_io::error_code& error)
{
if (!error && !self->halt)