From b140be11bd074984b3439ec3cb30fb2814f2474d Mon Sep 17 00:00:00 2001 From: Matt Olson Date: Mon, 21 Nov 2022 10:25:00 -0800 Subject: [PATCH] Add write buffer to improve performance (#59) --- src/main.c | 416 ++++++++++++++++++++++++++++++++++++++++++++++++++- src/pcapng.h | 368 --------------------------------------------- 2 files changed, 414 insertions(+), 370 deletions(-) delete mode 100644 src/pcapng.h diff --git a/src/main.c b/src/main.c index 315eb5b..51f3548 100644 --- a/src/main.c +++ b/src/main.c @@ -31,14 +31,420 @@ in Windows that produces packet capture events) to pcapng format #include #include #include -#include #define USAGE \ "etl2pcapng \n" \ "Converts a packet capture from etl to pcapng format.\n" // Increment when adding features -#define VERSION "1.9.0" +#define VERSION "1.10.0" + +// A write buffer to reduce the number of calls to WriteFile to improve performance. +// BufferBytes is called each time that WriteFile would normally be called; then +// at the end FlushBufferBytes is called once. + +#define WRITEBUF_SIZE 500000 +char WriteBuf[WRITEBUF_SIZE]; +unsigned long WriteBufNext = 0; // The offset of the next byte to be written into the buffer. + +BOOLEAN BufferBytes(HANDLE File, void* Buf, unsigned long BufSize) +{ + unsigned long CurSpace = WRITEBUF_SIZE - WriteBufNext; + + if (BufSize > CurSpace && CurSpace < WRITEBUF_SIZE) { + // Flush write buffer to make space for the new bytes. + if (!WriteFile(File, WriteBuf, WriteBufNext, NULL, NULL)) { + return FALSE; + } + WriteBufNext = 0; + CurSpace = WRITEBUF_SIZE; + } + + if (BufSize > CurSpace) { + // The buffer is empty and we still don't have enough space. + // Bypass the buffer and write directly to the file. + if (!WriteFile(File, Buf, BufSize, NULL, NULL)) { + return FALSE; + } + } else { + memcpy(WriteBuf + WriteBufNext, (char*)Buf, BufSize); + WriteBufNext += BufSize; + } + + return TRUE; +} + +BOOLEAN FlushBufferBytes(HANDLE File) +{ + if (!WriteFile(File, WriteBuf, WriteBufNext, NULL, NULL)) { + return FALSE; + } + WriteBufNext = 0; + + return TRUE; +} + +// Helpers for working with .pcapng files. +// https://github.com/pcapng/pcapng + +#pragma warning(disable:4200) // zero-sized array + +#define PCAPNG_BLOCKTYPE_SECTION_HEADER 0x0a0d0d0a +#define PCAPNG_BLOCKTYPE_INTERFACEDESC 0x00000001 +#define PCAPNG_BLOCKTYPE_ENHANCED_PACKET 0x00000006 + +#define PCAPNG_OPTIONCODE_ENDOFOPT 0 +#define PCAPNG_OPTIONCODE_COMMENT 1 +#define PCAPNG_OPTIONCODE_EPB_FLAGS 2 +#define PCAPNG_OPTIONCODE_IDB_IF_NAME 2 +#define PCAPNG_OPTIONCODE_IDB_IF_DESC 3 + +#define PCAPNG_LINKTYPE_ETHERNET 1 +#define PCAPNG_LINKTYPE_RAW 101 +#define PCAPNG_LINKTYPE_IEEE802_11 105 + +#define PCAPNG_SECTION_HEADER_MAGIC 0x1a2b3c4d // for byte order detection + +#define PAD_TO_32BIT(x) ((4 - ((x) & 3)) & 3) + +#include +struct PCAPNG_BLOCK_HEAD { + unsigned long Type; + unsigned long Length; +}; +struct PCAPNG_SECTION_HEADER_BODY { + unsigned long Magic; // endian detection (set this to PCAPNG_SECTION_HEADER_MAGIC) + unsigned short MajorVersion; + unsigned short MinorVersion; + long long Length; +}; +struct PCAPNG_INTERFACE_DESC_BODY { + unsigned short LinkType; + unsigned short Reserved; + unsigned long SnapLen; +}; +struct PCAPNG_ENHANCED_PACKET_BODY { + unsigned long InterfaceId; + unsigned long TimeStampHigh; + unsigned long TimeStampLow; + unsigned long CapturedLength; // excludes padding + unsigned long PacketLength; // excludes padding + unsigned char PacketData[0]; // padded to 4 bytes +}; +struct PCAPNG_BLOCK_OPTION_ENDOFOPT { + unsigned short Code; // PCAPNG_OPTIONCODE_ENDOFOPT + unsigned short Length; // 0 +}; +struct PCAPNG_BLOCK_OPTION_EPB_FLAGS { + unsigned short Code; // PCAPNG_OPTIONCODE_EPB_FLAGS + unsigned short Length; // 4 + unsigned long Value; +}; +struct PCAPNG_BLOCK_OPTION_VAR_LENGTH { + unsigned short Code; + unsigned short Length; +}; +struct PCAPNG_BLOCK_TAIL { + unsigned long Length; // Same as PCAPNG_BLOCK_HEAD.Length, for easier backward processing. +}; +#include + +struct PCAPNG_BLOCK_OPTION_ENDOFOPT EndOption = { .Code = PCAPNG_OPTIONCODE_ENDOFOPT, .Length = 0}; + +inline int +PcapNgWriteSectionHeader( + HANDLE File + ) +{ + int Err = NO_ERROR; + struct PCAPNG_BLOCK_HEAD Head; + struct PCAPNG_SECTION_HEADER_BODY Body; + struct PCAPNG_BLOCK_TAIL Tail; + int TotalLength = sizeof(Head) + sizeof(Body) + sizeof(Tail); + + Head.Type = PCAPNG_BLOCKTYPE_SECTION_HEADER; + Head.Length = TotalLength; + if (!BufferBytes(File, &Head, sizeof(Head))) { + Err = GetLastError(); + printf("WriteFile failed with %u\n", Err); + goto Done; + } + + Body.Magic = PCAPNG_SECTION_HEADER_MAGIC; + Body.MajorVersion = 1; + Body.MinorVersion = 0; + Body.Length = -1; + if (!BufferBytes(File, &Body, sizeof(Body))) { + Err = GetLastError(); + printf("WriteFile failed with %u\n", Err); + goto Done; + } + + Tail.Length = TotalLength; + if (!BufferBytes(File, &Tail, sizeof(Tail))) { + Err = GetLastError(); + printf("WriteFile failed with %u\n", Err); + goto Done; + } + +Done: + + return Err; +} + +inline int +PcapNgWriteInterfaceDesc( + HANDLE File, + short LinkType, + long SnapLen, + char* IfName, + unsigned short IfNameLength, + char* IfDesc, + unsigned short IfDescLength + ) +{ + int Err = NO_ERROR; + struct PCAPNG_BLOCK_HEAD Head; + struct PCAPNG_INTERFACE_DESC_BODY Body; + struct PCAPNG_BLOCK_TAIL Tail; + struct PCAPNG_BLOCK_OPTION_VAR_LENGTH IfNameOpt; + struct PCAPNG_BLOCK_OPTION_VAR_LENGTH IfDescOpt; + char Pad[4] = { 0 }; + + int TotalLength = sizeof(Head) + sizeof(Body) + sizeof(Tail); + + if (IfName != NULL) { + IfNameOpt.Code = PCAPNG_OPTIONCODE_IDB_IF_NAME; + IfNameOpt.Length = IfNameLength; + TotalLength += sizeof(IfNameOpt) + IfNameLength + PAD_TO_32BIT(IfNameLength); + } + + if (IfDesc != NULL) { + IfDescOpt.Code = PCAPNG_OPTIONCODE_IDB_IF_DESC; + IfDescOpt.Length = IfDescLength; + TotalLength += sizeof(IfDescOpt) + IfDescLength + PAD_TO_32BIT(IfDescLength); + } + + if (IfName != NULL || IfDesc != NULL) { + TotalLength += sizeof(EndOption); + } + + Head.Type = PCAPNG_BLOCKTYPE_INTERFACEDESC; + Head.Length = TotalLength; + if (!BufferBytes(File, &Head, sizeof(Head))) { + Err = GetLastError(); + printf("WriteFile failed with %u\n", Err); + goto Done; + } + + Body.LinkType = LinkType; + Body.Reserved = 0; + Body.SnapLen = SnapLen; + if (!BufferBytes(File, &Body, sizeof(Body))) { + Err = GetLastError(); + printf("WriteFile failed with %u\n", Err); + goto Done; + } + + if (IfName != NULL) { + if (!BufferBytes(File, &IfNameOpt, sizeof(IfNameOpt))) { + Err = GetLastError(); + printf("WriteFile failed with %u\n", Err); + goto Done; + } + + if (!BufferBytes(File, IfName, IfNameLength)) { + Err = GetLastError(); + printf("WriteFile failed with %u\n", Err); + goto Done; + } + + if (PAD_TO_32BIT(IfNameLength) > 0) { + if (!BufferBytes(File, Pad, PAD_TO_32BIT(IfNameLength))) { + Err = GetLastError(); + printf("WriteFile failed with %u\n", Err); + goto Done; + } + } + } + + if (IfDesc != NULL) { + if (!BufferBytes(File, &IfDescOpt, sizeof(IfDescOpt))) { + Err = GetLastError(); + printf("WriteFile failed with %u\n", Err); + goto Done; + } + + if (!BufferBytes(File, IfDesc, IfDescLength)) { + Err = GetLastError(); + printf("WriteFile failed with %u\n", Err); + goto Done; + } + + if (PAD_TO_32BIT(IfDescLength) > 0) { + if (!BufferBytes(File, Pad, PAD_TO_32BIT(IfDescLength))) { + Err = GetLastError(); + printf("WriteFile failed with %u\n", Err); + goto Done; + } + } + } + + if (!BufferBytes(File, &EndOption, sizeof(EndOption))) { + Err = GetLastError(); + printf("WriteFile failed with %u\n", Err); + goto Done; + } + + Tail.Length = TotalLength; + if (!BufferBytes(File, &Tail, sizeof(Tail))) { + Err = GetLastError(); + printf("WriteFile failed with %u\n", Err); + goto Done; + } + +Done: + + return Err; +} + +inline int +PcapNgWriteCommentOption( + HANDLE File, + PCHAR CommentBuffer, + unsigned short CommentLength, + int CommentPadLength + ) +{ + int Err = NO_ERROR; + struct PCAPNG_BLOCK_OPTION_VAR_LENGTH Comment; + char Pad[4] = { 0 }; + + Comment.Code = PCAPNG_OPTIONCODE_COMMENT; + Comment.Length = CommentLength; + + if (!BufferBytes(File, &Comment, sizeof(Comment))) { + Err = GetLastError(); + printf("WriteFile failed with %u\n", Err); + goto Done; + } + if (!BufferBytes(File, CommentBuffer, CommentLength)) { + Err = GetLastError(); + printf("WriteFile failed with %u\n", Err); + goto Done; + } + if (CommentPadLength > 0) { + if (!BufferBytes(File, Pad, CommentPadLength)) { + Err = GetLastError(); + printf("WriteFile failed with %u\n", Err); + goto Done; + } + } + +Done: + + return Err; +} + +inline int +PcapNgWriteEnhancedPacket( + HANDLE File, + char* FragBuf, + unsigned long FragLength, + unsigned long OrigFragLength, + long InterfaceId, + long IsSend, + long TimeStampHigh, // usec (unless if_tsresol is used) + long TimeStampLow, + char* Comment, + unsigned short CommentLength + ) +{ + int Err = NO_ERROR; + struct PCAPNG_BLOCK_HEAD Head; + struct PCAPNG_ENHANCED_PACKET_BODY Body; + struct PCAPNG_BLOCK_OPTION_EPB_FLAGS EpbFlagsOption; + struct PCAPNG_BLOCK_TAIL Tail; + char Pad[4] = {0}; + BOOLEAN CommentProvided = (CommentLength > 0 && Comment != NULL); + int CommentPadLength = PAD_TO_32BIT(CommentLength); + int FragPadLength = PAD_TO_32BIT(sizeof(Body) + FragLength); + int TotalLength = + sizeof(Head) + sizeof(Body) + FragLength + FragPadLength + + sizeof(EpbFlagsOption) + sizeof(EndOption) + sizeof(Tail) + + (CommentProvided ? + sizeof(struct PCAPNG_BLOCK_OPTION_VAR_LENGTH) + CommentLength + CommentPadLength : 0); + + Head.Type = PCAPNG_BLOCKTYPE_ENHANCED_PACKET; + Head.Length = TotalLength; + if (!BufferBytes(File, &Head, sizeof(Head))) { + Err = GetLastError(); + printf("WriteFile failed with %u\n", Err); + goto Done; + } + + Body.InterfaceId = InterfaceId; + Body.TimeStampHigh = TimeStampHigh; + Body.TimeStampLow = TimeStampLow; + Body.PacketLength = OrigFragLength; // original length + Body.CapturedLength = FragLength; // truncated length + if (!BufferBytes(File, &Body, sizeof(Body))) { + Err = GetLastError(); + printf("WriteFile failed with %u\n", Err); + goto Done; + } + if (!BufferBytes(File, FragBuf, FragLength)) { + Err = GetLastError(); + printf("WriteFile failed with %u\n", Err); + goto Done; + } + if (FragPadLength > 0) { + if (!BufferBytes(File, Pad, FragPadLength)) { + Err = GetLastError(); + printf("WriteFile failed with %u\n", Err); + goto Done; + } + } + + EpbFlagsOption.Code = PCAPNG_OPTIONCODE_EPB_FLAGS; + EpbFlagsOption.Length = 4; + EpbFlagsOption.Value = IsSend ? 2 : 1; + if (!BufferBytes(File, &EpbFlagsOption, sizeof(EpbFlagsOption))) { + Err = GetLastError(); + printf("WriteFile failed with %u\n", Err); + goto Done; + } + + if (CommentProvided) { + Err = PcapNgWriteCommentOption( + File, + Comment, + CommentLength, + CommentPadLength); + if (Err != NO_ERROR) { + goto Done; + } + } + + if (!BufferBytes(File, &EndOption, sizeof(EndOption))) { + Err = GetLastError(); + printf("WriteFile failed with %u\n", Err); + goto Done; + } + + Tail.Length = TotalLength; + if (!BufferBytes(File, &Tail, sizeof(Tail))) { + Err = GetLastError(); + printf("WriteFile failed with %u\n", Err); + goto Done; + } + +Done: + + return Err; +} + +// End pcapng helpers. #define MAX_PACKET_SIZE 65535 @@ -977,6 +1383,12 @@ int __cdecl wmain(int argc, wchar_t** argv) goto Done; } + if (!FlushBufferBytes(OutFile)) { + Err = GetLastError(); + printf("WriteFile failed with %u\n", Err); + goto Done; + } + if (NumFramesConverted == 0) { printf("Input ETL file does not contain a packet capture.\n"); } else { diff --git a/src/pcapng.h b/src/pcapng.h deleted file mode 100644 index acf49a9..0000000 --- a/src/pcapng.h +++ /dev/null @@ -1,368 +0,0 @@ -/* - -Copyright (c) Microsoft Corporation. -Licensed under the MIT License. - -Helpers for working with .pcapng files. -https://github.com/pcapng/pcapng - -*/ - -#pragma once -#pragma warning(disable:4200) // zero-sized array - -#define PCAPNG_BLOCKTYPE_SECTION_HEADER 0x0a0d0d0a -#define PCAPNG_BLOCKTYPE_INTERFACEDESC 0x00000001 -#define PCAPNG_BLOCKTYPE_ENHANCED_PACKET 0x00000006 - -#define PCAPNG_OPTIONCODE_ENDOFOPT 0 -#define PCAPNG_OPTIONCODE_COMMENT 1 -#define PCAPNG_OPTIONCODE_EPB_FLAGS 2 -#define PCAPNG_OPTIONCODE_IDB_IF_NAME 2 -#define PCAPNG_OPTIONCODE_IDB_IF_DESC 3 - -#define PCAPNG_LINKTYPE_ETHERNET 1 -#define PCAPNG_LINKTYPE_RAW 101 -#define PCAPNG_LINKTYPE_IEEE802_11 105 - -#define PCAPNG_SECTION_HEADER_MAGIC 0x1a2b3c4d // for byte order detection - -#define PAD_TO_32BIT(x) ((4 - ((x) & 3)) & 3) - -#include -struct PCAPNG_BLOCK_HEAD { - unsigned long Type; - unsigned long Length; -}; -struct PCAPNG_SECTION_HEADER_BODY { - unsigned long Magic; // endian detection (set this to PCAPNG_SECTION_HEADER_MAGIC) - unsigned short MajorVersion; - unsigned short MinorVersion; - long long Length; -}; -struct PCAPNG_INTERFACE_DESC_BODY { - unsigned short LinkType; - unsigned short Reserved; - unsigned long SnapLen; -}; -struct PCAPNG_ENHANCED_PACKET_BODY { - unsigned long InterfaceId; - unsigned long TimeStampHigh; - unsigned long TimeStampLow; - unsigned long CapturedLength; // excludes padding - unsigned long PacketLength; // excludes padding - unsigned char PacketData[0]; // padded to 4 bytes -}; -struct PCAPNG_BLOCK_OPTION_ENDOFOPT { - unsigned short Code; // PCAPNG_OPTIONCODE_ENDOFOPT - unsigned short Length; // 0 -}; -struct PCAPNG_BLOCK_OPTION_EPB_FLAGS { - unsigned short Code; // PCAPNG_OPTIONCODE_EPB_FLAGS - unsigned short Length; // 4 - unsigned long Value; -}; -struct PCAPNG_BLOCK_OPTION_VAR_LENGTH { - unsigned short Code; - unsigned short Length; -}; -struct PCAPNG_BLOCK_TAIL { - unsigned long Length; // Same as PCAPNG_BLOCK_HEAD.Length, for easier backward processing. -}; -#include - -struct PCAPNG_BLOCK_OPTION_ENDOFOPT EndOption = { .Code = PCAPNG_OPTIONCODE_ENDOFOPT, .Length = 0}; - -inline int -PcapNgWriteSectionHeader( - HANDLE File - ) -{ - int Err = NO_ERROR; - struct PCAPNG_BLOCK_HEAD Head; - struct PCAPNG_SECTION_HEADER_BODY Body; - struct PCAPNG_BLOCK_TAIL Tail; - int TotalLength = sizeof(Head) + sizeof(Body) + sizeof(Tail); - - Head.Type = PCAPNG_BLOCKTYPE_SECTION_HEADER; - Head.Length = TotalLength; - if (!WriteFile(File, &Head, sizeof(Head), NULL, NULL)) { - Err = GetLastError(); - printf("WriteFile failed with %u\n", Err); - goto Done; - } - - Body.Magic = PCAPNG_SECTION_HEADER_MAGIC; - Body.MajorVersion = 1; - Body.MinorVersion = 0; - Body.Length = -1; - if (!WriteFile(File, &Body, sizeof(Body), NULL, NULL)) { - Err = GetLastError(); - printf("WriteFile failed with %u\n", Err); - goto Done; - } - - Tail.Length = TotalLength; - if (!WriteFile(File, &Tail, sizeof(Tail), NULL, NULL)) { - Err = GetLastError(); - printf("WriteFile failed with %u\n", Err); - goto Done; - } - -Done: - - return Err; -} - -inline int -PcapNgWriteInterfaceDesc( - HANDLE File, - short LinkType, - long SnapLen, - char* IfName, - unsigned short IfNameLength, - char* IfDesc, - unsigned short IfDescLength - ) -{ - int Err = NO_ERROR; - struct PCAPNG_BLOCK_HEAD Head; - struct PCAPNG_INTERFACE_DESC_BODY Body; - struct PCAPNG_BLOCK_TAIL Tail; - struct PCAPNG_BLOCK_OPTION_VAR_LENGTH IfNameOpt; - struct PCAPNG_BLOCK_OPTION_VAR_LENGTH IfDescOpt; - char Pad[4] = { 0 }; - - int TotalLength = sizeof(Head) + sizeof(Body) + sizeof(Tail); - - if (IfName != NULL) { - IfNameOpt.Code = PCAPNG_OPTIONCODE_IDB_IF_NAME; - IfNameOpt.Length = IfNameLength; - TotalLength += sizeof(IfNameOpt) + IfNameLength + PAD_TO_32BIT(IfNameLength); - } - - if (IfDesc != NULL) { - IfDescOpt.Code = PCAPNG_OPTIONCODE_IDB_IF_DESC; - IfDescOpt.Length = IfDescLength; - TotalLength += sizeof(IfDescOpt) + IfDescLength + PAD_TO_32BIT(IfDescLength); - } - - if (IfName != NULL || IfDesc != NULL) { - TotalLength += sizeof(EndOption); - } - - Head.Type = PCAPNG_BLOCKTYPE_INTERFACEDESC; - Head.Length = TotalLength; - if (!WriteFile(File, &Head, sizeof(Head), NULL, NULL)) { - Err = GetLastError(); - printf("WriteFile failed with %u\n", Err); - goto Done; - } - - Body.LinkType = LinkType; - Body.Reserved = 0; - Body.SnapLen = SnapLen; - if (!WriteFile(File, &Body, sizeof(Body), NULL, NULL)) { - Err = GetLastError(); - printf("WriteFile failed with %u\n", Err); - goto Done; - } - - if (IfName != NULL) { - if (!WriteFile(File, &IfNameOpt, sizeof(IfNameOpt), NULL, NULL)) { - Err = GetLastError(); - printf("WriteFile failed with %u\n", Err); - goto Done; - } - - if (!WriteFile(File, IfName, IfNameLength, NULL, NULL)) { - Err = GetLastError(); - printf("WriteFile failed with %u\n", Err); - goto Done; - } - - if (PAD_TO_32BIT(IfNameLength) > 0) { - if (!WriteFile(File, Pad, PAD_TO_32BIT(IfNameLength), NULL, NULL)) { - Err = GetLastError(); - printf("WriteFile failed with %u\n", Err); - goto Done; - } - } - } - - if (IfDesc != NULL) { - if (!WriteFile(File, &IfDescOpt, sizeof(IfDescOpt), NULL, NULL)) { - Err = GetLastError(); - printf("WriteFile failed with %u\n", Err); - goto Done; - } - - if (!WriteFile(File, IfDesc, IfDescLength, NULL, NULL)) { - Err = GetLastError(); - printf("WriteFile failed with %u\n", Err); - goto Done; - } - - if (PAD_TO_32BIT(IfDescLength) > 0) { - if (!WriteFile(File, Pad, PAD_TO_32BIT(IfDescLength), NULL, NULL)) { - Err = GetLastError(); - printf("WriteFile failed with %u\n", Err); - goto Done; - } - } - } - - if (!WriteFile(File, &EndOption, sizeof(EndOption), NULL, NULL)) { - Err = GetLastError(); - printf("WriteFile failed with %u\n", Err); - goto Done; - } - - Tail.Length = TotalLength; - if (!WriteFile(File, &Tail, sizeof(Tail), NULL, NULL)) { - Err = GetLastError(); - printf("WriteFile failed with %u\n", Err); - goto Done; - } - -Done: - - return Err; -} - -inline int -PcapNgWriteCommentOption( - HANDLE File, - PCHAR CommentBuffer, - unsigned short CommentLength, - int CommentPadLength - ) -{ - int Err = NO_ERROR; - struct PCAPNG_BLOCK_OPTION_VAR_LENGTH Comment; - char Pad[4] = { 0 }; - - Comment.Code = PCAPNG_OPTIONCODE_COMMENT; - Comment.Length = CommentLength; - - if (!WriteFile(File, &Comment, sizeof(Comment), NULL, NULL)) { - Err = GetLastError(); - printf("WriteFile failed with %u\n", Err); - goto Done; - } - if (!WriteFile(File, CommentBuffer, CommentLength, NULL, NULL)) { - Err = GetLastError(); - printf("WriteFile failed with %u\n", Err); - goto Done; - } - if (CommentPadLength > 0) { - if (!WriteFile(File, Pad, CommentPadLength, NULL, NULL)) { - Err = GetLastError(); - printf("WriteFile failed with %u\n", Err); - goto Done; - } - } - -Done: - - return Err; -} - -inline int -PcapNgWriteEnhancedPacket( - HANDLE File, - char* FragBuf, - unsigned long FragLength, - unsigned long OrigFragLength, - long InterfaceId, - long IsSend, - long TimeStampHigh, // usec (unless if_tsresol is used) - long TimeStampLow, - char* Comment, - unsigned short CommentLength - ) -{ - int Err = NO_ERROR; - struct PCAPNG_BLOCK_HEAD Head; - struct PCAPNG_ENHANCED_PACKET_BODY Body; - struct PCAPNG_BLOCK_OPTION_EPB_FLAGS EpbFlagsOption; - struct PCAPNG_BLOCK_TAIL Tail; - char Pad[4] = {0}; - BOOLEAN CommentProvided = (CommentLength > 0 && Comment != NULL); - int CommentPadLength = PAD_TO_32BIT(CommentLength); - int FragPadLength = PAD_TO_32BIT(sizeof(Body) + FragLength); - int TotalLength = - sizeof(Head) + sizeof(Body) + FragLength + FragPadLength + - sizeof(EpbFlagsOption) + sizeof(EndOption) + sizeof(Tail) + - (CommentProvided ? - sizeof(struct PCAPNG_BLOCK_OPTION_VAR_LENGTH) + CommentLength + CommentPadLength : 0); - - Head.Type = PCAPNG_BLOCKTYPE_ENHANCED_PACKET; - Head.Length = TotalLength; - if (!WriteFile(File, &Head, sizeof(Head), NULL, NULL)) { - Err = GetLastError(); - printf("WriteFile failed with %u\n", Err); - goto Done; - } - - Body.InterfaceId = InterfaceId; - Body.TimeStampHigh = TimeStampHigh; - Body.TimeStampLow = TimeStampLow; - Body.PacketLength = OrigFragLength; // original length - Body.CapturedLength = FragLength; // truncated length - if (!WriteFile(File, &Body, sizeof(Body), NULL, NULL)) { - Err = GetLastError(); - printf("WriteFile failed with %u\n", Err); - goto Done; - } - if (!WriteFile(File, FragBuf, FragLength, NULL, NULL)) { - Err = GetLastError(); - printf("WriteFile failed with %u\n", Err); - goto Done; - } - if (FragPadLength > 0) { - if (!WriteFile(File, Pad, FragPadLength, NULL, NULL)) { - Err = GetLastError(); - printf("WriteFile failed with %u\n", Err); - goto Done; - } - } - - EpbFlagsOption.Code = PCAPNG_OPTIONCODE_EPB_FLAGS; - EpbFlagsOption.Length = 4; - EpbFlagsOption.Value = IsSend ? 2 : 1; - if (!WriteFile(File, &EpbFlagsOption, sizeof(EpbFlagsOption), NULL, NULL)) { - Err = GetLastError(); - printf("WriteFile failed with %u\n", Err); - goto Done; - } - - if (CommentProvided) { - Err = PcapNgWriteCommentOption( - File, - Comment, - CommentLength, - CommentPadLength); - if (Err != NO_ERROR) { - printf("WriteFile failed with %u\n", Err); - goto Done; - } - } - - if (!WriteFile(File, &EndOption, sizeof(EndOption), NULL, NULL)) { - Err = GetLastError(); - printf("WriteFile failed with %u\n", Err); - goto Done; - } - - Tail.Length = TotalLength; - if (!WriteFile(File, &Tail, sizeof(Tail), NULL, NULL)) { - Err = GetLastError(); - printf("WriteFile failed with %u\n", Err); - goto Done; - } - -Done: - - return Err; -}