summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDavid Lönnhager <david.l@mullvad.net>2020-03-02 13:42:30 +0100
committerDavid Lönnhager <david.l@mullvad.net>2020-06-02 10:05:02 +0200
commit222683ef805d3baefe1113be1c597bd9150b0c94 (patch)
tree605117c8c0be35c1b55d871560b509225f9fc181
parent15f4738ad0b22e74d7b294ea329fce6fe8b35468 (diff)
downloadmullvadvpn-222683ef805d3baefe1113be1c597bd9150b0c94.tar.xz
mullvadvpn-222683ef805d3baefe1113be1c597bd9150b0c94.zip
Add function to obtain the default route for the physical interface
-rw-r--r--talpid-core/src/split.rs46
1 files changed, 45 insertions, 1 deletions
diff --git a/talpid-core/src/split.rs b/talpid-core/src/split.rs
index 2b012f076a..320ca30f37 100644
--- a/talpid-core/src/split.rs
+++ b/talpid-core/src/split.rs
@@ -2,9 +2,10 @@ use regex::Regex;
use std::{
fs,
io::{self, BufRead, BufReader, Write},
- net::IpAddr,
+ net::{AddrParseError, IpAddr},
path::Path,
process::Command,
+ str::FromStr,
};
const NETCLS_DIR: &str = "/sys/fs/cgroup/net_cls/";
@@ -23,6 +24,18 @@ const RT_TABLES_PATH: &str = "/etc/iproute2/rt_tables";
#[derive(err_derive::Error, Debug)]
#[error(no_from)]
pub enum Error {
+ /// Unable to list routing table entries.
+ #[error(display = "Failed to enumerate routes")]
+ EnumerateRoutes(#[error(source)] io::Error),
+
+ /// Unable to find the interface/ip pair used by the physical interface.
+ #[error(display = "No default route found")]
+ NoDefaultRoute,
+
+ /// Failed to parse string containing an IP address. May be invalid.
+ #[error(display = "Failed to parse IP address")]
+ ParseIpError(#[error(source)] AddrParseError),
+
/// Unable to create routing table for tagged connections and packets.
#[error(display = "Unable to create routing table")]
RoutingTableSetup(#[error(source)] io::Error),
@@ -56,6 +69,37 @@ pub enum Error {
FlushDns(#[error(source)] io::Error),
}
+struct DefaultRoute {
+ interface: String,
+ address: IpAddr,
+}
+
+fn get_default_route() -> Result<DefaultRoute, Error> {
+ // FIXME: use netlink
+ let mut cmd = Command::new("ip");
+ cmd.args(&["-4", "route", "list", "table", "main"]);
+ log::trace!("running cmd - {:?}", &cmd);
+ let out = cmd.output().map_err(Error::EnumerateRoutes)?;
+ let out_str = String::from_utf8_lossy(&out.stdout);
+
+ // Find "default" row
+ let expression = Regex::new(r"^default via ([0-9.]+) dev (\w+)").unwrap();
+
+ for line in out_str.lines() {
+ if let Some(captures) = expression.captures(&line) {
+ let ip_str = captures.get(1).unwrap().as_str();
+ let interface = captures.get(2).unwrap().as_str().to_string();
+
+ return Ok(DefaultRoute {
+ interface,
+ address: IpAddr::from_str(ip_str).map_err(Error::ParseIpError)?,
+ });
+ }
+ }
+
+ Err(Error::NoDefaultRoute)
+}
+
/// Route PID-associated packets through the physical interface.
pub fn route_marked_packets() -> Result<(), Error> {
// TODO: IPv6