fix: added forgotten error handling

AggregateInterface was lacking some special error handling for certain cases
This commit is contained in:
Andrew Rioux 2023-05-01 12:52:32 -04:00
parent 24dff10b6b
commit c142af62f1
2 changed files with 68 additions and 26 deletions

View File

@ -89,7 +89,7 @@ async fn main() -> anyhow::Result<()> {
interface.set_filter("inbound and udp port 54248", true, None)?; interface.set_filter("inbound and udp port 54248", true, None)?;
interface.prune(|_, interface| interface.datalink() == pcap_sys::consts::DLT_EN10MB); interface.prune(|_, interface| interface.datalink() != pcap_sys::consts::DLT_EN10MB);
enum EventType { enum EventType {
Packet((String, Result<EthernetPacket, pcap_sys::error::Error>)), Packet((String, Result<EthernetPacket, pcap_sys::error::Error>)),

View File

@ -50,7 +50,7 @@ pub mod consts {
} }
use ffi::PcapDevIf; use ffi::PcapDevIf;
use futures::{ready, Stream, StreamExt}; use futures::{ready, StreamExt};
use tokio::io::unix::AsyncFd; use tokio::io::unix::AsyncFd;
use tokio_stream::StreamMap; use tokio_stream::StreamMap;
@ -492,6 +492,10 @@ where
Interface::<DevDisabled>::new(&if_name) Interface::<DevDisabled>::new(&if_name)
.map(|interface| (if_name, interface)) .map(|interface| (if_name, interface))
.ok() .ok()
.or_else(|| {
println!("{} failed to create device", new_name);
None
})
}) })
.collect::<HashMap<_, _>>() .collect::<HashMap<_, _>>()
}; };
@ -533,6 +537,10 @@ impl<T: State> AggregateInterface<T> {
}) })
.collect::<error::Result<_>>() .collect::<error::Result<_>>()
} }
pub fn get_ifnames(&self) -> Vec<&str> {
self.interfaces.keys().map(|n| &**n).collect::<_>()
}
} }
impl<T: Disabled> AggregateInterface<T> { impl<T: Disabled> AggregateInterface<T> {
@ -562,16 +570,34 @@ impl<T: Disabled> AggregateInterface<T> {
pub fn activate(self) -> error::Result<AggregateInterface<DevActivated>> { pub fn activate(self) -> error::Result<AggregateInterface<DevActivated>> {
Ok(AggregateInterface { Ok(AggregateInterface {
interfaces: self.interfaces interfaces: if self.crash {
.into_iter() self.interfaces
.map(|(name, interface)| { .into_iter()
let new_name = name.clone(); .map(|(name, interface)| {
interface let new_name = name.clone();
.activate() interface
.map(|interface| (name, interface)) .activate()
.map_err(|e| e.add_ifname(&new_name)) .map(|interface| (name, interface))
}) .map_err(|e| e.add_ifname(&new_name))
.collect::<error::Result<_>>()? })
.collect::<error::Result<_>>()?
} else {
self.interfaces
.into_iter()
.filter_map(|(name, interface)| {
let name_clone = name.clone();
interface
.activate()
.map(|interface| (name, interface))
.ok()
.or_else(|| {
println!("{} failed to activate", name_clone);
None
})
})
.collect::<_>()
},
crash: self.crash
}) })
} }
} }
@ -612,14 +638,30 @@ impl<T: Activated> AggregateInterface<T> {
optimize: bool, optimize: bool,
mask: Option<u32> mask: Option<u32>
) -> error::Result<HashMap<&str, Box<ffi::BpfProgram>>> { ) -> error::Result<HashMap<&str, Box<ffi::BpfProgram>>> {
self.interfaces if self.crash {
.iter_mut() self.interfaces
.map(|(name, interface)| { .iter_mut()
interface.set_filter(filter, optimize, mask) .map(|(name, interface)| {
.map(|bpf| (&**name, bpf)) interface.set_filter(filter, optimize, mask)
.map_err(|e| e.add_ifname(&name)) .map(|bpf| (&**name, bpf))
}) .map_err(|e| e.add_ifname(&name))
.collect::<error::Result<_>>() })
.collect::<error::Result<_>>()
} else {
Ok(self.interfaces
.iter_mut()
.filter_map(|(name, interface)| {
let name_clone = name.clone();
interface.set_filter(filter, optimize, mask)
.map(|bpf| (&**name, bpf))
.ok()
.or_else(|| {
println!("{} failed to set filter", name_clone);
None
})
})
.collect::<_>())
}
} }
pub fn sendpacket(&self, ifname: &str, packet: packets::EthernetPkt) -> error::Result<()> { pub fn sendpacket(&self, ifname: &str, packet: packets::EthernetPkt) -> error::Result<()> {
@ -653,19 +695,19 @@ pub struct AggregateInterfaceStream<T: Activated> {
} }
impl<T: Activated> AggregateInterfaceStream<T> { impl<T: Activated> AggregateInterfaceStream<T> {
pub fn get_ifnames(&self) -> Vec<&str> {
self.streams.keys().map(|n| &**n).collect::<_>()
}
pub fn sendpacket(&mut self, ifname: &str, packet: packets::EthernetPkt) -> error::Result<()> { pub fn sendpacket(&mut self, ifname: &str, packet: packets::EthernetPkt) -> error::Result<()> {
if let Some(interface) = self.streams if let Some(interface) = self.streams
.values_mut() .values_mut()
.find(|interface| { .find(|interface| {
let dev_name = interface.inner interface.inner
.get_ref() .get_ref()
.interface .interface
.dev_name .dev_name
.clone(); .as_bytes() == ifname.as_bytes()
CString::new(ifname).map(|ifname|
ifname == dev_name)
.unwrap_or(false)
}) { }) {
interface.sendpacket(packet)?; interface.sendpacket(packet)?;
} }