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>
35#define TAG WINPR_TAG("utils.wlog")
39 if (pcap && pcap->fp && fread((
void*)header,
sizeof(
wPcapHeader), 1, pcap->fp) == 1)
46 if (pcap && pcap->fp && fwrite((
void*)header,
sizeof(
wPcapHeader), 1, pcap->fp) == 1)
53 if (pcap && pcap->fp && fwrite((
void*)record,
sizeof(
wPcapRecordHeader), 1, pcap->fp) == 1)
60 if (pcap && pcap->fp && fwrite(record->data, record->length, 1, pcap->fp) == 1)
67 return Pcap_Write_RecordHeader(pcap, &record->header) && Pcap_Write_RecordContent(pcap, record);
70wPcap* Pcap_Open(
char* name, BOOL write)
73 FILE* pcap_fp = winpr_fopen(name, write ?
"w+b" :
"rb");
77 WLog_ERR(TAG,
"opening pcap file");
88 pcap->record_count = 0;
93 pcap->header.magic_number = PCAP_MAGIC_NUMBER;
94 pcap->header.version_major = 2;
95 pcap->header.version_minor = 4;
96 pcap->header.thiszone = 0;
97 pcap->header.sigfigs = 0;
98 pcap->header.snaplen = 0xFFFFFFFF;
99 pcap->header.network = 1;
100 if (!Pcap_Write_Header(pcap, &pcap->header))
105 if (_fseeki64(pcap->fp, 0, SEEK_END) < 0)
107 pcap->file_size = (SSIZE_T)_ftelli64(pcap->fp);
108 if (pcap->file_size < 0)
110 if (_fseeki64(pcap->fp, 0, SEEK_SET) < 0)
112 if (!Pcap_Read_Header(pcap, &pcap->header))
120 (void)fclose(pcap_fp);
125void Pcap_Flush(
wPcap* pcap)
127 if (!pcap || !pcap->fp)
132 if (!Pcap_Write_Record(pcap, pcap->record))
134 pcap->record = pcap->record->next;
137 (void)fflush(pcap->fp);
140void Pcap_Close(
wPcap* pcap)
142 if (!pcap || !pcap->fp)
146 (void)fclose(pcap->fp);
154 BYTE buffer[14] = { 0 };
157 if (!pcap || !pcap->fp || !ethernet)
160 s = Stream_StaticInit(&sbuffer, buffer,
sizeof(buffer));
163 Stream_Write(s, ethernet->Destination, 6);
164 Stream_Write(s, ethernet->Source, 6);
165 Stream_Write_UINT16_BE(s, ethernet->Type);
166 if (fwrite(buffer,
sizeof(buffer), 1, pcap->fp) != 1)
172static UINT16 IPv4Checksum(
const BYTE* ipv4,
int length)
178 const UINT16 tmp16 = *((
const UINT16*)ipv4);
187 while (checksum >> 16)
188 checksum = (checksum & 0xFFFF) + (checksum >> 16);
190 return (UINT16)(~checksum);
193static BOOL WLog_PacketMessage_Write_IPv4Header(
wPcap* pcap,
wIPv4Header* ipv4)
197 BYTE buffer[20] = { 0 };
200 if (!pcap || !pcap->fp || !ipv4)
203 s = Stream_StaticInit(&sbuffer, buffer,
sizeof(buffer));
206 Stream_Write_UINT8(s, (BYTE)((ipv4->Version << 4) | ipv4->InternetHeaderLength));
207 Stream_Write_UINT8(s, ipv4->TypeOfService);
208 Stream_Write_UINT16_BE(s, ipv4->TotalLength);
209 Stream_Write_UINT16_BE(s, ipv4->Identification);
210 Stream_Write_UINT16_BE(s, (UINT16)((ipv4->InternetProtocolFlags << 13) | ipv4->FragmentOffset));
211 Stream_Write_UINT8(s, ipv4->TimeToLive);
212 Stream_Write_UINT8(s, ipv4->Protocol);
213 Stream_Write_UINT16(s, ipv4->HeaderChecksum);
214 Stream_Write_UINT32_BE(s, ipv4->SourceAddress);
215 Stream_Write_UINT32_BE(s, ipv4->DestinationAddress);
216 ipv4->HeaderChecksum = IPv4Checksum((BYTE*)buffer, 20);
217 Stream_Rewind(s, 10);
218 Stream_Write_UINT16(s, ipv4->HeaderChecksum);
220 if (fwrite(buffer,
sizeof(buffer), 1, pcap->fp) != 1)
226static BOOL WLog_PacketMessage_Write_TcpHeader(
wPcap* pcap,
wTcpHeader* tcp)
230 BYTE buffer[20] = { 0 };
233 if (!pcap || !pcap->fp || !tcp)
236 s = Stream_StaticInit(&sbuffer, buffer,
sizeof(buffer));
239 Stream_Write_UINT16_BE(s, tcp->SourcePort);
240 Stream_Write_UINT16_BE(s, tcp->DestinationPort);
241 Stream_Write_UINT32_BE(s, tcp->SequenceNumber);
242 Stream_Write_UINT32_BE(s, tcp->AcknowledgementNumber);
243 Stream_Write_UINT8(s, (UINT8)((tcp->Offset << 4) | (tcp->Reserved & 0xF)));
244 Stream_Write_UINT8(s, tcp->TcpFlags);
245 Stream_Write_UINT16_BE(s, tcp->Window);
246 Stream_Write_UINT16_BE(s, tcp->Checksum);
247 Stream_Write_UINT16_BE(s, tcp->UrgentPointer);
251 if (fwrite(buffer,
sizeof(buffer), 1, pcap->fp) != 1)
258static UINT32 g_InboundSequenceNumber = 0;
259static UINT32 g_OutboundSequenceNumber = 0;
261BOOL WLog_PacketMessage_Write(
wPcap* pcap,
void* data,
size_t length, DWORD flags)
267 ethernet.Type = 0x0800;
269 if (!pcap || !pcap->fp)
272 if (flags & WLOG_PACKET_OUTBOUND)
275 ethernet.Source[0] = 0x00;
276 ethernet.Source[1] = 0x15;
277 ethernet.Source[2] = 0x5D;
278 ethernet.Source[3] = 0x01;
279 ethernet.Source[4] = 0x64;
280 ethernet.Source[5] = 0x04;
282 ethernet.Destination[0] = 0x00;
283 ethernet.Destination[1] = 0x15;
284 ethernet.Destination[2] = 0x5D;
285 ethernet.Destination[3] = 0x01;
286 ethernet.Destination[4] = 0x64;
287 ethernet.Destination[5] = 0x01;
292 ethernet.Source[0] = 0x00;
293 ethernet.Source[1] = 0x15;
294 ethernet.Source[2] = 0x5D;
295 ethernet.Source[3] = 0x01;
296 ethernet.Source[4] = 0x64;
297 ethernet.Source[5] = 0x01;
299 ethernet.Destination[0] = 0x00;
300 ethernet.Destination[1] = 0x15;
301 ethernet.Destination[2] = 0x5D;
302 ethernet.Destination[3] = 0x01;
303 ethernet.Destination[4] = 0x64;
304 ethernet.Destination[5] = 0x04;
308 ipv4.InternetHeaderLength = 5;
309 ipv4.TypeOfService = 0;
310 ipv4.TotalLength = (UINT16)(length + 20 + 20);
311 ipv4.Identification = 0;
312 ipv4.InternetProtocolFlags = 0x02;
313 ipv4.FragmentOffset = 0;
314 ipv4.TimeToLive = 128;
316 ipv4.HeaderChecksum = 0;
318 if (flags & WLOG_PACKET_OUTBOUND)
320 ipv4.SourceAddress = 0xC0A80196;
321 ipv4.DestinationAddress = 0x4A7D64C8;
325 ipv4.SourceAddress = 0x4A7D64C8;
326 ipv4.DestinationAddress = 0xC0A80196;
329 tcp.SourcePort = 3389;
330 tcp.DestinationPort = 3389;
332 if (flags & WLOG_PACKET_OUTBOUND)
334 tcp.SequenceNumber = g_OutboundSequenceNumber;
335 tcp.AcknowledgementNumber = g_InboundSequenceNumber;
336 WINPR_ASSERT(length + g_OutboundSequenceNumber <= UINT32_MAX);
337 g_OutboundSequenceNumber += WINPR_ASSERTING_INT_CAST(uint32_t, length);
341 tcp.SequenceNumber = g_InboundSequenceNumber;
342 tcp.AcknowledgementNumber = g_OutboundSequenceNumber;
344 WINPR_ASSERT(length + g_InboundSequenceNumber <= UINT32_MAX);
345 g_InboundSequenceNumber += WINPR_ASSERTING_INT_CAST(uint32_t, length);
350 tcp.TcpFlags = 0x0018;
353 tcp.UrgentPointer = 0;
355 record.length = length;
356 const size_t offset = 14 + 20 + 20;
357 WINPR_ASSERT(record.length <= UINT32_MAX - offset);
358 const uint32_t rloff = WINPR_ASSERTING_INT_CAST(uint32_t, record.length + offset);
359 record.header.incl_len = rloff;
360 record.header.orig_len = rloff;
363 UINT64 ns = winpr_GetUnixTimeNS();
364 record.header.ts_sec = (UINT32)WINPR_TIME_NS_TO_S(ns);
365 record.header.ts_usec = WINPR_TIME_NS_REM_US(ns);
367 if (!Pcap_Write_RecordHeader(pcap, &record.header) ||
368 !WLog_PacketMessage_Write_EthernetHeader(pcap, ðernet) ||
369 !WLog_PacketMessage_Write_IPv4Header(pcap, &ipv4) ||
370 !WLog_PacketMessage_Write_TcpHeader(pcap, &tcp) || !Pcap_Write_RecordContent(pcap, &record))
372 (void)fflush(pcap->fp);