18#ifndef OPENVPN_CLIENT_CLIOPT_H
19#define OPENVPN_CLIENT_CLIOPT_H
23#include <unordered_set>
60#ifdef OPENVPN_PLATFORM_ANDROID
64#ifdef OPENVPN_EXTERNAL_TRANSPORT_FACTORY
69#ifdef OPENVPN_EXTERNAL_TUN_FACTORY
72#elif defined(USE_TUN_BUILDER)
74#elif defined(OPENVPN_PLATFORM_LINUX) && !defined(OPENVPN_FORCE_TUN_NULL)
76#ifdef OPENVPN_COMMAND_AGENT
79#elif defined(OPENVPN_PLATFORM_MAC) && !defined(OPENVPN_FORCE_TUN_NULL)
82#ifdef OPENVPN_COMMAND_AGENT
85#elif defined(OPENVPN_PLATFORM_WIN) && !defined(OPENVPN_FORCE_TUN_NULL)
87#ifdef OPENVPN_COMMAND_AGENT
94#ifdef PRIVATE_TUNNEL_PROXY
95#include <openvpn/pt/ptproxy.hpp>
98#if defined(ENABLE_KOVPN) || defined(ENABLE_OVPNDCO) || defined(ENABLE_OVPNDCOWIN)
102#ifndef OPENVPN_UNUSED_OPTIONS
103#define OPENVPN_UNUSED_OPTIONS "UNKNOWN/UNSUPPORTED OPTIONS"
119 ClientAPI::ConfigCommon::operator=(
config);
121 if (!
config.protoOverride.empty())
124 if (
config.protoVersionOverride == 4)
126 else if (
config.protoVersionOverride == 6)
129 if (!
config.allowUnusedAddrFamilies.empty())
169#ifdef OPENVPN_PLATFORM_ANDROID
170 bool enable_route_emulation =
true;
172#ifdef OPENVPN_GREMLIN
183#ifdef USE_TUN_BUILDER
187#ifdef OPENVPN_EXTERNAL_TUN_FACTORY
191#ifdef OPENVPN_EXTERNAL_TRANSPORT_FACTORY
208#ifdef OPENVPN_GREMLIN
209 gremlin_config(
config.gremlin_config),
216#ifdef OPENVPN_EXTERNAL_TRANSPORT_FACTORY
218 extern_transport_factory(
config.extern_transport_factory)
259 CryptoAlgs::allow_default_dc_algs<SSLLib::CryptoAPI>(
cp_main->ssl_factory->libctx(),
260 !
config.clientconf.enableNonPreferredDCAlgorithms,
261 config.clientconf.enableLegacyAlgorithms);
263#if (defined(ENABLE_KOVPN) || defined(ENABLE_OVPNDCO) || defined(ENABLE_OVPNDCOWIN)) && !defined(OPENVPN_FORCE_TUN_NULL) && !defined(OPENVPN_EXTERNAL_TUN_FACTORY)
264 if (
config.clientconf.dco)
265#if defined(USE_TUN_BUILDER)
266 dco = DCOTransport::new_controller(
config.builder);
268 dco = DCOTransport::new_controller(
nullptr);
274#ifdef PRIVATE_TUNNEL_PROXY
284 if (
config.remote_override)
292 throw option_error(ERR_INVALID_CONFIG,
"no remote option specified");
309 if (opt.
exists(
"remote-random"))
330 bool dco_compatible =
false;
332 if (
config.clientconf.dco && !dco_compatible)
334 throw option_error(ERR_INVALID_CONFIG,
"dco_compatibility: config/options are not compatible with dco");
337#ifdef OPENVPN_PLATFORM_UWP
344#ifdef OPENVPN_TLS_LINK
347 tls_ca = opt.
cat(
"tls-ca");
354 [[maybe_unused]]
const bool allow =
config.clientconf.allowLocalDnsResolvers || (block && block->
parameter_exists(
"allow-loopback"));
360#if defined(OPENVPN_COMMAND_AGENT) && defined(OPENVPN_PLATFORM_WIN)
373#if defined(OPENVPN_PLATFORM_WIN)
374 if (
config.clientconf.tunPersist)
381#ifdef OPENVPN_EXTERNAL_TUN_FACTORY
398 throw option_error(ERR_INVALID_CONFIG,
"OPENVPN_EXTERNAL_TUN_FACTORY: no tun factory");
400#elif defined(USE_TUN_BUILDER)
403 tunconf->builder =
config.builder;
404 tunconf->tun_prop.session_name = session_name;
405 tunconf->tun_prop.google_dns_fallback =
config.clientconf.googleDnsFallback;
406 tunconf->tun_prop.dhcp_search_domains_as_split_domains =
config.clientconf.dhcpSearchDomainsAsSplitDomains;
407 tunconf->tun_prop.allow_local_lan_access =
config.clientconf.allowLocalLanAccess;
409 tunconf->tun_prop.mtu = tun_mtu;
410 tunconf->tun_prop.mtu_max = tun_mtu_max;
411 tunconf->frame =
frame;
415#if defined(OPENVPN_PLATFORM_IPHONE)
416 tunconf->retain_sd =
true;
417 tunconf->tun_prefix =
true;
418 if (
config.clientconf.tunPersist)
419 tunconf->tun_prop.remote_bypass =
true;
421#if defined(OPENVPN_PLATFORM_ANDROID)
424 if (
config.enable_route_emulation)
430 tunconf->eer_factory.
reset(
nullptr);
433#if defined(OPENVPN_PLATFORM_MAC)
434 tunconf->tun_prefix =
true;
436 if (
config.clientconf.tunPersist)
440#elif defined(OPENVPN_PLATFORM_LINUX) && !defined(OPENVPN_FORCE_TUN_NULL)
443 tunconf->tun_prop.layer =
layer;
444 tunconf->tun_prop.session_name = session_name;
446 tunconf->tun_prop.mtu = tun_mtu;
447 tunconf->tun_prop.mtu_max = tun_mtu_max;
448 tunconf->tun_prop.google_dns_fallback =
config.clientconf.googleDnsFallback;
449 tunconf->tun_prop.dhcp_search_domains_as_split_domains =
config.clientconf.dhcpSearchDomainsAsSplitDomains;
450 tunconf->generate_tun_builder_capture_event =
config.clientconf.generateTunBuilderCaptureEvent;
452 tunconf->frame =
frame;
454 if (
config.clientconf.tunPersist)
459#elif defined(OPENVPN_PLATFORM_MAC) && !defined(OPENVPN_FORCE_TUN_NULL)
462 tunconf->tun_prop.layer =
layer;
463 tunconf->tun_prop.session_name = session_name;
464 tunconf->tun_prop.google_dns_fallback =
config.clientconf.googleDnsFallback;
465 tunconf->tun_prop.dhcp_search_domains_as_split_domains =
config.clientconf.dhcpSearchDomainsAsSplitDomains;
467 tunconf->tun_prop.mtu = tun_mtu;
468 tunconf->tun_prop.mtu_max = tun_mtu_max;
469 tunconf->frame =
frame;
471 tunconf->stop =
config.stop;
472 if (
config.clientconf.tunPersist)
475#ifndef OPENVPN_COMMAND_AGENT
477 tunconf->tun_prop.remote_bypass =
true;
482#ifdef OPENVPN_COMMAND_AGENT
487#elif defined(OPENVPN_PLATFORM_WIN) && !defined(OPENVPN_FORCE_TUN_NULL)
490 tunconf->tun_prop.layer =
layer;
491 tunconf->tun_prop.session_name = session_name;
492 tunconf->tun_prop.google_dns_fallback =
config.clientconf.googleDnsFallback;
493 tunconf->tun_prop.dhcp_search_domains_as_split_domains =
config.clientconf.dhcpSearchDomainsAsSplitDomains;
495 tunconf->tun_prop.mtu = tun_mtu;
496 tunconf->tun_prop.mtu_max = tun_mtu_max;
497 tunconf->frame =
frame;
499 tunconf->stop =
config.stop;
501 tunconf->allow_local_dns_resolvers = allow;
502 if (
config.clientconf.tunPersist)
505#ifndef OPENVPN_COMMAND_AGENT
507 tunconf->tun_prop.remote_bypass =
true;
511#ifdef OPENVPN_COMMAND_AGENT
519 tunconf->frame =
frame;
613 return std::make_tuple(
true,
"");
616 std::vector<std::string> reasons;
622 reasons.push_back(
"option " +
optname +
" is not compatible with dco");
626 if (
config.enableLegacyAlgorithms)
628 reasons.emplace_back(
"legacy algorithms are not compatible with dco");
631 if (
config.enableNonPreferredDCAlgorithms)
633 reasons.emplace_back(
"non-preferred data channel algorithms are not compatible with dco");
636 if (!
config.proxyHost.empty())
638 reasons.emplace_back(
"proxyHost config setting is not compatible with dco");
643 return std::make_tuple(
true,
"");
646 return std::make_tuple(
false,
string::join(reasons,
"\n"));
655 throw option_error(ERR_INVALID_OPTION_CRYPTO,
"sorry, static key encryption mode (non-SSL/TLS) is not supported");
658 if (opt.
exists(
"fragment"))
659 throw option_error(ERR_INVALID_OPTION_VAL,
"sorry, 'fragment' directive is not supported, nor is connecting to a server that uses 'fragment' directive");
661 if (!opt.
exists(
"client"))
662 throw option_error(ERR_INVALID_CONFIG,
"Neither 'client' nor both 'tls-client' and 'pull' options declared. OpenVPN3 client only supports --client mode.");
667 const auto &mode = opt.
get(
"mode");
668 if (mode.size() != 2 || mode.get(1, 128) !=
"p2p")
670 throw option_error(ERR_INVALID_CONFIG,
"Only 'mode p2p' supported");
675 if (opt.
exists(
"key-method"))
677 auto keymethod = opt.
get(
"key-method");
678 if (keymethod.size() != 2 || keymethod.get(1, 128) !=
"2")
680 throw option_error(ERR_INVALID_OPTION_VAL,
"Only 'key-method 2' is supported: " + keymethod.get(1, 128));
687 "allow-recursive-routing",
694 "data-ciphers-fallback",
698 "explicit-exit-notify",
704 "machine-readable-output",
724 "suppress-timestamps",
734 "auth-gen-token-secret",
735 "auth-user-pass-optional",
736 "auth-user-pass-verify",
748 "ifconfig-ipv6-pool",
750 "ifconfig-pool-persist",
752 "ifconfig-push-constraint",
756 "max-routes-per-client",
763 "stale-routes-check",
764 "tls-crypt-v2-verify",
765 "username-as-common-name",
766 "verify-client-cert",
801 "x509-username-field",
870 "mtu-dynamic",
"no-replay",
"no-name-remapping",
"compat-names",
"ncp-disable",
"no-iv"};
876 "mute-replay-warnings",
904 std::ostringstream os;
908 if (!options.empty())
912 os << category <<
": ";
913 std::vector<std::string> opts;
914 for (
size_t i = 0; i < options.size(); ++i)
916 auto &o = options[i];
918 opts.push_back(o.get(0, 64));
949 std::unordered_set<std::string> ignoreMetaOptions = {
950 "CLI_PREF_ALLOW_WEB_IMPORT",
951 "CLI_PREF_BASIC_CLIENT",
952 "CLI_PREF_ENABLE_CONNECT",
953 "CLI_PREF_ENABLE_XD_PROXY",
960 std::unordered_set<std::string> ignore_unknown_option_list;
962 if (opt.
exists(
"ignore-unknown-option"))
964 auto igOptlist = opt.
get_index(
"ignore-unknown-option");
965 for (
auto igUnOptIdx : igOptlist)
967 const Option &o = opt[igUnOptIdx];
968 for (
size_t i = 1; i < o.
size(); i++)
970 const auto &optionToIgnore = o.
get(i, 0);
972 ignore_unknown_option_list.insert(optionToIgnore);
978 for (
const auto &o : opt)
984 if (o.meta() && ignoreMetaOptions.contains(o.get(0, 0)))
995 OPENVPN_LOG_NTNL(
"NOTE: This configuration contains options that were not used:\n");
1007 showUnusedOptionsByList(opt, ignore_unknown_option_list,
"Ignored by option 'ignore-unknown-option'",
false, errors);
1010 auto ignoredBySetenvOpt = [](
const Option &option)
1011 {
return !option.touched() && option.warnonlyunknown(); };
1012 showOptionsByFunction(opt, ignoredBySetenvOpt,
"Ignored options prefixed with 'setenv opt'",
false, errors);
1014 auto unusedMetaOpt = [](
const Option &option)
1015 {
return !option.touched() && option.meta(); };
1018 auto managmentOpt = [](
const Option &option)
1019 {
return !option.touched() && option.get(0, 0).rfind(
"management", 0) == 0; };
1020 showOptionsByFunction(opt, managmentOpt,
"OpenVPN management interface is not supported by this client",
true, errors);
1023 auto onlyLightlyTouchedOptions = [](
const Option &option)
1024 {
return option.touched_lightly(); };
1025 showOptionsByFunction(opt, onlyLightlyTouchedOptions,
"Unused options, probably specified multiple times in the configuration file",
false, errors);
1027 auto nonTouchedOptions = [](
const Option &option)
1028 {
return !option.touched() && !option.touched_lightly(); };
1031 errors.print_option_errors();
1036 auto func = [&option_set](
const Option &opt)
1037 {
return !opt.touched() && option_set.contains(opt.get(0, 0)); };
1043 template <
typename T>
1046 for (
size_t i = 0; i < opt.size(); ++i)
1064 pi->emplace_back(
"IV_AUTO_SESS",
"1");
1071 if (!
config.clientconf.hwAddrOverride.empty())
1073 pi->emplace_back(
"IV_HWADDR",
config.clientconf.hwAddrOverride);
1078 if (!
config.clientconf.platformVersion.empty())
1079 pi->emplace_back(
"IV_PLAT_VER",
config.clientconf.platformVersion);
1082 std::unordered_map<std::string, std::string> extra_values;
1088 extra_values[kv.key] = kv.value;
1093 if (
config.extra_peer_info.get())
1095 for (
const auto &kv : *
config.extra_peer_info.get())
1097 extra_values[kv.key] = kv.value;
1101 for (
auto kv : extra_values)
1103 pi->emplace_back(kv.first, kv.second);
1108 if (!
config.clientconf.guiVersion.empty())
1109 pi->emplace_back(
"IV_GUI_VER",
config.clientconf.guiVersion);
1112 if (!
config.clientconf.ssoMethods.empty())
1113 pi->emplace_back(
"IV_SSO",
config.clientconf.ssoMethods);
1115 if (!
config.clientconf.appCustomProtocols.empty())
1116 pi->emplace_back(
"IV_ACC",
"2048,6:A," +
config.clientconf.appCustomProtocols);
1123 bool omit_next =
false;
1170 cli_config->creds =
creds;
1180 cli_config->proto_context_config->set_xmit_creds(
true);
1292 const bool relay_mode)
1295 if (relay_mode && !opt.
exists(
"relay-mode"))
1304 SSLLib::SSLAPI::Config::Ptr cc(
new SSLLib::SSLAPI::Config());
1305 cc->set_external_pki_callback(
config.external_pki,
config.clientconf.external_pki_alias);
1306 cc->set_frame(
frame);
1308 cc->set_debug_level(
config.clientconf.sslDebugLevel);
1312 cc->enable_legacy_algorithms(
config.clientconf.enableLegacyAlgorithms);
1313 cc->set_private_key_password(
config.clientconf.privateKeyPassword);
1314 cc->load(opt, lflags);
1315 cc->set_tls_version_min_override(
config.clientconf.tlsVersionMinOverride);
1316 cc->set_tls_cert_profile_override(
config.clientconf.tlsCertProfileOverride);
1317 cc->set_tls_cipher_list(
config.clientconf.tlsCipherList);
1318 cc->set_tls_ciphersuite_list(
config.clientconf.tlsCiphersuitesList);
1322 cp->ssl_factory = cc->new_factory();
1323 cp->relay_mode = relay_mode;
1325 cp->dc_deferred =
true;
1333 cp->extra_peer_info_push_peerinfo = pcc.
pushPeerInfo();
1352#ifdef OPENVPN_EXTERNAL_TRANSPORT_FACTORY
1360 transconf.
protocol = transport_protocol;
1362#ifdef OPENVPN_GREMLIN
1363 udpconf->gremlin_config = gremlin_config;
1370 transconf.
protocol = transport_protocol;
1381 throw option_error(ERR_INVALID_CONFIG,
"internal error: no TCP server entries for " +
alt_proxy->
name() +
" transport");
1393 if (!transport_protocol.
is_tcp())
1394 throw option_error(ERR_INVALID_CONFIG,
"internal error: no TCP server entries for HTTP proxy transport");
1399 httpconf->frame =
frame;
1404 httpconf->rng =
rng;
1405#ifdef PRIVATE_TUNNEL_PROXY
1406 httpconf->skip_html =
true;
1412 if (transport_protocol.
is_udp())
1417 udpconf->frame =
frame;
1421#ifdef OPENVPN_GREMLIN
1422 udpconf->gremlin_config = gremlin_config;
1426 else if (transport_protocol.
is_tcp()
1427#ifdef OPENVPN_TLS_LINK
1428 || transport_protocol.
is_tls()
1435 tcpconf->frame =
frame;
1438#ifdef OPENVPN_TLS_LINK
1439 if (transport_protocol.
is_tls())
1440 tcpconf->use_tls =
true;
1441 tcpconf->tls_ca = tls_ca;
1443#ifdef OPENVPN_GREMLIN
1444 tcpconf->gremlin_config = gremlin_config;
1449 throw option_error(ERR_INVALID_OPTION_VAL,
"internal error: unknown transport protocol");
1477#ifdef OPENVPN_GREMLIN
1491#ifdef OPENVPN_EXTERNAL_TRANSPORT_FACTORY
1494#ifdef OPENVPN_TLS_LINK
bool username_defined() const
void set_username(const std::string &username_arg)
std::string get_http_proxy_username() const
bool http_proxy_password_defined() const
std::string get_http_proxy_password() const
bool session_id_defined() const
void set_password(const std::string &password_arg)
bool http_proxy_username_defined() const
void save_username_for_session_id()
std::map< std::string, std::vector< Option > > options_per_category
void print_option_errors()
void add_failed_opt(const Option &o, const std::string &message, bool fatal_arg)
void check_for_incompatible_options(const OptionList &opt)
std::unordered_set< std::string > settings_standalone_options
void showOptionsByFunction(const OptionList &opt, T func, const std::string &message, bool fatal, OptionErrors &errors)
ReconnectNotify * reconnect_notify
const SessionStats::Ptr & stats_ptr() const
ProtoContext::ProtoConfig & proto_config_cached(const bool relay_mode)
void showUnusedOptionsByList(const OptionList &optlist, std::unordered_set< std::string > option_set, const std::string &message, bool fatal, OptionErrors &errors)
std::unordered_set< std::string > settings_ignoreSilently
std::unordered_set< std::string > settings_feature_not_implemented_warn
void handle_unused_options(const OptionList &opt)
ProtoContext::ProtoConfig::Ptr cp_main
PushOptionsBase::Ptr push_base
static std::tuple< bool, std::string > check_dco_compatibility(const ClientAPI::ConfigCommon &config, const OptionList &opt)
std::unordered_set< std::string > settings_ignoreWithWarning
TransportClientFactory::Ptr transport_factory
ClientEvent::Queue::Ptr cli_events
HTTPProxyTransport::Options::Ptr http_proxy_options
std::unordered_set< std::string > settings_removedOptions
unsigned int server_poll_timeout_
ClientLifeCycle::Ptr client_lifecycle
TunClientFactory::Ptr tun_factory
void finalize(const bool disconnected)
unsigned int tcp_queue_limit
std::unordered_set< std::string > settings_script_plugin_feature
static PeerInfo::Set::Ptr build_peer_info(const Config &config, const ParseClientConfig &pcc, const bool autologin_sessions)
std::unordered_set< std::string > settings_serverOnlyOptions
SocketProtect * socket_protect
ProtoContext::ProtoConfig::Ptr cp_relay
SessionStats::Ptr cli_stats
bool server_poll_timeout_enabled() const
RemoteList::Ptr remote_list
bool asio_work_always_on() const
ClientConfigParsed clientconf
bool pause_on_connection_timeout()
void next(RemoteList::Advance type)
static std::unordered_set< std::string > dco_incompatible_opts
ClientEvent::Queue & events()
OptionList::FilterBase::Ptr pushed_options_filter
ClientLifeCycle * lifecycle()
std::unordered_set< std::string > settings_pushonlyoptions
Time::Duration server_poll_timeout() const
bool synchronous_dns_lookup
bool retry_on_auth_failed() const
ClientOptions(const OptionList &opt, const Config &config)
std::string userlocked_username
void submit_creds(const ClientCreds::Ptr &creds_arg)
std::string load_transport_config()
ProtoContext::ProtoConfig::Ptr proto_config(const OptionList &opt, const Config &config, const ParseClientConfig &pcc, const bool relay_mode)
std::unordered_set< std::string > settings_feature_not_implemented_fatal
ProtoContextCompressionOptions::Ptr proto_context_options
RemoteList::Ptr remote_list_precache() const
Client::Config::Ptr client_config(const bool relay_mode)
void remote_reset_cache_item()
bool asio_work_always_on_
static Ptr parse(const OptionList &opt)
std::string cat(const std::string &name) const
void extend(const OptionList &other, FilterBase *filt=nullptr)
const IndexList & get_index(const std::string &name) const
T get_num(const std::string &name, const size_t idx, const T default_value) const
void touch(const std::string &name) const
const Option & get(const std::string &name) const
size_t n_unused(bool ignore_meta=false) const
const Option * get_ptr(const std::string &name) const
bool exists(const std::string &name) const
void touch(bool lightly=false) const
const std::string & get(const size_t index, const size_t max_len) const
bool parameter_exists(const std::string ¶meter) const
bool hasEmbeddedPassword() const
const std::string & embeddedPassword() const
const PeerInfo::Set * peerInfoUV() const
bool pushPeerInfo() const
const std::string & userlockedUsername() const
bool clientCertEnabled() const
static constexpr size_t MAX_CONTROL_WRAP_OVERHEAD
static Protocol parse(const std::string &str, const AllowSuffix allow_suffix, const char *title=nullptr)
void reset() noexcept
Points this RCPtr<T> to nullptr safely.
T * get() const noexcept
Returns the raw pointer to the object T, or nullptr.
Reference count base class for objects tracked by RCPtr. Disallows copying and assignment.
virtual bool pause_on_connection_timeout()=0
void set_server_override(const std::string &server_override)
void next(Advance type=Advance::Addr)
void handle_proto_override(const Protocol &proto_override, const bool tcp_proxy_enabled)
void set_enable_cache(const bool enable_cache_arg)
void set_random(const RandomAPI::Ptr &rng_arg)
void set_proto_version_override(const IP::Addr::Version v)
void set_port_override(const std::string &port_override)
const Protocol & current_transport_protocol() const
std::string current_server_host() const
static TriStateSetting parse(const std::string &str)
TunBuilder methods, loosely based on the Android VpnService.Builder abstraction.
static TunBuilderSetup::Factory::Ptr new_agent(const OptionList &opt)
static TunWin::SetupFactory::Ptr new_agent(const OptionList &opt)
#define OPENVPN_UNUSED_OPTIONS
#define OPENVPN_LOG_NTNL(args)
#define OPENVPN_LOG(args)
auto join(const T &strings, const typename T::value_type &delim, const bool tail=false)
unsigned int parse_tun_mtu_max(const OptionList &opt, unsigned int default_value)
Frame::Ptr frame_init(const bool align_adjust_3_1, const size_t tun_mtu_max, const size_t control_channel_payload, const bool verbose)
unsigned int parse_tun_mtu(const OptionList &opt, unsigned int default_value)
const std::string get_ssl_library_version()
SocketProtect * socket_protect
DigestFactory::Ptr digest_factory
RemoteList::Ptr remote_list
virtual TransportClientFactory::Ptr new_transport_client_factory(const Config &)=0
virtual std::string name() const =0
virtual void precache(RemoteList::Ptr &r)=0
virtual bool requires_tcp() const =0
virtual void set_enable_cache(const bool enable_cache)=0
TriStateSetting allowUnusedAddrFamilies
std::string external_pki_alias
IP::Addr::Version proto_version_override
void import_client_settings(const ClientAPI::Config &config)
ReconnectNotify * reconnect_notify
ClientEvent::Queue::Ptr cli_events
ClientConfigParsed clientconf
PeerInfo::Set::Ptr extra_peer_info
RemoteList::RemoteOverride * remote_override
int default_key_direction
ExternalPKIBase * external_pki
SessionStats::Ptr cli_stats
ProtoContextCompressionOptions::Ptr proto_context_options
bool synchronous_dns_lookup
HTTPProxyTransport::Options::Ptr http_proxy_options
SocketProtect * socket_protect
RemoteList::Ptr remote_list
SocketProtect * socket_protect
bool allow_local_dns_resolvers
virtual TunClientFactory::Ptr new_tun_factory(const TunConfig &conf, const OptionList &opt)=0
virtual TransportClientFactory::Ptr new_transport_factory(const TransportConfig &conf)=0
RemoteList::Ptr remote_list
SocketProtect * socket_protect
bool synchronous_dns_lookup
virtual void finalize(const bool disconnected)
RemoteList::Ptr remote_list
bool dhcp_search_domains_as_split_domains
static const char config[]
const std::string optname