diff options
| author | David Lönnhager <david.l@mullvad.net> | 2020-11-17 17:51:45 +0100 |
|---|---|---|
| committer | David Lönnhager <david.l@mullvad.net> | 2020-11-24 12:29:47 +0100 |
| commit | 819ec03b833a322fd59f87d27a0d5dad4539fcde (patch) | |
| tree | 6c40dc7a78e6892a397a7655f9a474dd65aae339 | |
| parent | 0db3a44b9b4700273535070181a6518e2b7bfe16 (diff) | |
| download | mullvadvpn-819ec03b833a322fd59f87d27a0d5dad4539fcde.tar.xz mullvadvpn-819ec03b833a322fd59f87d27a0d5dad4539fcde.zip | |
Be more lenient in identifying routing rules for deletion
| -rw-r--r-- | talpid-core/src/routing/linux.rs | 59 |
1 files changed, 58 insertions, 1 deletions
diff --git a/talpid-core/src/routing/linux.rs b/talpid-core/src/routing/linux.rs index 0e546d11a4..2f90bab2fc 100644 --- a/talpid-core/src/routing/linux.rs +++ b/talpid-core/src/routing/linux.rs @@ -215,6 +215,7 @@ impl RouteManagerImpl { } async fn clear_routing_rules(&mut self) -> Result<()> { + let rules = self.get_rules().await?; for rule in &[ &*EXCLUSIONS_RULE_V4, &*EXCLUSIONS_RULE_V6, @@ -223,11 +224,67 @@ impl RouteManagerImpl { &*NO_FWMARK_RULE_V4, &*NO_FWMARK_RULE_V6, ] { - self.delete_rule_if_exists((*rule).clone()).await?; + let mut matching_rule = None; + + // `RTM_DELRULE` is way too picky about which rules are considered the same. + // So iterate over all rules and ignore irrelevant attributes. + for found_rule in &rules { + // Match header + if found_rule.header.family != rule.header.family { + continue; + } + if found_rule.header.action != rule.header.action { + continue; + } + if (found_rule.header.flags & rule.header.flags) != rule.header.flags { + continue; + } + // Match NLAs + let mut contains_nlas = true; + for nla in &rule.nlas { + if !found_rule.nlas.contains(nla) { + contains_nlas = false; + break; + } + } + if contains_nlas { + log::trace!("Existing routing rule matched: {:?}", found_rule); + matching_rule = Some(found_rule); + break; + } + } + + if let Some(rule) = matching_rule { + self.delete_rule_if_exists((*rule).clone()).await?; + } } Ok(()) } + async fn get_rules(&mut self) -> Result<Vec<RuleMessage>> { + use netlink_packet_route::constants::*; + + let mut req = NetlinkMessage::from(RtnlMessage::GetRule(RuleMessage::default())); + req.header.flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_DUMP; + + let mut response = self.handle.request(req).map_err(Error::NetlinkError)?; + + let mut rules = vec![]; + + while let Some(message) = response.next().await { + match message.payload { + NetlinkPayload::InnerMessage(RtnlMessage::NewRule(rule)) => { + rules.push(rule); + } + NetlinkPayload::Error(error) => { + return Err(Error::NetlinkError(rtnetlink::Error::NetlinkError(error))); + } + _ => (), + } + } + Ok(rules) + } + async fn delete_rule_if_exists(&mut self, rule: RuleMessage) -> Result<()> { use netlink_packet_route::constants::*; |
