mirror of
https://github.com/SoftEtherVPN/SoftEtherVPN.git
synced 2024-12-26 01:59:53 +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:
parent
cd850c07ae
commit
8685fe0da1
@ -2,21 +2,19 @@
|
||||
|
||||
#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)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
container_1 = *(PROTO_CONTAINER **)p1;
|
||||
container_2 = *(PROTO_CONTAINER **)p2;
|
||||
|
||||
return false;
|
||||
return StrCmpi(container_1->Name, container_2->Name);
|
||||
}
|
||||
|
||||
int ProtoSessionCompare(void *p1, void *p2)
|
||||
@ -126,15 +124,15 @@ PROTO *ProtoNew(CEDAR *cedar)
|
||||
|
||||
proto = Malloc(sizeof(PROTO));
|
||||
proto->Cedar = cedar;
|
||||
proto->Impls = NewList(ProtoImplCompare);
|
||||
proto->Containers = NewList(ProtoContainerCompare);
|
||||
proto->Sessions = NewHashList(ProtoSessionHash, ProtoSessionCompare, 0, true);
|
||||
|
||||
AddRef(cedar->ref);
|
||||
|
||||
// OpenVPN
|
||||
ProtoImplAdd(proto, OvsGetProtoImpl());
|
||||
Add(proto->Containers, ProtoContainerNew(OvsGetProtoImpl()));
|
||||
// SSTP
|
||||
ProtoImplAdd(proto, SstpGetProtoImpl());
|
||||
Add(proto->Containers, ProtoContainerNew(SstpGetProtoImpl()));
|
||||
|
||||
proto->UdpListener = NewUdpListener(ProtoHandleDatagrams, proto, &cedar->Server->ListenIP);
|
||||
|
||||
@ -156,28 +154,49 @@ void ProtoDelete(PROTO *proto)
|
||||
{
|
||||
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);
|
||||
ReleaseHashList(proto->Sessions);
|
||||
ReleaseList(proto->Impls);
|
||||
ReleaseCedar(proto->Cedar);
|
||||
Free(proto);
|
||||
}
|
||||
|
||||
bool ProtoImplAdd(PROTO *proto, PROTO_IMPL *impl) {
|
||||
if (proto == NULL || impl == NULL)
|
||||
PROTO_CONTAINER *ProtoContainerNew(const PROTO_IMPL *impl)
|
||||
{
|
||||
UINT i;
|
||||
PROTO_CONTAINER *container;
|
||||
|
||||
if (impl == NULL)
|
||||
{
|
||||
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;
|
||||
|
||||
@ -186,45 +205,47 @@ PROTO_IMPL *ProtoImplDetect(PROTO *proto, const PROTO_MODE mode, const UCHAR *da
|
||||
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);
|
||||
if (impl->IsPacketForMe == NULL || impl->IsPacketForMe(mode, data, size) == false)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
const PROTO_CONTAINER *container = LIST_DATA(proto->Containers, i);
|
||||
const PROTO_IMPL *impl = container->Impl;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
Debug("ProtoImplDetect(): %s detected\n", impl->Name());
|
||||
return impl;
|
||||
if (impl->IsPacketForMe != NULL && impl->IsPacketForMe(mode, data, size))
|
||||
{
|
||||
Debug("ProtoDetect(): %s detected\n", container->Name);
|
||||
return container;
|
||||
}
|
||||
}
|
||||
|
||||
Debug("ProtoImplDetect(): unrecognized protocol\n");
|
||||
Debug("ProtoDetect(): unrecognized protocol\n");
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
session = ZeroMalloc(sizeof(PROTO_SESSION));
|
||||
impl = container->Impl;
|
||||
|
||||
session = ZeroMalloc(sizeof(PROTO_SESSION));
|
||||
session->SockEvent = NewSockEvent();
|
||||
session->InterruptManager = NewInterruptManager();
|
||||
|
||||
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);
|
||||
FreeInterruptManager(session->InterruptManager);
|
||||
@ -313,7 +334,7 @@ bool ProtoSetUdpPorts(PROTO *proto, const LIST *ports)
|
||||
|
||||
bool ProtoHandleConnection(PROTO *proto, SOCK *sock, const char *protocol)
|
||||
{
|
||||
const PROTO_IMPL *impl = NULL;
|
||||
const PROTO_IMPL *impl;
|
||||
void *impl_data = NULL;
|
||||
|
||||
UCHAR *buf;
|
||||
@ -327,44 +348,51 @@ bool ProtoHandleConnection(PROTO *proto, SOCK *sock, const char *protocol)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (protocol != NULL)
|
||||
{
|
||||
UINT i;
|
||||
for (i = 0; i < LIST_NUM(proto->Impls); ++i)
|
||||
const PROTO_CONTAINER *container = NULL;
|
||||
|
||||
if (protocol != NULL)
|
||||
{
|
||||
const PROTO_IMPL *tmp = LIST_DATA(proto->Impls, i);
|
||||
if (StrCmp(tmp->Name(), protocol) == 0)
|
||||
UINT i;
|
||||
for (i = 0; i < LIST_NUM(proto->Containers); ++i)
|
||||
{
|
||||
impl = tmp;
|
||||
break;
|
||||
const PROTO_CONTAINER *tmp = LIST_DATA(proto->Containers, i);
|
||||
if (StrCmp(tmp->Name, protocol) == 0)
|
||||
{
|
||||
impl = container->Impl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
UCHAR tmp[PROTO_CHECK_BUFFER_SIZE];
|
||||
if (Peek(sock, tmp, sizeof(tmp)) == 0)
|
||||
else
|
||||
{
|
||||
UCHAR tmp[PROTO_CHECK_BUFFER_SIZE];
|
||||
|
||||
if (Peek(sock, tmp, sizeof(tmp)) == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
container = ProtoDetect(proto, PROTO_MODE_TCP, tmp, sizeof(tmp));
|
||||
}
|
||||
|
||||
if (container == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
impl = ProtoImplDetect(proto, PROTO_MODE_TCP, tmp, sizeof(tmp));
|
||||
}
|
||||
impl = container->Impl;
|
||||
|
||||
if (impl == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
im = NewInterruptManager();
|
||||
se = NewSockEvent();
|
||||
|
||||
im = NewInterruptManager();
|
||||
se = NewSockEvent();
|
||||
|
||||
if (impl->Init != NULL && impl->Init(&impl_data, proto->Cedar, im, se, sock->CipherName, sock->RemoteHostname) == false)
|
||||
{
|
||||
Debug("ProtoHandleConnection(): failed to initialize %s\n", impl->Name());
|
||||
FreeInterruptManager(im);
|
||||
ReleaseSockEvent(se);
|
||||
return false;
|
||||
if (impl->Init != NULL && impl->Init(&impl_data, proto->Cedar, im, se, sock->CipherName, sock->RemoteHostname) == false)
|
||||
{
|
||||
Debug("ProtoHandleConnection(): failed to initialize %s\n", container->Name);
|
||||
FreeInterruptManager(im);
|
||||
ReleaseSockEvent(se);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
SetTimeout(sock, TIMEOUT_INFINITE);
|
||||
@ -484,13 +512,13 @@ void ProtoHandleDatagrams(UDPLISTENER *listener, LIST *datagrams)
|
||||
session = SearchHash(sessions, &tmp);
|
||||
if (session == NULL)
|
||||
{
|
||||
tmp.Impl = ProtoImplDetect(proto, PROTO_MODE_UDP, datagram->Data, datagram->Size);
|
||||
if (tmp.Impl == NULL)
|
||||
const PROTO_CONTAINER *container = ProtoDetect(proto, PROTO_MODE_UDP, datagram->Data, datagram->Size);
|
||||
if (container == NULL)
|
||||
{
|
||||
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)
|
||||
{
|
||||
continue;
|
||||
@ -539,7 +567,7 @@ void ProtoSessionThread(THREAD *thread, void *param)
|
||||
bool ok;
|
||||
UINT interval;
|
||||
void *param = session->Param;
|
||||
PROTO_IMPL *impl = session->Impl;
|
||||
const PROTO_IMPL *impl = session->Impl;
|
||||
LIST *received = session->DatagramsIn;
|
||||
LIST *to_send = session->DatagramsOut;
|
||||
|
||||
|
@ -17,7 +17,7 @@ typedef enum PROTO_MODE
|
||||
typedef struct PROTO
|
||||
{
|
||||
CEDAR *Cedar;
|
||||
LIST *Impls;
|
||||
LIST *Containers;
|
||||
HASH_LIST *Sessions;
|
||||
UDPLISTENER *UdpListener;
|
||||
} PROTO;
|
||||
@ -32,11 +32,17 @@ typedef struct PROTO_IMPL
|
||||
bool (*ProcessDatagrams)(void *param, LIST *in, LIST *out);
|
||||
} PROTO_IMPL;
|
||||
|
||||
typedef struct PROTO_CONTAINER
|
||||
{
|
||||
const char *Name;
|
||||
const PROTO_IMPL *Impl;
|
||||
} PROTO_CONTAINER;
|
||||
|
||||
typedef struct PROTO_SESSION
|
||||
{
|
||||
void *Param;
|
||||
PROTO *Proto;
|
||||
PROTO_IMPL *Impl;
|
||||
const PROTO *Proto;
|
||||
const PROTO_IMPL *Impl;
|
||||
IP SrcIp;
|
||||
USHORT SrcPort;
|
||||
IP DstIp;
|
||||
@ -50,7 +56,7 @@ typedef struct PROTO_SESSION
|
||||
volatile bool Halt;
|
||||
} PROTO_SESSION;
|
||||
|
||||
int ProtoImplCompare(void *p1, void *p2);
|
||||
int ProtoContainerCompare(void *p1, void *p2);
|
||||
int ProtoSessionCompare(void *p1, void *p2);
|
||||
|
||||
UINT ProtoSessionHash(void *p);
|
||||
@ -58,10 +64,12 @@ UINT ProtoSessionHash(void *p);
|
||||
PROTO *ProtoNew(CEDAR *cedar);
|
||||
void ProtoDelete(PROTO *proto);
|
||||
|
||||
bool ProtoImplAdd(PROTO *proto, PROTO_IMPL *impl);
|
||||
PROTO_IMPL *ProtoImplDetect(PROTO *proto, const PROTO_MODE mode, const UCHAR *data, const UINT size);
|
||||
PROTO_CONTAINER *ProtoContainerNew(const PROTO_IMPL *impl);
|
||||
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);
|
||||
|
||||
bool ProtoSetListenIP(PROTO *proto, const IP *ip);
|
||||
|
Loading…
Reference in New Issue
Block a user