summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDavid Lönnhager <david.l@mullvad.net>2020-03-19 17:53:58 +0100
committerDavid Lönnhager <david.l@mullvad.net>2020-06-02 10:05:02 +0200
commit36c1dd005e79e3d2beb9bfb04235150e7e82b34c (patch)
treefc6bada4e3ce185c4c12f0c01e65618abb9307a8
parent5be8c76e9a67aec7dd8084425313ed03ed996d44 (diff)
downloadmullvadvpn-36c1dd005e79e3d2beb9bfb04235150e7e82b34c.tar.xz
mullvadvpn-36c1dd005e79e3d2beb9bfb04235150e7e82b34c.zip
Pick a free routing table id
-rw-r--r--talpid-core/src/split.rs42
1 files changed, 23 insertions, 19 deletions
diff --git a/talpid-core/src/split.rs b/talpid-core/src/split.rs
index d72d41cc8f..090a497c9a 100644
--- a/talpid-core/src/split.rs
+++ b/talpid-core/src/split.rs
@@ -17,7 +17,6 @@ pub const NETCLS_CLASSID: u32 = 0x4d9f41;
pub const MARK: i32 = 0xf41;
const CGROUP_NAME: &str = "mullvad-exclusions";
-static mut ROUTING_TABLE_ID: i32 = 19;
const ROUTING_TABLE_NAME: &str = "mullvad_exclusions";
const RT_TABLES_PATH: &str = "/etc/iproute2/rt_tables";
@@ -99,19 +98,20 @@ fn get_default_route() -> Result<DefaultRoute, Error> {
}
/// Manage routing for split tunneling cgroup.
-pub struct SplitTunnel;
+pub struct SplitTunnel {
+ table_id: i32,
+}
impl SplitTunnel {
/// Object that allows specified applications to not pass through the tunnel
pub fn new() -> Result<SplitTunnel, Error> {
- Self::initialize_routing_table()?;
- Ok(SplitTunnel {})
+ let mut tunnel = SplitTunnel { table_id: 0 };
+ tunnel.initialize_routing_table()?;
+ Ok(tunnel)
}
/// Set up policy-based routing for marked packets.
- fn initialize_routing_table() -> Result<(), Error> {
- // TODO: ensure the ID does not conflict with that of another table
-
+ fn initialize_routing_table(&mut self) -> Result<(), Error> {
// Add routing table to /etc/iproute2/rt_tables, if it does not exist
let mut file = fs::OpenOptions::new()
@@ -123,6 +123,8 @@ impl SplitTunnel {
let buf_reader = BufReader::new(file.try_clone().map_err(Error::RoutingTableSetup)?);
let expression = Regex::new(r"^\s*(\d+)\s+(\w+)").unwrap();
+ let mut used_ids = Vec::<i32>::new();
+
for line in buf_reader.lines() {
let line = line.map_err(Error::RoutingTableSetup)?;
if let Some(captures) = expression.captures(&line) {
@@ -134,24 +136,26 @@ impl SplitTunnel {
.expect("Table ID does not fit i32");
let table_name = captures.get(2).unwrap().as_str();
- // Already added
if table_name == ROUTING_TABLE_NAME {
- if table_id != unsafe { ROUTING_TABLE_ID } {
- unsafe { ROUTING_TABLE_ID = table_id };
- }
-
+ // The table has already been added
+ self.table_id = table_id;
return Ok(());
}
+
+ used_ids.push(table_id);
+ }
+ }
+
+ used_ids.sort_unstable();
+ for id in 1..256 {
+ if used_ids.binary_search(&id).is_err() {
+ // Assign a free id to the table
+ self.table_id = id;
+ break;
}
}
- write!(
- file,
- "{} {}",
- unsafe { ROUTING_TABLE_ID },
- ROUTING_TABLE_NAME
- )
- .map_err(Error::RoutingTableSetup)
+ write!(file, "{} {}", self.table_id, ROUTING_TABLE_NAME).map_err(Error::RoutingTableSetup)
}
/// Reset the split-tunneling routing table to its default state