use std::collections::HashMap;
use netlink_packet_route::rtnl::route::nlas::Nla;
use rtnetlink::RouteGetRequest;
use crate::{NisporError, Route, RouteProtocol, RouteScope};
#[derive(Debug, PartialEq, Eq, Clone, Default)]
#[non_exhaustive]
pub struct NetStateRouteFilter {
pub protocol: Option<RouteProtocol>,
pub scope: Option<RouteScope>,
pub oif: Option<String>,
pub table: Option<u8>,
}
pub(crate) fn apply_kernel_route_filter(
handle: &mut RouteGetRequest,
filter: &NetStateRouteFilter,
iface_name2index: &HashMap<String, u32>,
) -> Result<(), NisporError> {
let mut rt_nlmsg = handle.message_mut();
if let Some(protocol) = filter.protocol.as_ref() {
rt_nlmsg.header.protocol = protocol.into();
}
if let Some(scope) = filter.scope.as_ref() {
rt_nlmsg.header.scope = scope.into();
}
if let Some(oif) = filter.oif.as_ref() {
match iface_name2index.get(oif) {
Some(index) => rt_nlmsg.nlas.push(Nla::Oif(*index)),
None => {
let e = NisporError::invalid_argument(format!(
"Interface {oif} not found"
));
log::error!("{}", e);
return Err(e);
}
}
}
if let Some(table) = filter.table {
rt_nlmsg.nlas.push(Nla::Table(table.into()));
}
Ok(())
}
pub(crate) fn should_drop_by_filter(
route: &Route,
filter: &NetStateRouteFilter,
) -> bool {
if Some(&RouteScope::Universe) == filter.scope.as_ref() {
route.scope != RouteScope::Universe
} else {
false
}
}