使用Pcap.Net片段化Ipv6数据包

时间:2017-06-22 12:51:44

标签: c# fragment packet pcap.net

所以我找到了IpV4的解决方案:

private IEnumerable<Packet> SplitPacket(Packet packet, int numberOfFragments)
{
    IpV4Datagram ipV4Datagram = packet.Ethernet.IpV4;

    if (ipV4Datagram.Protocol == IpV4Protocol.Tcp || ipV4Datagram.Protocol == IpV4Protocol.Udp)
    {
        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;
        //(http://en.wikipedia.org/wiki/IPv4#Fragmentation_and_reassembly)
        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
            Packet newPacket = null;

            if (packet.Ethernet.IpV4.Protocol == IpV4Protocol.Tcp)
            {
                TcpLayer tcpLayer = (TcpLayer)packet.Ethernet.IpV4.Tcp.ExtractLayer();
                tcpLayer.Checksum = null;
                newPacket = PacketBuilder.Build(packetTimestamp, ethernet, ipV4Layer, tcpLayer, newPayload);
            }
            else if (packet.Ethernet.IpV4.Protocol == IpV4Protocol.Udp)
            {
                UdpLayer udpLayer = (UdpLayer)packet.Ethernet.IpV4.Udp.ExtractLayer();
                udpLayer.Checksum = null;
                newPacket = PacketBuilder.Build(packetTimestamp, ethernet, ipV4Layer, udpLayer, newPayload);
            }

            yield return newPacket;
            //yield return PacketBuilder.Build(packetTimestamp, ethernet, ipV4Layer, tcpLayer, newPayload); //return
            offset += (ushort)fragmentLength; //next offset
        }
    }
}

由于Ipv6Layer不包含IpV4layer中的多个字段,例如IpV4FragmentationOptions,我想知道Fragmentation是如何实现的IpV6

1 个答案:

答案 0 :(得分:0)

来自Wikipedia

  

<强>碎片

     

与IPv4不同,IPv6路由器永远不会分裂IPv6数据包。包   超过目的地最大传输单位的大小   链路被丢弃,这个条件由Packet太大发出信号   ICMPv6类型2消息到源节点,类似于IPv4   设置Do not Fragment位时的方法。

     

IPv6中的终端节点应该执行路径MTU发现   确定要发送的数据包的最大大小,以及上层   协议有望限制有效载荷大小。但是,如果   上层协议无法这样做,发送主机可能会使用   片段扩展标头,以执行端到端的碎片   的IPv6数据包。传输IPv6数据的任何数据链路层都必须是   能够提供包含1280字节的IP数据包而无需   需要在IP层调用端到端的碎片。

     

<强>粉碎

     

包含原始(较大)数据包片段的数据包   两部分:原始数据包的不可分段部分(即   对于所有片段都是一样的),以及片段的一部分   由片段偏移标识的原始数据包。碎片   第一个(“最左边”)片段的偏移量为0。

     

数据包的不可分段部分包括固定标头和   原始数据包的一些扩展头(如果存在):全部   扩展标头,包括路由扩展标头,或   否则是Hop-by-Hop扩展头。如果两个扩展标头都不是   目前,不可分割的部分只是固定的标题。

     

最后一个(扩展名)标题的Next Header值   不可分段的部分设置为44表示片段扩展   标题如下。 Fragment扩展头之后的一个片段   其余的原始数据包如下。

     

第一个片段包含其余的扩展标头(如果   当下)。之后,其余的有效载荷随之而来。每个片段都是   除最后一个片段外,长度为8个八位字节的倍数。

     

每个Fragment扩展标头的M标志设置为1(表示   更多片段跟随),除了最后一个,其标志设置为0。

     

<强>重组

     

接收节点通过收集重新组装原始数据包   所有碎片并将每个碎片放置在右侧偏移处   丢弃携带的数据包的Fragment扩展头   他们。包含片段的数据包不需要按顺序到达;他们   将由接收节点重新安排。

     

如果不是在收到后60秒内收到所有碎片   带有片段的第一个数据包,重新组装原始数据包   被遗弃,所有碎片都被丢弃了。如果第一个片段是   收到(包含固定标头),超时时间消息   (ICMPv6类型3,代码1)返回到发起的节点   碎片包,如果因为这个原因丢弃了包。

     

接收主机必须尽最大努力重新组装   碎片化的IP数据报,重组后最多包含1500个   字节。允许主机尝试重新组合碎片   数据报大于1500字节,但也允许它们   在它变得明显之后,默默地丢弃任何数据报   重组的数据包大于1500字节。因此,发件人   应该避免发送重新组合的碎片化IP数据报   大小超过1500字节,除非他们事先得到保证   接收器能够重新组装这样大的数据报。

     

安全

     

研究表明,可以利用碎片的使用   逃避网络安全控制。因此,RFC 7112要求   IPv6数据包的第一个片段包含整个IPv6标头   链,这是一些非常病态的碎片案例   禁止。此外,作为对逃避的研究的结果   RFC 7113中的RA-Guard,RFC 6980已经弃用了碎片   使用邻居发现,并且不鼓励使用碎片   安全邻居发现(SEND)。