All,
I've spent a fair part of the day looking at various PCAP libraries and before I commit to writing a PCAP writer I'd like to describe my scenario and solicit input.
I have a client that has asked that I provide a service that reads pcap files and writes the packets into their database of choice. The client then can query the database (datetime range) and the result should eventually be a pcap file containing the packets that matched that range criteria.
What I have found with the libraries so far is that the 'dumping', that is writing, of pcap seems to only be avaiable when associated with a specific capture device. This is not the case for my scenario.
I am using PCAP.NET to read the original pcap files and extract the packets. I store the packets into the database and then I can read the data out of the database and recreate the packets but I am not finding a way to write the results of the query into a pcap file.
The simplest case, consider a data structure of List of type Packet (so new to to actually writing to stack overflow that I don't know how to write List of T with the angle brackets not getting filtered) - do any of the available libraries support writing that structure to pcap?
Given that this does not appear to be a common scenario, I am wondering at the validity of the entire scenario. I should also point out that I have a grand total of two days of working with PCAP data, this was supposed to be a proof of concept application and therefore it is entirely possible that I am missing a piece of knowledge that makes this trivial.
Thank you for your valuable time and consideration and apologies in advance if my attempts with Google and even more time with Stack Overflow searching overlooked the obvious.
Chris
I believe that Pcap.Net's static method PacketDumpFile.Dump() gives you exactly what you need.
Here is simple tool in C# I wrote to convert ETL to PCAP files, an example of how you can write PCAP file. This writes the file with Link-Layer Header Type of Ethernet. Refer to http://www.tcpdump.org/linktypes.html for other types.
Visual Studio Solution here https://github.com/chentiangemalc/EtlToCap
using System;
using System.Collections.Generic;
using System.Diagnostics.Eventing.Reader;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace chentiangemalc
{
public static class NetworkRoutines
{
public static long ConvertEtlToPcap(string source, string destination, UInt32 maxPacketSize)
{
int result = 0;
using (BinaryWriter writer = new BinaryWriter(File.Open(destination, FileMode.Create)))
{
UInt32 magic_number = 0xa1b2c3d4;
UInt16 version_major = 2;
UInt16 version_minor = 4;
Int32 thiszone = 0;
UInt32 sigfigs = 0;
UInt32 snaplen = maxPacketSize;
UInt32 network = 1; // LINKTYPE_ETHERNET
writer.Write(magic_number);
writer.Write(version_major);
writer.Write(version_minor);
writer.Write(thiszone);
writer.Write(sigfigs);
writer.Write(snaplen);
writer.Write(network);
long c = 0;
long t = 0;
using (var reader = new EventLogReader(source, PathType.FilePath))
{
EventRecord record;
while ((record = reader.ReadEvent()) != null)
{
c++;
t++;
if (c == 100000)
{
Console.WriteLine(String.Format("Processed {0} events",t));
c = 0;
}
using (record)
{
if (record.Id == 1001 && record.ProviderName == "Microsoft-Windows-NDIS-PacketCapture")
{
result++;
DateTime timeCreated = (DateTime)record.TimeCreated;
UInt32 ts_sec = (UInt32)((timeCreated.Subtract(new DateTime(1970, 1, 1))).TotalSeconds);
UInt32 ts_usec = (UInt32)(((timeCreated.Subtract(new DateTime(1970, 1, 1))).TotalMilliseconds) - ((UInt32)((timeCreated.Subtract(new DateTime(1970, 1, 1))).TotalSeconds * 1000))) * 1000;
UInt32 incl_len = (UInt32)record.Properties[2].Value;
if (incl_len > maxPacketSize)
{
Console.WriteLine(String.Format("Packet size of {0} exceeded max packet size {1}, packet ignored",incl_len,maxPacketSize));
}
UInt32 orig_len = incl_len;
writer.Write(ts_sec);
writer.Write(ts_usec);
writer.Write(incl_len);
writer.Write(orig_len);
writer.Write((byte[])record.Properties[3].Value);
}
}
}
}
}
return result;
}
}
}