This project is read-only.

IP fragmentation

Jan 22, 2015 at 5:20 PM
Edited Jan 30, 2015 at 7:04 AM
I try to fragment my traffic and using this function:
private IEnumerable<Packet> SplitPacket(Packet packet, int numberOfFragments)
            IpV4Datagram ipV4Datagram = packet.Ethernet.IpV4;
            Datagram datagram = packet.Ethernet.IpV4.Payload;
            TransportLayer transportlayer = GetTransportLayer(packet);
            if (transportlayer != null)
                EthernetLayer ethernet = (EthernetLayer)packet.Ethernet.ExtractLayer();
                ILayer layer = packet.Ethernet.IpV4.ExtractLayer();
                IpV4Layer ipV4Layer = (IpV4Layer)packet.Ethernet.IpV4.ExtractLayer();
                ipV4Layer.HeaderChecksum = null;
                DateTime packetTimestamp = packet.Timestamp;                
                PayloadLayer payload = (PayloadLayer)packet.Ethernet.IpV4.Payload.ExtractLayer(); //extract the data

                int totalLength = payload.Length;
                int partialLength = totalLength / numberOfFragments; //split data into smaller segments
                partialLength = (partialLength / 8) * 8; //make sure it's divisible with 8
                if (partialLength == 0)
                    partialLength = 8;
                ushort offset = 0; //send one by one

                while (offset < totalLength)
                    int fragmentLength = partialLength; //get length for this fragment
                    IpV4FragmentationOptions options = IpV4FragmentationOptions.MoreFragments;

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

                    byte[] newBuffer = ipV4Datagram.Payload.ToArray(); //copy the actual data into a new buffer
                    PayloadLayer newPayload = new PayloadLayer { Data = new Datagram(newBuffer, offset, fragmentLength) };
                    ipV4Layer.Fragmentation = new IpV4Fragmentation(options, offset); //change IP layer fragmentation options
                    transportlayer.Checksum = null;
                    yield return PacketBuilder.Build(packetTimestamp, ethernet, ipV4Layer, transportlayer, newPayload);
                   offset +=  (ushort)fragmentLength; //next offset
I call this function this way:
SplitPacket(MyPacket, 4);
After run this function and looking in Wireshark the last TCP packet i received (4 packets total) is with bad TCP checksum and Wireshark show this message:
Checksum: 0x5d17 [incorrect, should be 0xabb7 (maybe caused by "TCP checksum offload"?)]
I edit the checksum of my capture to what Wireshark snuggested (0xabb7) via HEX editor and after save this file now it seems that the packet is OK, in my function i am calculate the checksum Transport layer :
transportlayer.Checksum = null;
Am i doing something wrong ?
Please see the original packet and the fragmentation capture (without HEX editor edit) :
Jan 30, 2015 at 8:40 AM
Edited Jan 30, 2015 at 8:45 AM
  1. What does GetTransportLayer() do?
  2. You don't use the 'layer' variable.
  3. I couldn't download the files from the link you provided.
Jan 30, 2015 at 10:28 AM
Edited Jan 30, 2015 at 1:40 PM
1.  private TransportLayer GetTransportLayer(Packet packet)
                return (TransportLayer)packet.Ethernet.IpV4.Transport.ExtractLayer();
            catch (Exception)
                return null;
Do you think i need to use other way ?
  1. i think this leftovers from my tests and i don't need this.
Jan 31, 2015 at 2:26 PM
One thing that seems wrong in your code is that you copy the payload of the IP layer to be the payload of the TCP layer.
I don't see how this would work.
Jan 31, 2015 at 2:52 PM
Edited Jan 31, 2015 at 2:55 PM
You mean this:
yield return PacketBuilder.Build(packetTimestamp, ethernet, ipV4Layer, newPayload);
should be instead of this:
yield return PacketBuilder.Build(packetTimestamp, ethernet, ipV4Layer, transportlayer, newPayload);
Feb 6, 2015 at 12:33 PM
Yes, because newPayload is based on newBuffer which is the IPv4 payload and not the transport payload.