use std::mem;
use crate::{
capture::{Active, Capture, Inactive},
device::Device,
raw, Error,
};
#[cfg(libpcap_1_5_0)]
use crate::capture::Precision;
impl Capture<Inactive> {
pub fn from_device<D: Into<Device>>(device: D) -> Result<Capture<Inactive>, Error> {
let device: Device = device.into();
Capture::new_raw(Some(&device.name), |name, err| unsafe {
raw::pcap_create(name, err)
})
}
pub fn open(self) -> Result<Capture<Active>, Error> {
unsafe {
self.check_err(raw::pcap_activate(self.handle.as_ptr()) == 0)?;
Ok(mem::transmute::<Capture<Inactive>, Capture<Active>>(self))
}
}
pub fn timeout(self, ms: i32) -> Capture<Inactive> {
unsafe { raw::pcap_set_timeout(self.handle.as_ptr(), ms) };
self
}
#[cfg(libpcap_1_2_1)]
pub fn tstamp_type(self, tstamp_type: TimestampType) -> Capture<Inactive> {
unsafe { raw::pcap_set_tstamp_type(self.handle.as_ptr(), tstamp_type as _) };
self
}
pub fn promisc(self, to: bool) -> Capture<Inactive> {
unsafe { raw::pcap_set_promisc(self.handle.as_ptr(), to as _) };
self
}
#[cfg(any(libpcap_1_5_0, windows))]
pub fn immediate_mode(self, to: bool) -> Capture<Inactive> {
#[cfg(libpcap_1_5_0)]
unsafe {
raw::pcap_set_immediate_mode(self.handle.as_ptr(), to as _)
};
#[cfg(all(windows, not(libpcap_1_5_0)))]
unsafe {
raw::pcap_setmintocopy(
self.handle.as_ptr(),
if to {
0
} else {
raw::WINPCAP_MINTOCOPY_DEFAULT
},
)
};
self
}
#[cfg(all(libpcap_1_5_3, target_os = "macos"))]
pub fn want_pktap(self, to: bool) -> Capture<Inactive> {
unsafe { raw::pcap_set_want_pktap(self.handle.as_ptr(), to as _) };
self
}
#[cfg(not(windows))]
pub fn rfmon(self, to: bool) -> Capture<Inactive> {
unsafe { raw::pcap_set_rfmon(self.handle.as_ptr(), to as _) };
self
}
pub fn buffer_size(self, to: i32) -> Capture<Inactive> {
unsafe { raw::pcap_set_buffer_size(self.handle.as_ptr(), to) };
self
}
#[cfg(libpcap_1_5_0)]
pub fn precision(self, precision: Precision) -> Capture<Inactive> {
unsafe { raw::pcap_set_tstamp_precision(self.handle.as_ptr(), precision as _) };
self
}
pub fn snaplen(self, to: i32) -> Capture<Inactive> {
unsafe { raw::pcap_set_snaplen(self.handle.as_ptr(), to) };
self
}
}
#[repr(i32)]
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum TimestampType {
Host = 0,
HostLowPrec = 1,
HostHighPrec = 2,
Adapter = 3,
AdapterUnsynced = 4,
}
#[cfg(test)]
mod tests {
use crate::{
capture::testmod::test_capture,
raw::testmod::{as_pcap_t, geterr_expect, RAWMTX},
};
use super::*;
#[test]
fn test_from_device() {
let _m = RAWMTX.lock();
let mut dummy: isize = 777;
let pcap = as_pcap_t(&mut dummy);
let ctx = raw::pcap_create_context();
ctx.expect().return_once_st(move |_, _| pcap);
let ctx = raw::pcap_close_context();
ctx.expect()
.withf_st(move |ptr| *ptr == pcap)
.return_once(|_| {});
let result = Capture::from_device("some_device");
assert!(result.is_ok());
}
#[test]
fn test_from_device_error() {
let _m = RAWMTX.lock();
let ctx = raw::pcap_create_context();
ctx.expect().return_once_st(|_, _| std::ptr::null_mut());
let result = Capture::from_device("some_device");
assert!(result.is_err());
}
#[test]
fn test_open() {
let _m = RAWMTX.lock();
let mut dummy: isize = 777;
let pcap = as_pcap_t(&mut dummy);
let test_capture = test_capture::<Inactive>(pcap);
let capture = test_capture.capture;
let ctx = raw::pcap_activate_context();
ctx.expect()
.withf_st(move |arg1| *arg1 == pcap)
.return_once(|_| 0);
let result = capture.open();
assert!(result.is_ok());
}
#[test]
fn test_open_error() {
let _m = RAWMTX.lock();
let mut dummy: isize = 777;
let pcap = as_pcap_t(&mut dummy);
let test_capture = test_capture::<Inactive>(pcap);
let capture = test_capture.capture;
let ctx = raw::pcap_activate_context();
ctx.expect()
.withf_st(move |arg1| *arg1 == pcap)
.return_once(|_| -1);
let _err = geterr_expect(pcap);
let result = capture.open();
assert!(result.is_err());
}
#[test]
fn test_timeout() {
let _m = RAWMTX.lock();
let mut dummy: isize = 777;
let pcap = as_pcap_t(&mut dummy);
let test_capture = test_capture::<Inactive>(pcap);
let capture = test_capture.capture;
let ctx = raw::pcap_set_timeout_context();
ctx.expect()
.withf_st(move |arg1, _| *arg1 == pcap)
.return_once(|_, _| 0);
let _capture = capture.timeout(5);
}
#[test]
#[cfg(libpcap_1_2_1)]
fn test_timstamp_type() {
let _m = RAWMTX.lock();
let mut dummy: isize = 777;
let pcap = as_pcap_t(&mut dummy);
let test_capture = test_capture::<Inactive>(pcap);
let capture = test_capture.capture;
let ctx = raw::pcap_set_tstamp_type_context();
ctx.expect()
.withf_st(move |arg1, _| *arg1 == pcap)
.return_once(|_, _| 0);
let _capture = capture.tstamp_type(TimestampType::Host);
assert_ne!(TimestampType::Host, TimestampType::HostLowPrec);
assert_ne!(TimestampType::Host, TimestampType::HostHighPrec);
}
#[test]
fn test_promisc() {
let _m = RAWMTX.lock();
let mut dummy: isize = 777;
let pcap = as_pcap_t(&mut dummy);
let test_capture = test_capture::<Inactive>(pcap);
let capture = test_capture.capture;
let ctx = raw::pcap_set_promisc_context();
ctx.expect()
.withf_st(move |arg1, _| *arg1 == pcap)
.return_once(|_, _| 0);
let _capture = capture.promisc(true);
}
#[cfg(libpcap_1_5_0)]
struct ImmediateModeExpect(raw::__pcap_set_immediate_mode::Context);
#[cfg(all(windows, not(libpcap_1_5_0)))]
struct ImmediateModeExpect(raw::__pcap_setmintocopy::Context);
#[cfg(any(libpcap_1_5_0, windows))]
fn immediate_mode_expect(pcap: *mut raw::pcap_t) -> ImmediateModeExpect {
#[cfg(libpcap_1_5_0)]
{
let ctx = raw::pcap_set_immediate_mode_context();
ctx.checkpoint();
ctx.expect()
.withf_st(move |arg1, _| *arg1 == pcap)
.return_once(|_, _| 0);
ImmediateModeExpect(ctx)
}
#[cfg(all(windows, not(libpcap_1_5_0)))]
{
let ctx = raw::pcap_setmintocopy_context();
ctx.checkpoint();
ctx.expect()
.withf_st(move |arg1, _| *arg1 == pcap)
.return_once(|_, _| 0);
ImmediateModeExpect(ctx)
}
}
#[test]
#[cfg(any(libpcap_1_5_0, windows))]
fn test_immediate_mode() {
let _m = RAWMTX.lock();
let mut dummy: isize = 777;
let pcap = as_pcap_t(&mut dummy);
let test_capture = test_capture::<Inactive>(pcap);
let capture = test_capture.capture;
let _ctx = immediate_mode_expect(pcap);
let capture = capture.immediate_mode(true);
let _ctx = immediate_mode_expect(pcap);
let _capture = capture.immediate_mode(false);
}
#[test]
#[cfg(all(libpcap_1_5_3, target_os = "macos"))]
fn test_want_pktap() {
let _m = RAWMTX.lock();
let mut dummy: isize = 777;
let pcap = as_pcap_t(&mut dummy);
let test_capture = test_capture::<Inactive>(pcap);
let capture = test_capture.capture;
let ctx = raw::pcap_set_want_pktap_context();
ctx.expect()
.withf_st(move |arg1, _| *arg1 == pcap)
.return_once(|_, _| 0);
let _capture = capture.want_pktap(true);
}
#[test]
#[cfg(not(windows))]
fn test_rfmon() {
let _m = RAWMTX.lock();
let mut dummy: isize = 777;
let pcap = as_pcap_t(&mut dummy);
let test_capture = test_capture::<Inactive>(pcap);
let capture = test_capture.capture;
let ctx = raw::pcap_set_rfmon_context();
ctx.expect()
.withf_st(move |arg1, _| *arg1 == pcap)
.return_once(|_, _| 0);
let _capture = capture.rfmon(true);
}
#[test]
fn test_buffer_size() {
let _m = RAWMTX.lock();
let mut dummy: isize = 777;
let pcap = as_pcap_t(&mut dummy);
let test_capture = test_capture::<Inactive>(pcap);
let capture = test_capture.capture;
let ctx = raw::pcap_set_buffer_size_context();
ctx.expect()
.withf_st(move |arg1, _| *arg1 == pcap)
.return_once(|_, _| 0);
let _capture = capture.buffer_size(10);
}
#[test]
#[cfg(libpcap_1_5_0)]
fn test_precision() {
let _m = RAWMTX.lock();
let mut dummy: isize = 777;
let pcap = as_pcap_t(&mut dummy);
let test_capture = test_capture::<Inactive>(pcap);
let capture = test_capture.capture;
let ctx = raw::pcap_set_tstamp_precision_context();
ctx.expect()
.withf_st(move |arg1, _| *arg1 == pcap)
.return_once(|_, _| 0);
let _capture = capture.precision(Precision::Nano);
}
#[test]
fn test_snaplen() {
let _m = RAWMTX.lock();
let mut dummy: isize = 777;
let pcap = as_pcap_t(&mut dummy);
let test_capture = test_capture::<Inactive>(pcap);
let capture = test_capture.capture;
let ctx = raw::pcap_set_snaplen_context();
ctx.expect()
.withf_st(move |arg1, _| *arg1 == pcap)
.return_once(|_, _| 0);
let _capture = capture.snaplen(10);
}
}