43#if defined(__MINGW32__)
44const IN_ADDR in4addr_any = { 0 };
53 for (
int i = 0; i < 20; ++i)
55 MIB_IPINTERFACE_ROW row = { .InterfaceIndex = idx, .Family = AF_INET };
56 if (GetIpInterfaceEntry(&row) != ERROR_NOT_FOUND)
81 HANDLE h = CreateFile(
"\\\\.\\ovpn-dco-ver", GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
83 if (h == INVALID_HANDLE_VALUE)
86 h = CreateFile(
"\\\\.\\ovpn-dco", GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
89 if (h == INVALID_HANDLE_VALUE)
94 DWORD bytes_returned = 0;
96 &bytes_returned, NULL))
104 if (h != INVALID_HANDLE_VALUE)
126 ASSERT(dco->ifmode == DCO_MODE_UNINIT);
127 dco->ifmode = DCO_MODE_MP;
132 dco->ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
133 if (dco->ov.hEvent == NULL)
135 msg(
M_ERR,
"Error: ovpn_dco_init: CreateEvent failed");
138 dco->rwhandle.read = dco->ov.hEvent;
142 const char *device_guid;
148 DWORD bytes_returned = 0;
150 &bytes_returned, NULL))
152 msg(
M_ERR,
"DeviceIoControl(OVPN_IOCTL_SET_MODE) failed");
169 DWORD bytes_returned = 0;
172 msg(
M_ERR,
"DeviceIoControl(OVPN_IOCTL_START_VPN) failed");
201 dco->ifmode = DCO_MODE_P2P;
227 DWORD timeout_msec = timeout * 1000;
228 const int poll_interval_ms = 50;
230 while (timeout_msec > 0)
232 timeout_msec -= poll_interval_ms;
235 if (GetOverlappedResultEx(handle, ov, &transferred, poll_interval_ms, FALSE) != 0)
241 DWORD err = GetLastError();
242 if ((err != WAIT_TIMEOUT) && (err != ERROR_IO_INCOMPLETE))
251 if (*signal_received)
280 const struct addrinfo *cur = NULL;
282 for (cur = local; cur; cur = cur->ai_next)
284 if (cur->ai_family == ai_family)
291 msg(
M_FATAL,
"%s: Socket bind failed: Addr to bind has no %s record", __func__,
297 if (ai_family == AF_INET)
309 DWORD bytes_returned = 0;
311 &bytes_returned, NULL))
313 msg(
M_ERR,
"DeviceIoControl(OVPN_IOCTL_MP_START_VPN) failed");
327 struct sockaddr *local = NULL;
328 const struct sockaddr *remote = remoteaddr->ai_addr;
330 if (remoteaddr->ai_protocol == IPPROTO_TCP || remoteaddr->ai_socktype == SOCK_STREAM)
343 while (bind && !local)
345 if (bind->ai_family == remote->sa_family)
347 local = bind->ai_addr;
349 bind = bind->ai_next;
355 msg(
M_FATAL,
"DCO: Socket bind failed: Address to bind lacks %s record",
359 if (remote->sa_family == AF_INET6)
361 peer.
Remote.
Addr6 = *((SOCKADDR_IN6 *)(remoteaddr->ai_addr));
373 else if (remote->sa_family == AF_INET)
375 peer.
Remote.
Addr4 = *((SOCKADDR_IN *)(remoteaddr->ai_addr));
395 DWORD err = GetLastError();
396 if (err != ERROR_IO_PENDING)
398 msg(
M_ERR,
"DeviceIoControl(OVPN_IOCTL_NEW_PEER) failed");
410 struct sockaddr *localaddr,
struct sockaddr *remoteaddr,
411 const struct in_addr *vpn_ipv4,
const struct in6_addr *vpn_ipv6)
415 if (dco->ifmode == DCO_MODE_P2P)
426 newPeer.
Local.
Addr4.sin_family = remoteaddr->sa_family;
428 if (remoteaddr->sa_family == AF_INET)
430 memcpy(&newPeer.
Remote.
Addr4, remoteaddr,
sizeof(
struct sockaddr_in));
434 memcpy(&newPeer.
Remote.
Addr6, remoteaddr,
sizeof(
struct sockaddr_in6));
452 &bytesReturned, NULL))
471 if (dco->ifmode == DCO_MODE_MP)
475 len =
sizeof(del_peer);
478 DWORD bytes_returned = 0;
479 if (!DeviceIoControl(dco->tt->hand, ioctl, buf, len, NULL, 0, &bytes_returned, NULL))
491 msg(
D_DCO_DEBUG,
"%s: peer-id %u, keepalive %d/%d, mss %d", __func__, peerid,
492 keepalive_interval, keepalive_timeout, mss);
494 OVPN_MP_SET_PEER mp_peer = { peerid, keepalive_interval, keepalive_timeout, mss };
495 OVPN_SET_PEER peer = { keepalive_interval, keepalive_timeout, mss };
500 if (dco->ifmode == DCO_MODE_MP)
511 DWORD bytes_returned = 0;
512 if (!DeviceIoControl(dco->tt->hand, ioctl, buf, len, NULL, 0, &bytes_returned, NULL))
523 const uint8_t *encrypt_key,
const uint8_t *encrypt_iv,
const uint8_t *decrypt_key,
524 const uint8_t *decrypt_iv,
const char *ciphername,
bool epoch)
526 msg(
D_DCO_DEBUG,
"%s: slot %d, key-id %d, peer-id %u, cipher %s", __func__, slot, keyid, peerid,
529 const int nonce_len = 8;
534 ZeroMemory(&crypto_data,
sizeof(crypto_data));
538 v1->
CipherAlg = dco_get_cipher(ciphername);
539 ASSERT(keyid >= 0 && keyid <= UCHAR_MAX);
540 v1->
KeyId = (
unsigned char)keyid;
545 CopyMemory(v1->
Encrypt.
Key, encrypt_key, epoch ? 32 : key_len);
549 CopyMemory(v1->
Decrypt.
Key, decrypt_key, epoch ? 32 : key_len);
556 VOID *buf = &crypto_data.
V1;
557 DWORD bufSize =
sizeof(crypto_data.
V1);
563 bufSize =
sizeof(crypto_data);
566 DWORD bytes_returned = 0;
568 if (!DeviceIoControl(dco->tt->hand, ioctl, buf, bufSize, NULL, 0, &bytes_returned, NULL))
579 msg(
D_DCO,
"%s: peer-id %u, slot %d called but ignored", __func__, peerid, slot);
594 if (dco->ifmode == DCO_MODE_MP)
601 DWORD bytes_returned = 0;
602 if (!DeviceIoControl(dco->tt->hand, ioctl, buf, len, NULL, 0, &bytes_returned, NULL))
614 HANDLE h = CreateFile(
"\\\\.\\ovpn-dco", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
615 FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, NULL);
617 if (h != INVALID_HANDLE_VALUE)
623 DWORD err = GetLastError();
624 if (err == ERROR_ACCESS_DENIED)
633 msg(msglevel,
"Note: ovpn-dco-win driver is missing, disabling data channel offload.");
667 DWORD bytes_read = 0;
668 BOOL res = GetOverlappedResult(dco->tt->hand, &dco->ov, &bytes_read, FALSE);
671 msg(
D_DCO_DEBUG,
"%s: completion%s success [%lu]", __func__, queued ?
"" :
" non-queued",
674 dco->dco_message_peer_id = dco->notif_buf.PeerId;
675 dco->dco_message_type = dco->notif_buf.Cmd;
676 dco->dco_del_peer_reason = dco->notif_buf.DelPeerReason;
677 dco->dco_float_peer_ss = dco->notif_buf.FloatAddress;
688 if (dco->ifmode != DCO_MODE_MP)
693 dco->dco_message_peer_id = -1;
694 dco->dco_message_type = 0;
696 switch (dco->iostate)
701 ASSERT(ResetEvent(dco->ov.hEvent));
708 ASSERT(ResetEvent(dco->ov.hEvent));
710 if (dco->ov_ret == ERROR_SUCCESS)
716 SetLastError(dco->ov_ret);
723 if (dco->c->mode ==
CM_TOP)
753 DWORD required_size = 0, bytes_returned = 0;
757 if (GetLastError() == ERROR_MORE_DATA)
759 if (bytes_returned !=
sizeof(DWORD))
761 msg(
M_WARN,
"%s: invalid bytes returned for size query (%lu, expected %zu)", __func__, bytes_returned,
sizeof(DWORD));
766 if (required_size == 0)
780 msg(
M_WARN |
M_ERRNO,
"%s: failed to fetch required buffer size", __func__);
788 if (bytes_returned == 0)
794 msg(
M_WARN,
"%s: first DeviceIoControl call succeeded unexpectedly (%lu bytes returned)", __func__, bytes_returned);
804 msg(
M_WARN,
"%s: failed to allocate buffer of size %lu", __func__, required_size);
812 if (GetLastError() == ERROR_MORE_DATA)
814 msg(
M_WARN,
"%s: peer has been added, skip fetching stats", __func__);
829 if (stat->
PeerId >= (
int)
dco->c->multi->max_clients)
831 msg(
M_WARN,
"%s: received out of bound peer_id %d (max=%u)", __func__, stat->
PeerId,
832 dco->c->multi->max_clients);
839 msg(
M_WARN,
"%s: received data for a non-existing peer %d", __func__, stat->
PeerId);
854 if (raise_sigusr1_on_err && ret < 0)
875 DWORD bytes_returned = 0;
877 &bytes_returned, NULL))
905 DWORD bytes_returned = 0;
907 &bytes_returned, NULL))
909 if (GetLastError() == ERROR_INVALID_FUNCTION)
915 msg(
M_WARN |
M_ERRNO,
"%s: DeviceIoControl(OVPN_IOCTL_GET_PEER_STATS) failed", __func__);
921 msg(
M_WARN |
M_ERRNO,
"%s: DeviceIoControl(OVPN_IOCTL_GET_PEER_STATS) returned invalid size", __func__);
936 if (
dco->ifmode != DCO_MODE_MP)
950 sizeof(
dco->notif_buf), NULL, &
dco->ov))
952 DWORD err = GetLastError();
953 if (err == ERROR_IO_PENDING)
956 dco->ov_ret = ERROR_SUCCESS;
974 dco->ov_ret = ERROR_SUCCESS;
991 NTSTATUS
status = BCryptOpenAlgorithmProvider(&h, L
"CHACHA20_POLY1305", NULL, 0);
992 if (BCRYPT_SUCCESS(
status))
994 BCryptCloseAlgorithmProvider(h, 0);
995 return "AES-128-GCM:AES-256-GCM:AES-192-GCM:CHACHA20-POLY1305";
999 return "AES-128-GCM:AES-256-GCM:AES-192-GCM";
1012 unsigned int peer_id)
1017 .Addr.Addr4.S_un.S_addr = dst, .Netbits = netbits, .PeerId = peer_id, .IPv6 = 0
1023 DWORD bytes_returned = 0;
1025 &bytes_returned, NULL))
1035 unsigned int peer_id)
1039 OVPN_MP_IROUTE route = { .Addr.Addr6 = dst, .Netbits = netbits, .PeerId = peer_id, .IPv6 = 1 };
1044 DWORD bytes_returned = 0;
1046 &bytes_returned, NULL))
1060 .Addr.Addr4.S_un.S_addr = dst, .Netbits = netbits, .PeerId = -1, .IPv6 = 0
1065 DWORD bytes_returned = 0;
1067 &bytes_returned, NULL))
1080 OVPN_MP_IROUTE route = { .Addr.Addr6 = dst, .Netbits = netbits, .PeerId = -1, .IPv6 = 1 };
1084 DWORD bytes_returned = 0;
1086 &bytes_returned, NULL))
bool buf_printf(struct buffer *buf, const char *format,...)
printf-style append to a buffer with overflow check.
void * gc_malloc(size_t size, bool clear, struct gc_arena *a)
Allocate memory and, optionally, zero it.
struct buffer alloc_buf_gc(size_t size, struct gc_arena *gc)
Allocate a buffer of the given size under garbage collection.
#define BSTR(buf)
Return the buffer content pointer cast to char *.
static void gc_free(struct gc_arena *a)
Free all allocations in a garbage collection arena.
static struct gc_arena gc_new(void)
Allocate and return a new, empty garbage collection arena.
Data Channel Cryptography Module.
unsigned int cipher_kt_key_size(const char *ciphername)
Returns the size of keys used by the cipher, in bytes.
int open_tun_dco(struct tuntap *tt, openvpn_net_ctx_t *ctx, const char *dev)
int dco_del_key(dco_context_t *dco, unsigned int peerid, dco_key_slot_t slot)
bool dco_available(msglvl_t msglevel)
void dco_mp_start_vpn(HANDLE handle, struct link_socket *sock)
Initializes and binds the kernel UDP transport socket for multipeer mode.
int dco_del_peer(dco_context_t *dco, unsigned int peerid)
void dco_win_add_iroute_ipv6(dco_context_t *dco, struct in6_addr dst, unsigned int netbits, unsigned int peer_id)
const char * dco_version_string(struct gc_arena *gc)
void dco_p2p_start_vpn(struct tuntap *tt)
Transitions the DCO adapter to the connected state in P2P mode.
bool dco_supports_epoch_data(const struct context *c)
int dco_read_and_process(dco_context_t *dco)
const char * dco_get_supported_ciphers(void)
bool ovpn_dco_init(struct context *c)
Initializes DCO depends on mode.
static void dco_connect_wait(HANDLE handle, OVERLAPPED *ov, int timeout, struct signal_info *sig_info)
void dco_win_del_iroute_ipv4(dco_context_t *dco, in_addr_t dst, unsigned int netbits)
bool dco_win_supports_multipeer(void)
int dco_get_peer_stats_multi(dco_context_t *dco, const bool raise_sigusr1_on_err)
void dco_win_del_iroute_ipv6(dco_context_t *dco, struct in6_addr dst, unsigned int netbits)
int dco_get_peer_stats_fallback(struct context *c, const bool raise_sigusr1_on_err)
static void dco_wait_ready(DWORD idx)
int dco_set_peer(dco_context_t *dco, unsigned int peerid, int keepalive_interval, int keepalive_timeout, int mss)
int dco_swap_keys(dco_context_t *dco, unsigned int peer_id)
void ovpn_dco_init_mp(dco_context_t *dco, const char *dev_node)
Initializes the DCO adapter in multipeer mode and sets it to "connected" state.
int dco_new_peer(dco_context_t *dco, unsigned int peerid, socket_descriptor_t sd, struct sockaddr *localaddr, struct sockaddr *remoteaddr, const struct in_addr *vpn_ipv4, const struct in6_addr *vpn_ipv6)
int dco_get_peer_stats(struct context *c, const bool raise_sigusr1_on_err)
static void dco_handle_overlapped_success(dco_context_t *dco, bool queued)
Handles successful completion of overlapped operation.
static bool dco_get_version(OVPN_VERSION *version)
Gets version of dco-win driver.
void dco_p2p_new_peer(HANDLE handle, OVERLAPPED *ov, struct link_socket *sock, struct signal_info *sig_info)
void dco_win_add_iroute_ipv4(dco_context_t *dco, in_addr_t dst, unsigned int netbits, unsigned int peer_id)
void dco_event_set(dco_context_t *dco, struct event_set *es, void *arg)
int dco_new_key(dco_context_t *dco, unsigned int peerid, int keyid, dco_key_slot_t slot, const uint8_t *encrypt_key, const uint8_t *encrypt_iv, const uint8_t *decrypt_key, const uint8_t *decrypt_iv, const char *ciphername, bool epoch)
static void event_ctl(struct event_set *es, event_t event, unsigned int rwflags, void *arg)
int get_server_poll_remaining_time(const struct event_timeout *server_poll_timeout)
void process_incoming_dco(dco_context_t *dco)
Process an incoming DCO message (from kernel space).
Interface functions to the internal and external multiplexers.
static SERVICE_STATUS status
void management_sleep(const int n)
A sleep function that services the management layer for n seconds rather than doing nothing.
Header file for server-mode related structures and functions.
void multi_process_incoming_dco(dco_context_t *dco)
Process an incoming DCO message (from kernel space).
#define MODE_POINT_TO_POINT
#define OVPN_GET_PEER_STATS
#define OVPN_IOCTL_GET_STATS
#define OVPN_IOCTL_NEW_KEY_V2
#define OVPN_IOCTL_GET_VERSION
struct _OVPN_MP_IROUTE OVPN_MP_IROUTE
#define OVPN_IOCTL_SWAP_KEYS
#define OVPN_IOCTL_NEW_KEY
struct _OVPN_MP_DEL_PEER OVPN_MP_DEL_PEER
struct _OVPN_MP_NEW_PEER OVPN_MP_NEW_PEER
#define OVPN_IOCTL_NOTIFY_EVENT
struct _OVPN_STATS OVPN_STATS
#define OVPN_IOCTL_MP_DEL_IROUTE
struct _OVPN_MP_START_VPN OVPN_MP_START_VPN
#define OVPN_IOCTL_MP_SET_PEER
struct _OVPN_CRYPTO_DATA_V2 OVPN_CRYPTO_DATA_V2
#define OVPN_IOCTL_MP_SWAP_KEYS
#define OVPN_IOCTL_GET_PEER_STATS
struct _OVPN_MP_SWAP_KEYS OVPN_MP_SWAP_KEYS
#define OVPN_IOCTL_SET_PEER
#define OVPN_IOCTL_NEW_PEER
#define OVPN_IOCTL_MP_ADD_IROUTE
#define CRYPTO_OPTIONS_EPOCH
#define OVPN_IOCTL_START_VPN
#define OVPN_IOCTL_MP_NEW_PEER
#define OVPN_IOCTL_SET_MODE
#define OVPN_IOCTL_DEL_PEER
#define OVPN_IOCTL_MP_START_VPN
struct _OVPN_VERSION OVPN_VERSION
struct _OVPN_CRYPTO_DATA OVPN_CRYPTO_DATA
struct _OVPN_MP_SET_PEER OVPN_MP_SET_PEER
#define OVPN_IOCTL_MP_DEL_PEER
struct _OVPN_PEER_STATS OVPN_PEER_STATS
void register_signal(struct signal_info *si, int signum, const char *signal_text)
Register a soft signal in the signal_info struct si respecting priority.
static void get_signal(volatile int *sig)
Copy the global signal_received (if non-zero) to the passed-in argument sig.
const char * print_in6_addr(struct in6_addr a6, unsigned int flags, struct gc_arena *gc)
const char * print_in_addr_t(in_addr_t addr, unsigned int flags, struct gc_arena *gc)
const char * addr_family_name(int af)
Control Channel Common Data Structures.
OVPN_KEY_DIRECTION Decrypt
OVPN_KEY_DIRECTION Encrypt
OVPN_CIPHER_ALG CipherAlg
unsigned char NonceTail[8]
union _OVPN_MP_NEW_PEER::@154222247220254132247112372341347172022241014216 Local
union _OVPN_MP_NEW_PEER::@336125357256240101005276246004055135062237254057 Remote
union _OVPN_MP_START_VPN::@001225273056113363034117247127012245227164361074 ListenAddress
union _OVPN_NEW_PEER::@141250316313243125126215064345100320263262322310 Local
union _OVPN_NEW_PEER::@237172216164222172232202270364342002262023021255 Remote
LONG64 TransportBytesSent
LONG64 TransportBytesReceived
Wrapper structure for dynamically allocated memory.
struct tuntap * tuntap
Tun/tap virtual network interface.
Level 2 context containing state that is reset on both SIGHUP and SIGUSR1 restarts.
counter_type dco_read_bytes
counter_type tun_read_bytes
counter_type dco_write_bytes
struct tls_multi * tls_multi
TLS state structure for this VPN tunnel.
counter_type tun_write_bytes
Contains all state information for one tunnel.
int mode
Role of this context within the OpenVPN process.
struct context_2 c2
Level 2 context.
struct options options
Options loaded from command line or configuration file.
struct context_1 c1
Level 1 context.
Garbage collection arena used to keep track of dynamically allocated memory.
struct addrinfo * bind_local
struct addrinfo * current_remote
struct link_socket_addr * lsa
struct event_timeout * server_poll_timeout
struct link_socket_info info
Server-mode state structure for one single VPN tunnel.
struct context context
The context structure storing state for this VPN tunnel.
volatile int signal_received
int dco_peer_id
This is the handle that DCO uses to identify this session with the kernel.
SOCKET socket_descriptor_t
void tun_open_device(struct tuntap *tt, const char *dev_node, const char **device_guid, struct gc_arena *gc)
static bool tuntap_defined(const struct tuntap *tt)
#define IOSTATE_IMMEDIATE_RETURN