Фрагмент пакета Ipv6 с использованием 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 ответ
Из Википедии:
фрагментация
В отличие от IPv4, маршрутизаторы IPv6 никогда не фрагментируют пакеты IPv6. Пакеты, размер которых превышает максимальный размер единицы передачи канала назначения, отбрасываются, и об этом состоянии сигнализирует отправляющий узел слишком большой пакет ICMPv6 типа 2, аналогично методу IPv4, когда установлен бит "Не фрагментировать".
Ожидается, что конечные узлы в IPv6 будут выполнять обнаружение MTU пути для определения максимального размера пакетов для отправки, а протокол верхнего уровня должен ограничивать размер полезной нагрузки. Однако, если протокол верхнего уровня не может этого сделать, хост-отправитель может использовать заголовок расширения фрагмента для выполнения сквозной фрагментации пакетов IPv6. Любой канальный уровень, передающий данные IPv6, должен быть способен доставлять IP-пакет, содержащий 1280 байтов, без необходимости вызывать сквозную фрагментацию на IP-уровне.
Фрагментация
Пакет, содержащий фрагмент исходного (большего) пакета, состоит из двух частей: нефрагментируемой части исходного пакета (которая одинакова для всех фрагментов) и части фрагментируемой части исходного пакета, идентифицируемой фрагментом смещение. Смещение фрагмента первого ("самого левого") фрагмента равно 0.
Нефрагментируемая часть пакета состоит из фиксированного заголовка и некоторых заголовков расширения исходного пакета (если имеется): всех заголовков расширения вплоть до заголовка расширения маршрутизации или включая заголовок расширения Hop-by-Hop. Если ни один из заголовков расширения не присутствует, нефрагментируемая часть - это просто фиксированный заголовок.
Значение следующего заголовка последнего (расширенного) заголовка нефрагментируемой части устанавливается равным 44, чтобы указать, что следует заголовок расширения фрагмента. После заголовка расширения фрагмента следует фрагмент остальной части исходного пакета.
Первый фрагмент (ы) содержит остальные заголовки расширения (если есть). После этого следует остальная часть полезной нагрузки. Каждый фрагмент кратен 8 октетам в длину, за исключением последнего фрагмента.
Каждый заголовок расширения фрагмента имеет свой флаг M, установленный в 1 (указывая на то, что следуют дополнительные фрагменты), кроме последнего, флаг которого установлен в 0.
Reassembly
Исходный пакет повторно собирается принимающим узлом, собирая все фрагменты и помещая каждый фрагмент с правым смещением и отбрасывая заголовки расширения фрагмента пакетов, которые их переносили. Пакеты, содержащие фрагменты, не обязательно должны поступать последовательно; они будут переупорядочены принимающим узлом.
Если не все фрагменты получены в течение 60 секунд после получения первого пакета с фрагментом, повторная сборка исходного пакета прекращается, и все фрагменты отбрасываются. Если был получен первый фрагмент (который содержит фиксированный заголовок), сообщение Time Exceeded (ICMPv6 тип 3, код 1) возвращается узлу, инициирующему фрагментированный пакет, если пакет был отброшен по этой причине.
Принимающие хосты должны сделать все возможное для повторной сборки фрагментированных дейтаграмм IP, которые после повторной сборки содержат до 1500 байт. Хостам разрешается делать попытку повторной сборки фрагментированных дейтаграмм размером более 1500 байт, но им также разрешается молча отбрасывать любые дейтаграммы после того, как становится очевидно, что повторно собранный пакет будет иметь размер более 1500 байт. Поэтому отправителям следует избегать отправки фрагментированных дейтаграмм IP с общим повторно собранным размером, превышающим 1500 байтов, если они не имеют предыдущей гарантии того, что получатель способен повторно собрать такие большие дейтаграммы.
Безопасность
Исследования показали, что использование фрагментации может использоваться для обхода средств контроля безопасности сети. В результате RFC 7112 требует, чтобы первый фрагмент пакета IPv6 содержал всю цепочку заголовков IPv6, так что некоторые очень патологические случаи фрагментации запрещены. Кроме того, в результате исследований об уклонении RA-Guard в RFC 7113, RFC 6980 устарел использовать фрагментацию с Neighbor Discovery и не рекомендовал использовать фрагментацию с Secure Neighbor Discovery (SEND).