Skip to content

Commit

Permalink
datalink: layer2: filter bpf
Browse files Browse the repository at this point in the history
  • Loading branch information
Martichou committed Sep 1, 2022
1 parent c3eb5d4 commit 5838e67
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 26 deletions.
2 changes: 1 addition & 1 deletion examples/arp_packet.rs
Expand Up @@ -103,4 +103,4 @@ fn main() {
let target_mac = get_mac_through_arp(interface, target_ip.unwrap());

println!("Target MAC address: {}", target_mac);
}
}
1 change: 1 addition & 0 deletions pnet_datalink/Cargo.toml
Expand Up @@ -17,6 +17,7 @@ std = ["pnet_base/std"]
default = ["std"]

[dependencies]
bpf = "0.1"
libc = "0.2.126"
ipnetwork = "0.19.0"
pnet_base = { path = "../pnet_base", version = "0.31.0", default-features = false }
Expand Down
6 changes: 6 additions & 0 deletions pnet_datalink/src/linux.rs
Expand Up @@ -13,6 +13,7 @@ extern crate libc;
use crate::bindings::linux;
use crate::{DataLinkReceiver, DataLinkSender, MacAddr, NetworkInterface};

use bpf::bpfprog;
use pnet_sys;

use std::cmp;
Expand Down Expand Up @@ -188,6 +189,11 @@ pub fn channel(network_interface: &NetworkInterface, config: Config) -> io::Resu
}
}

let filter = bpfprog!(27,40 0 0 12,21 0 9 34525,48 0 0 20,21 2 0 132,21 1 0 6,21 0 20 17,40 0 0 54,21 17 0 67,21 16 0 68,40 0 0 56,21 14 13 67,21 0 14 2048,48 0 0 23,21 2 0 132,21 1 0 6,21 0 10 17,40 0 0 20,69 8 0 8191,177 0 0 14,72 0 0 14,21 4 0 67,21 3 0 68,72 0 0 16,21 1 0 67,21 0 1 68,6 0 0 262144,6 0 0 0);
if let Err(err) = bpf::attach_filter(socket, filter) {
return Err(err);
}

