mirror of
https://github.com/SoftEtherVPN/SoftEtherVPN.git
synced 2024-11-22 17:39:53 +03:00
Cedar: prepare Proto for UDP support
- An additional parameter is added to IsPacketForMe(), used to specify the protocol type (currently either TCP or UDP). - SupportedModes() is dropped because it's now redundant. - IsOk() and EstablishedSessions() are dropped because error checking should be handled by the implementation. - ProtoImplDetect() now takes a buffer and its size rather than a SOCK, so that it can be used to detect UDP protocols. - The OpenVPN toggle check is moved to ProtoImplDetect(), so that we don't have to duplicate it once UDP support is implemented.
This commit is contained in:
parent
7e8b3c0b39
commit
667108319d
@ -65,31 +65,34 @@ 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;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,29 +107,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 +205,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
|
||||||
|
@ -7,8 +7,12 @@
|
|||||||
|
|
||||||
#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
|
||||||
{
|
{
|
||||||
@ -21,12 +25,9 @@ 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 *received_data, FIFO *data_to_send);
|
bool (*ProcessData)(void *param, TCP_RAW_DATA *received_data, FIFO *data_to_send);
|
||||||
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;
|
||||||
|
|
||||||
int ProtoImplCompare(void *p1, void *p2);
|
int ProtoImplCompare(void *p1, void *p2);
|
||||||
@ -35,7 +36,7 @@ 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);
|
||||||
|
|
||||||
bool ProtoHandleConnection(PROTO *proto, SOCK *sock);
|
bool ProtoHandleConnection(PROTO *proto, SOCK *sock);
|
||||||
|
|
||||||
|
@ -21,12 +21,9 @@ PROTO_IMPL *OvsGetProtoImpl()
|
|||||||
OvsInit,
|
OvsInit,
|
||||||
OvsFree,
|
OvsFree,
|
||||||
OvsName,
|
OvsName,
|
||||||
OvsSupportedModes,
|
|
||||||
OvsIsPacketForMe,
|
OvsIsPacketForMe,
|
||||||
OvsProcessData,
|
OvsProcessData,
|
||||||
OvsBufferLimit,
|
OvsBufferLimit,
|
||||||
OvsIsOk,
|
|
||||||
OvsEstablishedSessions
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return &impl;
|
return &impl;
|
||||||
@ -55,24 +52,32 @@ 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;
|
||||||
}
|
}
|
||||||
@ -81,16 +86,14 @@ bool OvsProcessData(void *param, TCP_RAW_DATA *received_data, FIFO *data_to_send
|
|||||||
{
|
{
|
||||||
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 || received_data == NULL || data_to_send == 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)
|
||||||
{
|
{
|
||||||
@ -166,6 +169,21 @@ bool OvsProcessData(void *param, TCP_RAW_DATA *received_data, FIFO *data_to_send
|
|||||||
|
|
||||||
DeleteAll(server->SendPacketList);
|
DeleteAll(server->SendPacketList);
|
||||||
|
|
||||||
|
if (server->Giveup <= server->Now)
|
||||||
|
{
|
||||||
|
for (UINT 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -179,46 +197,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, ...)
|
||||||
{
|
{
|
||||||
@ -2924,6 +2902,7 @@ 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;
|
||||||
|
|
||||||
|
@ -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
|
||||||
@ -220,8 +221,7 @@ 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 *received_data, FIFO *data_to_send);
|
bool OvsProcessData(void *param, TCP_RAW_DATA *received_data, FIFO *data_to_send);
|
||||||
void OvsBufferLimit(void *param, const bool reached);
|
void OvsBufferLimit(void *param, const bool reached);
|
||||||
bool OvsIsOk(void *param);
|
bool OvsIsOk(void *param);
|
||||||
|
Loading…
Reference in New Issue
Block a user