rwhod: implement packet sender if filtering

This commit is contained in:
2026-07-20 20:01:50 +09:00
parent dada91184d
commit 59621048f8
4 changed files with 43 additions and 15 deletions
+4 -11
View File
@@ -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)]
+19 -2
View File
@@ -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());
}
}