Skip to main content

stackforge_core/sniffer/
config.rs

1use std::time::Duration;
2
3/// Configuration for a packet capture session.
4#[derive(Debug, Clone)]
5pub struct SnifferConfig {
6    /// Network interface name (e.g., "en0", "eth0", "lo0").
7    pub iface: String,
8    /// BPF filter string (e.g., "tcp port 80").
9    pub filter: Option<String>,
10    /// Maximum number of packets to capture. 0 means unlimited.
11    pub count: usize,
12    /// Capture timeout. `None` means no timeout.
13    pub timeout: Option<Duration>,
14    /// Snapshot length — max bytes captured per packet.
15    pub snaplen: i32,
16    /// Whether to enable promiscuous mode.
17    pub promisc: bool,
18    /// Channel buffer capacity (number of packets).
19    pub channel_capacity: usize,
20}
21
22impl Default for SnifferConfig {
23    fn default() -> Self {
24        Self {
25            iface: default_iface(),
26            filter: None,
27            count: 0,
28            timeout: None,
29            snaplen: 65535,
30            promisc: true,
31            channel_capacity: 4096,
32        }
33    }
34}
35
36impl SnifferConfig {
37    #[must_use]
38    pub fn new(iface: impl Into<String>) -> Self {
39        Self {
40            iface: iface.into(),
41            ..Default::default()
42        }
43    }
44
45    #[must_use]
46    pub fn filter(mut self, filter: impl Into<String>) -> Self {
47        self.filter = Some(filter.into());
48        self
49    }
50
51    #[must_use]
52    pub fn count(mut self, count: usize) -> Self {
53        self.count = count;
54        self
55    }
56
57    #[must_use]
58    pub fn timeout(mut self, timeout: Duration) -> Self {
59        self.timeout = Some(timeout);
60        self
61    }
62
63    #[must_use]
64    pub fn snaplen(mut self, snaplen: i32) -> Self {
65        self.snaplen = snaplen;
66        self
67    }
68
69    #[must_use]
70    pub fn promisc(mut self, promisc: bool) -> Self {
71        self.promisc = promisc;
72        self
73    }
74
75    #[must_use]
76    pub fn channel_capacity(mut self, capacity: usize) -> Self {
77        self.channel_capacity = capacity;
78        self
79    }
80}
81
82/// Returns a sensible default interface name for the current platform.
83fn default_iface() -> String {
84    // Try to find the default network interface
85    if let Some(iface) = default_net::get_default_interface().ok() {
86        return iface.name;
87    }
88
89    // Fallback based on platform
90    if cfg!(target_os = "macos") {
91        "en0".to_string()
92    } else if cfg!(target_os = "linux") {
93        "eth0".to_string()
94    } else {
95        "lo".to_string()
96    }
97}