Skip to content

Commit

Permalink
Move peer-specific data to separate struct
Browse files Browse the repository at this point in the history
In preparation to multipeer support, move peer-specific
data from OVPN_DEVICE to OvpnPeerContext.

Peers (so far single one) are stored in splay tree,
implemented with RTL_GENERIC_TABLE.

Fixes #56.

Signed-off-by: Lev Stipakov <[email protected]>
Signed-off-by: Leon Dang <[email protected]>

Co-authored-by: Leon Dang <[email protected]>
  • Loading branch information
lstipakov and ldnetgate committed Dec 28, 2023
1 parent 794f731 commit 06099dc
Show file tree
Hide file tree
Showing 12 changed files with 351 additions and 129 deletions.
52 changes: 50 additions & 2 deletions Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
* ovpn-dco-win OpenVPN protocol accelerator for Windows
*
* Copyright (C) 2020-2021 OpenVPN Inc <[email protected]>
* Copyright (C) 2023 Rubicon Communications LLC (Netgate)
*
* Author: Lev Stipakov <[email protected]>
*
Expand Down Expand Up @@ -309,8 +310,6 @@ VOID OvpnEvtFileCleanup(WDFFILEOBJECT fileObject) {
// peer might already be deleted
(VOID)OvpnPeerDel(device);

InterlockedExchange(&device->UserspacePid, 0);

if (device->Adapter != NULL) {
OvpnAdapterSetLinkState(OvpnGetAdapterContext(device->Adapter), MediaConnectStateDisconnected);
}
Expand Down Expand Up @@ -476,10 +475,59 @@ OvpnEvtDeviceAdd(WDFDRIVER wdfDriver, PWDFDEVICE_INIT deviceInit) {

GOTO_IF_NOT_NT_SUCCESS(done, status, OvpnCryptoInitAlgHandles(&device->AesAlgHandle, &device->ChachaAlgHandle));

// Initialize peers tree
RtlInitializeGenericTable(&device->Peers, OvpnPeerCompareByPeerIdRoutine, OvpnPeerAllocateRoutine, OvpnPeerFreeRoutine, NULL);

LOG_IF_NOT_NT_SUCCESS(status = OvpnAdapterCreate(device));

done:
LOG_EXIT();

return status;
}

_Use_decl_annotations_
NTSTATUS
OvpnAddPeer(POVPN_DEVICE device, OvpnPeerContext* peer)
{
NTSTATUS status;
BOOLEAN newElem;

RtlInsertElementGenericTable(&device->Peers, (PVOID)&peer, sizeof(OvpnPeerContext*), &newElem);

if (newElem) {
status = STATUS_SUCCESS;
}
else {
LOG_ERROR("Unable to add new peer");
status = STATUS_NO_MEMORY;
}
return status;
}

_Use_decl_annotations_
VOID
OvpnFlushPeers(POVPN_DEVICE device) {
OvpnCleanupPeerTable(&device->Peers);
}

_Use_decl_annotations_
VOID
OvpnCleanupPeerTable(RTL_GENERIC_TABLE* peers)
{
while (!RtlIsGenericTableEmpty(peers)) {
PVOID ptr = RtlGetElementGenericTable(peers, 0);
OvpnPeerContext* peer = *(OvpnPeerContext**)ptr;
RtlDeleteElementGenericTable(peers, ptr);

OvpnPeerCtxFree(peer);
}
}

_Use_decl_annotations_
OvpnPeerContext*
OvpnGetFirstPeer(RTL_GENERIC_TABLE* peers)
{
OvpnPeerContext** ptr = (OvpnPeerContext**)RtlGetElementGenericTable(peers, 0);
return ptr ? (OvpnPeerContext*)*ptr : NULL;
}
49 changes: 27 additions & 22 deletions Driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,43 +76,48 @@ struct OVPN_DEVICE {

OVPN_STATS Stats;

// keepalive interval in seconds
_Guarded_by_(SpinLock)
LONG KeepaliveInterval;

// keepalive timeout in seconds
_Guarded_by_(SpinLock)
LONG KeepaliveTimeout;

// timer used to send periodic ping messages to the server if no data has been sent within the past KeepaliveInterval seconds
_Guarded_by_(SpinLock)
WDFTIMER KeepaliveXmitTimer;

// timer used to report keepalive timeout error to userspace when no data has been received for KeepaliveTimeout seconds
_Guarded_by_(SpinLock)
WDFTIMER KeepaliveRecvTimer;

BCRYPT_ALG_HANDLE AesAlgHandle;
BCRYPT_ALG_HANDLE ChachaAlgHandle;

// set from the userspace, defines TCP Maximum Segment Size
_Guarded_by_(SpinLock)
UINT16 MSS;

_Guarded_by_(SpinLock)
OvpnCryptoContext CryptoContext;

_Guarded_by_(SpinLock)
OvpnSocket Socket;

_Guarded_by_(SpinLock)
NETADAPTER Adapter;

// pid of userspace process which called NEW_PEER
_Interlocked_
LONG UserspacePid;
_Guarded_by_(SpinLock)
RTL_GENERIC_TABLE Peers;

SIZE_T CryptoOverhead;
};

typedef OVPN_DEVICE * POVPN_DEVICE;

WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(OVPN_DEVICE, OvpnGetDeviceContext)

static inline
BOOLEAN
OvpnHasPeers(_In_ POVPN_DEVICE device)
{
return !RtlIsGenericTableEmpty(&device->Peers);
}

struct OvpnPeerContext;

_Must_inspect_result_
NTSTATUS
OvpnAddPeer(_In_ POVPN_DEVICE device, _In_ OvpnPeerContext* PeerCtx);

VOID
OvpnFlushPeers(_In_ POVPN_DEVICE device);

VOID
OvpnCleanupPeerTable(_In_ RTL_GENERIC_TABLE*);

_Must_inspect_result_
OvpnPeerContext*
OvpnGetFirstPeer(_In_ RTL_GENERIC_TABLE*);
4 changes: 0 additions & 4 deletions crypto.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -263,17 +263,13 @@ OvpnCryptoNewKey(OvpnCryptoContext* cryptoContext, POVPN_CRYPTO_DATA cryptoData,
keySlot->KeyId = cryptoData->KeyId;
keySlot->PeerId = cryptoData->PeerId;

cryptoContext->CryptoOverhead = AEAD_CRYPTO_OVERHEAD;

LOG_INFO("New key", TraceLoggingValue(cryptoData->CipherAlg == OVPN_CIPHER_ALG_AES_GCM ? "aes-gcm" : "chacha20-poly1305", "alg"),
TraceLoggingValue(cryptoData->KeyId, "KeyId"), TraceLoggingValue(cryptoData->KeyId, "PeerId"));
}
else if (cryptoData->CipherAlg == OVPN_CIPHER_ALG_NONE) {
cryptoContext->Encrypt = OvpnCryptoEncryptNone;
cryptoContext->Decrypt = OvpnCryptoDecryptNone;

cryptoContext->CryptoOverhead = NONE_CRYPTO_OVERHEAD;

LOG_INFO("Using cipher none");
}
else {
Expand Down
1 change: 1 addition & 0 deletions crypto.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
* ovpn-dco-win OpenVPN protocol accelerator for Windows
*
* Copyright (C) 2020-2021 OpenVPN Inc <[email protected]>
* Copyright (C) 2023 Rubicon Communications LLC (Netgate)
*
* Author: Lev Stipakov <[email protected]>
*
Expand Down
Loading

0 comments on commit 06099dc

Please sign in to comment.