# UNDF: UNDF-2026-000000334 --- a/lib/virtual-net/src/ruleset.rs +++ b/lib/virtual-net/src/ruleset.rs @@ -666,7 +666,14 @@ pub enum Rule { /// control the inbound and outbound traffic of a network. #[derive(Debug, Clone)] pub struct Ruleset { - rules: Arc>>, + /// All rules — kept for iteration order and serialization. + rules: Arc>>, + /// Pre-partitioned views for O(1) dispatch: + /// IP rules (IPV4/IPV6/Neg(IP)) — consulted by allows_socket/blocks_socket. + ip_rules: Arc>>, + /// DNS rules (DNS/Neg(DNS)) — consulted by allows_domain/blocks_domain. + dns_rules: Arc>>, } +impl Ruleset { + fn add_rule_internal( + rules: &mut Vec, + ip_rules: &mut Vec, + dns_rules: &mut Vec, + rule: Rule, + ) { + match &rule { + Rule::DNS(_) => dns_rules.push(rule.clone()), + Rule::Neg(inner) => match inner.as_ref() { + Rule::DNS(_) => dns_rules.push(rule.clone()), + _ => ip_rules.push(rule.clone()), + }, + _ => ip_rules.push(rule.clone()), + } + rules.push(rule); + } +} + impl Ruleset { /// Returns `true` if at least one rule allows accessing `socket_addr` in the specific `direction` /// and no rule blocks it pub fn allows_socket(&self, addr: impl Into, dir: Direction) -> bool { let addr = addr.into(); { - let ruleset = self.rules.read().unwrap(); + // Only IP rules are relevant for socket checks — skip DNS rules entirely. + let ruleset = self.ip_rules.read().unwrap(); let is_blacklisted = ruleset.iter().any(|r| r.blocks_socket(addr, dir)); if is_blacklisted { @@ -695,7 +702,8 @@ impl Ruleset { pub fn allows_domain(&self, domain: impl AsRef) -> bool { let domain = domain.as_ref(); { - let ruleset = self.rules.read().unwrap(); + // Only DNS rules are relevant for domain checks — skip IP rules entirely. + let ruleset = self.dns_rules.read().unwrap(); let is_blacklisted = ruleset.iter().any(|r| r.blocks_domain(domain)); if is_blacklisted {