Question

How can I split a packet into two packets using pcapdotnet? This is what I tried, but I don't know whether it's correct:

    public IEnumerable<Packet> splitPacket(Packet packet)
    {
        EthernetLayer ethernet = (EthernetLayer)packet.Ethernet.ExtractLayer();
        IpV4Layer ipV4Layer = (IpV4Layer)packet.Ethernet.IpV4.ExtractLayer();
        DateTime packetTimestamp = packet.Timestamp;
        ILayer payload = packet.Ethernet.IpV4.Payload.ExtractLayer();
        IpV4Fragmentation.Equals(packet, packet);

        yield return PacketBuilder.Build(packetTimestamp, ethernet, ipV4Layer, payload);
    }
Was it helpful?

Solution

I have never used Pcap.Net, so I am not sure if this will work, but the general idea is to split the data (the "payload layer") into several chunks and then send it. To make sure the fragments can be reassembled, you also need to add some info about the position (offset) of each fragment.

In Pcap.Net, the IpV4Fragmentation class contains two properties which define this:

  • IpV4Fragmentation.Options:
    • for all fragments except tha last one, it should be set to IpV4FragmentationOptions.MoreFragments,
    • for the last fragment, it should be set to IpV4FragmentationOptions.None
  • IpV4Fragmentation.Offset:
    • contains the offset of the fragment (which must be divisible by 8). This offset is zero for the first fragment.

With this in mind, I would write something like this:

(Disclaimer: this was written in Notepad, I have no clue if it even compiles, let alone works as it should):

public IEnumerable<Packet> Split(Packet packet, int numberOfFragments)
{
    // get original layers
    var ethernet = (EthernetLayer)packet.Ethernet.ExtractLayer();
    var ipV4 = (IpV4Layer)packet.Ethernet.IpV4.ExtractLayer();
    var time = packet.Timestamp;

    // extract the data
    var payload = (PayloadLayer)packet.Ethernet.IpV4.Payload.ExtractLayer();
    var totalLength = payload.Length;

    // split data into smaller segments
    var partialLength = totalLength / numberOfFragments;

    // make sure it's divisible with 8
    // (see http://en.wikipedia.org/wiki/IPv4#Fragmentation_and_reassembly)
    partialLength = (partialLength / 8) * 8;

    // send one by one
    var offset = 0;
    while (offset < totalLength)
    {
        // get length for this fragment
        var fragmentLength = partialLength;
        var options = IpV4FragmentationOptions.MoreFragments;            

        // is this the last fragment? trim length if needed
        if (offset + fragmentLength >= totalLength) 
        {
            options = IpV4FragmentationOptions.None;
            fragmentLength = totalLength - offset;
        }

        // copy the actual data into a new buffer
        var newBuffer = payload.ReadBytes(offset, fragmentLength);
        var newPayload = new PayloadLayer() { Data = newBuffer };

        // change IP layer fragmentation options
        ipV4.Fragmentation = new IpV4Fragmentation(options, offset);

        // return it
        yield return PacketBuilder.Build(time, ethernet, ipV4, newPayload);

        // next offset
        offset += fragmentLength;
    }
}

[Updated with @brickner's suggestions]

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top