rwhod: implement packet sender if filtering
This commit is contained in:
+4
-11
@@ -1,4 +1,4 @@
|
||||
use std::{net::SocketAddrV4, path::PathBuf};
|
||||
use std::{collections::HashSet, path::PathBuf};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
@@ -39,17 +39,10 @@ pub struct RwhodConfig {
|
||||
/// Path to the ignore list for users that should be hidden from rwhod.
|
||||
pub ignore_list_path: Option<PathBuf>,
|
||||
|
||||
/// Network interfaces to listen on (e.g., ["eth0", "wlan0"]).
|
||||
/// Network interfaces to send rwhod packets on (e.g., ["eth0", "wlan0"]).
|
||||
///
|
||||
/// If left as `None`, the server will automatically determine relevant interfaces.
|
||||
///
|
||||
/// Note that if `broadcast_addresses` is specified, this field is ignored.
|
||||
pub interfaces: Option<Vec<String>>,
|
||||
|
||||
/// Broadcast addresses to send rwhod packets to.
|
||||
///
|
||||
/// If left as `None`, the server will automatically determine broadcast addresses for the selected interfaces.
|
||||
pub broadcast_addresses: Option<Vec<SocketAddrV4>>,
|
||||
/// If left as `None`, the server will send on all relevant interfaces it can find.
|
||||
pub interfaces: Option<HashSet<String>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
|
||||
@@ -29,7 +29,12 @@ pub struct RwhodSendTarget {
|
||||
}
|
||||
|
||||
/// Find all networks network interfaces suitable for rwhod communication.
|
||||
pub fn determine_relevant_interfaces() -> anyhow::Result<Vec<RwhodSendTarget>> {
|
||||
///
|
||||
/// If `allowed_interfaces` is `Some`, only interfaces whose name is contained
|
||||
/// in it are considered; otherwise all suitable interfaces are returned.
|
||||
pub fn determine_relevant_interfaces(
|
||||
allowed_interfaces: Option<&HashSet<String>>,
|
||||
) -> anyhow::Result<Vec<RwhodSendTarget>> {
|
||||
getifaddrs().map_err(|e| e.into()).map(|ifaces| {
|
||||
ifaces
|
||||
// interface must be up
|
||||
@@ -40,6 +45,11 @@ pub fn determine_relevant_interfaces() -> anyhow::Result<Vec<RwhodSendTarget>> {
|
||||
.flags
|
||||
.intersects(InterfaceFlags::IFF_BROADCAST | InterfaceFlags::IFF_POINTOPOINT)
|
||||
})
|
||||
// interface must be in the configured allowlist, if any
|
||||
.filter(|iface| {
|
||||
allowed_interfaces
|
||||
.is_none_or(|allowed| allowed.contains(iface.interface_name.as_str()))
|
||||
})
|
||||
.filter_map(|iface| {
|
||||
let neighbor_addr = if iface.flags.contains(InterfaceFlags::IFF_BROADCAST) {
|
||||
iface.broadcast
|
||||
@@ -137,9 +147,16 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_determine_relevant_interfaces() {
|
||||
let interfaces = determine_relevant_interfaces().unwrap();
|
||||
let interfaces = determine_relevant_interfaces(None).unwrap();
|
||||
for interface in interfaces {
|
||||
println!("Interface: {} Address: {}", interface.name, interface.addr);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_determine_relevant_interfaces_with_allowlist_excludes_unlisted() {
|
||||
let allowed = HashSet::from(["definitely-not-a-real-interface".to_string()]);
|
||||
let interfaces = determine_relevant_interfaces(Some(&allowed)).unwrap();
|
||||
assert!(interfaces.is_empty());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user