1
0
mirror of https://github.com/SoftEtherVPN/SoftEtherVPN.git synced 2024-11-22 09:29:52 +03:00

Cedar/Proto: introduce PROTO_CONTAINER, to store data for each implementation

ProtoImplDetect() is renamed to ProtoDetect(), because it now returns a pointer to a PROTO_CONTAINER (if successful).
This commit is contained in:
Davide Beatrici 2020-07-18 17:54:36 +02:00
parent cd850c07ae
commit 8685fe0da1
2 changed files with 109 additions and 73 deletions

View File

@ -2,21 +2,19 @@
#include "Proto_OpenVPN.h" #include "Proto_OpenVPN.h"
int ProtoImplCompare(void *p1, void *p2) int ProtoContainerCompare(void *p1, void *p2)
{ {
PROTO_IMPL *impl_1 = p1, *impl_2 = p2; PROTO_CONTAINER *container_1, *container_2;
if (impl_1 == NULL || impl_2 == NULL) if (p1 == NULL || p2 == NULL)
{ {
return 0; return (p1 == NULL && p2 == NULL ? 0 : (p1 == NULL ? -1 : 1));
} }
if (StrCmp(impl_1->Name(), impl_2->Name()) == 0) container_1 = *(PROTO_CONTAINER **)p1;
{ container_2 = *(PROTO_CONTAINER **)p2;
return true;
}
return false; return StrCmpi(container_1->Name, container_2->Name);
} }
int ProtoSessionCompare(void *p1, void *p2) int ProtoSessionCompare(void *p1, void *p2)
@ -126,15 +124,15 @@ PROTO *ProtoNew(CEDAR *cedar)
proto = Malloc(sizeof(PROTO)); proto = Malloc(sizeof(PROTO));
proto->Cedar = cedar; proto->Cedar = cedar;
proto->Impls = NewList(ProtoImplCompare); proto->Containers = NewList(ProtoContainerCompare);
proto->Sessions = NewHashList(ProtoSessionHash, ProtoSessionCompare, 0, true); proto->Sessions = NewHashList(ProtoSessionHash, ProtoSessionCompare, 0, true);
AddRef(cedar->ref); AddRef(cedar->ref);
// OpenVPN // OpenVPN
ProtoImplAdd(proto, OvsGetProtoImpl()); Add(proto->Containers, ProtoContainerNew(OvsGetProtoImpl()));
// SSTP // SSTP
ProtoImplAdd(proto, SstpGetProtoImpl()); Add(proto->Containers, ProtoContainerNew(SstpGetProtoImpl()));
proto->UdpListener = NewUdpListener(ProtoHandleDatagrams, proto, &cedar->Server->ListenIP); proto->UdpListener = NewUdpListener(ProtoHandleDatagrams, proto, &cedar->Server->ListenIP);
@ -156,28 +154,49 @@ void ProtoDelete(PROTO *proto)
{ {
ProtoDeleteSession(LIST_DATA(proto->Sessions->AllList, i)); ProtoDeleteSession(LIST_DATA(proto->Sessions->AllList, i));
} }
ReleaseHashList(proto->Sessions);
for (i = 0; i < LIST_NUM(proto->Containers); ++i)
{
ProtoContainerDelete(LIST_DATA(proto->Containers, i));
}
ReleaseList(proto->Containers);
FreeUdpListener(proto->UdpListener); FreeUdpListener(proto->UdpListener);
ReleaseHashList(proto->Sessions);
ReleaseList(proto->Impls);
ReleaseCedar(proto->Cedar); ReleaseCedar(proto->Cedar);
Free(proto); Free(proto);
} }
bool ProtoImplAdd(PROTO *proto, PROTO_IMPL *impl) { PROTO_CONTAINER *ProtoContainerNew(const PROTO_IMPL *impl)
if (proto == NULL || impl == NULL) {
UINT i;
PROTO_CONTAINER *container;
if (impl == NULL)
{ {
return false; return false;
} }
Add(proto->Impls, impl); container = Malloc(sizeof(PROTO_CONTAINER));
container->Name = impl->Name();
container->Impl = impl;
Debug("ProtoImplAdd(): added %s\n", impl->Name()); Debug("ProtoContainerNew(): %s\n", container->Name);
return true; return container;
} }
PROTO_IMPL *ProtoImplDetect(PROTO *proto, const PROTO_MODE mode, const UCHAR *data, const UINT size) void ProtoContainerDelete(PROTO_CONTAINER *container)
{
if (container == NULL)
{
return;
}
Free(container);
}
const PROTO_CONTAINER *ProtoDetect(const PROTO *proto, const PROTO_MODE mode, const UCHAR *data, const UINT size)
{ {
UINT i; UINT i;
@ -186,45 +205,47 @@ PROTO_IMPL *ProtoImplDetect(PROTO *proto, const PROTO_MODE mode, const UCHAR *da
return NULL; return NULL;
} }
for (i = 0; i < LIST_NUM(proto->Impls); ++i) for (i = 0; i < LIST_NUM(proto->Containers); ++i)
{ {
PROTO_IMPL *impl = LIST_DATA(proto->Impls, i); const PROTO_CONTAINER *container = LIST_DATA(proto->Containers, i);
if (impl->IsPacketForMe == NULL || impl->IsPacketForMe(mode, data, size) == false) const PROTO_IMPL *impl = container->Impl;
{
continue;
}
if (StrCmp(impl->Name(), "OpenVPN") == 0 && proto->Cedar->Server->DisableOpenVPNServer) if (StrCmp(impl->Name(), "OpenVPN") == 0 && proto->Cedar->Server->DisableOpenVPNServer)
{ {
Debug("ProtoImplDetect(): OpenVPN detected, but it's disabled\n"); Debug("ProtoDetect(): OpenVPN detected, but it's disabled\n");
continue; continue;
} }
Debug("ProtoImplDetect(): %s detected\n", impl->Name()); if (impl->IsPacketForMe != NULL && impl->IsPacketForMe(mode, data, size))
return impl; {
Debug("ProtoDetect(): %s detected\n", container->Name);
return container;
}
} }
Debug("ProtoImplDetect(): unrecognized protocol\n"); Debug("ProtoDetect(): unrecognized protocol\n");
return NULL; return NULL;
} }
PROTO_SESSION *ProtoNewSession(PROTO *proto, PROTO_IMPL *impl, const IP *src_ip, const USHORT src_port, const IP *dst_ip, const USHORT dst_port) PROTO_SESSION *ProtoNewSession(PROTO *proto, const PROTO_CONTAINER *container, const IP *src_ip, const USHORT src_port, const IP *dst_ip, const USHORT dst_port)
{ {
PROTO_SESSION *session; PROTO_SESSION *session;
const PROTO_IMPL *impl;
if (impl == NULL || src_ip == NULL || src_port == 0 || dst_ip == NULL || dst_port == 0) if (container == NULL || src_ip == NULL || src_port == 0 || dst_ip == NULL || dst_port == 0)
{ {
return NULL; return NULL;
} }
session = ZeroMalloc(sizeof(PROTO_SESSION)); impl = container->Impl;
session = ZeroMalloc(sizeof(PROTO_SESSION));
session->SockEvent = NewSockEvent(); session->SockEvent = NewSockEvent();
session->InterruptManager = NewInterruptManager(); session->InterruptManager = NewInterruptManager();
if (impl->Init != NULL && impl->Init(&session->Param, proto->Cedar, session->InterruptManager, session->SockEvent, NULL, NULL) == false) if (impl->Init != NULL && impl->Init(&session->Param, proto->Cedar, session->InterruptManager, session->SockEvent, NULL, NULL) == false)
{ {
Debug("ProtoNewSession(): failed to initialize %s\n", impl->Name()); Debug("ProtoNewSession(): failed to initialize %s\n", container->Name);
ReleaseSockEvent(session->SockEvent); ReleaseSockEvent(session->SockEvent);
FreeInterruptManager(session->InterruptManager); FreeInterruptManager(session->InterruptManager);
@ -313,7 +334,7 @@ bool ProtoSetUdpPorts(PROTO *proto, const LIST *ports)
bool ProtoHandleConnection(PROTO *proto, SOCK *sock, const char *protocol) bool ProtoHandleConnection(PROTO *proto, SOCK *sock, const char *protocol)
{ {
const PROTO_IMPL *impl = NULL; const PROTO_IMPL *impl;
void *impl_data = NULL; void *impl_data = NULL;
UCHAR *buf; UCHAR *buf;
@ -327,44 +348,51 @@ bool ProtoHandleConnection(PROTO *proto, SOCK *sock, const char *protocol)
return false; return false;
} }
if (protocol != NULL)
{ {
UINT i; const PROTO_CONTAINER *container = NULL;
for (i = 0; i < LIST_NUM(proto->Impls); ++i)
if (protocol != NULL)
{ {
const PROTO_IMPL *tmp = LIST_DATA(proto->Impls, i); UINT i;
if (StrCmp(tmp->Name(), protocol) == 0) for (i = 0; i < LIST_NUM(proto->Containers); ++i)
{ {
impl = tmp; const PROTO_CONTAINER *tmp = LIST_DATA(proto->Containers, i);
break; if (StrCmp(tmp->Name, protocol) == 0)
{
impl = container->Impl;
break;
}
} }
} }
} else
else {
{ UCHAR tmp[PROTO_CHECK_BUFFER_SIZE];
UCHAR tmp[PROTO_CHECK_BUFFER_SIZE];
if (Peek(sock, tmp, sizeof(tmp)) == 0) if (Peek(sock, tmp, sizeof(tmp)) == 0)
{
return false;
}
container = ProtoDetect(proto, PROTO_MODE_TCP, tmp, sizeof(tmp));
}
if (container == NULL)
{ {
return false; return false;
} }
impl = ProtoImplDetect(proto, PROTO_MODE_TCP, tmp, sizeof(tmp)); impl = container->Impl;
}
if (impl == NULL) im = NewInterruptManager();
{ se = NewSockEvent();
return false;
}
im = NewInterruptManager(); if (impl->Init != NULL && impl->Init(&impl_data, proto->Cedar, im, se, sock->CipherName, sock->RemoteHostname) == false)
se = NewSockEvent(); {
Debug("ProtoHandleConnection(): failed to initialize %s\n", container->Name);
if (impl->Init != NULL && impl->Init(&impl_data, proto->Cedar, im, se, sock->CipherName, sock->RemoteHostname) == false) FreeInterruptManager(im);
{ ReleaseSockEvent(se);
Debug("ProtoHandleConnection(): failed to initialize %s\n", impl->Name()); return false;
FreeInterruptManager(im); }
ReleaseSockEvent(se);
return false;
} }
SetTimeout(sock, TIMEOUT_INFINITE); SetTimeout(sock, TIMEOUT_INFINITE);
@ -484,13 +512,13 @@ void ProtoHandleDatagrams(UDPLISTENER *listener, LIST *datagrams)
session = SearchHash(sessions, &tmp); session = SearchHash(sessions, &tmp);
if (session == NULL) if (session == NULL)
{ {
tmp.Impl = ProtoImplDetect(proto, PROTO_MODE_UDP, datagram->Data, datagram->Size); const PROTO_CONTAINER *container = ProtoDetect(proto, PROTO_MODE_UDP, datagram->Data, datagram->Size);
if (tmp.Impl == NULL) if (container == NULL)
{ {
continue; continue;
} }
session = ProtoNewSession(proto, tmp.Impl, &tmp.SrcIp, tmp.SrcPort, &tmp.DstIp, tmp.DstPort); session = ProtoNewSession(proto, container, &tmp.SrcIp, tmp.SrcPort, &tmp.DstIp, tmp.DstPort);
if (session == NULL) if (session == NULL)
{ {
continue; continue;
@ -539,7 +567,7 @@ void ProtoSessionThread(THREAD *thread, void *param)
bool ok; bool ok;
UINT interval; UINT interval;
void *param = session->Param; void *param = session->Param;
PROTO_IMPL *impl = session->Impl; const PROTO_IMPL *impl = session->Impl;
LIST *received = session->DatagramsIn; LIST *received = session->DatagramsIn;
LIST *to_send = session->DatagramsOut; LIST *to_send = session->DatagramsOut;

View File

@ -17,7 +17,7 @@ typedef enum PROTO_MODE
typedef struct PROTO typedef struct PROTO
{ {
CEDAR *Cedar; CEDAR *Cedar;
LIST *Impls; LIST *Containers;
HASH_LIST *Sessions; HASH_LIST *Sessions;
UDPLISTENER *UdpListener; UDPLISTENER *UdpListener;
} PROTO; } PROTO;
@ -32,11 +32,17 @@ typedef struct PROTO_IMPL
bool (*ProcessDatagrams)(void *param, LIST *in, LIST *out); bool (*ProcessDatagrams)(void *param, LIST *in, LIST *out);
} PROTO_IMPL; } PROTO_IMPL;
typedef struct PROTO_CONTAINER
{
const char *Name;
const PROTO_IMPL *Impl;
} PROTO_CONTAINER;
typedef struct PROTO_SESSION typedef struct PROTO_SESSION
{ {
void *Param; void *Param;
PROTO *Proto; const PROTO *Proto;
PROTO_IMPL *Impl; const PROTO_IMPL *Impl;
IP SrcIp; IP SrcIp;
USHORT SrcPort; USHORT SrcPort;
IP DstIp; IP DstIp;
@ -50,7 +56,7 @@ typedef struct PROTO_SESSION
volatile bool Halt; volatile bool Halt;
} PROTO_SESSION; } PROTO_SESSION;
int ProtoImplCompare(void *p1, void *p2); int ProtoContainerCompare(void *p1, void *p2);
int ProtoSessionCompare(void *p1, void *p2); int ProtoSessionCompare(void *p1, void *p2);
UINT ProtoSessionHash(void *p); UINT ProtoSessionHash(void *p);
@ -58,10 +64,12 @@ UINT ProtoSessionHash(void *p);
PROTO *ProtoNew(CEDAR *cedar); PROTO *ProtoNew(CEDAR *cedar);
void ProtoDelete(PROTO *proto); void ProtoDelete(PROTO *proto);
bool ProtoImplAdd(PROTO *proto, PROTO_IMPL *impl); PROTO_CONTAINER *ProtoContainerNew(const PROTO_IMPL *impl);
PROTO_IMPL *ProtoImplDetect(PROTO *proto, const PROTO_MODE mode, const UCHAR *data, const UINT size); void ProtoContainerDelete(PROTO_CONTAINER *container);
PROTO_SESSION *ProtoNewSession(PROTO *proto, PROTO_IMPL *impl, const IP *src_ip, const USHORT src_port, const IP *dst_ip, const USHORT dst_port); const PROTO_CONTAINER *ProtoDetect(const PROTO *proto, const PROTO_MODE mode, const UCHAR *data, const UINT size);
PROTO_SESSION *ProtoNewSession(PROTO *proto, const PROTO_CONTAINER *container, const IP *src_ip, const USHORT src_port, const IP *dst_ip, const USHORT dst_port);
void ProtoDeleteSession(PROTO_SESSION *session); void ProtoDeleteSession(PROTO_SESSION *session);
bool ProtoSetListenIP(PROTO *proto, const IP *ip); bool ProtoSetListenIP(PROTO *proto, const IP *ip);