創建,解析和操縱數據包。該板條箱提供的工具可用於使用直觀的高級接口輕鬆與數據包一起使用。如果您想請求任何功能或改進,請只需打開一個問題,同樣可以報告任何錯誤。
請注意,本文檔中的任何類型註釋,例如let data: Vec<u8> = packet.into_vec(); ,僅添加為了清楚起見,並且在您的代碼中不需要。
步驟1
導入軟件包的適當部分,並創建一個新的數據包結構以開始填充它。有兩種創建新數據包的方法,方法1將將內部緩衝區的容量設置為適合給定協議的長度,而方法2只會創建一個完全空的數據包,內部緩衝區容量設置為0。對於大型數據包,方法1是優選的,因為它將更有效,因為它將不需要不需要增加每個時間數據的時間數據,卻不需要增加每個時間數據的時間數據。
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> 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 Echos之類的情況下,此步驟可能並不總是必要的,因為只有讀取標題,因此不需要數據。但是,在許多情況下,您可能需要添加一些有效負載數據。同樣,有兩種方法可以做到這一點,方法1將覆蓋Exisising有效載荷數據(如果這是一個新數據包,則無論如何都不會,但是如果它是從原始數據中解析的數據包,則可能會有一些),方法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> 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);
}