22#include <winpr/config.h>
26#include "PacketMessage.h"
28#include <winpr/wtypes.h>
30#include <winpr/file.h>
31#include <winpr/stream.h>
32#include <winpr/sysinfo.h>
36 return (pcap && pcap->fp && fread((
void*)header,
sizeof(
wPcapHeader), 1, pcap->fp) == 1);
41 return (pcap && pcap->fp && fwrite((
void*)header,
sizeof(
wPcapHeader), 1, pcap->fp) == 1);
46 return (pcap && pcap->fp && fwrite((
void*)record,
sizeof(
wPcapRecordHeader), 1, pcap->fp) == 1);
51 return (pcap && pcap->fp && fwrite(record->data, record->length, 1, pcap->fp) == 1);
56 return Pcap_Write_RecordHeader(pcap, &record->header) && Pcap_Write_RecordContent(pcap, record);
59wPcap* Pcap_Open(
char* name, BOOL write)
69 pcap->fp = winpr_fopen(name, write ?
"w+b" :
"rb");
76 pcap->record_count = 0;
80 pcap->header.magic_number = PCAP_MAGIC_NUMBER;
81 pcap->header.version_major = 2;
82 pcap->header.version_minor = 4;
83 pcap->header.thiszone = 0;
84 pcap->header.sigfigs = 0;
85 pcap->header.snaplen = 0xFFFFFFFF;
86 pcap->header.network = 1;
87 if (!Pcap_Write_Header(pcap, &pcap->header))
92 if (_fseeki64(pcap->fp, 0, SEEK_END) < 0)
94 pcap->file_size = (SSIZE_T)_ftelli64(pcap->fp);
95 if (pcap->file_size < 0)
97 if (_fseeki64(pcap->fp, 0, SEEK_SET) < 0)
99 if (!Pcap_Read_Header(pcap, &pcap->header))
110void Pcap_Flush(
wPcap* pcap)
112 if (!pcap || !pcap->fp)
117 if (!Pcap_Write_Record(pcap, pcap->record))
119 pcap->record = pcap->record->next;
122 (void)fflush(pcap->fp);
125void Pcap_Close(
wPcap* pcap)
132 (void)fclose(pcap->fp);
139 wStream sbuffer = WINPR_C_ARRAY_INIT;
140 BYTE buffer[14] = WINPR_C_ARRAY_INIT;
143 if (!pcap || !pcap->fp || !ethernet)
146 s = Stream_StaticInit(&sbuffer, buffer,
sizeof(buffer));
149 Stream_Write(s, ethernet->Destination, 6);
150 Stream_Write(s, ethernet->Source, 6);
151 Stream_Write_UINT16_BE(s, ethernet->Type);
152 if (fwrite(buffer,
sizeof(buffer), 1, pcap->fp) != 1)
158static UINT16 IPv4Checksum(
const BYTE* ipv4,
int length)
164 const UINT16 tmp16 = *((
const UINT16*)ipv4);
173 while (checksum >> 16)
174 checksum = (checksum & 0xFFFF) + (checksum >> 16);
176 return (UINT16)(~checksum);
179static BOOL WLog_PacketMessage_Write_IPv4Header(
wPcap* pcap,
wIPv4Header* ipv4)
182 wStream sbuffer = WINPR_C_ARRAY_INIT;
183 BYTE buffer[20] = WINPR_C_ARRAY_INIT;
186 if (!pcap || !pcap->fp || !ipv4)
189 s = Stream_StaticInit(&sbuffer, buffer,
sizeof(buffer));
192 Stream_Write_UINT8(s, (BYTE)((ipv4->Version << 4) | ipv4->InternetHeaderLength));
193 Stream_Write_UINT8(s, ipv4->TypeOfService);
194 Stream_Write_UINT16_BE(s, ipv4->TotalLength);
195 Stream_Write_UINT16_BE(s, ipv4->Identification);
196 Stream_Write_UINT16_BE(s, (UINT16)((ipv4->InternetProtocolFlags << 13) | ipv4->FragmentOffset));
197 Stream_Write_UINT8(s, ipv4->TimeToLive);
198 Stream_Write_UINT8(s, ipv4->Protocol);
199 Stream_Write_UINT16(s, ipv4->HeaderChecksum);
200 Stream_Write_UINT32_BE(s, ipv4->SourceAddress);
201 Stream_Write_UINT32_BE(s, ipv4->DestinationAddress);
202 ipv4->HeaderChecksum = IPv4Checksum((BYTE*)buffer, 20);
203 Stream_Rewind(s, 10);
204 Stream_Write_UINT16(s, ipv4->HeaderChecksum);
206 if (fwrite(buffer,
sizeof(buffer), 1, pcap->fp) != 1)
212static BOOL WLog_PacketMessage_Write_TcpHeader(
wPcap* pcap,
wTcpHeader* tcp)
215 wStream sbuffer = WINPR_C_ARRAY_INIT;
216 BYTE buffer[20] = WINPR_C_ARRAY_INIT;
219 if (!pcap || !pcap->fp || !tcp)
222 s = Stream_StaticInit(&sbuffer, buffer,
sizeof(buffer));
225 Stream_Write_UINT16_BE(s, tcp->SourcePort);
226 Stream_Write_UINT16_BE(s, tcp->DestinationPort);
227 Stream_Write_UINT32_BE(s, tcp->SequenceNumber);
228 Stream_Write_UINT32_BE(s, tcp->AcknowledgementNumber);
229 Stream_Write_UINT8(s, (UINT8)((tcp->Offset << 4) | (tcp->Reserved & 0xF)));
230 Stream_Write_UINT8(s, tcp->TcpFlags);
231 Stream_Write_UINT16_BE(s, tcp->Window);
232 Stream_Write_UINT16_BE(s, tcp->Checksum);
233 Stream_Write_UINT16_BE(s, tcp->UrgentPointer);
237 if (fwrite(buffer,
sizeof(buffer), 1, pcap->fp) != 1)
244static UINT32 g_InboundSequenceNumber = 0;
245static UINT32 g_OutboundSequenceNumber = 0;
247BOOL WLog_PacketMessage_Write(
wPcap* pcap,
void* data,
size_t length, DWORD flags)
253 ethernet.Type = 0x0800;
255 if (!pcap || !pcap->fp)
258 if (flags & WLOG_PACKET_OUTBOUND)
261 ethernet.Source[0] = 0x00;
262 ethernet.Source[1] = 0x15;
263 ethernet.Source[2] = 0x5D;
264 ethernet.Source[3] = 0x01;
265 ethernet.Source[4] = 0x64;
266 ethernet.Source[5] = 0x04;
268 ethernet.Destination[0] = 0x00;
269 ethernet.Destination[1] = 0x15;
270 ethernet.Destination[2] = 0x5D;
271 ethernet.Destination[3] = 0x01;
272 ethernet.Destination[4] = 0x64;
273 ethernet.Destination[5] = 0x01;
278 ethernet.Source[0] = 0x00;
279 ethernet.Source[1] = 0x15;
280 ethernet.Source[2] = 0x5D;
281 ethernet.Source[3] = 0x01;
282 ethernet.Source[4] = 0x64;
283 ethernet.Source[5] = 0x01;
285 ethernet.Destination[0] = 0x00;
286 ethernet.Destination[1] = 0x15;
287 ethernet.Destination[2] = 0x5D;
288 ethernet.Destination[3] = 0x01;
289 ethernet.Destination[4] = 0x64;
290 ethernet.Destination[5] = 0x04;
294 ipv4.InternetHeaderLength = 5;
295 ipv4.TypeOfService = 0;
296 ipv4.TotalLength = (UINT16)(length + 20 + 20);
297 ipv4.Identification = 0;
298 ipv4.InternetProtocolFlags = 0x02;
299 ipv4.FragmentOffset = 0;
300 ipv4.TimeToLive = 128;
302 ipv4.HeaderChecksum = 0;
304 if (flags & WLOG_PACKET_OUTBOUND)
306 ipv4.SourceAddress = 0xC0A80196;
307 ipv4.DestinationAddress = 0x4A7D64C8;
311 ipv4.SourceAddress = 0x4A7D64C8;
312 ipv4.DestinationAddress = 0xC0A80196;
315 tcp.SourcePort = 3389;
316 tcp.DestinationPort = 3389;
318 if (flags & WLOG_PACKET_OUTBOUND)
320 tcp.SequenceNumber = g_OutboundSequenceNumber;
321 tcp.AcknowledgementNumber = g_InboundSequenceNumber;
322 WINPR_ASSERT(length + g_OutboundSequenceNumber <= UINT32_MAX);
323 g_OutboundSequenceNumber += WINPR_ASSERTING_INT_CAST(uint32_t, length);
327 tcp.SequenceNumber = g_InboundSequenceNumber;
328 tcp.AcknowledgementNumber = g_OutboundSequenceNumber;
330 WINPR_ASSERT(length + g_InboundSequenceNumber <= UINT32_MAX);
331 g_InboundSequenceNumber += WINPR_ASSERTING_INT_CAST(uint32_t, length);
336 tcp.TcpFlags = 0x0018;
339 tcp.UrgentPointer = 0;
341 record.length = length;
342 const size_t offset = 14 + 20 + 20;
343 WINPR_ASSERT(record.length <= UINT32_MAX - offset);
344 const uint32_t rloff = WINPR_ASSERTING_INT_CAST(uint32_t, record.length + offset);
345 record.header.incl_len = rloff;
346 record.header.orig_len = rloff;
347 record.next =
nullptr;
349 UINT64 ns = winpr_GetUnixTimeNS();
350 record.header.ts_sec = (UINT32)WINPR_TIME_NS_TO_S(ns);
351 record.header.ts_usec = WINPR_TIME_NS_REM_US(ns);
353 if (!Pcap_Write_RecordHeader(pcap, &record.header) ||
354 !WLog_PacketMessage_Write_EthernetHeader(pcap, ðernet) ||
355 !WLog_PacketMessage_Write_IPv4Header(pcap, &ipv4) ||
356 !WLog_PacketMessage_Write_TcpHeader(pcap, &tcp) || !Pcap_Write_RecordContent(pcap, &record))
358 (void)fflush(pcap->fp);