2

I'm trying to implement IP fragmentation using Pcap.Net. It is simple for packets that are already built as the L3 payload is just split into parts. I have a code that does it. It returns the list of packet fragments for sending it into the wire.

    private static List<Packet> FragmentPacket(Packet packet)
    {
        EthernetLayer ethernetLayer = (EthernetLayer)packet.Ethernet.ExtractLayer();
        IpV4Layer ipV4Layer = (IpV4Layer)packet.Ethernet.IpV4.ExtractLayer();
        PayloadLayer payload = (PayloadLayer)packet.Ethernet.IpV4.Payload.ExtractLayer();

        // implement IP fragmentation
        int totalLength = payload.Length;
        int fragmentLength = 1480;
        int fragmentOffset = 0;
        IpV4FragmentationOptions FragOptions;

        List<Packet> fragmentsList = new List<Packet>();

        while (fragmentOffset < totalLength)
        {
            if (fragmentOffset + fragmentLength >= totalLength)
            {
                //last fragment
                FragOptions = IpV4FragmentationOptions.None;
                fragmentLength = totalLength - fragmentOffset;
            }
            else
            {
                //more fragments to go
                FragOptions = IpV4FragmentationOptions.MoreFragments;
            }

            IpV4Layer newipV4Layer =
                new IpV4Layer
                {
                    Source = ipV4Layer.Source,
                    CurrentDestination = ipV4Layer.CurrentDestination,
                    Fragmentation = new IpV4Fragmentation(FragOptions, (ushort)fragmentOffset),
                    HeaderChecksum = null, // Will be filled automatically.
                    Identification = 123,
                    Options = IpV4Options.None,
                    Protocol = ipV4Layer.Protocol, 
                    Ttl = ipV4Layer.Ttl, // 128,
                    TypeOfService = ipV4Layer.TypeOfService,
                };

            byte[] newBuffer = payload.Data.ToArray();
            PayloadLayer fragmentedPayload = new PayloadLayer { Data = new Datagram(newBuffer, fragmentOffset, fragmentLength) };

            PacketBuilder builder = new PacketBuilder(ethernetLayer, ipV4Layer, fragmentedPayload);
            fragmentsList.Add(builder.Build(DateTime.Now));

            fragmentOffset = fragmentOffset + fragmentedPayload.Length;
        }

        return fragmentsList;
    }

But what I'm actually doing is:

1) receiving large packet via Loopback interface (it is usually bigger than physical interface's MTU)

2) disassembling it, modifying IP addresses

3) building a new packet and sending it via Ethernet interface

Unfortunately, if the IP payload is bigger than MTU, exception happens as the packet needs to be fragmented before sending.

Because I'm changing IP address, then for TCP/UDP packets, the L4 checksum must be recalculated and this recalculation must take into account L3 header. Therefore it is needed to build L3+L4+payload part (to have L4 checksum properly calculated) and then split L4+payload into parts to fit L3 MTU.

I came into a solution in which I'm building a new packet (which is bigger than MTU) and then push it via above function to tear it into parts, and then I'm sending it using:

foreach (Packet newpacket in packetList) communicator.SendPacket(newpacket);

This, however, requires to build the same packet twice and I'm trying to find a way in Pcap.Net to partially build a packet (including recalculation of L4 checksum) and at the same time divide it into fragments to fit MTU.

I don't know how to (and if this is possible in Pcap.Net) prepare L3 payload that would consist of tcpLayer/udpLayer + L4 payload since TCP checksum is calculated during building and then finally build the rest of packet. If that was possible, I would just need to build the packet once splitting it into parts at the same time.

kiziuk
  • 23
  • 5
  • If you have it for IP you shouldn't need it for any higher layer protocols. The IP layer should handle it. – fredrik Dec 26 '18 at 18:48
  • @fredrik unfortunately, TCP/UDP uses a concept of pseudo header during L4 checksum calculation. If I change IP address for existing packet, I need to recalculate L4 checksum as well. – kiziuk Dec 26 '18 at 19:21
  • Doesn't sound like fragmentation then. You're more into NAT than anything else. Maybe you should cross reference the two? – fredrik Dec 26 '18 at 19:26
  • 1
    What I'm implementing is in fact a kind of NAT. And this mechanism works very well, but I need to add IP fragmentation ability to it as well. And because Pcap.Net doesn't implement it natively. I'm trying to find an effective way to do it. – kiziuk Dec 26 '18 at 20:07

0 Answers0