データパケットを作成、解析、操作します。このクレートは、直感的な高レベルのインターフェイスを使用してデータパケットを簡単に連携するために使用できるツールを提供します。機能や改善をリクエストしたい場合は、もちろんバグを報告するために、問題を開くだけです。
let data: Vec<u8> = packet.into_vec(); 、明確にするためにのみ追加され、コードには必要ありません。
ステップ1
パッケージの適切な部分をインポートし、新しいパケット構造体を作成して、それを確立し始めます。新しいパケットを作成する方法は2つあります。方法1は、指定されたプロトコルの内部バッファーの容量を適切な長さに設定します。メソッド2は、内部バッファ容量が0に設定された完全に空のパケットを作成するだけです。
extern crate packet_crafter;
use packet_crafter::{
//import sub-modules
headers,
protocol_numbers,
ethertype_numbers,
//import data types
Packet,
Protocol
};
fn main() {
// method 1 (preferred)
let mut new_packet = Packet::new(
vec![
Protocol::ETH,
Protocol::IP,
Protocol::TCP
]
);
// method 2
let mut new_packet = Packet::new_empty();
ステップ2
ヘッダーを作成し、パケットに追加します。ここでは、ステップ1の方法1のパケット構造を使用します。イーサネット> ip> tcp
new_packet.add_header(
headers::EthernetHeader::new(
[6,5,4,3,2,1], // source mac address
[1,2,3,4,5,6], // destination mac address
ethertype_numbers::ETHERTYPE_IPV4
)
);
new_packet.add_header(
headers::IpHeader::new(
[192, 168, 1, 128], // source IP
[192, 168, 1, 38], // destination IP
Protocol::TCP // next protocol
)
);
new_packet.add_header(
headers::TcpHeader::new(
3838, // source port
3838 // destination port
)
);
ステップ3
ヘッダーのみが読み取られるため、データが必要である必要のないICMPエコーのような場合、このステップが必ずしも必要ではない場合があります。ただし、多くの場合、ペイロードデータを追加する必要があります。繰り返しますが、これを行うには2つの方法があります。方法1は既存のペイロードデータを上書きします(これが新しいパケットである場合、とにかく何もありませんが、生データから解析されたパケットである場合、いくつかがあるかもしれません)、および方法2は既存のペイロードデータに追加されます。方法2に.collect()がないことに注意してください。コードは引き続き動作しますが、必要ありません。ソース内の関数の署名を見ると、その理由がわかります。
// method 1
new_packet.set_payload("Hello, world!".bytes().collect());
// method 2
new_packet.extend_payload("Hello, world!".bytes());
ステップ4
データの準備が整うので、パケットを焼くだけです。これは、IPヘッダーのようなチェックサムフィールドと長さフィールドが登録される場所です(OSがそれらを上書きする可能性が高いにもかかわらず、これらを計算することにした理由の説明については、このドキュメントページを参照してください)
let data: Vec<u8> = new_packet.into_vec();
}
&Vec<u8>は&[u8]を期待する関数に渡すことができることを常に覚えておいてください:)
パケットがIPヘッダーまたはイーサネットIIヘッダーのいずれかから始まるものである限り、パケットを解析することは非常にシンプルになります。
extern crate packet_crafter;
use packet_crafter::Packet;
fn main() {
let raw_data: &[u8] = your_function_to_read_a_packet_from_socket();
let parsed_packet: Result<Packet, packet_crafter::ParseError> = Packet::parse(raw_data);
}
注:IPv6パケットにはまだ解析が実装されていません
作成された新しいパケット例で作成されたパケットを解析したばかりであるため、それはETH> IP> TCPパケットであり、TCPフィールドのデシエーションポートと宛先IPを更新する必要があります。
// imports elided
fn main() {
let raw_data: &[u8] = your_function_to_read_a_packet_from_socket();
let mut packet = Packet::parse(raw_data).unwrap();
let mut tcp_header = packet.get_tcp_header().unwrap();
tcp_header.set_dst_port(21);
let mut ip_header = packet.get_ip_header().unwrap();
ip_header.set_dst_ip([192, 168, 1, 84]);
packet.update_header(ip_header);
// packet is now good to go, so make it and then send it:
let data = packet.into_vec();
your_function_to_send_packet_down_socket(&data);
}