22 #include <winpr/config.h>
26 #include "PacketMessage.h"
28 #include <winpr/wtypes.h>
29 #include <winpr/crt.h>
30 #include <winpr/file.h>
31 #include <winpr/stream.h>
32 #include <winpr/sysinfo.h>
34 #include "../../log.h"
35 #define TAG WINPR_TAG("utils.wlog")
39 if (pcap && pcap->fp && fread((
void*)header,
sizeof(
wPcapHeader), 1, pcap->fp) == 1)
48 if (pcap && pcap->fp && (fread((
void*) record,
sizeof(
wPcapRecordHeader), 1, pcap->fp) == 1))
57 if (!Pcap_Read_RecordHeader(pcap, &record->header))
59 record->length = record->header.incl_len;
60 record->data = malloc(record->length);
63 if (fread(record->data, record->length, 1, pcap->fp) != 1)
74 static BOOL Pcap_Add_Record(
wPcap* pcap,
void* data, UINT32 length)
83 pcap->head = pcap->tail;
84 pcap->record = pcap->head;
92 pcap->tail->next = record;
97 pcap->record = record;
100 record->length = length;
101 record->header.incl_len = length;
102 record->header.orig_len = length;
104 UINT64 ns = winpr_GetUnixTimeNS();
105 record->header.ts_sec = WINPR_TIME_NS_TO_S(ns);
106 record->header.ts_usec = WINPR_TIME_NS_REM_US(ns);
110 static BOOL Pcap_HasNext_Record(
wPcap* pcap)
112 if (pcap->file_size - (_ftelli64(pcap->fp)) <= 16)
120 if (!Pcap_HasNext_Record(pcap) || !Pcap_Read_RecordHeader(pcap, &record->header))
123 record->length = record->header.incl_len;
129 if (pcap && pcap->fp && fread(record->data, record->length, 1, pcap->fp) == 1)
137 if (!Pcap_HasNext_Record(pcap))
140 return Pcap_Read_Record(pcap, record);
146 if (pcap && pcap->fp && fwrite((
void*)header,
sizeof(
wPcapHeader), 1, pcap->fp) == 1)
153 if (pcap && pcap->fp && fwrite((
void*)record,
sizeof(
wPcapRecordHeader), 1, pcap->fp) == 1)
160 if (pcap && pcap->fp && fwrite(record->data, record->length, 1, pcap->fp) == 1)
167 return Pcap_Write_RecordHeader(pcap, &record->header) && Pcap_Write_RecordContent(pcap, record);
170 wPcap* Pcap_Open(
char* name, BOOL write)
173 FILE* pcap_fp = winpr_fopen(name, write ?
"w+b" :
"rb");
177 WLog_ERR(TAG,
"opening pcap file");
188 pcap->record_count = 0;
193 pcap->header.magic_number = PCAP_MAGIC_NUMBER;
194 pcap->header.version_major = 2;
195 pcap->header.version_minor = 4;
196 pcap->header.thiszone = 0;
197 pcap->header.sigfigs = 0;
198 pcap->header.snaplen = 0xFFFFFFFF;
199 pcap->header.network = 1;
200 if (!Pcap_Write_Header(pcap, &pcap->header))
205 if (_fseeki64(pcap->fp, 0, SEEK_END) < 0)
207 pcap->file_size = (SSIZE_T)_ftelli64(pcap->fp);
208 if (pcap->file_size < 0)
210 if (_fseeki64(pcap->fp, 0, SEEK_SET) < 0)
212 if (!Pcap_Read_Header(pcap, &pcap->header))
220 (void)fclose(pcap_fp);
225 void Pcap_Flush(
wPcap* pcap)
227 if (!pcap || !pcap->fp)
232 if (!Pcap_Write_Record(pcap, pcap->record))
234 pcap->record = pcap->record->next;
237 (void)fflush(pcap->fp);
240 void Pcap_Close(
wPcap* pcap)
242 if (!pcap || !pcap->fp)
246 (void)fclose(pcap->fp);
254 BYTE buffer[14] = { 0 };
257 if (!pcap || !pcap->fp || !ethernet)
260 s = Stream_StaticInit(&sbuffer, buffer,
sizeof(buffer));
263 Stream_Write(s, ethernet->Destination, 6);
264 Stream_Write(s, ethernet->Source, 6);
265 Stream_Write_UINT16_BE(s, ethernet->Type);
266 if (fwrite(buffer,
sizeof(buffer), 1, pcap->fp) != 1)
272 static UINT16 IPv4Checksum(
const BYTE* ipv4,
int length)
278 const UINT16 tmp16 = *((
const UINT16*)ipv4);
287 while (checksum >> 16)
288 checksum = (checksum & 0xFFFF) + (checksum >> 16);
290 return (UINT16)(~checksum);
293 static BOOL WLog_PacketMessage_Write_IPv4Header(
wPcap* pcap,
wIPv4Header* ipv4)
297 BYTE buffer[20] = { 0 };
300 if (!pcap || !pcap->fp || !ipv4)
303 s = Stream_StaticInit(&sbuffer, buffer,
sizeof(buffer));
306 Stream_Write_UINT8(s, (BYTE)((ipv4->Version << 4) | ipv4->InternetHeaderLength));
307 Stream_Write_UINT8(s, ipv4->TypeOfService);
308 Stream_Write_UINT16_BE(s, ipv4->TotalLength);
309 Stream_Write_UINT16_BE(s, ipv4->Identification);
310 Stream_Write_UINT16_BE(s, (UINT16)((ipv4->InternetProtocolFlags << 13) | ipv4->FragmentOffset));
311 Stream_Write_UINT8(s, ipv4->TimeToLive);
312 Stream_Write_UINT8(s, ipv4->Protocol);
313 Stream_Write_UINT16(s, ipv4->HeaderChecksum);
314 Stream_Write_UINT32_BE(s, ipv4->SourceAddress);
315 Stream_Write_UINT32_BE(s, ipv4->DestinationAddress);
316 ipv4->HeaderChecksum = IPv4Checksum((BYTE*)buffer, 20);
317 Stream_Rewind(s, 10);
318 Stream_Write_UINT16(s, ipv4->HeaderChecksum);
320 if (fwrite(buffer,
sizeof(buffer), 1, pcap->fp) != 1)
326 static BOOL WLog_PacketMessage_Write_TcpHeader(
wPcap* pcap,
wTcpHeader* tcp)
330 BYTE buffer[20] = { 0 };
333 if (!pcap || !pcap->fp || !tcp)
336 s = Stream_StaticInit(&sbuffer, buffer,
sizeof(buffer));
339 Stream_Write_UINT16_BE(s, tcp->SourcePort);
340 Stream_Write_UINT16_BE(s, tcp->DestinationPort);
341 Stream_Write_UINT32_BE(s, tcp->SequenceNumber);
342 Stream_Write_UINT32_BE(s, tcp->AcknowledgementNumber);
343 Stream_Write_UINT8(s, (UINT8)((tcp->Offset << 4) | (tcp->Reserved & 0xF)));
344 Stream_Write_UINT8(s, tcp->TcpFlags);
345 Stream_Write_UINT16_BE(s, tcp->Window);
346 Stream_Write_UINT16_BE(s, tcp->Checksum);
347 Stream_Write_UINT16_BE(s, tcp->UrgentPointer);
351 if (fwrite(buffer,
sizeof(buffer), 1, pcap->fp) != 1)
358 static UINT32 g_InboundSequenceNumber = 0;
359 static UINT32 g_OutboundSequenceNumber = 0;
361 BOOL WLog_PacketMessage_Write(
wPcap* pcap,
void* data,
size_t length, DWORD flags)
367 ethernet.Type = 0x0800;
369 if (!pcap || !pcap->fp)
372 if (flags & WLOG_PACKET_OUTBOUND)
375 ethernet.Source[0] = 0x00;
376 ethernet.Source[1] = 0x15;
377 ethernet.Source[2] = 0x5D;
378 ethernet.Source[3] = 0x01;
379 ethernet.Source[4] = 0x64;
380 ethernet.Source[5] = 0x04;
382 ethernet.Destination[0] = 0x00;
383 ethernet.Destination[1] = 0x15;
384 ethernet.Destination[2] = 0x5D;
385 ethernet.Destination[3] = 0x01;
386 ethernet.Destination[4] = 0x64;
387 ethernet.Destination[5] = 0x01;
392 ethernet.Source[0] = 0x00;
393 ethernet.Source[1] = 0x15;
394 ethernet.Source[2] = 0x5D;
395 ethernet.Source[3] = 0x01;
396 ethernet.Source[4] = 0x64;
397 ethernet.Source[5] = 0x01;
399 ethernet.Destination[0] = 0x00;
400 ethernet.Destination[1] = 0x15;
401 ethernet.Destination[2] = 0x5D;
402 ethernet.Destination[3] = 0x01;
403 ethernet.Destination[4] = 0x64;
404 ethernet.Destination[5] = 0x04;
408 ipv4.InternetHeaderLength = 5;
409 ipv4.TypeOfService = 0;
410 ipv4.TotalLength = (UINT16)(length + 20 + 20);
411 ipv4.Identification = 0;
412 ipv4.InternetProtocolFlags = 0x02;
413 ipv4.FragmentOffset = 0;
414 ipv4.TimeToLive = 128;
416 ipv4.HeaderChecksum = 0;
418 if (flags & WLOG_PACKET_OUTBOUND)
420 ipv4.SourceAddress = 0xC0A80196;
421 ipv4.DestinationAddress = 0x4A7D64C8;
425 ipv4.SourceAddress = 0x4A7D64C8;
426 ipv4.DestinationAddress = 0xC0A80196;
429 tcp.SourcePort = 3389;
430 tcp.DestinationPort = 3389;
432 if (flags & WLOG_PACKET_OUTBOUND)
434 tcp.SequenceNumber = g_OutboundSequenceNumber;
435 tcp.AcknowledgementNumber = g_InboundSequenceNumber;
436 g_OutboundSequenceNumber += length;
440 tcp.SequenceNumber = g_InboundSequenceNumber;
441 tcp.AcknowledgementNumber = g_OutboundSequenceNumber;
442 g_InboundSequenceNumber += length;
447 tcp.TcpFlags = 0x0018;
450 tcp.UrgentPointer = 0;
452 record.length = length;
453 const size_t offset = 14 + 20 + 20;
454 WINPR_ASSERT(record.length <= UINT32_MAX - offset);
455 record.header.incl_len = (UINT32)record.length + offset;
456 record.header.orig_len = (UINT32)record.length + offset;
459 UINT64 ns = winpr_GetUnixTimeNS();
460 record.header.ts_sec = (UINT32)WINPR_TIME_NS_TO_S(ns);
461 record.header.ts_usec = WINPR_TIME_NS_REM_US(ns);
463 if (!Pcap_Write_RecordHeader(pcap, &record.header) ||
464 !WLog_PacketMessage_Write_EthernetHeader(pcap, ðernet) ||
465 !WLog_PacketMessage_Write_IPv4Header(pcap, &ipv4) ||
466 !WLog_PacketMessage_Write_TcpHeader(pcap, &tcp) || !Pcap_Write_RecordContent(pcap, &record))
468 (void)fflush(pcap->fp);