libpnet為Rust提供一組跨平臺的底層網路API。
依賴
[dependencies]
pnet = "0.25.0"
原始碼示例
use pnet::datalink::Channel::Ethernet;
use pnet::datalink::{self, NetworkInterface};
use pnet::packet::ethernet::{EtherTypes, EthernetPacket};
use pnet::packet::ip::IpNextHeaderProtocols;
use pnet::packet::ipv4::Ipv4Packet;
use pnet::packet::tcp::TcpPacket;
use pnet::packet::Packet;
use std::env;
fn handle_packet(ethernet: &EthernetPacket) {
// 對Ipv4的包按層解析
match ethernet.get_ethertype() {
EtherTypes::Ipv4 => {
let header = Ipv4Packet::new(ethernet.payload());
if let Some(header) = header {
match header.get_next_level_protocol() {
IpNextHeaderProtocols::Tcp => {
let tcp = TcpPacket::new(header.payload());
if let Some(tcp) = tcp {
println!(
"Got a TCP packet {}:{} to {}:{}",
header.get_source(),
tcp.get_source(),
header.get_destination(),
tcp.get_destination()
);
}
}
_ => println!("Ignoring non TCP packet"),
}
}
}
_ => println!("Ignoring non IPv4 packet"),
}
}
fn main() {
let interface_name = env::args().nth(1).unwrap();
// 獲取網路卡列表
let interfaces = datalink::interfaces();
let interface = interfaces
.into_iter()
.filter(|iface: &NetworkInterface| iface.name == interface_name)
.next()
.expect("Error getting interface");
let (_tx, mut rx) = match datalink::channel(&interface, Default::default()) {
Ok(Ethernet(tx, rx)) => (tx, rx),
Ok(_) => panic!("Unhandled channel type"),
Err(e) => panic!(
"An error occurred when creating the datalink channel: {}",
e
),
};
loop {
// 獲取收到的包
match rx.next() {
Ok(packet) => {
let packet = EthernetPacket::new(packet).unwrap();
handle_packet(&packet);
}
Err(e) => {
panic!("An error occurred while reading: {}", e);
}
}
}
}
執行:
sudo cargo run 網路卡名字 //例子:sudo cargo run enp0s3
本作品採用《CC 協議》,轉載必須註明作者和本文連結