2010-11-20 10:37:14 +00:00
|
|
|
/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
|
|
|
|
/* If you are missing that file, acquire a complete release at teeworlds.com. */
|
2009-10-27 14:38:53 +00:00
|
|
|
#include <base/system.h>
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
#include "config.h"
|
|
|
|
#include "huffman.h"
|
2020-09-26 19:41:58 +00:00
|
|
|
#include "network.h"
|
2009-10-27 14:38:53 +00:00
|
|
|
|
2022-03-21 08:01:56 +00:00
|
|
|
const unsigned char SECURITY_TOKEN_MAGIC[4] = {'T', 'K', 'E', 'N'};
|
|
|
|
|
2009-10-27 14:38:53 +00:00
|
|
|
void CNetRecvUnpacker::Clear()
|
|
|
|
{
|
|
|
|
m_Valid = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CNetRecvUnpacker::Start(const NETADDR *pAddr, CNetConnection *pConnection, int ClientID)
|
|
|
|
{
|
|
|
|
m_Addr = *pAddr;
|
|
|
|
m_pConnection = pConnection;
|
|
|
|
m_ClientID = ClientID;
|
|
|
|
m_CurrentChunk = 0;
|
|
|
|
m_Valid = true;
|
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
// TODO: rename this function
|
2009-10-27 14:38:53 +00:00
|
|
|
int CNetRecvUnpacker::FetchChunk(CNetChunk *pChunk)
|
|
|
|
{
|
|
|
|
CNetChunkHeader Header;
|
|
|
|
unsigned char *pEnd = m_Data.m_aChunkData + m_Data.m_DataSize;
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2022-02-14 23:12:52 +00:00
|
|
|
while(true)
|
2009-10-27 14:38:53 +00:00
|
|
|
{
|
|
|
|
unsigned char *pData = m_Data.m_aChunkData;
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
// check for old data to unpack
|
2009-10-27 14:38:53 +00:00
|
|
|
if(!m_Valid || m_CurrentChunk >= m_Data.m_NumChunks)
|
|
|
|
{
|
|
|
|
Clear();
|
|
|
|
return 0;
|
|
|
|
}
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
// TODO: add checking here so we don't read too far
|
2009-10-27 14:38:53 +00:00
|
|
|
for(int i = 0; i < m_CurrentChunk; i++)
|
|
|
|
{
|
2020-03-29 02:36:38 +00:00
|
|
|
pData = Header.Unpack(pData, (m_pConnection && m_pConnection->m_Sixup) ? 6 : 4);
|
2009-10-27 14:38:53 +00:00
|
|
|
pData += Header.m_Size;
|
|
|
|
}
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
// unpack the header
|
2020-03-29 02:36:38 +00:00
|
|
|
pData = Header.Unpack(pData, (m_pConnection && m_pConnection->m_Sixup) ? 6 : 4);
|
2009-10-27 14:38:53 +00:00
|
|
|
m_CurrentChunk++;
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2020-09-26 19:41:58 +00:00
|
|
|
if(pData + Header.m_Size > pEnd)
|
2009-10-27 14:38:53 +00:00
|
|
|
{
|
|
|
|
Clear();
|
|
|
|
return 0;
|
|
|
|
}
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
// handle sequence stuff
|
2020-09-26 19:41:58 +00:00
|
|
|
if(m_pConnection && (Header.m_Flags & NET_CHUNKFLAG_VITAL))
|
2009-10-27 14:38:53 +00:00
|
|
|
{
|
2015-08-14 11:49:10 +00:00
|
|
|
// anti spoof: ignore unknown sequence
|
2020-09-26 19:41:58 +00:00
|
|
|
if(Header.m_Sequence == (m_pConnection->m_Ack + 1) % NET_MAX_SEQUENCE || m_pConnection->m_UnknownSeq)
|
2009-10-27 14:38:53 +00:00
|
|
|
{
|
2015-08-14 11:49:10 +00:00
|
|
|
m_pConnection->m_UnknownSeq = false;
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
// in sequence
|
2015-08-14 11:49:10 +00:00
|
|
|
m_pConnection->m_Ack = Header.m_Sequence;
|
2009-10-27 14:38:53 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
// old packet that we already got
|
2009-10-27 14:38:53 +00:00
|
|
|
if(CNetBase::IsSeqInBackroom(Header.m_Sequence, m_pConnection->m_Ack))
|
|
|
|
continue;
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
// out of sequence, request resend
|
|
|
|
if(g_Config.m_Debug)
|
2020-09-26 19:41:58 +00:00
|
|
|
dbg_msg("conn", "asking for resend %d %d", Header.m_Sequence, (m_pConnection->m_Ack + 1) % NET_MAX_SEQUENCE);
|
2009-10-27 14:38:53 +00:00
|
|
|
m_pConnection->SignalResend();
|
2010-05-29 07:25:38 +00:00
|
|
|
continue; // take the next chunk in the packet
|
2009-10-27 14:38:53 +00:00
|
|
|
}
|
|
|
|
}
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
// fill in the info
|
2009-10-27 14:38:53 +00:00
|
|
|
pChunk->m_ClientID = m_ClientID;
|
|
|
|
pChunk->m_Address = m_Addr;
|
2015-03-19 08:57:47 +00:00
|
|
|
pChunk->m_Flags = Header.m_Flags;
|
2009-10-27 14:38:53 +00:00
|
|
|
pChunk->m_DataSize = Header.m_Size;
|
|
|
|
pChunk->m_pData = pData;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-29 10:56:13 +00:00
|
|
|
static const unsigned char NET_HEADER_EXTENDED[] = {'x', 'e'};
|
2010-05-29 07:25:38 +00:00
|
|
|
// packs the data tight and sends it
|
2017-03-29 10:56:13 +00:00
|
|
|
void CNetBase::SendPacketConnless(NETSOCKET Socket, NETADDR *pAddr, const void *pData, int DataSize, bool Extended, unsigned char aExtra[4])
|
2009-10-27 14:38:53 +00:00
|
|
|
{
|
|
|
|
unsigned char aBuffer[NET_MAX_PACKETSIZE];
|
2017-03-29 10:56:13 +00:00
|
|
|
const int DATA_OFFSET = 6;
|
|
|
|
if(!Extended)
|
|
|
|
{
|
|
|
|
for(int i = 0; i < DATA_OFFSET; i++)
|
|
|
|
aBuffer[i] = 0xff;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
mem_copy(aBuffer, NET_HEADER_EXTENDED, sizeof(NET_HEADER_EXTENDED));
|
|
|
|
mem_copy(aBuffer + sizeof(NET_HEADER_EXTENDED), aExtra, 4);
|
|
|
|
}
|
|
|
|
mem_copy(aBuffer + DATA_OFFSET, pData, DataSize);
|
|
|
|
net_udp_send(Socket, pAddr, aBuffer, DataSize + DATA_OFFSET);
|
2009-10-27 14:38:53 +00:00
|
|
|
}
|
|
|
|
|
2020-06-16 12:41:30 +00:00
|
|
|
void CNetBase::SendPacket(NETSOCKET Socket, NETADDR *pAddr, CNetPacketConstruct *pPacket, SECURITY_TOKEN SecurityToken, bool Sixup, bool NoCompress)
|
2009-10-27 14:38:53 +00:00
|
|
|
{
|
|
|
|
unsigned char aBuffer[NET_MAX_PACKETSIZE];
|
|
|
|
int CompressedSize = -1;
|
|
|
|
int FinalSize = -1;
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
// log the data
|
2009-10-27 14:38:53 +00:00
|
|
|
if(ms_DataLogSent)
|
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
int Type = 1;
|
|
|
|
io_write(ms_DataLogSent, &Type, sizeof(Type));
|
2009-10-27 14:38:53 +00:00
|
|
|
io_write(ms_DataLogSent, &pPacket->m_DataSize, sizeof(pPacket->m_DataSize));
|
|
|
|
io_write(ms_DataLogSent, &pPacket->m_aChunkData, pPacket->m_DataSize);
|
|
|
|
io_flush(ms_DataLogSent);
|
|
|
|
}
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2020-03-29 02:36:38 +00:00
|
|
|
int HeaderSize = NET_PACKETHEADERSIZE;
|
2020-09-26 19:41:58 +00:00
|
|
|
if(Sixup)
|
2020-03-29 02:36:38 +00:00
|
|
|
{
|
2022-07-17 18:34:56 +00:00
|
|
|
HeaderSize += sizeof(SecurityToken);
|
|
|
|
mem_copy(&aBuffer[3], &SecurityToken, sizeof(SecurityToken));
|
2020-03-29 02:36:38 +00:00
|
|
|
}
|
2020-09-26 19:41:58 +00:00
|
|
|
else if(SecurityToken != NET_SECURITY_TOKEN_UNSUPPORTED)
|
2015-03-04 08:38:34 +00:00
|
|
|
{
|
|
|
|
// append security token
|
|
|
|
// if SecurityToken is NET_SECURITY_TOKEN_UNKNOWN we will still append it hoping to negotiate it
|
|
|
|
mem_copy(&pPacket->m_aChunkData[pPacket->m_DataSize], &SecurityToken, sizeof(SecurityToken));
|
|
|
|
pPacket->m_DataSize += sizeof(SecurityToken);
|
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
// compress
|
2020-06-16 12:41:30 +00:00
|
|
|
if(!NoCompress)
|
2020-09-26 19:41:58 +00:00
|
|
|
CompressedSize = ms_Huffman.Compress(pPacket->m_aChunkData, pPacket->m_DataSize, &aBuffer[HeaderSize], NET_MAX_PACKETSIZE - HeaderSize);
|
2009-10-27 14:38:53 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
// check if the compression was enabled, successful and good enough
|
2020-06-16 12:41:30 +00:00
|
|
|
if(!NoCompress && CompressedSize > 0 && CompressedSize < pPacket->m_DataSize)
|
2009-10-27 14:38:53 +00:00
|
|
|
{
|
|
|
|
FinalSize = CompressedSize;
|
|
|
|
pPacket->m_Flags |= NET_PACKETFLAG_COMPRESSION;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
// use uncompressed data
|
2009-10-27 14:38:53 +00:00
|
|
|
FinalSize = pPacket->m_DataSize;
|
2020-03-29 02:36:38 +00:00
|
|
|
mem_copy(&aBuffer[HeaderSize], pPacket->m_aChunkData, pPacket->m_DataSize);
|
2009-10-27 14:38:53 +00:00
|
|
|
pPacket->m_Flags &= ~NET_PACKETFLAG_COMPRESSION;
|
|
|
|
}
|
|
|
|
|
2020-03-29 02:36:38 +00:00
|
|
|
if(Sixup)
|
|
|
|
{
|
|
|
|
unsigned Flags = 0;
|
2020-09-26 19:41:58 +00:00
|
|
|
if(pPacket->m_Flags & NET_PACKETFLAG_CONTROL)
|
|
|
|
Flags |= 1;
|
|
|
|
if(pPacket->m_Flags & NET_PACKETFLAG_RESEND)
|
|
|
|
Flags |= 2;
|
|
|
|
if(pPacket->m_Flags & NET_PACKETFLAG_COMPRESSION)
|
|
|
|
Flags |= 4;
|
2020-03-29 02:36:38 +00:00
|
|
|
pPacket->m_Flags = Flags;
|
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
// set header and send the packet if all things are good
|
2009-10-27 14:38:53 +00:00
|
|
|
if(FinalSize >= 0)
|
|
|
|
{
|
2020-03-29 02:36:38 +00:00
|
|
|
FinalSize += HeaderSize;
|
2020-09-26 19:41:58 +00:00
|
|
|
aBuffer[0] = ((pPacket->m_Flags << 2) & 0xfc) | ((pPacket->m_Ack >> 8) & 0x3);
|
|
|
|
aBuffer[1] = pPacket->m_Ack & 0xff;
|
2009-10-27 14:38:53 +00:00
|
|
|
aBuffer[2] = pPacket->m_NumChunks;
|
|
|
|
net_udp_send(Socket, pAddr, aBuffer, FinalSize);
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
// log raw socket data
|
2009-10-27 14:38:53 +00:00
|
|
|
if(ms_DataLogSent)
|
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
int Type = 0;
|
|
|
|
io_write(ms_DataLogSent, &Type, sizeof(Type));
|
2009-10-27 14:38:53 +00:00
|
|
|
io_write(ms_DataLogSent, &FinalSize, sizeof(FinalSize));
|
|
|
|
io_write(ms_DataLogSent, aBuffer, FinalSize);
|
|
|
|
io_flush(ms_DataLogSent);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
// TODO: rename this function
|
2020-10-27 17:57:14 +00:00
|
|
|
int CNetBase::UnpackPacket(unsigned char *pBuffer, int Size, CNetPacketConstruct *pPacket, bool &Sixup, SECURITY_TOKEN *pSecurityToken, SECURITY_TOKEN *pResponseToken)
|
2009-10-27 14:38:53 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
// check the size
|
2009-10-27 14:38:53 +00:00
|
|
|
if(Size < NET_PACKETHEADERSIZE || Size > NET_MAX_PACKETSIZE)
|
|
|
|
return -1;
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
// log the data
|
2009-10-27 14:38:53 +00:00
|
|
|
if(ms_DataLogRecv)
|
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
int Type = 0;
|
|
|
|
io_write(ms_DataLogRecv, &Type, sizeof(Type));
|
2009-10-27 14:38:53 +00:00
|
|
|
io_write(ms_DataLogRecv, &Size, sizeof(Size));
|
|
|
|
io_write(ms_DataLogRecv, pBuffer, Size);
|
|
|
|
io_flush(ms_DataLogRecv);
|
|
|
|
}
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
// read the packet
|
2020-09-26 19:41:58 +00:00
|
|
|
pPacket->m_Flags = pBuffer[0] >> 2;
|
2020-03-29 02:36:38 +00:00
|
|
|
|
2020-09-26 19:41:58 +00:00
|
|
|
if(pPacket->m_Flags & NET_PACKETFLAG_CONNLESS)
|
2009-10-27 14:38:53 +00:00
|
|
|
{
|
2020-09-26 19:41:58 +00:00
|
|
|
Sixup = (pBuffer[0] & 0x3) == 1;
|
Fix client crash when unpacking a sixup packet
The client crashes when trying to unpack a packet that has the sixup flag set, as `CNetClient` does not pass pointers for the output parameters `pSecurityToken` and `pResponseToken` to `CNetBase::UnpackPacket`.
Since the client does not handle sixup packets, checks are added to return an error and ignore the packet instead of crashing due to a null pointer access.
This was found by fuzzing the data returned by `net_udp_recv` with radamsa.
```
==6200==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x7f8d0fb8ba56 bp 0x7ffcbf67c7f0 sp 0x7ffcbf67c7a8 T0)
==6200==The signal is caused by a WRITE memory access.
==6200==Hint: address points to the zero page.
0 0x7f8d0fb8ba56 (/lib/x86_64-linux-gnu/libc.so.6+0xc4a56)
1 0x563a7e250fbe in mem_copy src/base/system.cpp:208
2 0x563a7e1bc6b6 in CNetBase::UnpackPacket(unsigned char*, int, CNetPacketConstruct*, bool&, int*, int*) src/engine/shared/network.cpp:263
3 0x563a7e1bf57e in CNetClient::Recv(CNetChunk*) src/engine/shared/network_client.cpp:100
4 0x563a7cfa76a2 in CClient::PumpNetwork() src/engine/client/client.cpp:2546
5 0x563a7cfb7cf6 in CClient::Update() src/engine/client/client.cpp:2838
6 0x563a7cfcfe47 in CClient::Run() src/engine/client/client.cpp:3214
7 0x563a7d04c631 in main src/engine/client/client.cpp:4702
8 0x7f8d0faf0d8f in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
9 0x7f8d0faf0e3f in __libc_start_main_impl ../csu/libc-start.c:392
10 0x563a7cb28754 in _start (build-asan/DDNet+0x2472754)
==8315==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x7f4accfe5a56 bp 0x7ffcf1318530 sp 0x7ffcf13184e8 T0)
==8315==The signal is caused by a WRITE memory access.
==8315==Hint: address points to the zero page.
0 0x7f4accfe5a56 (/lib/x86_64-linux-gnu/libc.so.6+0xc4a56)
1 0x560413603200 in mem_copy src/base/system.cpp:208
2 0x56041356d9c7 in CNetBase::UnpackPacket(unsigned char*, int, CNetPacketConstruct*, bool&, int*, int*) src/engine/shared/network.cpp:224
3 0x5604135717c0 in CNetClient::Recv(CNetChunk*) src/engine/shared/network_client.cpp:104
4 0x5604123597e2 in CClient::PumpNetwork() src/engine/client/client.cpp:2546
5 0x560412369e36 in CClient::Update() src/engine/client/client.cpp:2838
6 0x560412381f87 in CClient::Run() src/engine/client/client.cpp:3214
7 0x5604123fe771 in main src/engine/client/client.cpp:4702
8 0x7f4accf4ad8f in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
9 0x7f4accf4ae3f in __libc_start_main_impl ../csu/libc-start.c:392
10 0x560411eda894 in _start (build-asan/DDNet+0x2472894)
```
2022-11-24 20:10:39 +00:00
|
|
|
if(Sixup && (pSecurityToken == nullptr || pResponseToken == nullptr))
|
|
|
|
return -1;
|
2020-06-16 12:41:30 +00:00
|
|
|
int Offset = Sixup ? 9 : 6;
|
|
|
|
if(Size < Offset)
|
2009-10-27 14:38:53 +00:00
|
|
|
return -1;
|
2020-06-16 12:41:30 +00:00
|
|
|
|
|
|
|
if(Sixup)
|
|
|
|
{
|
2022-07-17 18:34:56 +00:00
|
|
|
mem_copy(pSecurityToken, &pBuffer[1], sizeof(*pSecurityToken));
|
|
|
|
mem_copy(pResponseToken, &pBuffer[5], sizeof(*pResponseToken));
|
2009-10-27 14:38:53 +00:00
|
|
|
}
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2009-10-27 14:38:53 +00:00
|
|
|
pPacket->m_Flags = NET_PACKETFLAG_CONNLESS;
|
|
|
|
pPacket->m_Ack = 0;
|
|
|
|
pPacket->m_NumChunks = 0;
|
2020-06-16 12:41:30 +00:00
|
|
|
pPacket->m_DataSize = Size - Offset;
|
|
|
|
mem_copy(pPacket->m_aChunkData, pBuffer + Offset, pPacket->m_DataSize);
|
2017-03-29 10:56:13 +00:00
|
|
|
|
2020-06-16 12:41:30 +00:00
|
|
|
if(!Sixup && mem_comp(pBuffer, NET_HEADER_EXTENDED, sizeof(NET_HEADER_EXTENDED)) == 0)
|
2017-03-29 10:56:13 +00:00
|
|
|
{
|
|
|
|
pPacket->m_Flags |= NET_PACKETFLAG_EXTENDED;
|
|
|
|
mem_copy(pPacket->m_aExtraData, pBuffer + sizeof(NET_HEADER_EXTENDED), sizeof(pPacket->m_aExtraData));
|
|
|
|
}
|
2009-10-27 14:38:53 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-09-26 19:41:58 +00:00
|
|
|
if(pPacket->m_Flags & NET_PACKETFLAG_UNUSED)
|
2020-06-16 12:41:30 +00:00
|
|
|
Sixup = true;
|
Fix client crash when unpacking a sixup packet
The client crashes when trying to unpack a packet that has the sixup flag set, as `CNetClient` does not pass pointers for the output parameters `pSecurityToken` and `pResponseToken` to `CNetBase::UnpackPacket`.
Since the client does not handle sixup packets, checks are added to return an error and ignore the packet instead of crashing due to a null pointer access.
This was found by fuzzing the data returned by `net_udp_recv` with radamsa.
```
==6200==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x7f8d0fb8ba56 bp 0x7ffcbf67c7f0 sp 0x7ffcbf67c7a8 T0)
==6200==The signal is caused by a WRITE memory access.
==6200==Hint: address points to the zero page.
0 0x7f8d0fb8ba56 (/lib/x86_64-linux-gnu/libc.so.6+0xc4a56)
1 0x563a7e250fbe in mem_copy src/base/system.cpp:208
2 0x563a7e1bc6b6 in CNetBase::UnpackPacket(unsigned char*, int, CNetPacketConstruct*, bool&, int*, int*) src/engine/shared/network.cpp:263
3 0x563a7e1bf57e in CNetClient::Recv(CNetChunk*) src/engine/shared/network_client.cpp:100
4 0x563a7cfa76a2 in CClient::PumpNetwork() src/engine/client/client.cpp:2546
5 0x563a7cfb7cf6 in CClient::Update() src/engine/client/client.cpp:2838
6 0x563a7cfcfe47 in CClient::Run() src/engine/client/client.cpp:3214
7 0x563a7d04c631 in main src/engine/client/client.cpp:4702
8 0x7f8d0faf0d8f in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
9 0x7f8d0faf0e3f in __libc_start_main_impl ../csu/libc-start.c:392
10 0x563a7cb28754 in _start (build-asan/DDNet+0x2472754)
==8315==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x7f4accfe5a56 bp 0x7ffcf1318530 sp 0x7ffcf13184e8 T0)
==8315==The signal is caused by a WRITE memory access.
==8315==Hint: address points to the zero page.
0 0x7f4accfe5a56 (/lib/x86_64-linux-gnu/libc.so.6+0xc4a56)
1 0x560413603200 in mem_copy src/base/system.cpp:208
2 0x56041356d9c7 in CNetBase::UnpackPacket(unsigned char*, int, CNetPacketConstruct*, bool&, int*, int*) src/engine/shared/network.cpp:224
3 0x5604135717c0 in CNetClient::Recv(CNetChunk*) src/engine/shared/network_client.cpp:104
4 0x5604123597e2 in CClient::PumpNetwork() src/engine/client/client.cpp:2546
5 0x560412369e36 in CClient::Update() src/engine/client/client.cpp:2838
6 0x560412381f87 in CClient::Run() src/engine/client/client.cpp:3214
7 0x5604123fe771 in main src/engine/client/client.cpp:4702
8 0x7f4accf4ad8f in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
9 0x7f4accf4ae3f in __libc_start_main_impl ../csu/libc-start.c:392
10 0x560411eda894 in _start (build-asan/DDNet+0x2472894)
```
2022-11-24 20:10:39 +00:00
|
|
|
if(Sixup && (pSecurityToken == nullptr || pResponseToken == nullptr))
|
|
|
|
return -1;
|
2020-06-16 12:41:30 +00:00
|
|
|
int DataStart = Sixup ? 7 : NET_PACKETHEADERSIZE;
|
|
|
|
if(Size < DataStart)
|
|
|
|
return -1;
|
|
|
|
|
2020-09-26 19:41:58 +00:00
|
|
|
pPacket->m_Ack = ((pBuffer[0] & 0x3) << 8) | pBuffer[1];
|
2020-06-16 12:41:30 +00:00
|
|
|
pPacket->m_NumChunks = pBuffer[2];
|
|
|
|
pPacket->m_DataSize = Size - DataStart;
|
|
|
|
|
2020-03-29 02:36:38 +00:00
|
|
|
if(Sixup)
|
|
|
|
{
|
2020-06-16 12:41:30 +00:00
|
|
|
unsigned Flags = 0;
|
2020-09-26 19:41:58 +00:00
|
|
|
if(pPacket->m_Flags & 1)
|
|
|
|
Flags |= NET_PACKETFLAG_CONTROL;
|
|
|
|
if(pPacket->m_Flags & 2)
|
|
|
|
Flags |= NET_PACKETFLAG_RESEND;
|
|
|
|
if(pPacket->m_Flags & 4)
|
|
|
|
Flags |= NET_PACKETFLAG_COMPRESSION;
|
2020-06-16 12:41:30 +00:00
|
|
|
pPacket->m_Flags = Flags;
|
|
|
|
|
2022-07-17 18:34:56 +00:00
|
|
|
mem_copy(pSecurityToken, &pBuffer[3], sizeof(*pSecurityToken));
|
2020-03-29 02:36:38 +00:00
|
|
|
}
|
2020-06-16 12:41:30 +00:00
|
|
|
|
2020-09-26 19:41:58 +00:00
|
|
|
if(pPacket->m_Flags & NET_PACKETFLAG_COMPRESSION)
|
2016-08-12 16:41:03 +00:00
|
|
|
{
|
|
|
|
// Don't allow compressed control packets.
|
2020-09-26 19:41:58 +00:00
|
|
|
if(pPacket->m_Flags & NET_PACKETFLAG_CONTROL)
|
2016-08-12 16:41:03 +00:00
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
2020-03-29 02:36:38 +00:00
|
|
|
pPacket->m_DataSize = ms_Huffman.Decompress(&pBuffer[DataStart], pPacket->m_DataSize, pPacket->m_aChunkData, sizeof(pPacket->m_aChunkData));
|
2016-08-12 16:41:03 +00:00
|
|
|
}
|
2009-10-27 14:38:53 +00:00
|
|
|
else
|
2020-03-29 02:36:38 +00:00
|
|
|
mem_copy(pPacket->m_aChunkData, &pBuffer[DataStart], pPacket->m_DataSize);
|
2009-10-27 14:38:53 +00:00
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
// check for errors
|
2009-10-27 14:38:53 +00:00
|
|
|
if(pPacket->m_DataSize < 0)
|
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
if(g_Config.m_Debug)
|
2009-10-27 14:38:53 +00:00
|
|
|
dbg_msg("network", "error during packet decoding");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
// log the data
|
2009-10-27 14:38:53 +00:00
|
|
|
if(ms_DataLogRecv)
|
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
int Type = 1;
|
|
|
|
io_write(ms_DataLogRecv, &Type, sizeof(Type));
|
2009-10-27 14:38:53 +00:00
|
|
|
io_write(ms_DataLogRecv, &pPacket->m_DataSize, sizeof(pPacket->m_DataSize));
|
|
|
|
io_write(ms_DataLogRecv, pPacket->m_aChunkData, pPacket->m_DataSize);
|
|
|
|
io_flush(ms_DataLogRecv);
|
|
|
|
}
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
// return success
|
2009-10-27 14:38:53 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-03-29 02:36:38 +00:00
|
|
|
void CNetBase::SendControlMsg(NETSOCKET Socket, NETADDR *pAddr, int Ack, int ControlMsg, const void *pExtra, int ExtraSize, SECURITY_TOKEN SecurityToken, bool Sixup)
|
2009-10-27 14:38:53 +00:00
|
|
|
{
|
|
|
|
CNetPacketConstruct Construct;
|
|
|
|
Construct.m_Flags = NET_PACKETFLAG_CONTROL;
|
|
|
|
Construct.m_Ack = Ack;
|
|
|
|
Construct.m_NumChunks = 0;
|
2020-09-26 19:41:58 +00:00
|
|
|
Construct.m_DataSize = 1 + ExtraSize;
|
2009-10-27 14:38:53 +00:00
|
|
|
Construct.m_aChunkData[0] = ControlMsg;
|
No null pointer to mem_copy in SendControlMsg
src/base/system.c:261:15: runtime error: null pointer passed as argument 2, which is declared to never be null
/usr/include/string.h:44:28: note: nonnull attribute specified here
#0 0x565165b348dc in mem_copy /media/ddnet/src/base/system.c:261:2
#1 0x565165aeb27d in CNetBase::SendControlMsg(NETSOCKET, NETADDR*, int, int, void const*, int, int, bool) /media/ddnet/src/engine/shared/network.cpp:313:2
#2 0x565165aeeb4e in CNetConnection::SendControl(int, void const*, int) /media/ddnet/src/engine/shared/network_conn.cpp:169:2
#3 0x565165af08c5 in CNetConnection::Feed(CNetPacketConstruct*, NETADDR*, int) /media/ddnet/src/engine/shared/network_conn.cpp:367:6
#4 0x565165aec7d2 in CNetClient::Recv(CNetChunk*) /media/ddnet/src/engine/shared/network_client.cpp:94:174
#5 0x565165c5d5ea in CClient::PumpNetwork() /media/ddnet/src/engine/client/client.cpp:2571:24
#6 0x565165c67a71 in CClient::Update() /media/ddnet/src/engine/client/client.cpp:2856:2
#7 0x565165c72f4e in CClient::Run() /media/ddnet/src/engine/client/client.cpp:3237:4
#8 0x565165c94b7e in main /media/ddnet/src/engine/client/client.cpp:4341:11
#9 0x7fba5af2c151 in __libc_start_main (/usr/lib/libc.so.6+0x28151)
#10 0x5651659e1e0d in _start (/media/ddnet/DDNet+0x705e0d)
2020-10-10 10:27:22 +00:00
|
|
|
if(pExtra)
|
|
|
|
mem_copy(&Construct.m_aChunkData[1], pExtra, ExtraSize);
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
// send the control message
|
2020-06-16 12:41:30 +00:00
|
|
|
CNetBase::SendPacket(Socket, pAddr, &Construct, SecurityToken, Sixup, true);
|
2009-10-27 14:38:53 +00:00
|
|
|
}
|
|
|
|
|
2020-10-27 17:57:14 +00:00
|
|
|
unsigned char *CNetChunkHeader::Pack(unsigned char *pData, int Split)
|
2009-10-27 14:38:53 +00:00
|
|
|
{
|
2020-10-27 17:57:14 +00:00
|
|
|
pData[0] = ((m_Flags & 3) << 6) | ((m_Size >> Split) & 0x3f);
|
|
|
|
pData[1] = (m_Size & ((1 << Split) - 1));
|
2020-09-26 19:41:58 +00:00
|
|
|
if(m_Flags & NET_CHUNKFLAG_VITAL)
|
2009-10-27 14:38:53 +00:00
|
|
|
{
|
2020-10-27 17:57:14 +00:00
|
|
|
pData[1] |= (m_Sequence >> 2) & (~((1 << Split) - 1));
|
2020-09-26 19:41:58 +00:00
|
|
|
pData[2] = m_Sequence & 0xff;
|
2009-10-27 14:38:53 +00:00
|
|
|
return pData + 3;
|
|
|
|
}
|
|
|
|
return pData + 2;
|
|
|
|
}
|
|
|
|
|
2020-10-27 17:57:14 +00:00
|
|
|
unsigned char *CNetChunkHeader::Unpack(unsigned char *pData, int Split)
|
2009-10-27 14:38:53 +00:00
|
|
|
{
|
2020-09-26 19:41:58 +00:00
|
|
|
m_Flags = (pData[0] >> 6) & 3;
|
2020-10-27 17:57:14 +00:00
|
|
|
m_Size = ((pData[0] & 0x3f) << Split) | (pData[1] & ((1 << Split) - 1));
|
2009-10-27 14:38:53 +00:00
|
|
|
m_Sequence = -1;
|
2020-09-26 19:41:58 +00:00
|
|
|
if(m_Flags & NET_CHUNKFLAG_VITAL)
|
2009-10-27 14:38:53 +00:00
|
|
|
{
|
2020-10-27 17:57:14 +00:00
|
|
|
m_Sequence = ((pData[1] & (~((1 << Split) - 1))) << 2) | pData[2];
|
2009-10-27 14:38:53 +00:00
|
|
|
return pData + 3;
|
|
|
|
}
|
|
|
|
return pData + 2;
|
|
|
|
}
|
|
|
|
|
2022-07-17 18:51:48 +00:00
|
|
|
bool CNetBase::IsSeqInBackroom(int Seq, int Ack)
|
2009-10-27 14:38:53 +00:00
|
|
|
{
|
2020-09-26 19:41:58 +00:00
|
|
|
int Bottom = (Ack - NET_MAX_SEQUENCE / 2);
|
2009-10-27 14:38:53 +00:00
|
|
|
if(Bottom < 0)
|
|
|
|
{
|
|
|
|
if(Seq <= Ack)
|
2022-07-17 18:51:48 +00:00
|
|
|
return true;
|
2009-10-27 14:38:53 +00:00
|
|
|
if(Seq >= (Bottom + NET_MAX_SEQUENCE))
|
2022-07-17 18:51:48 +00:00
|
|
|
return true;
|
2009-10-27 14:38:53 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if(Seq <= Ack && Seq >= Bottom)
|
2022-07-17 18:51:48 +00:00
|
|
|
return true;
|
2009-10-27 14:38:53 +00:00
|
|
|
}
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2022-07-17 18:51:48 +00:00
|
|
|
return false;
|
2009-10-27 14:38:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
IOHANDLE CNetBase::ms_DataLogSent = 0;
|
|
|
|
IOHANDLE CNetBase::ms_DataLogRecv = 0;
|
2010-05-29 07:25:38 +00:00
|
|
|
CHuffman CNetBase::ms_Huffman;
|
2009-10-27 14:38:53 +00:00
|
|
|
|
2011-03-05 10:46:24 +00:00
|
|
|
void CNetBase::OpenLog(IOHANDLE DataLogSent, IOHANDLE DataLogRecv)
|
2009-10-27 14:38:53 +00:00
|
|
|
{
|
2011-03-05 10:46:24 +00:00
|
|
|
if(DataLogSent)
|
2009-10-27 14:38:53 +00:00
|
|
|
{
|
2011-03-05 10:46:24 +00:00
|
|
|
ms_DataLogSent = DataLogSent;
|
|
|
|
dbg_msg("network", "logging sent packages");
|
2009-10-27 14:38:53 +00:00
|
|
|
}
|
2011-03-05 10:46:24 +00:00
|
|
|
else
|
|
|
|
dbg_msg("network", "failed to start logging sent packages");
|
|
|
|
|
|
|
|
if(DataLogRecv)
|
2009-10-27 14:38:53 +00:00
|
|
|
{
|
2011-03-05 10:46:24 +00:00
|
|
|
ms_DataLogRecv = DataLogRecv;
|
|
|
|
dbg_msg("network", "logging recv packages");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
dbg_msg("network", "failed to start logging recv packages");
|
|
|
|
}
|
|
|
|
|
|
|
|
void CNetBase::CloseLog()
|
|
|
|
{
|
|
|
|
if(ms_DataLogSent)
|
|
|
|
{
|
|
|
|
dbg_msg("network", "stopped logging sent packages");
|
|
|
|
io_close(ms_DataLogSent);
|
|
|
|
ms_DataLogSent = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(ms_DataLogRecv)
|
|
|
|
{
|
|
|
|
dbg_msg("network", "stopped logging recv packages");
|
|
|
|
io_close(ms_DataLogRecv);
|
|
|
|
ms_DataLogRecv = 0;
|
|
|
|
}
|
2009-10-27 14:38:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int CNetBase::Compress(const void *pData, int DataSize, void *pOutput, int OutputSize)
|
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
return ms_Huffman.Compress(pData, DataSize, pOutput, OutputSize);
|
2009-10-27 14:38:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int CNetBase::Decompress(const void *pData, int DataSize, void *pOutput, int OutputSize)
|
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
return ms_Huffman.Decompress(pData, DataSize, pOutput, OutputSize);
|
2009-10-27 14:38:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CNetBase::Init()
|
|
|
|
{
|
2022-03-05 09:50:48 +00:00
|
|
|
ms_Huffman.Init();
|
2009-10-27 14:38:53 +00:00
|
|
|
}
|