Closed dllu closed 3 years ago
FWIW in the 1514
I do see MTU, Maximum Transfer Unit, the max size of ethernet packets.
I don't think pcap is at the right level to do what you want to do . As @stappersg pointed out, you seem to be printing the length of individual Ethernet frames, because that's the granularity that libpcap
works at. I don't know if libpcap
has in-built functionality to assemble them into complete IP packets. If you can figure out the right libpcap
calls (as pcap
is just a Rust wrapper around it) then we can see if that can be done in pcap
too.
Alright it seems that libpcap doesn't have packet reassembly (see: https://stackoverflow.com/questions/2172782/libpcap-ip-packet-reassembly).
I guess I have to write my own packet reassembler. Here's my janky first attempt using pnet
.
use pnet::packet::{
ethernet::{EtherTypes, EthernetPacket},
ip::IpNextHeaderProtocols,
ipv4::Ipv4Packet,
udp::UdpPacket,
Packet,
};
struct Ipv4Reassembler {
cap: pcap::Capture<pcap::Offline>,
}
impl Iterator for Ipv4Reassembler {
type Item = Vec<u8>;
fn next(&mut self) -> Option<Self::Item> {
let mut payload = Vec::<u8>::new();
while let Some(packet) = self.cap.next().ok() {
let ethernet = EthernetPacket::new(packet.data).unwrap();
match ethernet.get_ethertype() {
EtherTypes::Ipv4 => {
let ipv4_packet = Ipv4Packet::new(ethernet.payload()).unwrap();
// dbg!(&ipv4_packet);
let off: usize = 8 * ipv4_packet.get_fragment_offset() as usize;
let end = off + ipv4_packet.payload().len();
if payload.len() < end {
payload.resize(end, 0);
}
payload[off..end].clone_from_slice(ipv4_packet.payload());
if ipv4_packet.get_flags() & 1 == 0 {
return Some(payload);
}
}
_ => {}
}
}
None
}
}
fn main() {
let pcap_path = "os-992114000702.pcap";
let reass = Ipv4Reassembler {
cap: pcap::Capture::from_file(&pcap_path).unwrap(),
};
for payload in reass {
let udp_packet = UdpPacket::new(&payload).unwrap();
dbg!(&udp_packet);
}
}
I am trying to read a pcap file that contains IP fragmented packets.
Currently I can print out the correct size of the packets using C++ with
libtins
, like soIs there any way to do something similar in rust using
pcap
?I am doing this currently:
But it prints out the wrong packet length.
c++ code above prints out:
whereas the rust code prints out: