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 return (pcap && pcap->fp && fread((
void*)header,
sizeof(
wPcapHeader), 1, pcap->fp) == 1);
44 return (pcap && pcap->fp && fwrite((
void*)header,
sizeof(
wPcapHeader), 1, pcap->fp) == 1);
49 return (pcap && pcap->fp && fwrite((
void*)record,
sizeof(
wPcapRecordHeader), 1, pcap->fp) == 1);
54 return (pcap && pcap->fp && fwrite(record->data, record->length, 1, pcap->fp) == 1);
59 return Pcap_Write_RecordHeader(pcap, &record->header) && Pcap_Write_RecordContent(pcap, record);
62wPcap* Pcap_Open(
char* name, BOOL write)
64 wPcap* pcap =
nullptr;
65 FILE* pcap_fp = winpr_fopen(name, write ?
"w+b" :
"rb");
69 WLog_ERR(TAG,
"opening pcap file");
80 pcap->record_count = 0;
85 pcap->header.magic_number = PCAP_MAGIC_NUMBER;
86 pcap->header.version_major = 2;
87 pcap->header.version_minor = 4;
88 pcap->header.thiszone = 0;
89 pcap->header.sigfigs = 0;
90 pcap->header.snaplen = 0xFFFFFFFF;
91 pcap->header.network = 1;
92 if (!Pcap_Write_Header(pcap, &pcap->header))
97 if (_fseeki64(pcap->fp, 0, SEEK_END) < 0)
99 pcap->file_size = (SSIZE_T)_ftelli64(pcap->fp);
100 if (pcap->file_size < 0)
102 if (_fseeki64(pcap->fp, 0, SEEK_SET) < 0)
104 if (!Pcap_Read_Header(pcap, &pcap->header))
112 (void)fclose(pcap_fp);
117void Pcap_Flush(
wPcap* pcap)
119 if (!pcap || !pcap->fp)
124 if (!Pcap_Write_Record(pcap, pcap->record))
126 pcap->record = pcap->record->next;
129 (void)fflush(pcap->fp);
132void Pcap_Close(
wPcap* pcap)
134 if (!pcap || !pcap->fp)
138 (void)fclose(pcap->fp);
145 wStream sbuffer = WINPR_C_ARRAY_INIT;
146 BYTE buffer[14] = WINPR_C_ARRAY_INIT;
149 if (!pcap || !pcap->fp || !ethernet)
152 s = Stream_StaticInit(&sbuffer, buffer,
sizeof(buffer));
155 Stream_Write(s, ethernet->Destination, 6);
156 Stream_Write(s, ethernet->Source, 6);
157 Stream_Write_UINT16_BE(s, ethernet->Type);
158 if (fwrite(buffer,
sizeof(buffer), 1, pcap->fp) != 1)
164static UINT16 IPv4Checksum(
const BYTE* ipv4,
int length)
170 const UINT16 tmp16 = *((
const UINT16*)ipv4);
179 while (checksum >> 16)
180 checksum = (checksum & 0xFFFF) + (checksum >> 16);
182 return (UINT16)(~checksum);
185static BOOL WLog_PacketMessage_Write_IPv4Header(
wPcap* pcap,
wIPv4Header* ipv4)
188 wStream sbuffer = WINPR_C_ARRAY_INIT;
189 BYTE buffer[20] = WINPR_C_ARRAY_INIT;
192 if (!pcap || !pcap->fp || !ipv4)
195 s = Stream_StaticInit(&sbuffer, buffer,
sizeof(buffer));
198 Stream_Write_UINT8(s, (BYTE)((ipv4->Version << 4) | ipv4->InternetHeaderLength));
199 Stream_Write_UINT8(s, ipv4->TypeOfService);
200 Stream_Write_UINT16_BE(s, ipv4->TotalLength);
201 Stream_Write_UINT16_BE(s, ipv4->Identification);
202 Stream_Write_UINT16_BE(s, (UINT16)((ipv4->InternetProtocolFlags << 13) | ipv4->FragmentOffset));
203 Stream_Write_UINT8(s, ipv4->TimeToLive);
204 Stream_Write_UINT8(s, ipv4->Protocol);
205 Stream_Write_UINT16(s, ipv4->HeaderChecksum);
206 Stream_Write_UINT32_BE(s, ipv4->SourceAddress);
207 Stream_Write_UINT32_BE(s, ipv4->DestinationAddress);
208 ipv4->HeaderChecksum = IPv4Checksum((BYTE*)buffer, 20);
209 Stream_Rewind(s, 10);
210 Stream_Write_UINT16(s, ipv4->HeaderChecksum);
212 if (fwrite(buffer,
sizeof(buffer), 1, pcap->fp) != 1)
218static BOOL WLog_PacketMessage_Write_TcpHeader(
wPcap* pcap,
wTcpHeader* tcp)
221 wStream sbuffer = WINPR_C_ARRAY_INIT;
222 BYTE buffer[20] = WINPR_C_ARRAY_INIT;
225 if (!pcap || !pcap->fp || !tcp)
228 s = Stream_StaticInit(&sbuffer, buffer,
sizeof(buffer));
231 Stream_Write_UINT16_BE(s, tcp->SourcePort);
232 Stream_Write_UINT16_BE(s, tcp->DestinationPort);
233 Stream_Write_UINT32_BE(s, tcp->SequenceNumber);
234 Stream_Write_UINT32_BE(s, tcp->AcknowledgementNumber);
235 Stream_Write_UINT8(s, (UINT8)((tcp->Offset << 4) | (tcp->Reserved & 0xF)));
236 Stream_Write_UINT8(s, tcp->TcpFlags);
237 Stream_Write_UINT16_BE(s, tcp->Window);
238 Stream_Write_UINT16_BE(s, tcp->Checksum);
239 Stream_Write_UINT16_BE(s, tcp->UrgentPointer);
243 if (fwrite(buffer,
sizeof(buffer), 1, pcap->fp) != 1)
250static UINT32 g_InboundSequenceNumber = 0;
251static UINT32 g_OutboundSequenceNumber = 0;
253BOOL WLog_PacketMessage_Write(
wPcap* pcap,
void* data,
size_t length, DWORD flags)
259 ethernet.Type = 0x0800;
261 if (!pcap || !pcap->fp)
264 if (flags & WLOG_PACKET_OUTBOUND)
267 ethernet.Source[0] = 0x00;
268 ethernet.Source[1] = 0x15;
269 ethernet.Source[2] = 0x5D;
270 ethernet.Source[3] = 0x01;
271 ethernet.Source[4] = 0x64;
272 ethernet.Source[5] = 0x04;
274 ethernet.Destination[0] = 0x00;
275 ethernet.Destination[1] = 0x15;
276 ethernet.Destination[2] = 0x5D;
277 ethernet.Destination[3] = 0x01;
278 ethernet.Destination[4] = 0x64;
279 ethernet.Destination[5] = 0x01;
284 ethernet.Source[0] = 0x00;
285 ethernet.Source[1] = 0x15;
286 ethernet.Source[2] = 0x5D;
287 ethernet.Source[3] = 0x01;
288 ethernet.Source[4] = 0x64;
289 ethernet.Source[5] = 0x01;
291 ethernet.Destination[0] = 0x00;
292 ethernet.Destination[1] = 0x15;
293 ethernet.Destination[2] = 0x5D;
294 ethernet.Destination[3] = 0x01;
295 ethernet.Destination[4] = 0x64;
296 ethernet.Destination[5] = 0x04;
300 ipv4.InternetHeaderLength = 5;
301 ipv4.TypeOfService = 0;
302 ipv4.TotalLength = (UINT16)(length + 20 + 20);
303 ipv4.Identification = 0;
304 ipv4.InternetProtocolFlags = 0x02;
305 ipv4.FragmentOffset = 0;
306 ipv4.TimeToLive = 128;
308 ipv4.HeaderChecksum = 0;
310 if (flags & WLOG_PACKET_OUTBOUND)
312 ipv4.SourceAddress = 0xC0A80196;
313 ipv4.DestinationAddress = 0x4A7D64C8;
317 ipv4.SourceAddress = 0x4A7D64C8;
318 ipv4.DestinationAddress = 0xC0A80196;
321 tcp.SourcePort = 3389;
322 tcp.DestinationPort = 3389;
324 if (flags & WLOG_PACKET_OUTBOUND)
326 tcp.SequenceNumber = g_OutboundSequenceNumber;
327 tcp.AcknowledgementNumber = g_InboundSequenceNumber;
328 WINPR_ASSERT(length + g_OutboundSequenceNumber <= UINT32_MAX);
329 g_OutboundSequenceNumber += WINPR_ASSERTING_INT_CAST(uint32_t, length);
333 tcp.SequenceNumber = g_InboundSequenceNumber;
334 tcp.AcknowledgementNumber = g_OutboundSequenceNumber;
336 WINPR_ASSERT(length + g_InboundSequenceNumber <= UINT32_MAX);
337 g_InboundSequenceNumber += WINPR_ASSERTING_INT_CAST(uint32_t, length);
342 tcp.TcpFlags = 0x0018;
345 tcp.UrgentPointer = 0;
347 record.length = length;
348 const size_t offset = 14 + 20 + 20;
349 WINPR_ASSERT(record.length <= UINT32_MAX - offset);
350 const uint32_t rloff = WINPR_ASSERTING_INT_CAST(uint32_t, record.length + offset);
351 record.header.incl_len = rloff;
352 record.header.orig_len = rloff;
353 record.next =
nullptr;
355 UINT64 ns = winpr_GetUnixTimeNS();
356 record.header.ts_sec = (UINT32)WINPR_TIME_NS_TO_S(ns);
357 record.header.ts_usec = WINPR_TIME_NS_REM_US(ns);
359 if (!Pcap_Write_RecordHeader(pcap, &record.header) ||
360 !WLog_PacketMessage_Write_EthernetHeader(pcap, ðernet) ||
361 !WLog_PacketMessage_Write_IPv4Header(pcap, &ipv4) ||
362 !WLog_PacketMessage_Write_TcpHeader(pcap, &tcp) || !Pcap_Write_RecordContent(pcap, &record))
364 (void)fflush(pcap->fp);