diff --git a/src/cli/mod.rs b/src/cli/mod.rs index 999c97f2..13323acd 100644 --- a/src/cli/mod.rs +++ b/src/cli/mod.rs @@ -158,7 +158,7 @@ fn test_restore_default_configs() { expanded: true, }, import_pcap_path: "whole_day.pcapng".to_string(), - ipfix_collector: Default::default(), + ipfix_socket: Default::default(), export_pcap: ExportPcap { enabled: true, file_name: "sniffnet.pcap".to_string(), diff --git a/src/gui/pages/initial_page.rs b/src/gui/pages/initial_page.rs index c7549162..76ff86e3 100644 --- a/src/gui/pages/initial_page.rs +++ b/src/gui/pages/initial_page.rs @@ -14,7 +14,7 @@ use crate::gui::types::filters::Filters; use crate::gui::types::message::Message; use crate::gui::types::settings::Settings; -use crate::networking::ipfix::IpfixCollectorConf; +use crate::networking::ipfix::MyIpfixSocket; use crate::networking::types::capture_context::{CaptureSource, CaptureSourcePicklist}; use crate::networking::types::my_device::MyDevice; use crate::networking::types::my_link_type::MyLinkType; @@ -163,7 +163,7 @@ fn get_col_data_source(sniffer: &Sniffer, language: Language) -> Column<'_, Mess CaptureSourcePicklist::Ipfix => { col = col.push(get_col_ipfix_collector( language, - &sniffer.conf.ipfix_collector, + &sniffer.conf.ipfix_socket, )); } } @@ -319,7 +319,7 @@ fn get_col_import_pcap<'a>( fn get_col_ipfix_collector<'a>( language: Language, - conf: &IpfixCollectorConf, + ipfix_socket: &MyIpfixSocket, ) -> Column<'a, Message, StyleType> { let addr_row = Row::new() .align_y(Alignment::Center) @@ -329,8 +329,8 @@ fn get_col_ipfix_collector<'a>( bind_address_translation(language) ))) .push( - TextInput::new("0.0.0.0", &conf.bind_addr) - .on_input(Message::SetIpfixBindAddr) + TextInput::new("0.0.0.0", &ipfix_socket.addr()) + .on_input(Message::SetIpfixAddr) .padding([2, 5]), ); let port_row = Row::new() @@ -338,8 +338,8 @@ fn get_col_ipfix_collector<'a>( .spacing(5) .push(Text::new(format!("{}:", port_translation(language)))) .push( - TextInput::new("4739", &conf.bind_port.to_string()) - .on_input(Message::SetIpfixBindPort) + TextInput::new("4739", &ipfix_socket.port()) + .on_input(Message::SetIpfixPort) .padding([2, 5]), ); let content = Column::new() diff --git a/src/gui/pages/waiting_page.rs b/src/gui/pages/waiting_page.rs index 0fa104b9..22980928 100644 --- a/src/gui/pages/waiting_page.rs +++ b/src/gui/pages/waiting_page.rs @@ -37,6 +37,12 @@ pub fn waiting_page(sniffer: &Sniffer) -> Option Task { Message::ScaleFactorShortcut(increase) => self.scale_factor_shortcut(increase), Message::SetNewerReleaseStatus(status) => self.set_newer_release_status(status), Message::SetPcapImport(path) => self.set_pcap_import(path), - Message::SetIpfixBindAddr(addr) => self.set_ipfix_bind_addr(addr), - Message::SetIpfixBindPort(port) => self.set_ipfix_bind_port(&port), + Message::SetIpfixAddr(addr) => self.set_ipfix_addr(addr), + Message::SetIpfixPort(port) => self.set_ipfix_port(port), Message::PendingHosts(cap_id, host_msgs) => self.pending_hosts(cap_id, host_msgs), Message::OfflineGap(cap_id, gap) => self.offline_gap(cap_id, gap), Message::Periodic => self.periodic(), @@ -507,8 +506,7 @@ fn set_capture_source(&mut self, cs_pick: CaptureSourcePicklist) { self.set_pcap_import(self.conf.import_pcap_path.clone()); } CaptureSourcePicklist::Ipfix => { - self.capture_source = - CaptureSource::Ipfix(MyIpfixCollector::from_conf(&self.conf.ipfix_collector)); + self.capture_source = CaptureSource::Ipfix(self.conf.ipfix_socket.clone()); } CaptureSourcePicklist::Device => { self.device_selection(&self.conf.device.device_name.clone()); @@ -820,24 +818,14 @@ fn set_pcap_import(&mut self, path: String) { } } - fn set_ipfix_bind_addr(&mut self, addr: String) { - self.conf.ipfix_collector.bind_addr = addr; - self.capture_source = - CaptureSource::Ipfix(MyIpfixCollector::from_conf(&self.conf.ipfix_collector)); + fn set_ipfix_addr(&mut self, addr: String) { + self.conf.ipfix_socket.set_addr(addr); + self.capture_source = CaptureSource::Ipfix(self.conf.ipfix_socket.clone()); } - fn set_ipfix_bind_port(&mut self, raw: &str) { - // Accept anything that parses as u16; ignore other input so the user can - // edit the field freely without losing focus. - if let Ok(port) = raw.parse::() { - self.conf.ipfix_collector.bind_port = port; - self.capture_source = - CaptureSource::Ipfix(MyIpfixCollector::from_conf(&self.conf.ipfix_collector)); - } else if raw.is_empty() { - self.conf.ipfix_collector.bind_port = 0; - self.capture_source = - CaptureSource::Ipfix(MyIpfixCollector::from_conf(&self.conf.ipfix_collector)); - } + fn set_ipfix_port(&mut self, port: String) { + self.conf.ipfix_socket.set_port(port); + self.capture_source = CaptureSource::Ipfix(self.conf.ipfix_socket.clone()); } fn pending_hosts(&mut self, cap_id: usize, host_msgs: Vec) { @@ -1000,9 +988,6 @@ fn start(&mut self) -> Task { let current_device_name = &self.capture_source.get_name(); self.device_selection(current_device_name); } - if matches!(&self.capture_source, CaptureSource::Ipfix(_)) { - return self.start_ipfix(); - } let pcap_path = self.conf.export_pcap.full_path(); let capture_context = CaptureContext::new(&self.capture_source, pcap_path.as_ref(), &self.conf.filters); @@ -1018,27 +1003,46 @@ fn start(&mut self) -> Task { .set_link_type(capture_context.my_link_type()); self.capture_source.set_addresses(); let capture_source = self.capture_source.clone(); - self.traffic_chart - .change_capture_source(matches!(capture_source, CaptureSource::Device(_))); + self.traffic_chart.change_capture_source(matches!( + capture_source, + CaptureSource::Device(_) | CaptureSource::Ipfix(_) + )); let (tx, rx) = async_channel::unbounded(); let (freeze_tx, freeze_rx) = tokio::sync::broadcast::channel(1_048_575); let freeze_rx2 = freeze_tx.subscribe(); let filters = self.conf.filters.clone(); - let _ = thread::Builder::new() - .name("thread_parse_packets".to_string()) - .spawn(move || { - parse_packets( - curr_cap_id, - capture_source, - mmdb_readers, - &ip_blacklist, - capture_context, - filters, - &tx, - (freeze_rx, freeze_rx2), - ); - }) - .log_err(location!()); + if let CaptureSource::Ipfix(collector) = &self.capture_source { + let collector = collector.clone(); + let _ = thread::Builder::new() + .name("thread_collect_ipfix".to_string()) + .spawn(move || { + collect_ipfix( + curr_cap_id, + capture_context, + mmdb_readers, + &ip_blacklist, + &tx, + (freeze_rx, freeze_rx2), + ); + }) + .log_err(location!()); + } else { + let _ = thread::Builder::new() + .name("thread_parse_packets".to_string()) + .spawn(move || { + parse_packets( + curr_cap_id, + capture_source, + mmdb_readers, + &ip_blacklist, + capture_context, + filters, + &tx, + (freeze_rx, freeze_rx2), + ); + }) + .log_err(location!()); + } self.current_capture_rx.1 = Some(rx.clone()); self.freeze_tx = Some(freeze_tx); @@ -1085,47 +1089,6 @@ fn start(&mut self) -> Task { Task::none() } - fn start_ipfix(&mut self) -> Task { - let CaptureSource::Ipfix(collector) = self.capture_source.clone() else { - return Task::none(); - }; - self.pcap_error = None; - self.running_page = Some(self.conf.last_opened_page); - - let curr_cap_id = self.current_capture_rx.0; - let mmdb_readers = self.mmdb_readers.clone(); - let ip_blacklist = self.ip_blacklist.clone(); - self.traffic_chart.change_capture_source(true); - let (tx, rx) = async_channel::unbounded(); - let (freeze_tx, freeze_rx) = tokio::sync::broadcast::channel(1_048_575); - let freeze_rx2 = freeze_tx.subscribe(); - let _ = thread::Builder::new() - .name("thread_collect_ipfix".to_string()) - .spawn(move || { - collect_ipfix( - curr_cap_id, - &collector, - mmdb_readers, - &ip_blacklist, - &tx, - (freeze_rx, freeze_rx2), - ); - }) - .log_err(location!()); - self.current_capture_rx.1 = Some(rx.clone()); - self.freeze_tx = Some(freeze_tx); - - Task::run(rx, |backend_msg| match backend_msg { - BackendTrafficMessage::TickRun(cap_id, msg, host_msg, no_more_packets) => { - Message::TickRun(cap_id, msg, host_msg, no_more_packets) - } - BackendTrafficMessage::PendingHosts(cap_id, host_msg) => { - Message::PendingHosts(cap_id, host_msg) - } - BackendTrafficMessage::OfflineGap(cap_id, gap) => Message::OfflineGap(cap_id, gap), - }) - } - fn reset(&mut self) -> Task { // close capture channel to kill previous captures if let Some(rx) = &self.current_capture_rx.1 { @@ -1480,8 +1443,8 @@ fn register_sigint_handler() -> Task { pub fn is_capture_source_consistent(&self) -> bool { match (self.conf.capture_source_picklist, &self.capture_source) { (CaptureSourcePicklist::Device, CaptureSource::Device(_)) - | (CaptureSourcePicklist::File, CaptureSource::File(_)) => true, - (CaptureSourcePicklist::Ipfix, CaptureSource::Ipfix(c)) => c.is_valid(), + | (CaptureSourcePicklist::File, CaptureSource::File(_)) + | (CaptureSourcePicklist::Ipfix, CaptureSource::Ipfix(_)) => true, _ => false, } } @@ -2278,7 +2241,7 @@ fn test_conf() { directory: "/".to_string() }, import_pcap_path: "/test.pcap".to_string(), - ipfix_collector: Default::default(), + ipfix_socket: Default::default(), data_repr: DataRepr::Bits, } ); diff --git a/src/gui/types/conf.rs b/src/gui/types/conf.rs index 2b712158..b96eeffb 100644 --- a/src/gui/types/conf.rs +++ b/src/gui/types/conf.rs @@ -5,7 +5,7 @@ use crate::gui::types::favorite::Favorites; use crate::gui::types::filters::Filters; use crate::gui::types::settings::Settings; -use crate::networking::ipfix::IpfixCollectorConf; +use crate::networking::ipfix::MyIpfixSocket; use crate::networking::types::capture_context::CaptureSourcePicklist; use crate::networking::types::config_device::ConfigDevice; use crate::networking::types::data_representation::DataRepr; @@ -48,9 +48,6 @@ pub struct Conf { /// Import path for PCAP file #[serde(deserialize_with = "deserialize_or_default")] pub import_pcap_path: String, - /// IPFIX collector configuration (bind address and port) - #[serde(deserialize_with = "deserialize_or_default")] - pub ipfix_collector: IpfixCollectorConf, /// Remembers the last opened setting page #[serde(deserialize_with = "deserialize_or_default")] pub last_opened_setting: SettingsPage, @@ -94,6 +91,9 @@ pub struct Conf { /// Information about PCAP file export #[serde(deserialize_with = "deserialize_or_default")] pub export_pcap: ExportPcap, + /// IPFIX collector configuration (bind address and port) + #[serde(deserialize_with = "deserialize_or_default")] + pub ipfix_socket: MyIpfixSocket, /// Parameters from settings pages #[serde(deserialize_with = "deserialize_or_default")] pub settings: Settings, diff --git a/src/gui/types/message.rs b/src/gui/types/message.rs index 3699e0f0..656ca7ce 100644 --- a/src/gui/types/message.rs +++ b/src/gui/types/message.rs @@ -146,9 +146,9 @@ pub enum Message { /// Set the pcap import path SetPcapImport(String), /// Set the IPFIX collector bind address - SetIpfixBindAddr(String), + SetIpfixAddr(String), /// Set the IPFIX collector bind port - SetIpfixBindPort(String), + SetIpfixPort(String), /// Sent by the backend parsing packets at the end of an offline capture; includes all the pending hosts PendingHosts(usize, Vec), /// Sent by offline captures: ticks without packets diff --git a/src/networking/ipfix/collect.rs b/src/networking/ipfix/collect.rs index 24cd5848..bced0b21 100644 --- a/src/networking/ipfix/collect.rs +++ b/src/networking/ipfix/collect.rs @@ -11,7 +11,7 @@ use crate::location; use crate::mmdb::types::mmdb_reader::MmdbReaders; -use crate::networking::ipfix::MyIpfixCollector; +use crate::networking::ipfix::MyIpfixSocket; use crate::networking::ipfix::templates::TemplateCache; use crate::networking::ipfix::wire::{ self, FlowRecord, IPFIX_VERSION, Set, decode_data_record, format_mac, parse_message, @@ -25,6 +25,7 @@ use crate::networking::types::address_port_pair::AddressPortPair; use crate::networking::types::arp_type::ArpType; use crate::networking::types::bogon::is_bogon; +use crate::networking::types::capture_context::{CaptureContext, CaptureType}; use crate::networking::types::data_info::DataInfo; use crate::networking::types::data_info_host::DataInfoHost; use crate::networking::types::icmp_type::IcmpType; @@ -47,7 +48,7 @@ /// second with the accumulated `InfoTraffic`. pub fn collect_ipfix( cap_id: usize, - collector: &MyIpfixCollector, + capture_context: CaptureContext, mmdb_readers: MmdbReaders, ip_blacklist: &IpBlacklist, tx: &Sender, @@ -55,19 +56,9 @@ pub fn collect_ipfix( ) { let (mut freeze_rx, _freeze_rx_2) = freeze_rxs; - let Some(bind) = collector.socket_addr() else { + let (Some(CaptureType::Ipfix(socket)), None) = capture_context.consume() else { return; }; - let Ok(socket) = UdpSocket::bind(bind).log_err(location!()) else { - return; - }; - if socket - .set_read_timeout(Some(RECV_TIMEOUT)) - .log_err(location!()) - .is_err() - { - return; - } let mut info_traffic_msg = InfoTraffic::default(); let mut templates = TemplateCache::new(); @@ -416,6 +407,10 @@ fn build_key(record: &FlowRecord) -> Option { /// Build a `[Address]` slice carrying just the exporter's IP, so direction /// classification treats the exporter as the local anchor. fn exporter_as_addresses(peer: IpAddr) -> Vec
{ + if peer.is_loopback() || peer.is_unspecified() { + return vec![]; + } + vec![Address { addr: peer, netmask: None, diff --git a/src/networking/ipfix/mod.rs b/src/networking/ipfix/mod.rs index 436d8256..3d7ff93e 100644 --- a/src/networking/ipfix/mod.rs +++ b/src/networking/ipfix/mod.rs @@ -9,8 +9,11 @@ pub mod templates; pub mod wire; +use crate::location; +use crate::utils::error_logger::ErrorLogger; use serde::{Deserialize, Serialize}; -use std::net::{IpAddr, SocketAddr}; +use std::net::{IpAddr, Ipv4Addr, SocketAddr, UdpSocket}; +use std::time::Duration; /// IANA-registered default IPFIX collector port. pub const DEFAULT_IPFIX_PORT: u16 = 4739; @@ -18,52 +21,50 @@ /// Persisted IPFIX collector configuration. #[derive(Serialize, Deserialize, Clone, PartialEq, Debug)] #[serde(default)] -pub struct IpfixCollectorConf { - pub bind_addr: String, - pub bind_port: u16, +pub struct MyIpfixSocket { + addr: String, + port: String, } -impl Default for IpfixCollectorConf { - fn default() -> Self { - Self { - bind_addr: String::from("0.0.0.0"), - bind_port: DEFAULT_IPFIX_PORT, - } - } -} - -/// Runtime handle for an IPFIX collector source, embedded in `CaptureSource::Ipfix`. -#[derive(Clone, Debug)] -pub struct MyIpfixCollector { - bind_addr: String, - bind_port: u16, -} - -impl MyIpfixCollector { - pub fn new(bind_addr: String, bind_port: u16) -> Self { - Self { - bind_addr, - bind_port, - } +impl MyIpfixSocket { + pub fn addr(&self) -> &str { + &self.addr } - pub fn from_conf(conf: &IpfixCollectorConf) -> Self { - Self::new(conf.bind_addr.clone(), conf.bind_port) + pub fn port(&self) -> &str { + &self.port } - /// Parse the configured bind address + port into a `SocketAddr`. Returns - /// `None` if `bind_addr` is not a valid IP literal. - pub fn socket_addr(&self) -> Option { - let ip: IpAddr = self.bind_addr.parse().ok()?; - Some(SocketAddr::new(ip, self.bind_port)) + pub fn set_addr(&mut self, addr: String) { + self.addr = addr; } - /// Whether the current config can be used to start a capture. - pub fn is_valid(&self) -> bool { - self.socket_addr().is_some() + pub fn set_port(&mut self, port: String) { + self.port = port; } pub fn display_name(&self) -> String { - format!("{}:{}", self.bind_addr, self.bind_port) + format!("{}:{}", self.addr, self.port) + } + + pub fn socket_addr(&self) -> Result { + let port = self + .port + .parse::() + .map_err(|_| format!("Invalid port number: {}", self.port))?; + let ip_addr = self + .addr + .parse::() + .map_err(|_| format!("Invalid IP address: {}", self.addr))?; + Ok(SocketAddr::new(ip_addr, port)) + } +} + +impl Default for MyIpfixSocket { + fn default() -> Self { + Self { + addr: IpAddr::V4(Ipv4Addr::UNSPECIFIED).to_string(), + port: DEFAULT_IPFIX_PORT.to_string(), + } } } diff --git a/src/networking/parse_packets.rs b/src/networking/parse_packets.rs index d2598d90..993a45ad 100644 --- a/src/networking/parse_packets.rs +++ b/src/networking/parse_packets.rs @@ -309,8 +309,6 @@ pub(super) fn get_sniffable_headers( MyLinkType::LinuxSll(_) => from_linux_sll(packet, true), MyLinkType::LinuxSll2(_) => from_linux_sll(packet, false), MyLinkType::Null(_) | MyLinkType::Loop(_) => from_null(packet), - // IPFIX never flows through this pcap-based path. - MyLinkType::Ipfix => None, } } diff --git a/src/networking/types/capture_context.rs b/src/networking/types/capture_context.rs index 51074b34..79042259 100644 --- a/src/networking/types/capture_context.rs +++ b/src/networking/types/capture_context.rs @@ -1,7 +1,7 @@ use crate::gui::types::conf::Conf; use crate::gui::types::filters::Filters; use crate::location; -use crate::networking::ipfix::MyIpfixCollector; +use crate::networking::ipfix::MyIpfixSocket; use crate::networking::types::my_device::MyDevice; use crate::networking::types::my_link_type::MyLinkType; use crate::translations::translations::network_adapter_translation; @@ -11,11 +11,14 @@ use crate::utils::error_logger::{ErrorLogger, Location}; use pcap::{Active, Address, Capture, Device, Error, Packet, Savefile, Stat}; use serde::{Deserialize, Serialize}; +use std::net::UdpSocket; +use std::time::Duration; pub enum CaptureContext { Live(Live), LiveWithSavefile(LiveWithSavefile), Offline(Offline), + Ipfix(Ipfix), Error(String), } @@ -23,7 +26,7 @@ impl CaptureContext { pub fn new(source: &CaptureSource, pcap_out_path: Option<&String>, filters: &Filters) -> Self { let mut cap_type = match CaptureType::from_source(source, pcap_out_path) { Ok(c) => c, - Err(e) => return Self::Error(e.to_string()), + Err(e) => return Self::Error(e), }; // only apply BPF filter if it is active, and return an error if it fails to apply @@ -36,6 +39,7 @@ pub fn new(source: &CaptureSource, pcap_out_path: Option<&String>, filters: &Fil let cap = match cap_type { CaptureType::Live(cap) => cap, CaptureType::Offline(cap) => return Self::new_offline(cap), + CaptureType::Ipfix(socket) => return Self::Ipfix(Ipfix { socket }), }; if let Some(out_path) = pcap_out_path { @@ -78,6 +82,7 @@ pub fn consume(self) -> (Option, Option) { (Some(CaptureType::Live(onws.live.cap)), Some(onws.savefile)) } Self::Offline(off) => (Some(CaptureType::Offline(off.cap)), None), + Self::Ipfix(ipfix) => (Some(CaptureType::Ipfix(ipfix.socket)), None), Self::Error(_) => (None, None), } } @@ -89,6 +94,7 @@ pub fn my_link_type(&self) -> MyLinkType { MyLinkType::from_pcap_link_type(onws.live.cap.get_datalink()) } Self::Offline(off) => MyLinkType::from_pcap_link_type(off.cap.get_datalink()), + Self::Ipfix(_) => MyLinkType::default(), Self::Error(_) => MyLinkType::default(), } } @@ -107,9 +113,14 @@ pub struct Offline { cap: Capture, } +pub struct Ipfix { + socket: UdpSocket, +} + pub enum CaptureType { Live(Capture), Offline(Capture), + Ipfix(UdpSocket), } impl CaptureType { @@ -117,6 +128,9 @@ pub fn next_packet(&mut self) -> Result, Error> { match self { Self::Live(on) => on.next_packet(), Self::Offline(off) => off.next_packet(), + Self::Ipfix(_) => Err(Error::PcapError( + "Cannot capture packets from IPFIX source".into(), + )), } } @@ -124,13 +138,17 @@ pub fn stats(&mut self) -> Result { match self { Self::Live(on) => on.stats(), Self::Offline(off) => off.stats(), + Self::Ipfix(_) => Err(Error::PcapError( + "Cannot get stats from IPFIX source".into(), + )), } } - fn from_source(source: &CaptureSource, pcap_out_path: Option<&String>) -> Result { + fn from_source(source: &CaptureSource, pcap_out_path: Option<&String>) -> Result { match source { CaptureSource::Device(device) => { - let inactive = Capture::from_device(device.to_pcap_device())?; + let inactive = + Capture::from_device(device.to_pcap_device()).map_err(|e| e.to_string())?; let cap = inactive .promisc(false) .buffer_size(2_000_000) // 2MB buffer -> 10k packets of 200 bytes @@ -141,13 +159,21 @@ fn from_source(source: &CaptureSource, pcap_out_path: Option<&String>) -> Result }) .immediate_mode(false) .timeout(150) // ensure UI is updated even if no packets are captured - .open()?; + .open() + .map_err(|e| e.to_string())?; Ok(Self::Live(cap)) } - CaptureSource::File(file) => Ok(Self::Offline(Capture::from_file(&file.path)?)), - CaptureSource::Ipfix(_) => Err(Error::PcapError(String::from( - "IPFIX collector does not use a pcap capture", - ))), + CaptureSource::File(file) => Ok(Self::Offline( + Capture::from_file(&file.path).map_err(|e| e.to_string())?, + )), + CaptureSource::Ipfix(ipfix_socket) => { + let socket = UdpSocket::bind(ipfix_socket.socket_addr()?) + .map_err(|e| format!("Failed to bind UDP socket: {e}"))?; + socket + .set_read_timeout(Some(Duration::from_millis(150))) + .map_err(|e| format!("Failed to set socket read timeout: {e}"))?; + Ok(Self::Ipfix(socket)) + } } } @@ -155,6 +181,9 @@ fn set_bpf(&mut self, bpf: &str) -> Result<(), Error> { match self { Self::Live(cap) => cap.filter(bpf, true), Self::Offline(cap) => cap.filter(bpf, true), + Self::Ipfix(_) => Err(Error::PcapError( + "Cannot set BPF filter on IPFIX source".into(), + )), } } @@ -179,7 +208,7 @@ pub fn resume(&mut self, filters: &Filters) { pub enum CaptureSource { Device(MyDevice), File(MyPcapImport), - Ipfix(MyIpfixCollector), + Ipfix(MyIpfixSocket), } impl CaptureSource { @@ -193,9 +222,7 @@ pub fn from_conf(conf: &Conf) -> Self { let path = conf.import_pcap_path.clone(); Self::File(MyPcapImport::new(path)) } - CaptureSourcePicklist::Ipfix => { - Self::Ipfix(MyIpfixCollector::from_conf(&conf.ipfix_collector)) - } + CaptureSourcePicklist::Ipfix => Self::Ipfix(conf.ipfix_socket.clone()), } } @@ -238,7 +265,7 @@ pub fn get_link_type(&self) -> MyLinkType { match self { Self::Device(device) => device.get_link_type(), Self::File(file) => file.link_type, - Self::Ipfix(_) => MyLinkType::Ipfix, + Self::Ipfix(_) => MyLinkType::default(), } } diff --git a/src/networking/types/my_link_type.rs b/src/networking/types/my_link_type.rs index 5b904850..cb7d19bf 100644 --- a/src/networking/types/my_link_type.rs +++ b/src/networking/types/my_link_type.rs @@ -15,8 +15,6 @@ pub enum MyLinkType { LinuxSll(Linktype), LinuxSll2(Linktype), Unsupported(Linktype), - /// IPFIX collector — flow records over UDP, no underlying link layer - Ipfix, #[default] NotYetAssigned, } @@ -62,9 +60,6 @@ pub fn full_print_on_one_line(self, language: Language) -> String { } ) } - Self::Ipfix => { - format!("{}: IPFIX", link_type_translation(language)) - } Self::NotYetAssigned => { format!("{}: -", link_type_translation(language)) }