use crate::configure::*;
use crate::packet::*;
use pcap::Activated;
use pcap::Capture as PcapCap;
use pcap::Device;
use std::sync::Arc;
#[derive(Debug)]
pub enum CaptureError {
CapErr,
}
pub struct Capture {
cap: PcapCap<dyn Activated>,
}
impl Capture {
pub fn init_capture(configure: &'static Configure) -> Result<Capture, CaptureError> {
if configure.pcap_file.is_some() {
return Ok(Self::init_from_file(configure).unwrap());
}
Self::init_interface(configure)
}
fn init_from_file(configure: &'static Configure) -> Result<Capture, CaptureError> {
let mut cap = PcapCap::from_file(configure.pcap_file.as_ref().unwrap()).unwrap();
if configure.filter.is_some() {
let res = cap.filter(configure.filter.as_ref().unwrap(), true);
if res.is_err() {
println!("capture filter error {:?}", res);
return Err(CaptureError::CapErr);
}
}
let capture = Capture { cap: cap.into() };
Ok(capture)
}
fn init_interface(configure: &'static Configure) -> Result<Capture, CaptureError> {
let device = Self::get_device(Some(&configure.interface))?;
let mut cap = pcap::Capture::from_device(device)
.unwrap()
.promisc(true)
.snaplen(configure.pkt_len)
.immediate_mode(true)
.open()
.unwrap();
if configure.filter.is_some() {
let res = cap.filter(configure.filter.as_ref().unwrap(), true);
if res.is_err() {
println!("capture filter error {:?}", res);
return Err(CaptureError::CapErr);
}
}
let capture = Capture { cap: cap.into() };
Ok(capture)
}
fn get_device(interface: Option<&String>) -> Result<Device, CaptureError> {
if let Some(name) = interface {
for dev in pcap::Device::list().expect("device lookup failed") {
if dev.name == *name {
return Ok(dev);
}
}
Err(CaptureError::CapErr)
} else {
let dev = pcap::Device::lookup()
.expect("device lookup failed")
.expect("no device available");
Ok(dev)
}
}
pub fn next_packet(&mut self, timestamp: u128) -> Result<Arc<Packet>, CaptureError> {
match self.cap.next_packet() {
Ok(pcap_pkt) => Ok(Arc::new(Packet::new(pcap_pkt.data.to_vec(), timestamp))),
Err(_) => Err(CaptureError::CapErr),
}
}
}