diff options
| author | David Lönnhager <david.l@mullvad.net> | 2020-03-19 17:53:58 +0100 |
|---|---|---|
| committer | David Lönnhager <david.l@mullvad.net> | 2020-06-02 10:05:02 +0200 |
| commit | 36c1dd005e79e3d2beb9bfb04235150e7e82b34c (patch) | |
| tree | fc6bada4e3ce185c4c12f0c01e65618abb9307a8 | |
| parent | 5be8c76e9a67aec7dd8084425313ed03ed996d44 (diff) | |
| download | mullvadvpn-36c1dd005e79e3d2beb9bfb04235150e7e82b34c.tar.xz mullvadvpn-36c1dd005e79e3d2beb9bfb04235150e7e82b34c.zip | |
Pick a free routing table id
| -rw-r--r-- | talpid-core/src/split.rs | 42 |
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 |
