私はPcap.Netを使用したことがないので、これが機能するかどうかはわかりませんが、一般的な考え方は、データ(「ペイロードレイヤー」)をいくつかのチャンクに分割してから送信することです。フラグメントを確実に再アセンブルできるようにするには、各フラグメントの位置(オフセット)に関する情報も追加する必要があります。
Pcap.Netでは、IpV4Fragmentation
クラスにはこれを定義する2つのプロパティが含まれています。
IpV4Fragmentation.Options
:
- 最後のフラグメントを除くすべてのフラグメントについては、に設定する必要があります
IpV4FragmentationOptions.MoreFragments
。
- 最後のフラグメントについては、次のように設定する必要があります
IpV4FragmentationOptions.None
IpV4Fragmentation.Offset
:
- フラグメントのオフセットが含まれます(8で割り切れる必要があります)。このオフセットは、最初のフラグメントではゼロです。
これを念頭に置いて、私は次のようなものを書きます:
(免責事項:これはメモ帳で書かれています。コンパイルすれば、ましてや正常に動作するかどうかはわかりません):
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;
}
}
[@bricknerの提案で更新]