pnet

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