15 public KoRekey::Receiver,
16 public SessionStats::DCOTransportSource
19 typedef RCPtr<OvpnDcoWinClient>
Ptr;
25 TunWin::Util::TapNameGuidPair tap;
26 TunWin::Type tun_type(TunWin::OvpnDco);
27 TunWin::Util::TapNameGuidPairList guids(tun_type);
28 Win::ScopedHANDLE hnd(TunWin::Util::tap_open(tun_type, guids, path, tap));
38 RemoteList &rl = *
config->transport.remote_list;
39 if (rl.endpoint_available(&server_host, &server_port, &
proto_))
42 openvpn_io::post(io_context, [self =
Ptr(
this)]()
45 self->start_impl_(); });
49 transport_parent->transport_pre_resolve();
50 async_resolve_name(server_host, server_port);
66 void setup_tun(
const OptionList &opt, TransportClient &transcli,
bool is_tun_start =
true)
68 const IP::Addr server_addr = transcli.server_endpoint_addr();
80 tun_parent->tun_pre_tun_config();
83 std::ostringstream
os;
89 TunBuilderCapture::Ptr po(
new TunBuilderCapture());
90 TunProp::configure_builder(po.get(),
93 transcli.server_endpoint_addr(),
101 tun_setup_->establish(*po, Win::module_name(), NULL,
os, NULL);
108 OPENVPN_LOG(
"TunPersist: saving tun context:" << std::endl
125 auto adapter_state =
tun_setup_->get_adapter_state();
133 tun_parent->tun_connected();
137 TransportClient &transcli,
138 CryptoDCSettings &dc_settings)
override
147 dc_settings.set_factory(CryptoDCFactory::Ptr(
new KoRekey::Factory(
148 dc_settings.factory(),
this,
config->transport.frame)));
150 tun_parent->tun_connected();
155 return "ovpn-dco-win";
164 return tun_persist->state().state->vpn_interface_index;
166 return INVALID_ADAPTER_INDEX;
174 self->tun_parent->tun_error(Error::TUN_IFACE_DISABLED,
"service failure"); });
185 return IP::Addr::from_asio(
endpoint_.address());
193 void rekey(
const CryptoDCInstance::RekeyType rktype,
194 const KoRekey::Info &rkinfo)
override
199 KoRekey::OvpnDcoKey key(rktype, rkinfo);
203 case CryptoDCInstance::ACTIVATE_PRIMARY:
207 case CryptoDCInstance::NEW_SECONDARY:
211 case CryptoDCInstance::PRIMARY_SECONDARY_SWAP:
215 case CryptoDCInstance::DEACTIVATE_SECONDARY:
218 case CryptoDCInstance::DEACTIVATE_ALL:
222 OPENVPN_LOG(
"ovpndcocli: unknown rekey type: " << rktype);
230 TransportClientParent *
parent)
236 results_type results)
override
243 std::ostringstream
os;
244 os <<
"DNS resolve error on '" << server_host <<
"' for "
245 <<
proto_.str() <<
" session: " << error.message();
248 config->transport.stats->error(Error::RESOLVE_ERROR);
249 transport_parent->transport_error(Error::UNDEF,
os.str());
253 config->transport.remote_list->set_endpoint_range(results);
268 if (
config->tun.tun_persist)
271 tun_persist.reset(
new TunWin::DcoTunPersist(
false, TunWrapObjRetain::NO_RETAIN,
nullptr));
275 std::ostringstream
os;
278 if (th == INVALID_HANDLE_VALUE)
281 handle_.reset(
new TunWin::TAPStream(io_context, th));
292 if (
config->transport.socket_protect)
297 config->transport.stats->error(Error::SOCKET_PROTECT_ERROR);
299 transport_parent->transport_error(Error::UNDEF,
"socket_protect error (dco-win)");
307 self->transport_parent->transport_connecting();
313 config->transport.stats->dco_configure(
this);
318 buf_.reset(0, 2048, BufAllocFlags::NO_FLAGS);
321 buf_.mutable_buffer_clamp(),
322 [self =
Ptr(
this)](
const openvpn_io::error_code &error,
323 const size_t bytes_recvd)
329 self->buf_.set_size(bytes_recvd);
330 self->transport_parent->transport_recv(self->buf_);
334 else if (!self->halt)
337 self->transport_parent->transport_error(Error::TRANSPORT_ERROR,
345 openvpn_io::error_code error;
346 get_handle()->write_some(buf.const_buffer(), error);
349 transport_parent->transport_error(Error::TRANSPORT_ERROR,
364 async_resolve_cancel();
370 catch (
const ErrorCode &e)
373 if (e.code() != Error::TUN_SETUP_FAILED)
383 template <
typename CB>
390 openvpn_io::ip::address addr =
endpoint_.address();
396 addr.to_v4().to_bytes().data(),
406 addr.to_v6().to_bytes().data(),
412 openvpn_io::windows::overlapped_ptr ov{io_context,
413 [self =
Ptr(
this), complete](
const openvpn_io::error_code &ec,
422 std::ostringstream errmsg;
423 errmsg <<
"TCP connection error: " << ec.message();
424 self->config->transport.stats->error(Error::TCP_CONNECT_ERROR);
425 self->transport_parent->transport_error(Error::UNDEF, errmsg.str());
431 if (ec == ERROR_SUCCESS)
433 else if (ec != ERROR_IO_PENDING)
435 std::ostringstream errmsg;
436 errmsg <<
"failed to connect '" << server_host <<
"' " <<
endpoint_;
437 config->transport.stats->error(Error::TCP_CONNECT_ERROR);
438 transport_parent->transport_error(Error::UNDEF, errmsg.str());
445 if (!transport_parent->is_keepalive_enabled())
448 unsigned int keepalive_interval = 0;
449 unsigned int keepalive_timeout = 0;
453 transport_parent->disable_keepalive(keepalive_interval, keepalive_timeout);
455 if (
config->ping_restart_override)
456 keepalive_timeout =
config->ping_restart_override;
459 OVPN_SET_PEER peer{
static_cast<LONG
>(keepalive_interval),
static_cast<LONG
>(keepalive_timeout), -1};
464 const KoRekey::KeyConfig *kc)
467 ZeroMemory(&data,
sizeof(data));
469 const size_t nonce_tail_len =
sizeof(kc->encrypt.nonce_tail);
471 data.Encrypt.KeyLen = kc->encrypt.cipher_key_size;
472 std::memcpy(data.Encrypt.Key, kc->encrypt.cipher_key, data.Encrypt.KeyLen);
473 std::memcpy(data.Encrypt.NonceTail, kc->encrypt.nonce_tail, nonce_tail_len);
475 data.Decrypt.KeyLen = kc->decrypt.cipher_key_size;
476 std::memcpy(data.Decrypt.Key, kc->decrypt.cipher_key, data.Decrypt.KeyLen);
477 std::memcpy(data.Decrypt.NonceTail, kc->decrypt.nonce_tail, nonce_tail_len);
479 data.KeyId = kc->key_id;
480 data.PeerId = kc->remote_peer_id;
482 data.KeySlot = (type == CryptoDCInstance::ACTIVATE_PRIMARY
483 ? OVPN_KEY_SLOT::OVPN_KEY_SLOT_PRIMARY
484 : OVPN_KEY_SLOT::OVPN_KEY_SLOT_SECONDARY);
496 const SessionStats::DCOTransportSource::Data old_stats =
last_stats;
502 if (res == ERROR_SUCCESS)
504 last_stats = SessionStats::DCOTransportSource::Data(stats.TransportBytesReceived, stats.TransportBytesSent, stats.TunBytesReceived, stats.TunBytesSent);
507 catch (
const ErrorCode &e)
510 if (e.code() != Error::TUN_SETUP_FAILED)
518 LPVOID in_buf = NULL,
519 DWORD in_buf_size = 0,
520 LPVOID out_buf = NULL,
521 DWORD out_buf_size = 0,
522 openvpn_io::windows::overlapped_ptr *ov =
nullptr)
524 static const std::map<const DWORD, const char *> code_str{
535 if (handle ==
nullptr)
536 throw ErrorCode(Error::TUN_SETUP_FAILED,
false,
"no device handle");
538 HANDLE th(handle->native_handle());
539 LPOVERLAPPED ov_ = (ov ? ov->get() : NULL);
540 if (!DeviceIoControl(th, code, in_buf, in_buf_size, out_buf, out_buf_size, NULL, ov_))
542 const DWORD error_code = GetLastError();
545 if (error_code == ERROR_IO_PENDING)
550 openvpn_io::error_code error(error_code, openvpn_io::system_category());
551 ov->complete(error, 0);
554 std::ostringstream
os;
555 os <<
"DeviceIoControl(" << code_str.at(code) <<
")"
556 <<
" failed with code " << error_code;
557 throw ErrorCode(Error::TUN_SETUP_FAILED,
true,
os.str());
559 return ERROR_SUCCESS;
577 SessionStats::DCOTransportSource::Data delta =
last_delta;
578 last_delta = SessionStats::DCOTransportSource::Data();
#define OPENVPN_ASYNC_HANDLER
SessionStats::DCOTransportSource::Data last_delta
Protocol transport_protocol() const override
void resolve_callback(const openvpn_io::error_code &error, results_type results) override
TunWin::ScopedTAPStream handle_
void transport_start() override
void tun_start(const OptionList &opt, TransportClient &transcli, CryptoDCSettings &dc_settings) override
void setup_tun(const OptionList &opt, TransportClient &transcli, bool is_tun_start=true)
void apply_push_update(const OptionList &opt, TransportClient &transcli) override
void rekey(const CryptoDCInstance::RekeyType rktype, const KoRekey::Info &rkinfo) override
std::uint32_t vpn_interface_index() const override
OvpnDcoWinClient(openvpn_io::io_context &io_context, ClientConfig *config, TransportClientParent *parent)
bool send_(const Buffer &buf)
void add_peer_(CB complete)
IP::Addr server_endpoint_addr() const override
SessionStats::DCOTransportSource::Data last_stats
TunWin::SetupBase::Ptr tun_setup_
virtual SessionStats::DCOTransportSource::Data dco_transport_stats_delta() override
std::string tun_name() const override
TunWin::DcoTunPersist::Ptr tun_persist
void add_crypto_(const CryptoDCInstance::RekeyType type, const KoRekey::KeyConfig *kc)
DWORD dco_ioctl_(DWORD code, LPVOID in_buf=NULL, DWORD in_buf_size=0, LPVOID out_buf=NULL, DWORD out_buf_size=0, openvpn_io::windows::overlapped_ptr *ov=nullptr)
bool transport_send_const(const Buffer &buf) override
void adjust_mss(int mss) override
friend class ClientConfig
RCPtr< OvpnDcoWinClient > Ptr
openvpn_io::ip::udp::endpoint endpoint_
void set_service_fail_handler()
bool transport_send(BufferAllocated &buf) override
TunWin::TAPStream * get_handle()
Private::ClientState * state
#define OPENVPN_LOG(args)
#define OPENVPN_LOG_STRING(str)
#define OVPN_IOCTL_GET_STATS
#define OVPN_IOCTL_SWAP_KEYS
#define OVPN_IOCTL_NEW_KEY
enum _OVPN_CIPHER_ALG OVPN_CIPHER_ALG
#define OVPN_IOCTL_SET_PEER
#define OVPN_IOCTL_NEW_PEER
#define OVPN_IOCTL_START_VPN
#define OVPN_IOCTL_DEL_PEER
union _OVPN_NEW_PEER::@41 Local
union _OVPN_NEW_PEER::@42 Remote
static const char config[]