// Enable nonblocking
if unsafe { libc::fcntl(socket, libc::F_SETFL, libc::O_NONBLOCK) } == -1 {
let err = io::Error::last_os_error();
Expand Down
92 changes: 67 additions & 25 deletions src/pnettest.rs
Expand Up @@ -17,14 +17,14 @@ use crate::packet::ipv6::MutableIpv6Packet;
use crate::packet::udp;
use crate::packet::udp::{MutableUdpPacket, UdpPacket};
use crate::packet::Packet;
use std::iter::Iterator;
use pnet_base::core_net::{IpAddr, Ipv4Addr, Ipv6Addr};
use std::sync::mpsc::channel;
use std::thread;
use crate::transport::TransportProtocol::{Ipv4, Ipv6};
use crate::transport::{
ipv4_packet_iter, transport_channel, udp_packet_iter, TransportChannelType, TransportProtocol,
};
use pnet_base::core_net::{IpAddr, Ipv4Addr, Ipv6Addr};
use std::iter::Iterator;
use std::sync::mpsc::channel;
use std::thread;

const IPV4_HEADER_LEN: usize = 20;
const IPV6_HEADER_LEN: usize = 40;
Expand All @@ -51,7 +51,8 @@ fn ipv6_destination() -> Ipv6Addr {
const TEST_PROTO: IpNextHeaderProtocol = IpNextHeaderProtocols::Test1;

fn build_ipv4_header(packet: &mut [u8], offset: usize) {
let mut ip_header = MutableIpv4Packet::new(&mut packet[offset..]).expect("could not create MutableIpv4Packet");
let mut ip_header =
MutableIpv4Packet::new(&mut packet[offset..]).expect("could not create MutableIpv4Packet");

let total_len = (IPV4_HEADER_LEN + UDP_HEADER_LEN + TEST_DATA_LEN) as u16;

Expand All @@ -67,7 +68,8 @@ fn build_ipv4_header(packet: &mut [u8], offset: usize) {
}

fn build_ipv6_header(packet: &mut [u8], offset: usize) {
let mut ip_header = MutableIpv6Packet::new(&mut packet[offset..]).expect("could not create MutableIpv6Packet");
let mut ip_header =
MutableIpv6Packet::new(&mut packet[offset..]).expect("could not create MutableIpv6Packet");

ip_header.set_version(6);
ip_header.set_payload_length((UDP_HEADER_LEN + TEST_DATA_LEN) as u16);
Expand All @@ -78,7 +80,8 @@ fn build_ipv6_header(packet: &mut [u8], offset: usize) {
}

fn build_udp_header(packet: &mut [u8], offset: usize) {
let mut udp_header = MutableUdpPacket::new(&mut packet[offset..]).expect("could not create MutableUdpPacket");
let mut udp_header =
MutableUdpPacket::new(&mut packet[offset..]).expect("could not create MutableUdpPacket");

udp_header.set_source(1234); // Arbitary port number
udp_header.set_destination(1234);
Expand Down Expand Up @@ -126,8 +129,14 @@ fn build_udp4_packet(
};

let slice = &mut packet[(start + IPV4_HEADER_LEN as usize)..];
let checksum = udp::ipv4_checksum(&UdpPacket::new(slice).expect("could not create UdpPacket"), &source, &dest);
MutableUdpPacket::new(slice).expect("could not create MutableUdpPacket").set_checksum(checksum);
let checksum = udp::ipv4_checksum(
&UdpPacket::new(slice).expect("could not create UdpPacket"),
&source,
&dest,
);
MutableUdpPacket::new(slice)
.expect("could not create MutableUdpPacket")
.set_checksum(checksum);
}

fn build_udp6_packet(packet: &mut [u8], start: usize, msg: &str) {
Expand All @@ -148,7 +157,9 @@ fn build_udp6_packet(packet: &mut [u8], start: usize, msg: &str) {
&ipv6_source(),
&ipv6_destination(),
);
MutableUdpPacket::new(slice).expect("could not create MutableUdpPacket").set_checksum(checksum);
MutableUdpPacket::new(slice)
.expect("could not create MutableUdpPacket")
.set_checksum(checksum);
}

// OSes have a nasty habit of tweaking IP fields, so we only check
Expand Down Expand Up @@ -204,7 +215,8 @@ fn layer4(ip: IpAddr, header_len: usize) {
assert_eq!(addr, ip);
assert_eq!(
header,
UdpPacket::new(&packet[header_len..packet_len]).expect("could not create UdpPacket")
UdpPacket::new(&packet[header_len..packet_len])
.expect("could not create UdpPacket")
);
break;
}
Expand All @@ -215,7 +227,8 @@ fn layer4(ip: IpAddr, header_len: usize) {
}
});

rx.recv().expect("failed to receive message through channel");
rx.recv()
.expect("failed to receive message through channel");
match ttx.send_to(udp, ip) {
Ok(res) => assert_eq!(res as usize, UDP_HEADER_LEN + TEST_DATA_LEN),
Err(e) => panic!("layer4_test failed: {}", e),
Expand Down Expand Up @@ -281,7 +294,8 @@ fn layer3_ipv4() {
.expect("could not create UdpPacket");
assert_eq!(
udp_header,
UdpPacket::new(&packet[IPV4_HEADER_LEN..]).expect("could not create UdpPacket")
UdpPacket::new(&packet[IPV4_HEADER_LEN..])
.expect("could not create UdpPacket")
);

assert_eq!(
Expand All @@ -297,8 +311,12 @@ fn layer3_ipv4() {
}
});

rx.recv().expect("unable to receive message through channel");
match ttx.send_to(Ipv4Packet::new(&packet[..]).expect("could not create Ipv4Packet"), send_addr) {
rx.recv()
.expect("unable to receive message through channel");
match ttx.send_to(
Ipv4Packet::new(&packet[..]).expect("could not create Ipv4Packet"),
send_addr,
) {
Ok(res) => assert_eq!(res as usize, packet.len()),
Err(e) => panic!("layer3_ipv4_test failed: {}", e),
}
Expand Down Expand Up @@ -355,9 +373,18 @@ fn layer2() {
let mut packet = [0u8; ETHERNET_HEADER_LEN + IPV4_HEADER_LEN + UDP_HEADER_LEN + TEST_DATA_LEN];

{
let mut ethernet_header = MutableEthernetPacket::new(&mut packet[..]).expect("could not create MutableEthernetPacket");
ethernet_header.set_source(interface.mac.expect("could not find mac address for test interface"));
ethernet_header.set_destination(interface.mac.expect("could not find mac address for test interface"));
let mut ethernet_header = MutableEthernetPacket::new(&mut packet[..])
.expect("could not create MutableEthernetPacket");
ethernet_header.set_source(
interface
.mac
.expect("could not find mac address for test interface"),
);
ethernet_header.set_destination(
interface
.mac
.expect("could not find mac address for test interface"),
);
ethernet_header.set_ethertype(EtherTypes::Ipv4);
}

Expand Down Expand Up @@ -394,8 +421,12 @@ fn layer2() {
if i == 10_000 {
panic!("layer2: did not find matching packet after 10_000 iterations");
}
if EthernetPacket::new(&packet[..]).expect("failed to create EthernetPacket").payload()
== EthernetPacket::new(eh).expect("failed to create EthernetPacket").payload()
if EthernetPacket::new(&packet[..])
.expect("failed to create EthernetPacket")
.payload()
== EthernetPacket::new(eh)
.expect("failed to create EthernetPacket")
.payload()
{
return;
}
Expand All @@ -408,7 +439,8 @@ fn layer2() {
}
});

rx.recv().expect("failed to receive message through channel");
rx.recv()
.expect("failed to receive message through channel");
match dltx.send_to(&packet[..], None) {
Some(Ok(())) => (),
Some(Err(e)) => panic!("layer2_test failed: {}", e),
Expand All @@ -434,9 +466,18 @@ fn layer2_timeouts() {
let mut packet = [0u8; ETHERNET_HEADER_LEN + IPV4_HEADER_LEN + UDP_HEADER_LEN + TEST_DATA_LEN];

{
let mut ethernet_header = MutableEthernetPacket::new(&mut packet[..]).expect("failed to create MutableEthernetPacket");
ethernet_header.set_source(interface.mac.expect("missing mac address for test interface"));
ethernet_header.set_destination(interface.mac.expect("missing mac address for test interface"));
let mut ethernet_header = MutableEthernetPacket::new(&mut packet[..])
.expect("failed to create MutableEthernetPacket");
ethernet_header.set_source(
interface
.mac
.expect("missing mac address for test interface"),
);
ethernet_header.set_destination(
interface
.mac
.expect("missing mac address for test interface"),
);
ethernet_header.set_ethertype(EtherTypes::Ipv4);
}

Expand Down Expand Up @@ -487,7 +528,8 @@ fn layer2_timeouts() {
}
}
});
rx.recv().expect("failed to receive message through channel");
rx.recv()
.expect("failed to receive message through channel");

// Wait a while
thread::sleep(Duration::from_millis(1000));
Expand Down

0 comments on commit 5838e67

Please sign in to comment.