mirror of
https://github.com/SoftEtherVPN/SoftEtherVPN.git
synced 2024-11-22 17:39:53 +03:00
Merge PR #1120: Cedar: implement UDP system in Proto
This commit is contained in:
commit
8fdf7302a5
@ -19,6 +19,102 @@ int ProtoImplCompare(void *p1, void *p2)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ProtoSessionCompare(void *p1, void *p2)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
PROTO_SESSION *session_1, *session_2;
|
||||||
|
|
||||||
|
if (p1 == NULL || p2 == NULL)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
session_1 = *(PROTO_SESSION **)p1;
|
||||||
|
session_2 = *(PROTO_SESSION **)p2;
|
||||||
|
|
||||||
|
// The source port must match
|
||||||
|
ret = COMPARE_RET(session_1->SrcPort, session_2->SrcPort);
|
||||||
|
if (ret != 0)
|
||||||
|
{
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The destination port must match
|
||||||
|
ret = COMPARE_RET(session_1->DstPort, session_2->DstPort);
|
||||||
|
if (ret != 0)
|
||||||
|
{
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The source IP address must match
|
||||||
|
ret = CmpIpAddr(&session_1->SrcIp, &session_2->SrcIp);
|
||||||
|
if (ret != 0)
|
||||||
|
{
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The destination IP address must match
|
||||||
|
return CmpIpAddr(&session_1->DstIp, &session_2->DstIp);
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT ProtoSessionHash(void *p)
|
||||||
|
{
|
||||||
|
IP *ip;
|
||||||
|
UINT ret = 0;
|
||||||
|
PROTO_SESSION *session = p;
|
||||||
|
|
||||||
|
if (session == NULL)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ip = &session->SrcIp;
|
||||||
|
if (IsIP6(ip))
|
||||||
|
{
|
||||||
|
UINT i;
|
||||||
|
for (i = 0; i < sizeof(ip->ipv6_addr); ++i)
|
||||||
|
{
|
||||||
|
ret += ip->ipv6_addr[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
ret += ip->ipv6_scope_id;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UINT i;
|
||||||
|
for (i = 0; i < sizeof(ip->addr); ++i)
|
||||||
|
{
|
||||||
|
ret += ip->addr[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret += session->SrcPort;
|
||||||
|
|
||||||
|
ip = &session->DstIp;
|
||||||
|
if (IsIP6(ip))
|
||||||
|
{
|
||||||
|
UINT i;
|
||||||
|
for (i = 0; i < sizeof(ip->ipv6_addr); ++i)
|
||||||
|
{
|
||||||
|
ret += ip->ipv6_addr[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
ret += ip->ipv6_scope_id;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UINT i;
|
||||||
|
for (i = 0; i < sizeof(ip->addr); ++i)
|
||||||
|
{
|
||||||
|
ret += ip->addr[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret += session->DstPort;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
PROTO *ProtoNew(CEDAR *cedar)
|
PROTO *ProtoNew(CEDAR *cedar)
|
||||||
{
|
{
|
||||||
PROTO *proto;
|
PROTO *proto;
|
||||||
@ -31,22 +127,36 @@ PROTO *ProtoNew(CEDAR *cedar)
|
|||||||
proto = Malloc(sizeof(PROTO));
|
proto = Malloc(sizeof(PROTO));
|
||||||
proto->Cedar = cedar;
|
proto->Cedar = cedar;
|
||||||
proto->Impls = NewList(ProtoImplCompare);
|
proto->Impls = NewList(ProtoImplCompare);
|
||||||
|
proto->Sessions = NewHashList(ProtoSessionHash, ProtoSessionCompare, 0, true);
|
||||||
|
|
||||||
AddRef(cedar->ref);
|
AddRef(cedar->ref);
|
||||||
|
|
||||||
// OpenVPN
|
// OpenVPN
|
||||||
ProtoImplAdd(proto, OvsGetProtoImpl());
|
ProtoImplAdd(proto, OvsGetProtoImpl());
|
||||||
|
|
||||||
|
proto->UdpListener = NewUdpListener(ProtoHandleDatagrams, proto, &cedar->Server->ListenIP);
|
||||||
|
|
||||||
return proto;
|
return proto;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProtoDelete(PROTO *proto)
|
void ProtoDelete(PROTO *proto)
|
||||||
{
|
{
|
||||||
|
UINT i = 0;
|
||||||
|
|
||||||
if (proto == NULL)
|
if (proto == NULL)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StopUdpListener(proto->UdpListener);
|
||||||
|
|
||||||
|
for (i = 0; i < HASH_LIST_NUM(proto->Sessions); ++i)
|
||||||
|
{
|
||||||
|
ProtoDeleteSession(LIST_DATA(proto->Sessions->AllList, i));
|
||||||
|
}
|
||||||
|
|
||||||
|
FreeUdpListener(proto->UdpListener);
|
||||||
|
ReleaseHashList(proto->Sessions);
|
||||||
ReleaseList(proto->Impls);
|
ReleaseList(proto->Impls);
|
||||||
ReleaseCedar(proto->Cedar);
|
ReleaseCedar(proto->Cedar);
|
||||||
Free(proto);
|
Free(proto);
|
||||||
@ -65,34 +175,140 @@ bool ProtoImplAdd(PROTO *proto, PROTO_IMPL *impl) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
PROTO_IMPL *ProtoImplDetect(PROTO *proto, SOCK *sock)
|
PROTO_IMPL *ProtoImplDetect(PROTO *proto, const PROTO_MODE mode, const UCHAR *data, const UINT size)
|
||||||
{
|
{
|
||||||
UCHAR buf[PROTO_CHECK_BUFFER_SIZE];
|
|
||||||
UINT i;
|
UINT i;
|
||||||
|
|
||||||
if (proto == NULL || sock == NULL)
|
if (proto == NULL || data == NULL || size == 0)
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Peek(sock, buf, sizeof(buf)) == 0)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < LIST_NUM(proto->Impls); ++i)
|
for (i = 0; i < LIST_NUM(proto->Impls); ++i)
|
||||||
{
|
{
|
||||||
PROTO_IMPL *impl = LIST_DATA(proto->Impls, i);
|
PROTO_IMPL *impl = LIST_DATA(proto->Impls, i);
|
||||||
if (impl->IsPacketForMe(buf, sizeof(buf)))
|
if (impl->IsPacketForMe(mode, data, size) == false)
|
||||||
{
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StrCmp(impl->Name(), "OpenVPN") == 0 && proto->Cedar->Server->DisableOpenVPNServer)
|
||||||
|
{
|
||||||
|
Debug("ProtoImplDetect(): OpenVPN detected, but it's disabled\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
Debug("ProtoImplDetect(): %s detected\n", impl->Name());
|
Debug("ProtoImplDetect(): %s detected\n", impl->Name());
|
||||||
return impl;
|
return impl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Debug("ProtoImplDetect(): 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 *session;
|
||||||
|
|
||||||
|
if (impl == NULL || src_ip == NULL || src_port == 0 || dst_ip == NULL || dst_port == 0)
|
||||||
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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) == false)
|
||||||
|
{
|
||||||
|
Debug("ProtoNewSession(): failed to initialize %s\n", impl->Name());
|
||||||
|
|
||||||
|
ReleaseSockEvent(session->SockEvent);
|
||||||
|
FreeInterruptManager(session->InterruptManager);
|
||||||
|
Free(session);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
session->Proto = proto;
|
||||||
|
session->Impl = impl;
|
||||||
|
|
||||||
|
CopyIP(&session->SrcIp, src_ip);
|
||||||
|
session->SrcPort = src_port;
|
||||||
|
CopyIP(&session->DstIp, dst_ip);
|
||||||
|
session->DstPort = dst_port;
|
||||||
|
|
||||||
|
session->DatagramsIn = NewListFast(NULL);
|
||||||
|
session->DatagramsOut = NewListFast(NULL);
|
||||||
|
|
||||||
|
session->Lock = NewLock();
|
||||||
|
session->Thread = NewThread(ProtoSessionThread, session);
|
||||||
|
|
||||||
|
return session;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtoDeleteSession(PROTO_SESSION *session)
|
||||||
|
{
|
||||||
|
if (session == NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
session->Halt = true;
|
||||||
|
SetSockEvent(session->SockEvent);
|
||||||
|
|
||||||
|
WaitThread(session->Thread, INFINITE);
|
||||||
|
ReleaseThread(session->Thread);
|
||||||
|
|
||||||
|
session->Impl->Free(session->Param);
|
||||||
|
|
||||||
|
ReleaseSockEvent(session->SockEvent);
|
||||||
|
FreeInterruptManager(session->InterruptManager);
|
||||||
|
|
||||||
|
ReleaseList(session->DatagramsIn);
|
||||||
|
ReleaseList(session->DatagramsOut);
|
||||||
|
|
||||||
|
DeleteLock(session->Lock);
|
||||||
|
|
||||||
|
Free(session);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ProtoSetListenIP(PROTO *proto, const IP *ip)
|
||||||
|
{
|
||||||
|
if (proto == NULL || ip == NULL)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Copy(&proto->UdpListener->ListenIP, ip, sizeof(proto->UdpListener->ListenIP));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ProtoSetUdpPorts(PROTO *proto, const LIST *ports)
|
||||||
|
{
|
||||||
|
UINT i = 0;
|
||||||
|
|
||||||
|
if (proto == NULL || ports == NULL)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
DeleteAllPortFromUdpListener(proto->UdpListener);
|
||||||
|
|
||||||
|
for (i = 0; i < LIST_NUM(ports); ++i)
|
||||||
|
{
|
||||||
|
UINT port = *((UINT *)LIST_DATA(ports, i));
|
||||||
|
if (port >= 1 && port <= 65535)
|
||||||
|
{
|
||||||
|
AddPortToUdpListener(proto->UdpListener, port);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool ProtoHandleConnection(PROTO *proto, SOCK *sock)
|
bool ProtoHandleConnection(PROTO *proto, SOCK *sock)
|
||||||
{
|
{
|
||||||
void *impl_data = NULL;
|
void *impl_data = NULL;
|
||||||
@ -104,29 +320,23 @@ bool ProtoHandleConnection(PROTO *proto, SOCK *sock)
|
|||||||
INTERRUPT_MANAGER *im;
|
INTERRUPT_MANAGER *im;
|
||||||
SOCK_EVENT *se;
|
SOCK_EVENT *se;
|
||||||
|
|
||||||
const UINT64 giveup = Tick64() + (UINT64)OPENVPN_NEW_SESSION_DEADLINE_TIMEOUT;
|
|
||||||
|
|
||||||
if (proto == NULL || sock == NULL)
|
if (proto == NULL || sock == NULL)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl = ProtoImplDetect(proto, sock);
|
{
|
||||||
|
UCHAR tmp[PROTO_CHECK_BUFFER_SIZE];
|
||||||
|
if (Peek(sock, tmp, sizeof(tmp)) == 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl = ProtoImplDetect(proto, PROTO_MODE_TCP, tmp, sizeof(tmp));
|
||||||
if (impl == NULL)
|
if (impl == NULL)
|
||||||
{
|
{
|
||||||
Debug("ProtoHandleConnection(): unrecognized protocol\n");
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (StrCmp(impl->Name(), "OpenVPN") == 0 && proto->Cedar->Server->DisableOpenVPNServer == true)
|
|
||||||
{
|
|
||||||
Debug("ProtoHandleConnection(): OpenVPN detected, but it's disabled\n");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((impl->SupportedModes() & PROTO_MODE_TCP) == false)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
im = NewInterruptManager();
|
im = NewInterruptManager();
|
||||||
@ -208,23 +418,6 @@ bool ProtoHandleConnection(PROTO *proto, SOCK *sock)
|
|||||||
|
|
||||||
impl->BufferLimit(impl_data, FifoSize(send_fifo) > MAX_BUFFERING_PACKET_SIZE);
|
impl->BufferLimit(impl_data, FifoSize(send_fifo) > MAX_BUFFERING_PACKET_SIZE);
|
||||||
|
|
||||||
if (impl->IsOk(impl_data) == false)
|
|
||||||
{
|
|
||||||
if (impl->EstablishedSessions(impl_data) == 0)
|
|
||||||
{
|
|
||||||
if (Tick64() >= giveup)
|
|
||||||
{
|
|
||||||
Debug("ProtoHandleConnection(): I waited too much for the session to start, I give up!\n");
|
|
||||||
stop = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Debug("ProtoHandleConnection(): implementation not OK, stopping the server\n");
|
|
||||||
stop = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stop)
|
if (stop)
|
||||||
{
|
{
|
||||||
// Error or disconnection occurs
|
// Error or disconnection occurs
|
||||||
@ -248,3 +441,120 @@ bool ProtoHandleConnection(PROTO *proto, SOCK *sock)
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ProtoHandleDatagrams(UDPLISTENER *listener, LIST *datagrams)
|
||||||
|
{
|
||||||
|
UINT i;
|
||||||
|
HASH_LIST *sessions;
|
||||||
|
PROTO *proto = listener->Param;
|
||||||
|
|
||||||
|
if (proto == NULL || listener == NULL || datagrams == NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sessions = proto->Sessions;
|
||||||
|
|
||||||
|
for (i = 0; i < LIST_NUM(datagrams); ++i)
|
||||||
|
{
|
||||||
|
UDPPACKET *datagram = LIST_DATA(datagrams, i);
|
||||||
|
PROTO_SESSION *session, tmp;
|
||||||
|
|
||||||
|
CopyIP(&tmp.SrcIp, &datagram->SrcIP);
|
||||||
|
tmp.SrcPort = datagram->SrcPort;
|
||||||
|
CopyIP(&tmp.DstIp, &datagram->DstIP);
|
||||||
|
tmp.DstPort = datagram->DestPort;
|
||||||
|
|
||||||
|
session = SearchHash(sessions, &tmp);
|
||||||
|
if (session == NULL)
|
||||||
|
{
|
||||||
|
tmp.Impl = ProtoImplDetect(proto, PROTO_MODE_UDP, datagram->Data, datagram->Size);
|
||||||
|
if (tmp.Impl == NULL)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
session = ProtoNewSession(proto, tmp.Impl, &tmp.SrcIp, tmp.SrcPort, &tmp.DstIp, tmp.DstPort);
|
||||||
|
if (session == NULL)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
AddHash(proto->Sessions, session);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (session->Halt)
|
||||||
|
{
|
||||||
|
DeleteHash(sessions, session);
|
||||||
|
ProtoDeleteSession(session);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Lock(session->Lock);
|
||||||
|
{
|
||||||
|
void *data = Clone(datagram->Data, datagram->Size);
|
||||||
|
UDPPACKET *packet = NewUdpPacket(&datagram->SrcIP, datagram->SrcPort, &datagram->DstIP, datagram->DestPort, data, datagram->Size);
|
||||||
|
Add(session->DatagramsIn, packet);
|
||||||
|
}
|
||||||
|
Unlock(session->Lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < LIST_NUM(sessions->AllList); ++i)
|
||||||
|
{
|
||||||
|
PROTO_SESSION *session = LIST_DATA(sessions->AllList, i);
|
||||||
|
if (LIST_NUM(session->DatagramsIn) > 0)
|
||||||
|
{
|
||||||
|
SetSockEvent(session->SockEvent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtoSessionThread(THREAD *thread, void *param)
|
||||||
|
{
|
||||||
|
PROTO_SESSION *session = param;
|
||||||
|
|
||||||
|
if (thread == NULL || session == NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (session->Halt == false)
|
||||||
|
{
|
||||||
|
bool ok;
|
||||||
|
UINT interval;
|
||||||
|
void *param = session->Param;
|
||||||
|
PROTO_IMPL *impl = session->Impl;
|
||||||
|
LIST *received = session->DatagramsIn;
|
||||||
|
LIST *to_send = session->DatagramsOut;
|
||||||
|
|
||||||
|
Lock(session->Lock);
|
||||||
|
{
|
||||||
|
UINT i;
|
||||||
|
|
||||||
|
ok = impl->ProcessDatagrams(param, received, to_send);
|
||||||
|
|
||||||
|
UdpListenerSendPackets(session->Proto->UdpListener, to_send);
|
||||||
|
|
||||||
|
for (i = 0; i < LIST_NUM(received); ++i)
|
||||||
|
{
|
||||||
|
FreeUdpPacket(LIST_DATA(received, i));
|
||||||
|
}
|
||||||
|
|
||||||
|
DeleteAll(received);
|
||||||
|
DeleteAll(to_send);
|
||||||
|
}
|
||||||
|
Unlock(session->Lock);
|
||||||
|
|
||||||
|
if (ok == false)
|
||||||
|
{
|
||||||
|
Debug("ProtoSessionThread(): breaking main loop\n");
|
||||||
|
session->Halt = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait until the next event occurs
|
||||||
|
interval = GetNextIntervalForInterrupt(session->InterruptManager);
|
||||||
|
interval = MIN(interval, UDPLISTENER_WAIT_INTERVAL);
|
||||||
|
WaitSockEvent(session->SockEvent, interval);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -7,13 +7,19 @@
|
|||||||
|
|
||||||
#define PROTO_TCP_BUFFER_SIZE (128 * 1024)
|
#define PROTO_TCP_BUFFER_SIZE (128 * 1024)
|
||||||
|
|
||||||
#define PROTO_MODE_TCP 1
|
typedef enum PROTO_MODE
|
||||||
#define PROTO_MODE_UDP 2
|
{
|
||||||
|
PROTO_MODE_UNKNOWN = 0,
|
||||||
|
PROTO_MODE_TCP = 1,
|
||||||
|
PROTO_MODE_UDP = 2
|
||||||
|
} PROTO_MODE;
|
||||||
|
|
||||||
typedef struct PROTO
|
typedef struct PROTO
|
||||||
{
|
{
|
||||||
CEDAR *Cedar;
|
CEDAR *Cedar;
|
||||||
LIST *Impls;
|
LIST *Impls;
|
||||||
|
HASH_LIST *Sessions;
|
||||||
|
UDPLISTENER *UdpListener;
|
||||||
} PROTO;
|
} PROTO;
|
||||||
|
|
||||||
typedef struct PROTO_IMPL
|
typedef struct PROTO_IMPL
|
||||||
@ -21,22 +27,49 @@ typedef struct PROTO_IMPL
|
|||||||
bool (*Init)(void **param, CEDAR *cedar, INTERRUPT_MANAGER *im, SOCK_EVENT *se);
|
bool (*Init)(void **param, CEDAR *cedar, INTERRUPT_MANAGER *im, SOCK_EVENT *se);
|
||||||
void (*Free)(void *param);
|
void (*Free)(void *param);
|
||||||
char *(*Name)();
|
char *(*Name)();
|
||||||
UINT (*SupportedModes)();
|
bool (*IsPacketForMe)(const PROTO_MODE mode, const UCHAR *data, const UINT size);
|
||||||
bool (*IsPacketForMe)(const UCHAR *data, const UINT size);
|
bool (*ProcessData)(void *param, TCP_RAW_DATA *in, FIFO *out);
|
||||||
bool (*ProcessData)(void *param, TCP_RAW_DATA *received_data, FIFO *data_to_send);
|
bool (*ProcessDatagrams)(void *param, LIST *in, LIST *out);
|
||||||
void (*BufferLimit)(void *param, const bool reached);
|
void (*BufferLimit)(void *param, const bool reached);
|
||||||
bool (*IsOk)(void *param);
|
|
||||||
UINT (*EstablishedSessions)(void *param);
|
|
||||||
} PROTO_IMPL;
|
} PROTO_IMPL;
|
||||||
|
|
||||||
|
typedef struct PROTO_SESSION
|
||||||
|
{
|
||||||
|
void *Param;
|
||||||
|
PROTO *Proto;
|
||||||
|
PROTO_IMPL *Impl;
|
||||||
|
IP SrcIp;
|
||||||
|
USHORT SrcPort;
|
||||||
|
IP DstIp;
|
||||||
|
USHORT DstPort;
|
||||||
|
LIST *DatagramsIn;
|
||||||
|
LIST *DatagramsOut;
|
||||||
|
SOCK_EVENT *SockEvent;
|
||||||
|
INTERRUPT_MANAGER *InterruptManager;
|
||||||
|
THREAD *Thread;
|
||||||
|
LOCK *Lock;
|
||||||
|
volatile bool Halt;
|
||||||
|
} PROTO_SESSION;
|
||||||
|
|
||||||
int ProtoImplCompare(void *p1, void *p2);
|
int ProtoImplCompare(void *p1, void *p2);
|
||||||
|
int ProtoSessionCompare(void *p1, void *p2);
|
||||||
|
|
||||||
|
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);
|
bool ProtoImplAdd(PROTO *proto, PROTO_IMPL *impl);
|
||||||
PROTO_IMPL *ProtoImplDetect(PROTO *proto, SOCK *sock);
|
PROTO_IMPL *ProtoImplDetect(PROTO *proto, const PROTO_MODE mode, const UCHAR *data, const UINT size);
|
||||||
|
|
||||||
|
PROTO_SESSION *ProtoNewSession(PROTO *proto, PROTO_IMPL *impl, 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);
|
||||||
|
bool ProtoSetUdpPorts(PROTO *proto, const LIST *ports);
|
||||||
|
|
||||||
bool ProtoHandleConnection(PROTO *proto, SOCK *sock);
|
bool ProtoHandleConnection(PROTO *proto, SOCK *sock);
|
||||||
|
void ProtoHandleDatagrams(UDPLISTENER *listener, LIST *datagrams);
|
||||||
|
void ProtoSessionThread(THREAD *thread, void *param);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -21,12 +21,10 @@ PROTO_IMPL *OvsGetProtoImpl()
|
|||||||
OvsInit,
|
OvsInit,
|
||||||
OvsFree,
|
OvsFree,
|
||||||
OvsName,
|
OvsName,
|
||||||
OvsSupportedModes,
|
|
||||||
OvsIsPacketForMe,
|
OvsIsPacketForMe,
|
||||||
OvsProcessData,
|
OvsProcessData,
|
||||||
|
OvsProcessDatagrams,
|
||||||
OvsBufferLimit,
|
OvsBufferLimit,
|
||||||
OvsIsOk,
|
|
||||||
OvsEstablishedSessions
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return &impl;
|
return &impl;
|
||||||
@ -55,48 +53,54 @@ char *OvsName()
|
|||||||
return "OpenVPN";
|
return "OpenVPN";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the supported modes (TCP & UDP)
|
|
||||||
UINT OvsSupportedModes()
|
|
||||||
{
|
|
||||||
return PROTO_MODE_TCP | PROTO_MODE_UDP;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check whether it's an OpenVPN packet
|
// Check whether it's an OpenVPN packet
|
||||||
bool OvsIsPacketForMe(const UCHAR *buf, const UINT size)
|
bool OvsIsPacketForMe(const PROTO_MODE mode, const UCHAR *data, const UINT size)
|
||||||
{
|
{
|
||||||
if (buf == NULL || size != 2)
|
if (mode == PROTO_MODE_TCP)
|
||||||
|
{
|
||||||
|
if (data == NULL || size < 2)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buf[0] == 0x00 && buf[1] == 0x0E)
|
if (data[0] == 0x00 && data[1] == 0x0E)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else if (mode == PROTO_MODE_UDP)
|
||||||
|
{
|
||||||
|
OPENVPN_PACKET *packet = OvsParsePacket(data, size);
|
||||||
|
if (packet == NULL)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
OvsFreePacket(packet);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OvsProcessData(void *param, TCP_RAW_DATA *received_data, FIFO *data_to_send)
|
bool OvsProcessData(void *param, TCP_RAW_DATA *in, FIFO *out)
|
||||||
{
|
{
|
||||||
bool ret = true;
|
bool ret = true;
|
||||||
UINT i;
|
UINT i;
|
||||||
OPENVPN_SERVER *server;
|
OPENVPN_SERVER *server = param;
|
||||||
UCHAR buf[OPENVPN_TCP_MAX_PACKET_SIZE];
|
UCHAR buf[OPENVPN_TCP_MAX_PACKET_SIZE];
|
||||||
|
|
||||||
if (param == NULL || received_data == NULL || data_to_send == NULL)
|
if (server == NULL || in == NULL || out == NULL)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
server = param;
|
|
||||||
|
|
||||||
// Separate to a list of datagrams by interpreting the data received from the TCP socket
|
// Separate to a list of datagrams by interpreting the data received from the TCP socket
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
UDPPACKET *packet;
|
UDPPACKET *packet;
|
||||||
USHORT payload_size, packet_size;
|
USHORT payload_size, packet_size;
|
||||||
FIFO *fifo = received_data->Data;
|
FIFO *fifo = in->Data;
|
||||||
const UINT fifo_size = FifoSize(fifo);
|
const UINT fifo_size = FifoSize(fifo);
|
||||||
|
|
||||||
if (fifo_size < sizeof(USHORT))
|
if (fifo_size < sizeof(USHORT))
|
||||||
@ -130,13 +134,12 @@ bool OvsProcessData(void *param, TCP_RAW_DATA *received_data, FIFO *data_to_send
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Insert packet into the list
|
// Insert packet into the list
|
||||||
packet = NewUdpPacket(&received_data->SrcIP, received_data->SrcPort, &received_data->DstIP, received_data->DstPort, Clone(buf + sizeof(USHORT), payload_size), payload_size);
|
packet = NewUdpPacket(&in->SrcIP, in->SrcPort, &in->DstIP, in->DstPort, Clone(buf + sizeof(USHORT), payload_size), payload_size);
|
||||||
packet->Type = OPENVPN_PROTOCOL_TCP;
|
|
||||||
Add(server->RecvPacketList, packet);
|
Add(server->RecvPacketList, packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process the list of received datagrams
|
// Process the list of received datagrams
|
||||||
OvsRecvPacket(server, server->RecvPacketList);
|
OvsRecvPacket(server, server->RecvPacketList, OPENVPN_PROTOCOL_TCP);
|
||||||
|
|
||||||
// Release the received packet list
|
// Release the received packet list
|
||||||
for (i = 0; i < LIST_NUM(server->RecvPacketList); ++i)
|
for (i = 0; i < LIST_NUM(server->RecvPacketList); ++i)
|
||||||
@ -155,10 +158,10 @@ bool OvsProcessData(void *param, TCP_RAW_DATA *received_data, FIFO *data_to_send
|
|||||||
// Store the size in the TCP send queue first
|
// Store the size in the TCP send queue first
|
||||||
USHORT us = Endian16((USHORT)p->Size);
|
USHORT us = Endian16((USHORT)p->Size);
|
||||||
|
|
||||||
WriteFifo(data_to_send, &us, sizeof(USHORT));
|
WriteFifo(out, &us, sizeof(USHORT));
|
||||||
|
|
||||||
// Write the data body
|
// Write the data body
|
||||||
WriteFifo(data_to_send, p->Data, p->Size);
|
WriteFifo(out, p->Data, p->Size);
|
||||||
|
|
||||||
// Packet release
|
// Packet release
|
||||||
FreeUdpPacket(p);
|
FreeUdpPacket(p);
|
||||||
@ -166,9 +169,66 @@ bool OvsProcessData(void *param, TCP_RAW_DATA *received_data, FIFO *data_to_send
|
|||||||
|
|
||||||
DeleteAll(server->SendPacketList);
|
DeleteAll(server->SendPacketList);
|
||||||
|
|
||||||
|
if (server->Giveup <= server->Now)
|
||||||
|
{
|
||||||
|
UINT i;
|
||||||
|
for (i = 0; i < LIST_NUM(server->SessionList); ++i)
|
||||||
|
{
|
||||||
|
OPENVPN_SESSION *se = LIST_DATA(server->SessionList, i);
|
||||||
|
|
||||||
|
if (se->Established)
|
||||||
|
{
|
||||||
|
return ret && server->DisconnectCount < 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool OvsProcessDatagrams(void *param, LIST *in, LIST *out)
|
||||||
|
{
|
||||||
|
UINT i;
|
||||||
|
LIST *to_send;
|
||||||
|
OPENVPN_SERVER *server = param;
|
||||||
|
|
||||||
|
if (server == NULL || in == NULL || out == NULL)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
OvsRecvPacket(server, in, OPENVPN_PROTOCOL_UDP);
|
||||||
|
|
||||||
|
to_send = server->SendPacketList;
|
||||||
|
|
||||||
|
for (i = 0; i < LIST_NUM(to_send); ++i)
|
||||||
|
{
|
||||||
|
Add(out, LIST_DATA(to_send, i));
|
||||||
|
}
|
||||||
|
|
||||||
|
DeleteAll(server->SendPacketList);
|
||||||
|
|
||||||
|
if (server->Giveup <= server->Now)
|
||||||
|
{
|
||||||
|
UINT i;
|
||||||
|
for (i = 0; i < LIST_NUM(server->SessionList); ++i)
|
||||||
|
{
|
||||||
|
OPENVPN_SESSION *se = LIST_DATA(server->SessionList, i);
|
||||||
|
|
||||||
|
if (se->Established)
|
||||||
|
{
|
||||||
|
return server->DisconnectCount < 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void OvsBufferLimit(void *param, const bool reached)
|
void OvsBufferLimit(void *param, const bool reached)
|
||||||
{
|
{
|
||||||
if (param == NULL)
|
if (param == NULL)
|
||||||
@ -179,46 +239,6 @@ void OvsBufferLimit(void *param, const bool reached)
|
|||||||
((OPENVPN_SERVER *)param)->SupressSendPacket = reached;
|
((OPENVPN_SERVER *)param)->SupressSendPacket = reached;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OvsIsOk(void *param)
|
|
||||||
{
|
|
||||||
OPENVPN_SERVER *s;
|
|
||||||
|
|
||||||
if (param == NULL)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
s = param;
|
|
||||||
|
|
||||||
return (s->DisconnectCount < 1) && (s->SessionEstablishedCount > 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
UINT OvsEstablishedSessions(void *param)
|
|
||||||
{
|
|
||||||
LIST *sessions;
|
|
||||||
UINT i;
|
|
||||||
UINT established_sessions = 0;
|
|
||||||
|
|
||||||
if (param == NULL)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
sessions = ((OPENVPN_SERVER *)param)->SessionList;
|
|
||||||
|
|
||||||
for (i = 0;i < LIST_NUM(sessions);i++)
|
|
||||||
{
|
|
||||||
OPENVPN_SESSION *se = LIST_DATA(sessions, i);
|
|
||||||
|
|
||||||
if (se->Established)
|
|
||||||
{
|
|
||||||
++established_sessions;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return established_sessions;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write the OpenVPN log
|
// Write the OpenVPN log
|
||||||
void OvsLog(OPENVPN_SERVER *s, OPENVPN_SESSION *se, OPENVPN_CHANNEL *c, char *name, ...)
|
void OvsLog(OPENVPN_SERVER *s, OPENVPN_SESSION *se, OPENVPN_CHANNEL *c, char *name, ...)
|
||||||
{
|
{
|
||||||
@ -529,7 +549,7 @@ final:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Process the received packet
|
// Process the received packet
|
||||||
void OvsProceccRecvPacket(OPENVPN_SERVER *s, UDPPACKET *p)
|
void OvsProceccRecvPacket(OPENVPN_SERVER *s, UDPPACKET *p, UINT protocol)
|
||||||
{
|
{
|
||||||
OPENVPN_CHANNEL *c;
|
OPENVPN_CHANNEL *c;
|
||||||
OPENVPN_SESSION *se;
|
OPENVPN_SESSION *se;
|
||||||
@ -541,7 +561,7 @@ void OvsProceccRecvPacket(OPENVPN_SERVER *s, UDPPACKET *p)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Search for the session
|
// Search for the session
|
||||||
se = OvsFindOrCreateSession(s, &p->DstIP, p->DestPort, &p->SrcIP, p->SrcPort, p->Type);
|
se = OvsFindOrCreateSession(s, &p->DstIP, p->DestPort, &p->SrcIP, p->SrcPort, protocol);
|
||||||
if (se == NULL)
|
if (se == NULL)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@ -771,8 +791,13 @@ void OvsProcessRecvControlPacket(OPENVPN_SERVER *s, OPENVPN_SESSION *se, OPENVPN
|
|||||||
// Create an SSL pipe
|
// Create an SSL pipe
|
||||||
Lock(s->Cedar->lock);
|
Lock(s->Cedar->lock);
|
||||||
{
|
{
|
||||||
bool cert_verify = true;
|
if (s->Dh->Size != s->Cedar->DhParamBits)
|
||||||
c->SslPipe = NewSslPipeEx(true, s->Cedar->ServerX, s->Cedar->ServerK, s->Dh, cert_verify, &c->ClientCert);
|
{
|
||||||
|
DhFree(s->Dh);
|
||||||
|
s->Dh = DhNewFromBits(s->Cedar->DhParamBits);
|
||||||
|
}
|
||||||
|
|
||||||
|
c->SslPipe = NewSslPipeEx(true, s->Cedar->ServerX, s->Cedar->ServerK, s->Dh, true, &c->ClientCert);
|
||||||
}
|
}
|
||||||
Unlock(s->Cedar->lock);
|
Unlock(s->Cedar->lock);
|
||||||
|
|
||||||
@ -2187,7 +2212,7 @@ OPENVPN_SESSION *OvsSearchSession(OPENVPN_SERVER *s, IP *server_ip, UINT server_
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Receive packets in the OpenVPN server
|
// Receive packets in the OpenVPN server
|
||||||
void OvsRecvPacket(OPENVPN_SERVER *s, LIST *recv_packet_list)
|
void OvsRecvPacket(OPENVPN_SERVER *s, LIST *recv_packet_list, UINT protocol)
|
||||||
{
|
{
|
||||||
UINT i, j;
|
UINT i, j;
|
||||||
LIST *delete_session_list = NULL;
|
LIST *delete_session_list = NULL;
|
||||||
@ -2219,7 +2244,7 @@ void OvsRecvPacket(OPENVPN_SERVER *s, LIST *recv_packet_list)
|
|||||||
{
|
{
|
||||||
UDPPACKET *p = LIST_DATA(recv_packet_list, i);
|
UDPPACKET *p = LIST_DATA(recv_packet_list, i);
|
||||||
|
|
||||||
OvsProceccRecvPacket(s, p);
|
OvsProceccRecvPacket(s, p, protocol);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Treat for all sessions and all channels
|
// Treat for all sessions and all channels
|
||||||
@ -2924,12 +2949,13 @@ OPENVPN_SERVER *NewOpenVpnServer(CEDAR *cedar, INTERRUPT_MANAGER *interrupt, SOC
|
|||||||
s->SendPacketList = NewListFast(NULL);
|
s->SendPacketList = NewListFast(NULL);
|
||||||
|
|
||||||
s->Now = Tick64();
|
s->Now = Tick64();
|
||||||
|
s->Giveup = s->Now + OPENVPN_NEW_SESSION_DEADLINE_TIMEOUT;
|
||||||
|
|
||||||
s->NextSessionId = 1;
|
s->NextSessionId = 1;
|
||||||
|
|
||||||
OvsLog(s, NULL, NULL, "LO_START");
|
OvsLog(s, NULL, NULL, "LO_START");
|
||||||
|
|
||||||
s->Dh = DhNewFromBits(DH_PARAM_BITS_DEFAULT);
|
s->Dh = DhNewFromBits(cedar->DhParamBits);
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
@ -2977,123 +3003,3 @@ void FreeOpenVpnServer(OPENVPN_SERVER *s)
|
|||||||
|
|
||||||
Free(s);
|
Free(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
// UDP reception procedure
|
|
||||||
void OpenVpnServerUdpListenerProc(UDPLISTENER *u, LIST *packet_list)
|
|
||||||
{
|
|
||||||
OPENVPN_SERVER_UDP *us;
|
|
||||||
// Validate arguments
|
|
||||||
if (u == NULL || packet_list == NULL)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
us = (OPENVPN_SERVER_UDP *)u->Param;
|
|
||||||
|
|
||||||
if (us->OpenVpnServer != NULL)
|
|
||||||
{
|
|
||||||
{
|
|
||||||
u->PollMyIpAndPort = false;
|
|
||||||
|
|
||||||
ClearStr(us->Cedar->OpenVPNPublicPorts, sizeof(us->Cedar->OpenVPNPublicPorts));
|
|
||||||
}
|
|
||||||
|
|
||||||
OvsRecvPacket(us->OpenVpnServer, packet_list);
|
|
||||||
|
|
||||||
UdpListenerSendPackets(u, us->OpenVpnServer->SendPacketList);
|
|
||||||
DeleteAll(us->OpenVpnServer->SendPacketList);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create an OpenVPN server (UDP mode)
|
|
||||||
OPENVPN_SERVER_UDP *NewOpenVpnServerUdp(CEDAR *cedar)
|
|
||||||
{
|
|
||||||
OPENVPN_SERVER_UDP *u;
|
|
||||||
// Validate arguments
|
|
||||||
if (cedar == NULL)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
u = ZeroMalloc(sizeof(OPENVPN_SERVER_UDP));
|
|
||||||
|
|
||||||
u->Cedar = cedar;
|
|
||||||
|
|
||||||
AddRef(u->Cedar->ref);
|
|
||||||
|
|
||||||
// Create a UDP listener
|
|
||||||
u->UdpListener = NewUdpListenerEx(OpenVpnServerUdpListenerProc, u, &cedar->Server->ListenIP, OPENVPN_PROTOCOL_UDP);
|
|
||||||
|
|
||||||
// Create an OpenVPN server
|
|
||||||
u->OpenVpnServer = NewOpenVpnServer(cedar, u->UdpListener->Interrupts, u->UdpListener->Event);
|
|
||||||
|
|
||||||
return u;
|
|
||||||
}
|
|
||||||
|
|
||||||
void OpenVpnServerUdpSetDhParam(OPENVPN_SERVER_UDP *u, DH_CTX *dh)
|
|
||||||
{
|
|
||||||
// Validate arguments
|
|
||||||
if (u == NULL) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (u->OpenVpnServer->Dh)
|
|
||||||
{
|
|
||||||
DhFree(u->OpenVpnServer->Dh);
|
|
||||||
}
|
|
||||||
|
|
||||||
u->OpenVpnServer->Dh = dh;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply the port list to the OpenVPN server
|
|
||||||
void OvsApplyUdpPortList(OPENVPN_SERVER_UDP *u, char *port_list, IP *listen_ip)
|
|
||||||
{
|
|
||||||
LIST *o;
|
|
||||||
UINT i;
|
|
||||||
// Validate arguments
|
|
||||||
if (u == NULL)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
DeleteAllPortFromUdpListener(u->UdpListener);
|
|
||||||
|
|
||||||
if (u->UdpListener != NULL && listen_ip != NULL)
|
|
||||||
{
|
|
||||||
Copy(&u->UdpListener->ListenIP, listen_ip, sizeof(IP));
|
|
||||||
}
|
|
||||||
|
|
||||||
o = StrToIntList(port_list, true);
|
|
||||||
|
|
||||||
for (i = 0;i < LIST_NUM(o);i++)
|
|
||||||
{
|
|
||||||
UINT port = *((UINT *)LIST_DATA(o, i));
|
|
||||||
|
|
||||||
if (port >= 1 && port <= 65535)
|
|
||||||
{
|
|
||||||
AddPortToUdpListener(u->UdpListener, port);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ReleaseIntList(o);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Release the OpenVPN server (UDP mode)
|
|
||||||
void FreeOpenVpnServerUdp(OPENVPN_SERVER_UDP *u)
|
|
||||||
{
|
|
||||||
// Validate arguments
|
|
||||||
if (u == NULL)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stop the UDP listener
|
|
||||||
FreeUdpListener(u->UdpListener);
|
|
||||||
|
|
||||||
// Release the OpenVPN server
|
|
||||||
FreeOpenVpnServer(u->OpenVpnServer);
|
|
||||||
|
|
||||||
ReleaseCedar(u->Cedar);
|
|
||||||
|
|
||||||
Free(u);
|
|
||||||
}
|
|
||||||
|
@ -194,6 +194,7 @@ struct OPENVPN_SERVER
|
|||||||
LIST *SendPacketList; // Transmission packet list
|
LIST *SendPacketList; // Transmission packet list
|
||||||
LIST *SessionList; // Session list
|
LIST *SessionList; // Session list
|
||||||
UINT64 Now; // Current time
|
UINT64 Now; // Current time
|
||||||
|
UINT64 Giveup; // Session establishment deadline
|
||||||
SOCK_EVENT *SockEvent; // Socket event
|
SOCK_EVENT *SockEvent; // Socket event
|
||||||
UCHAR TmpBuf[OPENVPN_TMP_BUFFER_SIZE]; // Temporary buffer
|
UCHAR TmpBuf[OPENVPN_TMP_BUFFER_SIZE]; // Temporary buffer
|
||||||
UINT DisconnectCount; // The number of session lost that have occurred so far
|
UINT DisconnectCount; // The number of session lost that have occurred so far
|
||||||
@ -203,15 +204,6 @@ struct OPENVPN_SERVER
|
|||||||
UINT SessionEstablishedCount; // Number of session establishment
|
UINT SessionEstablishedCount; // Number of session establishment
|
||||||
};
|
};
|
||||||
|
|
||||||
// OpenVPN server (UDP mode)
|
|
||||||
struct OPENVPN_SERVER_UDP
|
|
||||||
{
|
|
||||||
CEDAR *Cedar;
|
|
||||||
UDPLISTENER *UdpListener; // UDP listener
|
|
||||||
OPENVPN_SERVER *OpenVpnServer; // OpenVPN server
|
|
||||||
UINT64 VgsNextGetPublicPortsTick;
|
|
||||||
};
|
|
||||||
|
|
||||||
// OpenVPN Default Client Option String
|
// OpenVPN Default Client Option String
|
||||||
#define OVPN_DEF_CLIENT_OPTION_STRING "dev-type tun,link-mtu 1500,tun-mtu 1500,cipher AES-128-CBC,auth SHA1,keysize 128,key-method 2,tls-client"
|
#define OVPN_DEF_CLIENT_OPTION_STRING "dev-type tun,link-mtu 1500,tun-mtu 1500,cipher AES-128-CBC,auth SHA1,keysize 128,key-method 2,tls-client"
|
||||||
|
|
||||||
@ -220,22 +212,17 @@ PROTO_IMPL *OvsGetProtoImpl();
|
|||||||
bool OvsInit(void **param, CEDAR *cedar, INTERRUPT_MANAGER *im, SOCK_EVENT *se);
|
bool OvsInit(void **param, CEDAR *cedar, INTERRUPT_MANAGER *im, SOCK_EVENT *se);
|
||||||
void OvsFree(void *param);
|
void OvsFree(void *param);
|
||||||
char *OvsName();
|
char *OvsName();
|
||||||
UINT OvsSupportedModes();
|
bool OvsIsPacketForMe(const PROTO_MODE mode, const UCHAR *data, const UINT size);
|
||||||
bool OvsIsPacketForMe(const UCHAR *buf, const UINT size);
|
bool OvsProcessData(void *param, TCP_RAW_DATA *in, FIFO *out);
|
||||||
bool OvsProcessData(void *param, TCP_RAW_DATA *received_data, FIFO *data_to_send);
|
bool OvsProcessDatagrams(void *param, LIST *in, LIST *out);
|
||||||
void OvsBufferLimit(void *param, const bool reached);
|
void OvsBufferLimit(void *param, const bool reached);
|
||||||
bool OvsIsOk(void *param);
|
bool OvsIsOk(void *param);
|
||||||
UINT OvsEstablishedSessions(void *param);
|
UINT OvsEstablishedSessions(void *param);
|
||||||
|
|
||||||
OPENVPN_SERVER_UDP *NewOpenVpnServerUdp(CEDAR *cedar);
|
|
||||||
void FreeOpenVpnServerUdp(OPENVPN_SERVER_UDP *u);
|
|
||||||
void OpenVpnServerUdpListenerProc(UDPLISTENER *u, LIST *packet_list);
|
|
||||||
void OvsApplyUdpPortList(OPENVPN_SERVER_UDP *u, char *port_list, IP *listen_ip);
|
|
||||||
|
|
||||||
OPENVPN_SERVER *NewOpenVpnServer(CEDAR *cedar, INTERRUPT_MANAGER *interrupt, SOCK_EVENT *sock_event);
|
OPENVPN_SERVER *NewOpenVpnServer(CEDAR *cedar, INTERRUPT_MANAGER *interrupt, SOCK_EVENT *sock_event);
|
||||||
void FreeOpenVpnServer(OPENVPN_SERVER *s);
|
void FreeOpenVpnServer(OPENVPN_SERVER *s);
|
||||||
void OvsRecvPacket(OPENVPN_SERVER *s, LIST *recv_packet_list);
|
void OvsRecvPacket(OPENVPN_SERVER *s, LIST *recv_packet_list, UINT protocol);
|
||||||
void OvsProceccRecvPacket(OPENVPN_SERVER *s, UDPPACKET *p);
|
void OvsProceccRecvPacket(OPENVPN_SERVER *s, UDPPACKET *p, UINT protocol);
|
||||||
int OvsCompareSessionList(void *p1, void *p2);
|
int OvsCompareSessionList(void *p1, void *p2);
|
||||||
OPENVPN_SESSION *OvsSearchSession(OPENVPN_SERVER *s, IP *server_ip, UINT server_port, IP *client_ip, UINT client_port, UINT protocol);
|
OPENVPN_SESSION *OvsSearchSession(OPENVPN_SERVER *s, IP *server_ip, UINT server_port, IP *client_ip, UINT client_port, UINT protocol);
|
||||||
OPENVPN_SESSION *OvsNewSession(OPENVPN_SERVER *s, IP *server_ip, UINT server_port, IP *client_ip, UINT client_port, UINT protocol);
|
OPENVPN_SESSION *OvsNewSession(OPENVPN_SERVER *s, IP *server_ip, UINT server_port, IP *client_ip, UINT client_port, UINT protocol);
|
||||||
@ -279,6 +266,4 @@ UINT OvsCalcTcpMss(OPENVPN_SERVER *s, OPENVPN_SESSION *se, OPENVPN_CHANNEL *c);
|
|||||||
CIPHER *OvsGetCipher(char *name);
|
CIPHER *OvsGetCipher(char *name);
|
||||||
MD *OvsGetMd(char *name);
|
MD *OvsGetMd(char *name);
|
||||||
|
|
||||||
void OpenVpnServerUdpSetDhParam(OPENVPN_SERVER_UDP *u, DH_CTX *dh);
|
|
||||||
|
|
||||||
#endif // PROTO_OPENVPN_H
|
#endif // PROTO_OPENVPN_H
|
||||||
|
@ -33,6 +33,8 @@ void SiSetOpenVPNAndSSTPConfig(SERVER *s, OPENVPN_SSTP_CONFIG *c)
|
|||||||
|
|
||||||
Lock(s->OpenVpnSstpConfigLock);
|
Lock(s->OpenVpnSstpConfigLock);
|
||||||
{
|
{
|
||||||
|
LIST *ports;
|
||||||
|
|
||||||
// Save the settings
|
// Save the settings
|
||||||
if (s->Cedar->Bridge || s->ServerType != SERVER_TYPE_STANDALONE)
|
if (s->Cedar->Bridge || s->ServerType != SERVER_TYPE_STANDALONE)
|
||||||
{
|
{
|
||||||
@ -45,24 +47,14 @@ void SiSetOpenVPNAndSSTPConfig(SERVER *s, OPENVPN_SSTP_CONFIG *c)
|
|||||||
s->DisableOpenVPNServer = !c->EnableOpenVPN;
|
s->DisableOpenVPNServer = !c->EnableOpenVPN;
|
||||||
}
|
}
|
||||||
|
|
||||||
NormalizeIntListStr(s->OpenVpnServerUdpPorts, sizeof(s->OpenVpnServerUdpPorts),
|
// TODO: Now that we have a unified protocol interface (Proto), the setting's name should be changed.
|
||||||
c->OpenVPNPortList, true, ", ");
|
NormalizeIntListStr(s->OpenVpnServerUdpPorts, sizeof(s->OpenVpnServerUdpPorts), c->OpenVPNPortList, true, ", ");
|
||||||
|
ports = StrToIntList(s->OpenVpnServerUdpPorts, true);
|
||||||
|
ProtoSetUdpPorts(s->Proto, ports);
|
||||||
|
ReleaseIntList(ports);
|
||||||
|
|
||||||
s->Cedar->OpenVPNObfuscation = c->OpenVPNObfuscation;
|
s->Cedar->OpenVPNObfuscation = c->OpenVPNObfuscation;
|
||||||
StrCpy(s->Cedar->OpenVPNObfuscationMask, sizeof(s->Cedar->OpenVPNObfuscationMask), c->OpenVPNObfuscationMask);
|
StrCpy(s->Cedar->OpenVPNObfuscationMask, sizeof(s->Cedar->OpenVPNObfuscationMask), c->OpenVPNObfuscationMask);
|
||||||
|
|
||||||
// Apply the OpenVPN configuration
|
|
||||||
if (s->OpenVpnServerUdp != NULL)
|
|
||||||
{
|
|
||||||
if (s->DisableOpenVPNServer)
|
|
||||||
{
|
|
||||||
OvsApplyUdpPortList(s->OpenVpnServerUdp, "", NULL);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
OvsApplyUdpPortList(s->OpenVpnServerUdp, s->OpenVpnServerUdpPorts, &s->ListenIP);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Unlock(s->OpenVpnSstpConfigLock);
|
Unlock(s->OpenVpnSstpConfigLock);
|
||||||
}
|
}
|
||||||
@ -2629,8 +2621,6 @@ void SiInitConfiguration(SERVER *s)
|
|||||||
s->Proto = ProtoNew(s->Cedar);
|
s->Proto = ProtoNew(s->Cedar);
|
||||||
// IPsec server
|
// IPsec server
|
||||||
s->IPsecServer = NewIPsecServer(s->Cedar);
|
s->IPsecServer = NewIPsecServer(s->Cedar);
|
||||||
// OpenVPN server (UDP)
|
|
||||||
s->OpenVpnServerUdp = NewOpenVpnServerUdp(s->Cedar);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SLog(s->Cedar, "LS_LOAD_CONFIG_1");
|
SLog(s->Cedar, "LS_LOAD_CONFIG_1");
|
||||||
@ -5660,7 +5650,9 @@ void SiLoadServerCfg(SERVER *s, FOLDER *f)
|
|||||||
}
|
}
|
||||||
|
|
||||||
s->DontBackupConfig = CfgGetBool(f, "DontBackupConfig");
|
s->DontBackupConfig = CfgGetBool(f, "DontBackupConfig");
|
||||||
|
|
||||||
CfgGetIp(f, "ListenIP", &s->ListenIP);
|
CfgGetIp(f, "ListenIP", &s->ListenIP);
|
||||||
|
ProtoSetListenIP(s->Proto, &s->ListenIP);
|
||||||
|
|
||||||
if (CfgIsItem(f, "BackupConfigOnlyWhenModified"))
|
if (CfgIsItem(f, "BackupConfigOnlyWhenModified"))
|
||||||
{
|
{
|
||||||
@ -6036,10 +6028,6 @@ void SiLoadServerCfg(SERVER *s, FOLDER *f)
|
|||||||
}
|
}
|
||||||
|
|
||||||
SetDhParam(DhNewFromBits(c->DhParamBits));
|
SetDhParam(DhNewFromBits(c->DhParamBits));
|
||||||
if (s->OpenVpnServerUdp)
|
|
||||||
{
|
|
||||||
OpenVpnServerUdpSetDhParam(s->OpenVpnServerUdp, DhNewFromBits(c->DhParamBits));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Unlock(c->lock);
|
Unlock(c->lock);
|
||||||
|
|
||||||
@ -6549,14 +6537,6 @@ void SiFreeConfiguration(SERVER *s)
|
|||||||
s->IPsecServer = NULL;
|
s->IPsecServer = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Terminate the OpenVPN server
|
|
||||||
if (s->OpenVpnServerUdp != NULL)
|
|
||||||
{
|
|
||||||
FreeOpenVpnServerUdp(s->OpenVpnServerUdp);
|
|
||||||
s->OpenVpnServerUdp = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Terminate the DDNS client
|
// Terminate the DDNS client
|
||||||
if (s->DDnsClient != NULL)
|
if (s->DDnsClient != NULL)
|
||||||
{
|
{
|
||||||
|
@ -244,7 +244,6 @@ struct SERVER
|
|||||||
|
|
||||||
PROTO *Proto; // Protocols handler
|
PROTO *Proto; // Protocols handler
|
||||||
IPSEC_SERVER *IPsecServer; // IPsec server function
|
IPSEC_SERVER *IPsecServer; // IPsec server function
|
||||||
OPENVPN_SERVER_UDP *OpenVpnServerUdp; // OpenVPN server function
|
|
||||||
char OpenVpnServerUdpPorts[MAX_SIZE]; // UDP port list string
|
char OpenVpnServerUdpPorts[MAX_SIZE]; // UDP port list string
|
||||||
DDNS_CLIENT *DDnsClient; // DDNS client feature
|
DDNS_CLIENT *DDnsClient; // DDNS client feature
|
||||||
LOCK *OpenVpnSstpConfigLock; // Lock OpenVPN and SSTP configuration
|
LOCK *OpenVpnSstpConfigLock; // Lock OpenVPN and SSTP configuration
|
||||||
|
@ -19329,6 +19329,19 @@ UDPLISTENER *NewUdpListenerEx(UDPLISTENER_RECV_PROC *recv_proc, void *param, IP
|
|||||||
return u;
|
return u;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Stop the UDP listener
|
||||||
|
void StopUdpListener(UDPLISTENER *u)
|
||||||
|
{
|
||||||
|
if (u == NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
u->Halt = true;
|
||||||
|
SetSockEvent(u->Event);
|
||||||
|
WaitThread(u->Thread, INFINITE);
|
||||||
|
}
|
||||||
|
|
||||||
// Release the UDP listener
|
// Release the UDP listener
|
||||||
void FreeUdpListener(UDPLISTENER *u)
|
void FreeUdpListener(UDPLISTENER *u)
|
||||||
{
|
{
|
||||||
@ -19339,10 +19352,8 @@ void FreeUdpListener(UDPLISTENER *u)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
u->Halt = true;
|
StopUdpListener(u);
|
||||||
SetSockEvent(u->Event);
|
|
||||||
|
|
||||||
WaitThread(u->Thread, INFINITE);
|
|
||||||
ReleaseThread(u->Thread);
|
ReleaseThread(u->Thread);
|
||||||
ReleaseSockEvent(u->Event);
|
ReleaseSockEvent(u->Event);
|
||||||
|
|
||||||
|
@ -1357,6 +1357,7 @@ UINT64 GetHostIPAddressListHash();
|
|||||||
UDPLISTENER *NewUdpListener(UDPLISTENER_RECV_PROC *recv_proc, void *param, IP *listen_ip);
|
UDPLISTENER *NewUdpListener(UDPLISTENER_RECV_PROC *recv_proc, void *param, IP *listen_ip);
|
||||||
UDPLISTENER *NewUdpListenerEx(UDPLISTENER_RECV_PROC *recv_proc, void *param, IP *listen_ip, UINT packet_type);
|
UDPLISTENER *NewUdpListenerEx(UDPLISTENER_RECV_PROC *recv_proc, void *param, IP *listen_ip, UINT packet_type);
|
||||||
void UdpListenerThread(THREAD *thread, void *param);
|
void UdpListenerThread(THREAD *thread, void *param);
|
||||||
|
void StopUdpListener(UDPLISTENER *u);
|
||||||
void FreeUdpListener(UDPLISTENER *u);
|
void FreeUdpListener(UDPLISTENER *u);
|
||||||
void AddPortToUdpListener(UDPLISTENER *u, UINT port);
|
void AddPortToUdpListener(UDPLISTENER *u, UINT port);
|
||||||
void DeletePortFromUdpListener(UDPLISTENER *u, UINT port);
|
void DeletePortFromUdpListener(UDPLISTENER *u, UINT port);
|
||||||
|
Loading…
Reference in New Issue
Block a user