use bitcode::Decode;
use bitcode::Encode;
#[cfg(feature = "libpnet")]
use pnet::datalink;
#[cfg(feature = "libpnet")]
use pnet::datalink::Channel::Ethernet;
#[cfg(feature = "libpnet")]
use pnet::datalink::ChannelType;
#[cfg(feature = "libpnet")]
use pnet::datalink::Config;
#[cfg(feature = "libpnet")]
use pnet::datalink::DataLinkReceiver;
#[cfg(feature = "libpnet")]
use pnet::datalink::NetworkInterface;
use serde::Deserialize;
use serde::Serialize;
#[cfg(feature = "libpnet")]
use std::io::ErrorKind;
#[cfg(any(feature = "libpcap", feature = "libpnet"))]
use std::result;
#[cfg(feature = "libpnet")]
use std::time::Duration;
#[cfg(feature = "libpnet")]
use std::time::SystemTime;
#[cfg(feature = "libpnet")]
use std::time::UNIX_EPOCH;
pub mod error;
#[cfg(any(feature = "libpcap", feature = "libpnet"))]
pub mod filter;
pub mod fs;
pub mod libpcap;
#[cfg(feature = "libpnet")]
use crate::filter::Filter;
#[cfg(any(feature = "libpcap", feature = "libpnet"))]
use error::PcaptureError;
#[cfg(all(unix, feature = "libpcap"))]
use libpcap::Addresses;
#[cfg(all(unix, feature = "libpcap"))]
use libpcap::Libpcap;
#[cfg(any(
all(unix, any(feature = "libpcap", feature = "libpnet")),
all(windows, feature = "libpnet"),
))]
#[cfg(feature = "pcap")]
pub use fs::pcap::PacketRecord;
#[cfg(any(
all(unix, any(feature = "libpcap", feature = "libpnet")),
all(windows, feature = "libpnet"),
))]
#[cfg(feature = "pcap")]
pub use fs::pcap::Pcap;
#[cfg(any(
all(unix, any(feature = "libpcap", feature = "libpnet")),
all(windows, feature = "libpnet"),
))]
#[cfg(feature = "pcapng")]
pub use fs::pcapng::PcapNg;
#[cfg(any(
all(unix, any(feature = "libpcap", feature = "libpnet")),
all(windows, feature = "libpnet"),
))]
#[cfg(feature = "pcapng")]
use fs::pcapng::EnhancedPacketBlock;
#[cfg(any(
all(unix, any(feature = "libpcap", feature = "libpnet")),
all(windows, feature = "libpnet"),
))]
#[cfg(feature = "pcapng")]
use fs::pcapng::GeneralBlock;
#[cfg(any(
all(unix, any(feature = "libpcap", feature = "libpnet")),
all(windows, feature = "libpnet"),
))]
const DEFAULT_BUFFER_SIZE: usize = 4096;
#[cfg(feature = "libpnet")]
const DEFAULT_TIMEOUT: f32 = 0.1;
#[cfg(all(unix, feature = "libpcap"))]
const DEFAULT_TIMEOUT_MS: i32 = 1000;
#[cfg(any(
all(unix, any(feature = "libpcap", feature = "libpnet")),
all(windows, feature = "libpnet"),
))]
const DETAULT_SNAPLEN: usize = 65535;
#[cfg(any(feature = "libpcap", feature = "libpnet"))]
pub type Result<T, E = PcaptureError> = result::Result<T, E>;
#[derive(Debug, Clone)]
pub struct PacketData<'a> {
pub data: &'a [u8],
#[cfg(feature = "pcapng")]
pub ts_high: u32,
#[cfg(feature = "pcapng")]
pub ts_low: u32,
#[cfg(feature = "pcap")]
pub ts_sec: u32,
#[cfg(feature = "pcap")]
pub ts_usec: u32,
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, Encode, Decode)]
pub enum PcapByteOrder {
BigEndian,
LittleEndian,
WiresharkDefault,
}
#[cfg(feature = "libpnet")]
#[derive(Debug, Clone)]
pub struct Device(pub NetworkInterface);
#[cfg(all(unix, feature = "libpcap"))]
#[derive(Debug, Clone)]
pub struct Device {
pub name: String,
pub description: Option<String>,
pub addresses: Vec<Addresses>,
}
#[cfg(any(feature = "libpnet", feature = "libpcap"))]
impl Device {
#[cfg(feature = "libpnet")]
pub fn list() -> Result<Vec<Device>, PcaptureError> {
let nis = datalink::interfaces();
let mut ret = Vec::new();
for ni in nis {
let device = Device(ni);
ret.push(device);
}
Ok(ret)
}
#[cfg(feature = "libpcap")]
pub fn list() -> Result<Vec<Device>, PcaptureError> {
Libpcap::devices()
}
}
#[cfg(any(
all(unix, any(feature = "libpcap", feature = "libpnet")),
all(windows, feature = "libpnet"),
))]
#[derive(Debug, Clone)]
pub struct Iface {
pub id: u32,
pub device: Device,
}
#[cfg(feature = "libpnet")]
pub struct Capture {
pub name: String,
buffer_size: usize,
timeout: Duration,
snaplen: usize,
promisc: bool,
filter: Option<Filter>,
ifaces: Vec<Iface>,
iface_id: u32,
pnet_rx: Option<Box<dyn DataLinkReceiver>>,
}
#[cfg(feature = "libpnet")]
impl Capture {
pub fn new(name: &str) -> Result<Self, PcaptureError> {
let interfaces = datalink::interfaces();
let timeout = Duration::from_secs_f32(DEFAULT_TIMEOUT);
let buffer_size = DEFAULT_BUFFER_SIZE;
let snaplen = DETAULT_SNAPLEN;
let promisc = true;
let mut ifaces = Vec::new();
let mut i = 0;
let mut iface_id = 0;
let mut interface_exists = false;
for interface in interfaces {
if interface.name == name {
iface_id = i;
interface_exists = true;
}
let iface = Iface {
id: i as u32,
device: Device(interface),
};
ifaces.push(iface);
i += 1;
}
if !interface_exists {
let mut v = Vec::new();
for iface in &ifaces {
let name = &iface.device.0.name;
let description = &iface.device.0.description;
if description.len() == 0 {
v.push(format!("{}", name));
} else {
v.push(format!("{} ({})", name, description));
}
}
let available_interface = v.join(", ");
return Err(PcaptureError::InterfaceNotFound {
name: name.to_string(),
available_interface,
});
}
let config = Config {
write_buffer_size: buffer_size, read_buffer_size: buffer_size, read_timeout: Some(timeout),
write_timeout: Some(timeout),
channel_type: ChannelType::Layer2,
bpf_fd_attempts: 1000,
linux_fanout: None,
promiscuous: promisc,
socket_fd: None,
};
let iface = &ifaces[iface_id as usize];
let (_pnet_tx, pnet_rx) = match datalink::channel(&iface.device.0, config) {
Ok(Ethernet(tx, rx)) => (tx, rx),
Ok(_) => return Err(PcaptureError::UnhandledChannelType),
Err(e) => return Err(PcaptureError::UnableCreateChannel { e: e.to_string() }),
};
Ok(Capture {
name: name.to_string(),
buffer_size,
timeout,
snaplen,
promisc,
ifaces,
iface_id,
filter: None,
pnet_rx: Some(pnet_rx),
})
}
#[cfg(feature = "pcap")]
pub fn gen_pcap_header(&self, pbo: PcapByteOrder) -> Result<Pcap, PcaptureError> {
let pcap = Pcap::new(&self.name, pbo);
Ok(pcap)
}
#[cfg(feature = "pcapng")]
pub fn gen_pcapng_header(&self, pbo: PcapByteOrder) -> Result<PcapNg, PcaptureError> {
let pcapng = PcapNg::new(&self.ifaces, pbo);
Ok(pcapng)
}
pub fn set_buffer_size(&mut self, buffer_size: usize) {
self.buffer_size = buffer_size;
self.pnet_rx = None;
}
pub fn get_buffer_size(&self) -> usize {
self.buffer_size
}
pub fn set_timeout(&mut self, timeout: f32) {
let timeout_fix = Duration::from_secs_f32(timeout);
self.timeout = timeout_fix;
self.pnet_rx = None;
}
pub fn get_timeout(&self) -> f32 {
self.timeout.as_secs_f32()
}
pub fn set_promiscuous(&mut self, promiscuous: bool) {
self.promisc = promiscuous;
self.pnet_rx = None;
}
pub fn get_promiscuous(&self) -> bool {
self.promisc
}
pub fn set_snaplen(&mut self, snaplen: usize) {
self.snaplen = snaplen;
self.pnet_rx = None;
}
pub fn get_snaplen(&self) -> usize {
self.snaplen
}
pub fn set_filter(&mut self, filter: &str) -> Result<(), PcaptureError> {
let filter = Filter::parser(filter)?;
self.filter = filter;
self.pnet_rx = None;
Ok(())
}
pub fn get_filter(&self) -> Option<String> {
match &self.filter {
Some(f) => Some(f.input_str.to_string()),
None => None,
}
}
pub fn next(&'_ mut self) -> Result<PacketData<'_>, PcaptureError> {
if self.pnet_rx.is_none() {
let config = Config {
write_buffer_size: self.buffer_size, read_buffer_size: self.buffer_size, read_timeout: Some(self.timeout),
write_timeout: Some(self.timeout),
channel_type: ChannelType::Layer2,
bpf_fd_attempts: 1000,
linux_fanout: None,
promiscuous: self.promisc,
socket_fd: None,
};
let iface = &self.ifaces[self.iface_id as usize];
let (_pnet_tx, pnet_rx) = match datalink::channel(&iface.device.0, config) {
Ok(Ethernet(tx, rx)) => (tx, rx),
Ok(_) => return Err(PcaptureError::UnhandledChannelType),
Err(e) => return Err(PcaptureError::UnableCreateChannel { e: e.to_string() }),
};
self.pnet_rx = Some(pnet_rx);
}
match &mut self.pnet_rx {
Some(pnet_rx) => {
let data = pnet_rx.next()?; let now = SystemTime::now().duration_since(UNIX_EPOCH)?;
#[cfg(feature = "pcap")]
let ts_sec = now.as_secs() as u32;
#[cfg(feature = "pcap")]
let ts_usec = now.subsec_micros();
#[cfg(feature = "pcapng")]
let ts64: u64 = now.as_secs() * 1_000_000 + now.subsec_micros() as u64;
#[cfg(feature = "pcapng")]
let ts_high = (ts64 >> 32) as u32;
#[cfg(feature = "pcapng")]
let ts_low = (ts64 & 0xFFFF_FFFF) as u32;
let packet_data = PacketData {
data,
#[cfg(feature = "pcap")]
ts_sec,
#[cfg(feature = "pcap")]
ts_usec,
#[cfg(feature = "pcapng")]
ts_high,
#[cfg(feature = "pcapng")]
ts_low,
};
Ok(packet_data)
}
None => unreachable!("pnet_rx must have value"),
}
}
pub fn next_as_vec(&mut self) -> Result<Vec<u8>, PcaptureError> {
let filter = self.filter.clone();
loop {
let packet_data = match self.next() {
Ok(pd) => pd,
Err(e) => match e {
PcaptureError::IOError(e) => {
if e.kind() == ErrorKind::TimedOut {
continue;
} else {
return Err(e.into());
}
}
_ => return Err(e.into()),
},
};
match &filter {
Some(fls) => {
if fls.check(packet_data.data)? {
return Ok(packet_data.data.to_vec());
}
}
None => {
return Ok(packet_data.data.to_vec());
}
}
}
}
#[cfg(feature = "pcap")]
pub fn next_as_pcap(&mut self) -> Result<PacketRecord, PcaptureError> {
let filter = self.filter.clone();
let snaplen = self.snaplen;
loop {
let packet_data = match self.next() {
Ok(pd) => pd,
Err(e) => match e {
PcaptureError::IOError(e) => {
if e.kind() == ErrorKind::TimedOut {
continue;
} else {
return Err(e.into());
}
}
_ => return Err(e.into()),
},
};
match &filter {
Some(fls) => {
if fls.check(packet_data.data)? {
let pcap_record = PacketRecord::new(&packet_data.data, snaplen)?;
return Ok(pcap_record);
}
}
None => {
let pcap_record = PacketRecord::new(&packet_data.data, snaplen)?;
return Ok(pcap_record);
}
}
}
}
#[cfg(feature = "pcapng")]
pub fn next_as_pcapng(&mut self) -> Result<GeneralBlock, PcaptureError> {
let filter = self.filter.clone();
let snaplen = self.snaplen;
let iface_id = self.iface_id;
loop {
let packet_data = match self.next() {
Ok(pd) => pd,
Err(e) => match e {
PcaptureError::IOError(e) => {
if e.kind() == ErrorKind::TimedOut {
continue;
} else {
return Err(e.into());
}
}
_ => return Err(e.into()),
},
};
match &filter {
Some(fls) => {
if fls.check(packet_data.data)? {
let block = EnhancedPacketBlock::new(iface_id, &packet_data.data, snaplen)?;
let ret = GeneralBlock::EnhancedPacketBlock(block);
return Ok(ret);
}
}
None => {
let block = EnhancedPacketBlock::new(iface_id, &packet_data.data, snaplen)?;
let ret = GeneralBlock::EnhancedPacketBlock(block);
return Ok(ret);
}
}
}
}
}
#[cfg(all(unix, feature = "libpcap"))]
#[derive(Debug, Clone)]
pub struct Capture {
pub name: String,
buffer_size: usize,
timeout_ms: i32,
snaplen: usize,
promisc: bool,
immediate: bool,
nonblock: bool,
filter: Option<String>,
#[cfg(feature = "pcapng")]
ifaces: Vec<Iface>,
#[cfg(feature = "pcapng")]
iface_id: u32,
lp: Option<Libpcap>,
}
#[cfg(all(unix, feature = "libpcap"))]
impl Drop for Capture {
fn drop(&mut self) {
let _ = self.stop();
}
}
#[cfg(all(unix, feature = "libpcap"))]
impl<'a> Capture {
pub fn new(name: &str) -> Result<Self, PcaptureError> {
let devices = Libpcap::devices()?;
let timeout_ms = DEFAULT_TIMEOUT_MS;
let buffer_size = DEFAULT_BUFFER_SIZE;
let snaplen = DETAULT_SNAPLEN;
let promisc = false;
let immediate = false;
let nonblock = false;
let mut ifaces = Vec::new();
let mut i = 0;
#[cfg(feature = "pcapng")]
let mut iface_id = 0;
let mut interface_exists = false;
for device in devices {
if device.name == name {
#[cfg(feature = "pcapng")]
{
iface_id = i;
}
interface_exists = true;
}
let iface = Iface {
id: i as u32,
device,
};
ifaces.push(iface);
i += 1;
}
if !interface_exists {
let available_interface = ifaces
.iter()
.map(|iface| iface.device.name.clone())
.collect::<Vec<String>>()
.join(", ");
return Err(PcaptureError::InterfaceNotFound {
name: name.to_string(),
available_interface,
});
}
Ok(Self {
name: name.to_string(),
buffer_size,
timeout_ms,
snaplen,
promisc,
immediate,
#[cfg(feature = "pcapng")]
ifaces,
#[cfg(feature = "pcapng")]
iface_id,
nonblock,
filter: None,
lp: None,
})
}
#[cfg(feature = "pcap")]
pub fn gen_pcap_header(&self, pbo: PcapByteOrder) -> Result<Pcap, PcaptureError> {
let pcap = Pcap::new(&self.name, pbo);
Ok(pcap)
}
#[cfg(feature = "pcapng")]
pub fn gen_pcapng_header(&self, pbo: PcapByteOrder) -> Result<PcapNg, PcaptureError> {
let pcapng = PcapNg::new(&self.ifaces, pbo);
Ok(pcapng)
}
pub fn set_buffer_size(&mut self, buffer_size: usize) {
self.buffer_size = buffer_size;
self.lp = None;
}
pub fn get_buffer_size(&self) -> usize {
self.buffer_size
}
pub fn set_timeout(&mut self, timeout_ms: i32) {
self.timeout_ms = timeout_ms;
self.lp = None;
}
pub fn get_timeout(&self) -> i32 {
self.timeout_ms
}
pub fn set_promiscuous_mode(&mut self, promiscuous: bool) {
self.promisc = promiscuous;
self.lp = None;
}
pub fn get_promiscuous_mode(&self) -> bool {
self.promisc
}
pub fn set_immediate_mode(&mut self, immediate: bool) {
self.immediate = immediate;
self.lp = None;
}
pub fn get_immediate_mode(&self) -> bool {
self.immediate
}
pub fn set_snaplen(&mut self, snaplen: usize) {
self.snaplen = snaplen;
self.lp = None;
}
pub fn get_snaplen(&self) -> usize {
self.snaplen
}
pub fn set_nonblock(&mut self, nonblock: bool) {
self.nonblock = nonblock;
self.lp = None;
}
pub fn set_filter(&mut self, filter: &str) {
self.filter = Some(filter.to_string());
self.lp = None;
}
pub fn get_filter(&self) -> Option<String> {
self.filter.clone()
}
pub fn fetch(&mut self) -> Result<Vec<PacketData<'_>>, PcaptureError> {
match self.lp {
Some(_) => (),
None => {
let lp = Libpcap::new(
&self.name,
self.snaplen as i32,
self.promisc,
self.immediate,
self.timeout_ms,
self.buffer_size as i32,
self.nonblock,
self.filter.clone(),
)?;
self.lp = Some(lp);
}
}
match &mut self.lp {
Some(lp) => {
let packets = lp.fetch()?;
Ok(packets)
}
None => Ok(Vec::new()),
}
}
pub fn stop(&mut self) -> Result<(), PcaptureError> {
if let Some(libpcap) = &mut self.lp {
let _ = libpcap.stop()?;
}
Ok(())
}
pub fn fetch_as_vec(&'a mut self) -> Result<Vec<&'a [u8]>, PcaptureError> {
let packets = self.fetch()?;
let mut ret = Vec::new();
for p in packets {
ret.push(p.data)
}
return Ok(ret);
}
#[cfg(feature = "pcap")]
pub fn fetch_as_pcap(&mut self) -> Result<Vec<PacketRecord>, PcaptureError> {
let snaplen = self.snaplen as usize;
let packets = self.fetch()?;
let mut ret = Vec::new();
for p in packets {
let data = p.data;
let ts_sec = p.ts_sec;
let ts_usec = p.ts_usec;
let pcap_record = PacketRecord::new(data, snaplen, ts_sec, ts_usec)?;
ret.push(pcap_record);
}
return Ok(ret);
}
#[cfg(feature = "pcapng")]
pub fn fetch_as_pcapng(&mut self) -> Result<Vec<GeneralBlock>, PcaptureError> {
let snaplen = self.snaplen as usize;
let iface_id = self.iface_id;
let packets = self.fetch()?;
let mut ret = Vec::new();
for p in packets {
let data = p.data;
let ts_high = p.ts_high;
let ts_low = p.ts_low;
let block = EnhancedPacketBlock::new(iface_id, data, snaplen, ts_high, ts_low)?;
let block = GeneralBlock::EnhancedPacketBlock(block);
ret.push(block);
}
return Ok(ret);
}
}
#[cfg(all(unix, feature = "libpcap"))]
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn capture_raw() {
let mut cap = Capture::new("ens33").unwrap();
cap.set_buffer_size(4096);
for i in 0..5 {
let packet_raw = cap.fetch_as_vec().unwrap();
println!("fetch[{}], packets num: {}", i, packet_raw.len());
}
}
#[cfg(feature = "pcap")]
#[test]
fn capture_pcap() {
let path = "test_ens33.pcap";
let pbo = PcapByteOrder::WiresharkDefault;
let mut cap = Capture::new("ens33").unwrap();
cap.set_buffer_size(4096);
let mut pcap = cap.gen_pcap_header(pbo).unwrap();
let mut packet_count = 0;
for _ in 0..5 {
let record = cap.fetch_as_pcap().unwrap();
for r in record {
pcap.append(r);
packet_count += 1;
}
}
println!("packet count: {}", packet_count);
pcap.write_all(path).unwrap();
let read_pcap = Pcap::read_all(path, pbo).unwrap();
assert_eq!(read_pcap.records.len(), packet_count);
}
#[cfg(feature = "pcap")]
#[test]
fn capture_pcap_any() {
let path = "test_any.pcap";
let pbo = PcapByteOrder::WiresharkDefault;
let mut cap = Capture::new("any").unwrap();
cap.set_buffer_size(4096);
let mut pcap = cap.gen_pcap_header(pbo).unwrap();
let mut packet_count = 0;
for _ in 0..5 {
let record = cap.fetch_as_pcap().unwrap();
for r in record {
pcap.append(r);
packet_count += 1;
}
}
println!("packet count: {}", packet_count);
pcap.write_all(path).unwrap();
let read_pcap = Pcap::read_all(path, pbo).unwrap();
assert_eq!(read_pcap.records.len(), packet_count);
}
#[cfg(feature = "pcapng")]
#[test]
fn capture_pcapng() {
let path = "test_ens33.pcapng";
let pbo = PcapByteOrder::WiresharkDefault;
let mut cap = Capture::new("ens33").unwrap();
cap.set_buffer_size(4096);
cap.set_timeout(1);
cap.set_promiscuous_mode(true);
cap.set_snaplen(65535);
let mut pcapng = cap.gen_pcapng_header(pbo).unwrap();
println!("pcapng header len: {}", pcapng.blocks.len());
let mut packets_count = pcapng.blocks.len();
for _ in 0..5 {
let blocks = cap.fetch_as_pcapng().unwrap();
for b in blocks {
pcapng.append(b);
packets_count += 1;
}
}
pcapng.write_all(path).unwrap();
let read_pcapng = PcapNg::read_all(path, pbo).unwrap();
assert_eq!(read_pcapng.blocks.len(), packets_count);
}
#[cfg(feature = "pcapng")]
#[test]
fn capture_pcapng_any() {
let path = "test_any.pcapng";
let pbo = PcapByteOrder::WiresharkDefault;
let mut cap = Capture::new("any").unwrap();
cap.set_buffer_size(4096);
cap.set_timeout(1);
cap.set_promiscuous_mode(false);
cap.set_snaplen(65535);
let mut pcapng = cap.gen_pcapng_header(pbo).unwrap();
println!("pcapng header len: {}", pcapng.blocks.len());
let mut packets_count = pcapng.blocks.len();
for _ in 0..5 {
let blocks = cap.fetch_as_pcapng().unwrap();
for b in blocks {
pcapng.append(b);
packets_count += 1;
}
}
pcapng.write_all(path).unwrap();
let read_pcapng = PcapNg::read_all(path, pbo).unwrap();
assert_eq!(read_pcapng.blocks.len(), packets_count);
}
#[cfg(feature = "pcapng")]
#[test]
fn capture_pcapng_filter() {
let path = "test_filter.pcapng";
let pbo = PcapByteOrder::WiresharkDefault;
let filter = "host 192.168.5.2";
let mut cap = Capture::new("ens33").unwrap();
cap.set_filter(filter);
let mut pcapng = cap.gen_pcapng_header(pbo).unwrap();
for i in 0..5 {
println!("i: {}", i);
let block = cap.fetch_as_pcapng().unwrap();
for b in block {
pcapng.append(b);
}
}
pcapng.write_all(path).unwrap();
}
#[ignore]
#[test]
fn block_read() {
let pbo = PcapByteOrder::WiresharkDefault;
let path = "1.pcapng";
let read_pcapng = PcapNg::read_all(path, pbo).unwrap();
println!("blocks num: {}", read_pcapng.blocks.len());
for b in read_pcapng.blocks {
println!("block type: {}", b.name());
}
}
}
#[cfg(feature = "libpnet")]
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn capture_raw() {
let mut cap = Capture::new("ens33").unwrap();
cap.set_buffer_size(4096);
for i in 0..5 {
let packet_raw = cap.next_as_vec().unwrap();
println!("fetch[{}], packets num: {}", i, packet_raw.len());
}
}
#[cfg(feature = "pcap")]
#[test]
fn capture_pcap() {
let path = "test_ens33.pcap";
let pbo = PcapByteOrder::WiresharkDefault;
let mut cap = Capture::new("ens33").unwrap();
cap.set_buffer_size(4096);
let mut pcap = cap.gen_pcap_header(pbo).unwrap();
let mut packet_count = 0;
for _ in 0..5 {
let record = cap.next_as_pcap().unwrap();
pcap.append(record);
packet_count += 1;
}
println!("packet count: {}", packet_count);
pcap.write_all(path).unwrap();
let read_pcap = Pcap::read_all(path, pbo).unwrap();
assert_eq!(read_pcap.records.len(), packet_count);
}
#[cfg(feature = "pcapng")]
#[test]
fn capture_pcapng() {
let path = "test_ens33.pcapng";
let pbo = PcapByteOrder::WiresharkDefault;
let mut cap = Capture::new("ens33").unwrap();
cap.set_buffer_size(4096);
cap.set_timeout(1.0);
cap.set_promiscuous(true);
cap.set_snaplen(65535);
let mut pcapng = cap.gen_pcapng_header(pbo).unwrap();
println!("pcapng header len: {}", pcapng.blocks.len());
let mut packets_count = pcapng.blocks.len();
for _ in 0..5 {
let block = cap.next_as_pcapng().unwrap();
pcapng.append(block);
packets_count += 1;
}
pcapng.write_all(path).unwrap();
let read_pcapng = PcapNg::read_all(path, pbo).unwrap();
assert_eq!(read_pcapng.blocks.len(), packets_count);
}
#[cfg(feature = "pcapng")]
#[test]
fn capture_pcapng_filter() {
let path = "test_filter.pcapng";
let pbo = PcapByteOrder::WiresharkDefault;
let filter_str = "icmp and ip=192.168.5.2";
let mut cap = Capture::new("ens33").unwrap();
cap.set_filter(filter_str).unwrap();
let mut pcapng = cap.gen_pcapng_header(pbo).unwrap();
for i in 0..5 {
println!("i: {}", i);
let block = cap.next_as_pcapng().unwrap();
pcapng.append(block);
}
pcapng.write_all(path).unwrap();
}
}