创建,解析和操纵数据包。该板条箱提供的工具可用于使用直观的高级接口轻松与数据包一起使用。如果您想请求任何功能或改进,请只需打开一个问题,同样可以报告任何错误。
请注意,本文档中的任何类型注释,例如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);
}