1use bitcode::Decode;
2use bitcode::Encode;
3#[cfg(feature = "libpnet")]
4use pnet::datalink;
5#[cfg(feature = "libpnet")]
6use pnet::datalink::Channel::Ethernet;
7#[cfg(feature = "libpnet")]
8use pnet::datalink::ChannelType;
9#[cfg(feature = "libpnet")]
10use pnet::datalink::Config;
11#[cfg(feature = "libpnet")]
12use pnet::datalink::DataLinkReceiver;
13#[cfg(feature = "libpnet")]
14use pnet::datalink::NetworkInterface;
15use serde::Deserialize;
16use serde::Serialize;
17#[cfg(feature = "libpnet")]
18use std::io::ErrorKind;
19#[cfg(any(feature = "libpcap", feature = "libpnet"))]
20use std::result;
21#[cfg(feature = "libpnet")]
22use std::time::Duration;
23#[cfg(feature = "libpnet")]
24use std::time::SystemTime;
25#[cfg(feature = "libpnet")]
26use std::time::UNIX_EPOCH;
27
28pub mod error;
29#[cfg(any(feature = "libpcap", feature = "libpnet"))]
30pub mod filter;
31pub mod fs;
32pub mod libpcap;
33
34#[cfg(feature = "libpnet")]
35use crate::filter::Filter;
36#[cfg(any(feature = "libpcap", feature = "libpnet"))]
37use error::PcaptureError;
38#[cfg(all(unix, feature = "libpcap"))]
39use libpcap::Addresses;
40#[cfg(all(unix, feature = "libpcap"))]
41use libpcap::Libpcap;
42
43#[cfg(any(
44 all(unix, any(feature = "libpcap", feature = "libpnet")),
45 all(windows, feature = "libpnet"),
46))]
47#[cfg(feature = "pcap")]
48pub use fs::pcap::PacketRecord;
49#[cfg(any(
50 all(unix, any(feature = "libpcap", feature = "libpnet")),
51 all(windows, feature = "libpnet"),
52))]
53#[cfg(feature = "pcap")]
54pub use fs::pcap::Pcap;
55#[cfg(any(
56 all(unix, any(feature = "libpcap", feature = "libpnet")),
57 all(windows, feature = "libpnet"),
58))]
59#[cfg(feature = "pcapng")]
60pub use fs::pcapng::PcapNg;
61
62#[cfg(any(
63 all(unix, any(feature = "libpcap", feature = "libpnet")),
64 all(windows, feature = "libpnet"),
65))]
66#[cfg(feature = "pcapng")]
67use fs::pcapng::EnhancedPacketBlock;
68#[cfg(any(
69 all(unix, any(feature = "libpcap", feature = "libpnet")),
70 all(windows, feature = "libpnet"),
71))]
72#[cfg(feature = "pcapng")]
73use fs::pcapng::GeneralBlock;
74
75#[cfg(any(
76 all(unix, any(feature = "libpcap", feature = "libpnet")),
77 all(windows, feature = "libpnet"),
78))]
79const DEFAULT_BUFFER_SIZE: usize = 8 * 1024 * 1024; #[cfg(feature = "libpnet")]
81const DEFAULT_TIMEOUT: f32 = 0.1;
82
83#[cfg(all(unix, feature = "libpcap"))]
84const DEFAULT_TIMEOUT_MS: i32 = 1000;
85#[cfg(any(
86 all(unix, any(feature = "libpcap", feature = "libpnet")),
87 all(windows, feature = "libpnet"),
88))]
89const DETAULT_SNAPLEN: usize = 65535;
90
91#[cfg(any(feature = "libpcap", feature = "libpnet"))]
92pub type Result<T, E = PcaptureError> = result::Result<T, E>;
93
94#[derive(Debug, Clone)]
95pub struct PacketData<'a> {
96 pub data: &'a [u8],
97 #[cfg(feature = "pcapng")]
98 pub ts_high: u32,
99 #[cfg(feature = "pcapng")]
100 pub ts_low: u32,
101 #[cfg(feature = "pcap")]
102 pub ts_sec: u32,
103 #[cfg(feature = "pcap")]
104 pub ts_usec: u32,
105}
106
107#[derive(Debug, Clone, Copy, Serialize, Deserialize, Encode, Decode)]
108pub enum PcapByteOrder {
109 BigEndian,
110 LittleEndian,
111 WiresharkDefault,
113}
114
115#[cfg(feature = "libpnet")]
116#[derive(Debug, Clone)]
117pub struct Device(pub NetworkInterface);
118
119#[cfg(all(unix, feature = "libpcap"))]
120#[derive(Debug, Clone)]
121pub struct Device {
122 pub name: String,
124 pub description: Option<String>,
126 pub addresses: Vec<Addresses>,
128}
129
130#[cfg(any(feature = "libpnet", feature = "libpcap"))]
131impl Device {
132 #[cfg(feature = "libpnet")]
144 pub fn list() -> Result<Vec<Device>, PcaptureError> {
145 let nis = datalink::interfaces();
146 let mut ret = Vec::new();
147 for ni in nis {
148 let device = Device(ni);
149 ret.push(device);
150 }
151 Ok(ret)
152 }
153 #[cfg(feature = "libpcap")]
154 pub fn list() -> Result<Vec<Device>, PcaptureError> {
155 Libpcap::devices()
156 }
157}
158
159#[cfg(any(
160 all(unix, any(feature = "libpcap", feature = "libpnet")),
161 all(windows, feature = "libpnet"),
162))]
163#[derive(Debug, Clone)]
164pub struct Iface {
165 pub id: u32,
166 pub device: Device,
167}
168
169#[cfg(feature = "libpnet")]
170pub struct Capture {
171 pub name: String,
172 buffer_size: usize,
173 timeout: Duration,
174 snaplen: usize,
175 promisc: bool,
176 filter: Option<Filter>,
178 ifaces: Vec<Iface>,
180 iface_id: u32,
182 pnet_rx: Option<Box<dyn DataLinkReceiver>>,
184}
185
186#[cfg(feature = "libpnet")]
187impl Capture {
188 pub fn new(name: &str) -> Result<Self, PcaptureError> {
212 let interfaces = datalink::interfaces();
213 let timeout = Duration::from_secs_f32(DEFAULT_TIMEOUT);
214 let buffer_size = DEFAULT_BUFFER_SIZE;
215 let snaplen = DETAULT_SNAPLEN;
216 let promisc = true;
217
218 let mut ifaces = Vec::new();
219 let mut i = 0;
220 let mut iface_id = 0;
221 let mut interface_exists = false;
222 for interface in interfaces {
223 if interface.name == name {
224 iface_id = i;
225 interface_exists = true;
226 }
227 let iface = Iface {
228 id: i as u32,
229 device: Device(interface),
230 };
231 ifaces.push(iface);
232 i += 1;
233 }
234
235 if !interface_exists {
236 let mut v = Vec::new();
237 for iface in &ifaces {
238 let name = &iface.device.0.name;
239 let description = &iface.device.0.description;
240
241 if description.len() == 0 {
242 v.push(format!("{}", name));
243 } else {
244 v.push(format!("{} ({})", name, description));
245 }
246 }
247 let available_interface = v.join(", ");
248
249 return Err(PcaptureError::InterfaceNotFound {
250 name: name.to_string(),
251 available_interface,
252 });
253 }
254
255 let config = Config {
256 write_buffer_size: buffer_size, read_buffer_size: buffer_size, read_timeout: Some(timeout),
259 write_timeout: Some(timeout),
260 channel_type: ChannelType::Layer2,
261 bpf_fd_attempts: 1000,
262 linux_fanout: None,
263 promiscuous: promisc,
264 socket_fd: None,
265 };
266
267 let iface = &ifaces[iface_id as usize];
269 let (_pnet_tx, pnet_rx) = match datalink::channel(&iface.device.0, config) {
271 Ok(Ethernet(tx, rx)) => (tx, rx),
272 Ok(_) => return Err(PcaptureError::UnhandledChannelType),
273 Err(e) => return Err(PcaptureError::UnableCreateChannel { e: e.to_string() }),
274 };
275
276 Ok(Capture {
277 name: name.to_string(),
278 buffer_size,
279 timeout,
280 snaplen,
281 promisc,
282 ifaces,
283 iface_id,
284 filter: None,
285 pnet_rx: Some(pnet_rx),
286 })
287 }
288 #[cfg(feature = "pcap")]
290 pub fn gen_pcap_header(&self, pbo: PcapByteOrder) -> Result<Pcap, PcaptureError> {
291 let pcap = Pcap::new(&self.name, pbo);
292 Ok(pcap)
293 }
294 #[cfg(feature = "pcapng")]
296 pub fn gen_pcapng_header(&self, pbo: PcapByteOrder) -> Result<PcapNg, PcaptureError> {
297 let pcapng = PcapNg::new(&self.ifaces, pbo);
298 Ok(pcapng)
299 }
300 pub fn set_buffer_size(&mut self, buffer_size: usize) {
302 self.buffer_size = buffer_size;
303 self.pnet_rx = None;
305 }
306 pub fn get_buffer_size(&self) -> usize {
308 self.buffer_size
309 }
310 pub fn set_timeout(&mut self, timeout: f32) {
312 let timeout_fix = Duration::from_secs_f32(timeout);
313 self.timeout = timeout_fix;
314 self.pnet_rx = None;
316 }
317 pub fn get_timeout(&self) -> f32 {
319 self.timeout.as_secs_f32()
320 }
321 pub fn set_promiscuous(&mut self, promiscuous: bool) {
323 self.promisc = promiscuous;
324 self.pnet_rx = None;
326 }
327 pub fn get_promiscuous(&self) -> bool {
329 self.promisc
330 }
331 pub fn set_snaplen(&mut self, snaplen: usize) {
333 self.snaplen = snaplen;
334 self.pnet_rx = None;
336 }
337 pub fn get_snaplen(&self) -> usize {
339 self.snaplen
340 }
341 pub fn set_filter(&mut self, filter: &str) -> Result<(), PcaptureError> {
343 let filter = Filter::parser(filter)?;
344 self.filter = filter;
345 self.pnet_rx = None;
347 Ok(())
348 }
349 pub fn get_filter(&self) -> Option<String> {
351 if let Some(filter) = &self.filter {
352 Some(filter.input_str.to_string())
353 } else {
354 None
355 }
356 }
357 pub fn next(&'_ mut self) -> Result<PacketData<'_>, PcaptureError> {
359 if self.pnet_rx.is_none() {
360 let config = Config {
361 write_buffer_size: self.buffer_size, read_buffer_size: self.buffer_size, read_timeout: Some(self.timeout),
364 write_timeout: Some(self.timeout),
365 channel_type: ChannelType::Layer2,
366 bpf_fd_attempts: 1000,
367 linux_fanout: None,
368 promiscuous: self.promisc,
369 socket_fd: None,
370 };
371 let iface = &self.ifaces[self.iface_id as usize];
372 let (_pnet_tx, pnet_rx) = match datalink::channel(&iface.device.0, config) {
373 Ok(Ethernet(tx, rx)) => (tx, rx),
374 Ok(_) => return Err(PcaptureError::UnhandledChannelType),
375 Err(e) => return Err(PcaptureError::UnableCreateChannel { e: e.to_string() }),
376 };
377
378 self.pnet_rx = Some(pnet_rx);
379 }
380
381 if let Some(pnet_rx) = &mut self.pnet_rx {
382 let data = pnet_rx.next()?; let now = SystemTime::now().duration_since(UNIX_EPOCH)?;
384
385 #[cfg(feature = "pcap")]
386 let ts_sec = now.as_secs() as u32;
387 #[cfg(feature = "pcap")]
388 let ts_usec = now.subsec_micros();
389
390 #[cfg(feature = "pcapng")]
391 let ts64: u64 = now.as_secs() * 1_000_000 + now.subsec_micros() as u64;
392 #[cfg(feature = "pcapng")]
393 let ts_high = (ts64 >> 32) as u32;
394 #[cfg(feature = "pcapng")]
395 let ts_low = (ts64 & 0xFFFF_FFFF) as u32;
396
397 let packet_data = PacketData {
398 data,
399 #[cfg(feature = "pcap")]
400 ts_sec,
401 #[cfg(feature = "pcap")]
402 ts_usec,
403 #[cfg(feature = "pcapng")]
404 ts_high,
405 #[cfg(feature = "pcapng")]
406 ts_low,
407 };
408 Ok(packet_data)
409 } else {
410 unreachable!("pnet_rx must have value")
411 }
412 }
413 pub fn next_as_vec(&mut self) -> Result<Vec<u8>, PcaptureError> {
427 let filter = self.filter.clone();
428 loop {
429 let packet_data = match self.next() {
430 Ok(pd) => pd,
431 Err(e) => match e {
432 PcaptureError::IOError(e) => {
433 if e.kind() == ErrorKind::TimedOut {
434 continue;
435 } else {
436 return Err(e.into());
437 }
438 }
439 _ => return Err(e.into()),
440 },
441 };
442
443 match &filter {
444 Some(fls) => {
445 if fls.check(packet_data.data)? {
446 return Ok(packet_data.data.to_vec());
447 }
448 }
449 None => {
450 return Ok(packet_data.data.to_vec());
451 }
452 }
453 }
454 }
455 #[cfg(feature = "pcap")]
457 pub fn next_as_pcap(&mut self) -> Result<PacketRecord, PcaptureError> {
458 let filter = self.filter.clone();
459 let snaplen = self.snaplen;
460 loop {
461 let packet_data = match self.next() {
462 Ok(pd) => pd,
463 Err(e) => match e {
464 PcaptureError::IOError(e) => {
465 if e.kind() == ErrorKind::TimedOut {
466 continue;
467 } else {
468 return Err(e.into());
469 }
470 }
471 _ => return Err(e.into()),
472 },
473 };
474
475 match &filter {
476 Some(fls) => {
477 if fls.check(packet_data.data)? {
478 let pcap_record = PacketRecord::new(&packet_data.data, snaplen)?;
479 return Ok(pcap_record);
480 }
481 }
482 None => {
483 let pcap_record = PacketRecord::new(&packet_data.data, snaplen)?;
484 return Ok(pcap_record);
485 }
486 }
487 }
488 }
489 #[cfg(feature = "pcapng")]
491 pub fn next_as_pcapng(&mut self) -> Result<GeneralBlock, PcaptureError> {
492 let filter = self.filter.clone();
493 let snaplen = self.snaplen;
494 let iface_id = self.iface_id;
495
496 loop {
497 let packet_data = match self.next() {
498 Ok(pd) => pd,
499 Err(e) => match e {
500 PcaptureError::IOError(e) => {
501 if e.kind() == ErrorKind::TimedOut {
502 continue;
503 } else {
504 return Err(e.into());
505 }
506 }
507 _ => return Err(e.into()),
508 },
509 };
510
511 match &filter {
512 Some(fls) => {
513 if fls.check(packet_data.data)? {
514 let block = EnhancedPacketBlock::new(iface_id, &packet_data.data, snaplen)?;
515 let ret = GeneralBlock::EnhancedPacketBlock(block);
516 return Ok(ret);
517 }
518 }
519 None => {
520 let block = EnhancedPacketBlock::new(iface_id, &packet_data.data, snaplen)?;
521 let ret = GeneralBlock::EnhancedPacketBlock(block);
522 return Ok(ret);
523 }
524 }
525 }
526 }
527}
528
529#[cfg(all(unix, feature = "libpcap"))]
530#[derive(Debug, Clone)]
531pub struct Capture {
532 pub name: String,
533 buffer_size: usize,
534 timeout_ms: i32,
535 snaplen: usize,
536 promisc: bool,
537 immediate: bool,
538 filter: Option<String>,
540 #[cfg(feature = "pcapng")]
542 ifaces: Vec<Iface>,
543 #[cfg(feature = "pcapng")]
545 iface_id: u32,
546 lp: Option<Libpcap>,
548}
549
550#[cfg(all(unix, feature = "libpcap"))]
551impl Drop for Capture {
552 fn drop(&mut self) {
553 let _ = self.stop();
554 }
555}
556
557#[cfg(all(unix, feature = "libpcap"))]
558impl<'a> Capture {
559 pub fn new(name: &str) -> Result<Self, PcaptureError> {
596 let devices = Libpcap::devices()?;
597 let timeout_ms = DEFAULT_TIMEOUT_MS;
598 let buffer_size = DEFAULT_BUFFER_SIZE;
599 let snaplen = DETAULT_SNAPLEN;
600 let promisc = false;
601 let immediate = false;
602
603 let mut ifaces = Vec::new();
604 let mut i = 0;
605 #[cfg(feature = "pcapng")]
606 let mut iface_id = 0;
607 let mut interface_exists = false;
608 for device in devices {
609 if device.name == name {
610 #[cfg(feature = "pcapng")]
611 {
612 iface_id = i;
613 }
614 interface_exists = true;
615 }
616 let iface = Iface {
617 id: i as u32,
618 device,
619 };
620 ifaces.push(iface);
621 i += 1;
622 }
623
624 if !interface_exists {
625 let available_interface = ifaces
626 .iter()
627 .map(|iface| iface.device.name.clone())
628 .collect::<Vec<String>>()
629 .join(", ");
630
631 return Err(PcaptureError::InterfaceNotFound {
632 name: name.to_string(),
633 available_interface,
634 });
635 }
636
637 let filter = None;
638 let lp = Libpcap::new(
639 name,
640 snaplen as i32,
641 promisc,
642 immediate,
643 timeout_ms,
644 buffer_size as i32,
645 filter,
646 )?;
647
648 Ok(Self {
649 name: name.to_string(),
650 buffer_size,
651 timeout_ms,
652 snaplen,
653 promisc,
654 immediate,
655 #[cfg(feature = "pcapng")]
656 ifaces,
657 #[cfg(feature = "pcapng")]
658 iface_id,
659 filter: None,
660 lp: Some(lp),
661 })
662 }
663 #[cfg(feature = "pcap")]
665 pub fn gen_pcap_header(&self, pbo: PcapByteOrder) -> Result<Pcap, PcaptureError> {
666 let pcap = Pcap::new(&self.name, pbo);
667 Ok(pcap)
668 }
669 #[cfg(feature = "pcapng")]
671 pub fn gen_pcapng_header(&self, pbo: PcapByteOrder) -> Result<PcapNg, PcaptureError> {
672 let pcapng = PcapNg::new(&self.ifaces, pbo);
673 Ok(pcapng)
674 }
675 pub fn set_buffer_size(&mut self, buffer_size: usize) {
677 self.buffer_size = buffer_size;
678 self.lp = None;
680 }
681 pub fn get_buffer_size(&self) -> usize {
683 self.buffer_size
684 }
685 pub fn set_timeout(&mut self, timeout_ms: i32) {
687 self.timeout_ms = timeout_ms;
688 self.lp = None;
690 }
691 pub fn get_timeout(&self) -> i32 {
693 self.timeout_ms
694 }
695 pub fn set_promiscuous_mode(&mut self, promiscuous: bool) {
697 self.promisc = promiscuous;
698 self.lp = None;
700 }
701 pub fn get_promiscuous_mode(&self) -> bool {
703 self.promisc
704 }
705 pub fn set_immediate_mode(&mut self, immediate: bool) {
707 self.immediate = immediate;
708 self.lp = None;
710 }
711 pub fn get_immediate_mode(&self) -> bool {
713 self.immediate
714 }
715 pub fn set_snaplen(&mut self, snaplen: usize) {
717 self.snaplen = snaplen;
718 self.lp = None;
720 }
721 pub fn get_snaplen(&self) -> usize {
723 self.snaplen
724 }
725 pub fn set_filter(&mut self, filter: &str) {
727 self.filter = Some(filter.to_string());
728 self.lp = None;
730 }
731 pub fn get_filter(&self) -> Option<String> {
733 self.filter.clone()
734 }
735 pub fn fetch(&mut self) -> Result<Vec<PacketData<'_>>, PcaptureError> {
737 if self.lp.is_none() {
738 let lp = Libpcap::new(
739 &self.name,
740 self.snaplen as i32,
741 self.promisc,
742 self.immediate,
743 self.timeout_ms,
744 self.buffer_size as i32,
745 self.filter.clone(),
746 )?;
747 self.lp = Some(lp);
748 }
749
750 if let Some(lp) = &mut self.lp {
751 let packets = lp.fetch()?;
752 Ok(packets)
753 } else {
754 unreachable!("lp must have a value here");
755 }
756 }
757 pub fn stop(&mut self) -> Result<(), PcaptureError> {
760 if let Some(libpcap) = &mut self.lp {
761 let _ = libpcap.stop()?;
762 }
763 Ok(())
764 }
765 pub fn fetch_as_vec(&'a mut self) -> Result<Vec<&'a [u8]>, PcaptureError> {
782 let packets = self.fetch()?;
783 let mut ret = Vec::new();
784 for p in packets {
785 ret.push(p.data)
786 }
787 return Ok(ret);
788 }
789 #[cfg(feature = "pcap")]
791 pub fn fetch_as_pcap(&mut self) -> Result<Vec<PacketRecord>, PcaptureError> {
792 let snaplen = self.snaplen as usize;
793 let packets = self.fetch()?;
794
795 let mut ret = Vec::new();
796 for p in packets {
797 let data = p.data;
798 let ts_sec = p.ts_sec;
799 let ts_usec = p.ts_usec;
800 let pcap_record = PacketRecord::new(data, snaplen, ts_sec, ts_usec)?;
801 ret.push(pcap_record);
802 }
803 return Ok(ret);
804 }
805 #[cfg(feature = "pcapng")]
807 pub fn fetch_as_pcapng(&mut self) -> Result<Vec<GeneralBlock>, PcaptureError> {
808 let snaplen = self.snaplen as usize;
809 let iface_id = self.iface_id;
810 let packets = self.fetch()?;
811
812 let mut ret = Vec::new();
813 for p in packets {
814 let data = p.data;
815 let ts_high = p.ts_high;
816 let ts_low = p.ts_low;
817 let block = EnhancedPacketBlock::new(iface_id, data, snaplen, ts_high, ts_low)?;
818 let block = GeneralBlock::EnhancedPacketBlock(block);
819 ret.push(block);
820 }
821
822 return Ok(ret);
823 }
824}
825
826#[cfg(all(unix, feature = "libpcap"))]
827#[cfg(test)]
828mod tests {
829 use super::*;
830 #[test]
831 fn capture_raw() {
832 let mut cap = Capture::new("ens33").unwrap();
833 cap.set_buffer_size(4096);
834 for i in 0..5 {
835 let packet_raw = cap.fetch_as_vec().unwrap();
836 println!("fetch[{}], packets num: {}", i, packet_raw.len());
837 }
838 }
839 #[cfg(feature = "pcap")]
840 #[test]
841 fn capture_pcap() {
842 let path = "test_ens33.pcap";
843 let pbo = PcapByteOrder::WiresharkDefault;
844
845 let mut cap = Capture::new("ens33").unwrap();
846 cap.set_buffer_size(4096);
847 let mut pcap = cap.gen_pcap_header(pbo).unwrap();
848
849 let mut packet_count = 0;
850 for _ in 0..5 {
851 let record = cap.fetch_as_pcap().unwrap();
852 for r in record {
853 pcap.append(r);
854 packet_count += 1;
855 }
856 }
857 println!("packet count: {}", packet_count);
858
859 pcap.write_all(path).unwrap();
861
862 let read_pcap = Pcap::read_all(path, pbo).unwrap();
863 assert_eq!(read_pcap.records.len(), packet_count);
864 }
865 #[cfg(feature = "pcap")]
866 #[test]
867 fn capture_pcap_any() {
868 let path = "test_any.pcap";
869 let pbo = PcapByteOrder::WiresharkDefault;
870
871 let mut cap = Capture::new("any").unwrap();
872 cap.set_buffer_size(4096);
873 let mut pcap = cap.gen_pcap_header(pbo).unwrap();
874
875 let mut packet_count = 0;
876 for _ in 0..5 {
877 let record = cap.fetch_as_pcap().unwrap();
878 for r in record {
879 pcap.append(r);
880 packet_count += 1;
881 }
882 }
883 println!("packet count: {}", packet_count);
884
885 pcap.write_all(path).unwrap();
887
888 let read_pcap = Pcap::read_all(path, pbo).unwrap();
889 assert_eq!(read_pcap.records.len(), packet_count);
890 }
891
892 #[cfg(feature = "pcapng")]
893 #[test]
894 fn capture_pcapng() {
895 let path = "test_ens33.pcapng";
896 let pbo = PcapByteOrder::WiresharkDefault;
897
898 let mut cap = Capture::new("ens33").unwrap();
899 cap.set_buffer_size(4096);
900 cap.set_timeout(1);
901 cap.set_promiscuous_mode(true);
902 cap.set_snaplen(65535);
903
904 let mut pcapng = cap.gen_pcapng_header(pbo).unwrap();
905
906 println!("pcapng header len: {}", pcapng.blocks.len());
909
910 let mut packets_count = pcapng.blocks.len();
911 for _ in 0..5 {
912 let blocks = cap.fetch_as_pcapng().unwrap();
913 for b in blocks {
914 pcapng.append(b);
915 packets_count += 1;
916 }
917 }
918
919 pcapng.write_all(path).unwrap();
920
921 let read_pcapng = PcapNg::read_all(path, pbo).unwrap();
922 assert_eq!(read_pcapng.blocks.len(), packets_count);
924 }
925 #[cfg(feature = "pcapng")]
926 #[test]
927 fn capture_pcapng_any() {
928 let path = "test_any.pcapng";
929 let pbo = PcapByteOrder::WiresharkDefault;
930
931 let mut cap = Capture::new("any").unwrap();
932 cap.set_buffer_size(4096);
933 cap.set_timeout(1);
934 cap.set_promiscuous_mode(false);
935 cap.set_snaplen(65535);
936
937 let mut pcapng = cap.gen_pcapng_header(pbo).unwrap();
938
939 println!("pcapng header len: {}", pcapng.blocks.len());
942
943 let mut packets_count = pcapng.blocks.len();
944 for _ in 0..5 {
945 let blocks = cap.fetch_as_pcapng().unwrap();
946 for b in blocks {
947 pcapng.append(b);
948 packets_count += 1;
949 }
950 }
951
952 pcapng.write_all(path).unwrap();
953
954 let read_pcapng = PcapNg::read_all(path, pbo).unwrap();
955 assert_eq!(read_pcapng.blocks.len(), packets_count);
957 }
958 #[cfg(feature = "pcapng")]
959 #[test]
960 fn capture_pcapng_filter() {
961 let path = "test_filter.pcapng";
962 let pbo = PcapByteOrder::WiresharkDefault;
963 let filter = "host 192.168.5.2";
966
967 let mut cap = Capture::new("ens33").unwrap();
968 cap.set_filter(filter);
969
970 let mut pcapng = cap.gen_pcapng_header(pbo).unwrap();
971 for i in 0..5 {
972 println!("i: {}", i);
973 let block = cap.fetch_as_pcapng().unwrap();
974 for b in block {
975 pcapng.append(b);
976 }
977 }
978
979 pcapng.write_all(path).unwrap();
980 }
981 #[ignore]
982 #[test]
983 fn block_read() {
984 let pbo = PcapByteOrder::WiresharkDefault;
985 let path = "1.pcapng";
986 let read_pcapng = PcapNg::read_all(path, pbo).unwrap();
987 println!("blocks num: {}", read_pcapng.blocks.len());
988 for b in read_pcapng.blocks {
989 println!("block type: {}", b.name());
990 }
991 }
992}
993
994#[cfg(feature = "libpnet")]
995#[cfg(test)]
996mod tests {
997 use super::*;
998 #[test]
999 fn capture_raw() {
1000 let mut cap = Capture::new("ens33").unwrap();
1001 cap.set_buffer_size(4096);
1002 for i in 0..5 {
1003 let packet_raw = cap.next_as_vec().unwrap();
1004 println!("fetch[{}], packets num: {}", i, packet_raw.len());
1005 }
1006 }
1007 #[cfg(feature = "pcap")]
1008 #[test]
1009 fn capture_pcap() {
1010 let path = "test_ens33.pcap";
1011 let pbo = PcapByteOrder::WiresharkDefault;
1012
1013 let mut cap = Capture::new("ens33").unwrap();
1014 cap.set_buffer_size(4096);
1015 let mut pcap = cap.gen_pcap_header(pbo).unwrap();
1016
1017 let mut packet_count = 0;
1018 for _ in 0..5 {
1019 let record = cap.next_as_pcap().unwrap();
1020 pcap.append(record);
1021 packet_count += 1;
1022 }
1023 println!("packet count: {}", packet_count);
1024
1025 pcap.write_all(path).unwrap();
1027
1028 let read_pcap = Pcap::read_all(path, pbo).unwrap();
1029 assert_eq!(read_pcap.records.len(), packet_count);
1030 }
1031 #[cfg(feature = "pcapng")]
1032 #[test]
1033 fn capture_pcapng() {
1034 let path = "test_ens33.pcapng";
1035 let pbo = PcapByteOrder::WiresharkDefault;
1036
1037 let mut cap = Capture::new("ens33").unwrap();
1038 cap.set_buffer_size(4096);
1039 cap.set_timeout(1.0);
1040 cap.set_promiscuous(true);
1041 cap.set_snaplen(65535);
1042
1043 let mut pcapng = cap.gen_pcapng_header(pbo).unwrap();
1044
1045 println!("pcapng header len: {}", pcapng.blocks.len());
1048
1049 let mut packets_count = pcapng.blocks.len();
1050 for _ in 0..5 {
1051 let block = cap.next_as_pcapng().unwrap();
1052 pcapng.append(block);
1053 packets_count += 1;
1054 }
1055
1056 pcapng.write_all(path).unwrap();
1057
1058 let read_pcapng = PcapNg::read_all(path, pbo).unwrap();
1059 assert_eq!(read_pcapng.blocks.len(), packets_count);
1061 }
1062 #[cfg(feature = "pcapng")]
1063 #[test]
1064 fn capture_pcapng_filter() {
1065 let path = "test_filter.pcapng";
1066 let pbo = PcapByteOrder::WiresharkDefault;
1067 let filter_str = "icmp and ip=192.168.5.2";
1070
1071 let mut cap = Capture::new("ens33").unwrap();
1072 cap.set_filter(filter_str).unwrap();
1073
1074 let mut pcapng = cap.gen_pcapng_header(pbo).unwrap();
1075 for i in 0..5 {
1076 println!("i: {}", i);
1077 let block = cap.next_as_pcapng().unwrap();
1078 pcapng.append(block);
1079 }
1080
1081 pcapng.write_all(path).unwrap();
1082 }
1083}