summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock71
-rw-r--r--Cargo.toml6
-rw-r--r--talpid-routing/Cargo.toml7
-rw-r--r--talpid-routing/src/lib.rs5
-rw-r--r--talpid-routing/src/unix/linux.rs436
-rw-r--r--talpid-wireguard/Cargo.toml9
-rw-r--r--talpid-wireguard/src/wireguard_kernel/mod.rs151
-rw-r--r--talpid-wireguard/src/wireguard_kernel/nl_message.rs10
-rw-r--r--talpid-wireguard/src/wireguard_kernel/parsers.rs3
-rw-r--r--talpid-wireguard/src/wireguard_kernel/wg_message.rs61
10 files changed, 369 insertions, 390 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 6e651f17c6..b4917a5807 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1983,12 +1983,12 @@ dependencies = [
[[package]]
name = "htmlize"
-version = "1.0.5"
+version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4e81e415f6d22240930e82ae0f541b2dd494ca37daaf10c1d7b32546f3b1159f"
+checksum = "d347c0de239be20ba0982e4822de3124404281e119ae3e11f5d7425a414e1935"
dependencies = [
"memchr",
- "paste",
+ "pastey",
"phf",
"phf_codegen",
"serde_json",
@@ -3493,55 +3493,37 @@ dependencies = [
[[package]]
name = "netlink-packet-core"
-version = "0.4.2"
+version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "345b8ab5bd4e71a2986663e88c56856699d060e78e152e6e9d7966fcd5491297"
+checksum = "745d789fe0958caf7252f5e1e900ce5c09b6a5bf05c7bba02a9cc600866ce31e"
dependencies = [
- "anyhow",
- "byteorder",
- "libc",
- "netlink-packet-utils",
+ "pastey",
]
[[package]]
name = "netlink-packet-route"
-version = "0.13.0"
+version = "0.25.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f5dee5ed749373c298237fe694eb0a51887f4cc1a27370c8464bac4382348f1a"
+checksum = "3ec2f5b6839be2a19d7fa5aab5bc444380f6311c2b693551cb80f45caaa7b5ef"
dependencies = [
- "anyhow",
- "bitflags 1.3.2",
- "byteorder",
+ "bitflags 2.9.0",
"libc",
+ "log",
"netlink-packet-core",
- "netlink-packet-utils",
-]
-
-[[package]]
-name = "netlink-packet-utils"
-version = "0.5.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0ede8a08c71ad5a95cdd0e4e52facd37190977039a4704eb82a283f713747d34"
-dependencies = [
- "anyhow",
- "byteorder",
- "paste",
- "thiserror 1.0.59",
]
[[package]]
name = "netlink-proto"
-version = "0.10.0"
+version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "65b4b14489ab424703c092062176d52ba55485a89c076b4f9db05092b7223aa6"
+checksum = "b65d130ee111430e47eed7896ea43ca693c387f097dd97376bffafbf25812128"
dependencies = [
"bytes",
"futures",
"log",
"netlink-packet-core",
"netlink-sys",
- "thiserror 1.0.59",
- "tokio",
+ "thiserror 2.0.9",
]
[[package]]
@@ -3594,17 +3576,6 @@ dependencies = [
[[package]]
name = "nix"
-version = "0.24.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069"
-dependencies = [
- "bitflags 1.3.2",
- "cfg-if",
- "libc",
-]
-
-[[package]]
-name = "nix"
version = "0.28.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4"
@@ -4039,10 +4010,10 @@ dependencies = [
]
[[package]]
-name = "paste"
-version = "1.0.14"
+name = "pastey"
+version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c"
+checksum = "35fb2e5f958ec131621fdd531e9fc186ed768cbe395337403ae56c17a74c68ec"
[[package]]
name = "pcap"
@@ -4927,15 +4898,17 @@ checksum = "21efba391745f92fc14a5cccb008e711a1a3708d8dacd2e69d88d5de513c117a"
[[package]]
name = "rtnetlink"
-version = "0.11.0"
+version = "0.18.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "46f1cfa18f8cebe685373a2697915d7e0db3b4554918bba118385e0f71f258a7"
+checksum = "08fd15aa4c64c34d0b3178e45ec6dad313a9f02b193376d501668a7950264bb7"
dependencies = [
"futures",
"log",
+ "netlink-packet-core",
"netlink-packet-route",
"netlink-proto",
- "nix 0.24.3",
+ "netlink-sys",
+ "nix 0.29.0",
"thiserror 1.0.59",
"tokio",
]
@@ -5770,6 +5743,7 @@ dependencies = [
"jnix",
"libc",
"log",
+ "netlink-packet-core",
"netlink-packet-route",
"netlink-sys",
"nix 0.30.1",
@@ -5878,7 +5852,6 @@ dependencies = [
"maybenot",
"netlink-packet-core",
"netlink-packet-route",
- "netlink-packet-utils",
"netlink-proto",
"nix 0.30.1",
"once_cell",
diff --git a/Cargo.toml b/Cargo.toml
index e33522942f..4a787953bd 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -105,6 +105,12 @@ tun = { version = "0.5.5", features = ["async"] }
socket2 = "0.5.7"
reqwest = { version = "0.12.23", default-features = false, features = ["rustls-tls"] }
+rtnetlink = "0.18"
+netlink-packet-core = "0.8.0"
+netlink-packet-route = "0.25"
+netlink-proto = "0.12"
+netlink-sys = "0.8.3"
+
# Hickory & DNS
hickory-proto = "0.24.3"
hickory-resolver = "0.24.3"
diff --git a/talpid-routing/Cargo.toml b/talpid-routing/Cargo.toml
index b46a925488..4ba45beff2 100644
--- a/talpid-routing/Cargo.toml
+++ b/talpid-routing/Cargo.toml
@@ -23,9 +23,10 @@ jnix = { version = "0.5.2", features = ["derive"] }
[target.'cfg(target_os = "linux")'.dependencies]
libc = "0.2"
-rtnetlink = "0.11"
-netlink-packet-route = { version = "0.13", features = ["rich_nlas"] }
-netlink-sys = "0.8.3"
+rtnetlink = { workspace = true }
+netlink-packet-core = { workspace = true }
+netlink-packet-route = { workspace = true, features = ["rich_nlas"] }
+netlink-sys = { workspace = true }
[target.'cfg(target_os = "macos")'.dependencies]
nix = { workspace = true, features = ["socket", "fs", "net"] }
diff --git a/talpid-routing/src/lib.rs b/talpid-routing/src/lib.rs
index d3f828428a..22ba95fadf 100644
--- a/talpid-routing/src/lib.rs
+++ b/talpid-routing/src/lib.rs
@@ -20,9 +20,6 @@ pub use imp::{CallbackHandle, EventType, InterfaceAndGateway, get_best_default_r
#[path = "unix/mod.rs"]
mod imp;
-#[cfg(target_os = "linux")]
-use netlink_packet_route::rtnl::constants::RT_TABLE_MAIN;
-
#[cfg(target_os = "macos")]
pub use imp::{
PlatformError,
@@ -99,7 +96,7 @@ impl Route {
prefix,
metric: None,
#[cfg(target_os = "linux")]
- table_id: u32::from(RT_TABLE_MAIN),
+ table_id: u32::from(libc::RT_TABLE_MAIN),
#[cfg(any(target_os = "linux", target_os = "macos"))]
mtu: None,
}
diff --git a/talpid-routing/src/unix/linux.rs b/talpid-routing/src/unix/linux.rs
index 186fa07188..14a195d977 100644
--- a/talpid-routing/src/unix/linux.rs
+++ b/talpid-routing/src/unix/linux.rs
@@ -1,57 +1,61 @@
+use std::collections::{BTreeMap, HashSet};
+use std::io;
+use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
+use std::sync::LazyLock;
+
use crate::{
NetNode, Node, RequiredRoute, Route,
imp::{CallbackMessage, RouteManagerCommand},
};
-use netlink_sys::AsyncSocket;
-use std::{
- collections::{BTreeMap, HashSet},
- io,
- net::{IpAddr, Ipv4Addr, Ipv6Addr},
+use netlink_packet_core::{
+ Emitable, NLM_F_ACK, NLM_F_CREATE, NLM_F_DUMP, NLM_F_REPLACE, NLM_F_REQUEST, NetlinkMessage,
+ NetlinkPayload,
};
+use netlink_packet_route::route::RouteFlags;
+use netlink_sys::AsyncSocket;
use talpid_types::ErrorExt;
use futures::{
- StreamExt, TryStream, TryStreamExt,
+ StreamExt, TryStreamExt,
channel::mpsc::{UnboundedReceiver, UnboundedSender},
future::FutureExt,
};
use ipnetwork::IpNetwork;
-use libc::{AF_INET, AF_INET6};
+use libc::{RT_TABLE_COMPAT, RT_TABLE_MAIN};
use netlink_packet_route::{
- NetlinkMessage, NetlinkPayload, RtnlMessage,
- constants::{ARPHRD_LOOPBACK, FIB_RULE_INVERT, FR_ACT_TO_TBL, NLM_F_REQUEST},
- link::{LinkMessage, nlas::Nla as LinkNla},
- route::{Metrics, RouteHeader, RouteMessage, nlas::Nla as RouteNla},
- rtnl::{
- RouteFlags,
- constants::{
- RT_SCOPE_LINK, RT_SCOPE_UNIVERSE, RT_TABLE_COMPAT, RT_TABLE_MAIN, RTN_UNSPEC,
- RTPROT_UNSPEC,
- },
+ AddressFamily, RouteNetlinkMessage,
+ link::{LinkAttribute, LinkLayerType, LinkMessage},
+ route::{
+ RouteAddress, RouteAttribute, RouteMessage, RouteMetric, RouteProtocol, RouteScope,
+ RouteType, RouteVia,
},
- rule::{RuleHeader, RuleMessage, nlas::Nla as RuleNla},
+ rule::{RuleAction, RuleAttribute, RuleFlags, RuleHeader, RuleMessage},
};
use rtnetlink::{
- Handle, IpVersion,
+ Handle, RouteMessageBuilder,
constants::{RTMGRP_IPV4_ROUTE, RTMGRP_IPV6_ROUTE, RTMGRP_LINK, RTMGRP_NOTIFY},
sys::SocketAddr,
};
-use std::sync::LazyLock;
-static SUPPRESS_RULE_V4: LazyLock<RuleMessage> = LazyLock::new(|| RuleMessage {
- header: RuleHeader {
- family: AF_INET as u8,
- action: FR_ACT_TO_TBL,
+static SUPPRESS_RULE_V4: LazyLock<RuleMessage> = LazyLock::new(|| {
+ let mut rule_msg = RuleMessage::default();
+ let header = RuleHeader {
+ family: AddressFamily::Inet,
+ action: RuleAction::ToTable, // FR_ACT_TO_TBL
..RuleHeader::default()
- },
- nlas: vec![
- RuleNla::SuppressPrefixLen(0),
- RuleNla::Table(RT_TABLE_MAIN as u32),
- ],
+ };
+ let attributes = vec![
+ RuleAttribute::SuppressPrefixLen(0),
+ RuleAttribute::Table(RT_TABLE_MAIN as u32),
+ ];
+
+ rule_msg.header = header;
+ rule_msg.attributes = attributes;
+ rule_msg
});
static SUPPRESS_RULE_V6: LazyLock<RuleMessage> = LazyLock::new(|| {
let mut v6_rule = SUPPRESS_RULE_V4.clone();
- v6_rule.header.family = AF_INET6 as u8;
+ v6_rule.header.family = AddressFamily::Inet6;
v6_rule
});
@@ -65,20 +69,23 @@ fn all_rules(fwmark: u32, table: u32) -> [RuleMessage; 4] {
}
fn no_fwmark_rule_v4(fwmark: u32, table: u32) -> RuleMessage {
- RuleMessage {
- header: RuleHeader {
- family: AF_INET as u8,
- action: FR_ACT_TO_TBL,
- flags: FIB_RULE_INVERT,
- ..RuleHeader::default()
- },
- nlas: vec![RuleNla::FwMark(fwmark), RuleNla::Table(table)],
- }
+ let mut rule_msg = RuleMessage::default();
+ let header = RuleHeader {
+ family: AddressFamily::Inet, // AF_INET
+ action: RuleAction::ToTable, // FR_ACT_TO_TBL
+ flags: RuleFlags::Invert, // FIB_RULE_INVERT
+ ..RuleHeader::default()
+ };
+ let attributes = vec![RuleAttribute::FwMark(fwmark), RuleAttribute::Table(table)];
+
+ rule_msg.header = header;
+ rule_msg.attributes = attributes;
+ rule_msg
}
fn no_fwmark_rule_v6(fwmark: u32, table: u32) -> RuleMessage {
let mut v6_rule = no_fwmark_rule_v4(fwmark, table);
- v6_rule.header.family = AF_INET6 as u8;
+ v6_rule.header.family = AddressFamily::Inet6;
v6_rule
}
@@ -131,7 +138,7 @@ pub enum Error {
pub struct RouteManagerImpl {
handle: Handle,
- messages: UnboundedReceiver<(NetlinkMessage<RtnlMessage>, SocketAddr)>,
+ messages: UnboundedReceiver<(NetlinkMessage<RouteNetlinkMessage>, SocketAddr)>,
iface_map: BTreeMap<u32, NetworkInterface>,
listeners: Vec<UnboundedSender<CallbackMessage>>,
@@ -178,15 +185,13 @@ impl RouteManagerImpl {
}
async fn create_routing_rules(&mut self, enable_ipv6: bool) -> Result<()> {
- use netlink_packet_route::constants::*;
-
self.clear_routing_rules().await?;
for rule in all_rules(self.fwmark, self.table_id)
.iter()
- .filter(|rule| rule.header.family as u16 == AF_INET || enable_ipv6)
+ .filter(|rule| rule.header.family == AddressFamily::Inet || enable_ipv6)
{
- let mut req = NetlinkMessage::from(RtnlMessage::NewRule((*rule).clone()));
+ let mut req = NetlinkMessage::from(RouteNetlinkMessage::NewRule((*rule).clone()));
req.header.flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_CREATE | NLM_F_REPLACE;
let mut response = self.handle.request(req).map_err(Error::Netlink)?;
@@ -220,8 +225,8 @@ impl RouteManagerImpl {
}
// Match NLAs
let mut contains_nlas = true;
- for nla in &rule.nlas {
- if !found_rule.nlas.contains(nla) {
+ for nla in &rule.attributes {
+ if !found_rule.attributes.contains(nla) {
contains_nlas = false;
break;
}
@@ -241,9 +246,7 @@ impl RouteManagerImpl {
}
async fn get_rules(&mut self) -> Result<Vec<RuleMessage>> {
- use netlink_packet_route::constants::*;
-
- let mut req = NetlinkMessage::from(RtnlMessage::GetRule(RuleMessage::default()));
+ let mut req = NetlinkMessage::from(RouteNetlinkMessage::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::Netlink)?;
@@ -252,7 +255,7 @@ impl RouteManagerImpl {
while let Some(message) = response.next().await {
match message.payload {
- NetlinkPayload::InnerMessage(RtnlMessage::NewRule(rule)) => {
+ NetlinkPayload::InnerMessage(RouteNetlinkMessage::NewRule(rule)) => {
rules.push(rule);
}
NetlinkPayload::Error(error) => {
@@ -265,9 +268,7 @@ impl RouteManagerImpl {
}
async fn delete_rule_if_exists(&mut self, rule: RuleMessage) -> Result<()> {
- use netlink_packet_route::constants::*;
-
- let mut req = NetlinkMessage::from(RtnlMessage::DelRule(rule));
+ let mut req = NetlinkMessage::from(RouteNetlinkMessage::DelRule(rule));
req.header.flags = NLM_F_REQUEST | NLM_F_ACK;
let mut response = self.handle.request(req).map_err(Error::Netlink)?;
@@ -396,24 +397,24 @@ impl RouteManagerImpl {
Ok(())
}
- fn process_netlink_message(&mut self, msg: NetlinkMessage<RtnlMessage>) -> Result<()> {
+ fn process_netlink_message(&mut self, msg: NetlinkMessage<RouteNetlinkMessage>) -> Result<()> {
match msg.payload {
- NetlinkPayload::InnerMessage(RtnlMessage::NewLink(new_link)) => {
+ NetlinkPayload::InnerMessage(RouteNetlinkMessage::NewLink(new_link)) => {
if let Some((idx, name)) = Self::map_interface(new_link) {
self.iface_map.insert(idx, name);
}
}
- NetlinkPayload::InnerMessage(RtnlMessage::DelLink(old_link)) => {
+ NetlinkPayload::InnerMessage(RouteNetlinkMessage::DelLink(old_link)) => {
if let Some((idx, _)) = Self::map_interface(old_link) {
self.iface_map.remove(&idx);
}
}
- NetlinkPayload::InnerMessage(RtnlMessage::NewRoute(new_route)) => {
+ NetlinkPayload::InnerMessage(RouteNetlinkMessage::NewRoute(new_route)) => {
if let Some(addition) = self.parse_route_message(new_route)? {
self.notify_change_listeners(CallbackMessage::NewRoute(addition));
}
}
- NetlinkPayload::InnerMessage(RtnlMessage::DelRoute(old_route)) => {
+ NetlinkPayload::InnerMessage(RouteNetlinkMessage::DelRoute(old_route)) => {
if let Some(deletion) = self.parse_route_message(old_route)? {
self.process_deleted_route(&deletion)?;
self.notify_change_listeners(CallbackMessage::DelRoute(deletion));
@@ -431,13 +432,13 @@ impl RouteManagerImpl {
// Tries to coax a Route out of a RouteMessage
fn parse_route_message(&self, msg: RouteMessage) -> Result<Option<Route>> {
- let af_spec = msg.header.address_family;
+ let af = msg.header.address_family;
let destination_length = msg.header.destination_prefix_length;
- let is_ipv4 = match af_spec as i32 {
- AF_INET => true,
- AF_INET6 => false,
+ let is_ipv4 = match af {
+ AddressFamily::Inet => true,
+ AddressFamily::Inet6 => false,
af_spec => {
- log::error!("Unexpected routing protocol: {}", af_spec);
+ log::error!("Unexpected routing protocol: {:?}", af_spec);
return Ok(None);
}
};
@@ -460,9 +461,9 @@ impl RouteManagerImpl {
let mut table_id = u32::from(msg.header.table);
let mut route_mtu = None;
- for nla in msg.nlas.iter() {
+ for nla in msg.attributes.iter() {
match nla {
- RouteNla::Oif(device_idx) => {
+ RouteAttribute::Oif(device_idx) => {
match self.iface_map.get(device_idx) {
Some(route_device) => {
if !route_device.is_loopback() {
@@ -481,32 +482,37 @@ impl RouteManagerImpl {
};
}
- RouteNla::Via(addr) => {
- node_addr = Self::parse_ip(addr).map(Some)?;
+ RouteAttribute::Via(addr) => {
+ node_addr = Some(Self::parse_ip_from_via(addr)?);
}
- RouteNla::Destination(addr) => {
- prefix = Self::parse_ip(addr).and_then(|ip| {
- ipnetwork::IpNetwork::new(ip, destination_length)
- .map_err(Error::InvalidNetworkPrefix)
- })?;
+ RouteAttribute::Destination(addr) => {
+ let ip = Self::parse_ip_from_route_address(addr)?;
+ let network = ipnetwork::IpNetwork::new(ip, destination_length)
+ .map_err(Error::InvalidNetworkPrefix)?;
+ prefix = network;
}
// gateway NLAs indicate that this is actually a default route
- RouteNla::Gateway(gateway_ip) => {
- gateway = Self::parse_ip(gateway_ip).map(Some)?;
+ RouteAttribute::Gateway(gateway_ip) => {
+ gateway = Some(Self::parse_ip_from_route_address(gateway_ip)?)
}
- RouteNla::Priority(priority) => {
+ RouteAttribute::Priority(priority) => {
metric = Some(*priority);
}
- RouteNla::Table(id) => {
+ RouteAttribute::Table(id) => {
table_id = *id;
}
- RouteNla::Metrics(Metrics::Mtu(mtu)) => {
- route_mtu = Some(*mtu);
+ RouteAttribute::Metrics(metrics) => {
+ let get_mtu = |metric: &RouteMetric| match metric {
+ RouteMetric::Mtu(mtu) => Some(*mtu),
+ _ => None,
+ };
+ let mtu = metrics.iter().find_map(get_mtu);
+ route_mtu = mtu;
}
_ => continue,
}
@@ -533,8 +539,8 @@ impl RouteManagerImpl {
fn map_interface(msg: LinkMessage) -> Option<(u32, NetworkInterface)> {
let index = msg.header.index;
let link_layer_type = msg.header.link_layer_type;
- for nla in msg.nlas {
- if let LinkNla::IfName(name) = nla {
+ for nla in msg.attributes {
+ if let LinkAttribute::IfName(name) = nla {
return Some((
index,
NetworkInterface {
@@ -548,6 +554,18 @@ impl RouteManagerImpl {
None
}
+ fn parse_ip_from_via(via: &RouteVia) -> Result<IpAddr> {
+ let mut bytes = vec![0; via.buffer_len()];
+ via.emit(&mut bytes);
+ Self::parse_ip(&bytes)
+ }
+
+ fn parse_ip_from_route_address(route_address: &RouteAddress) -> Result<IpAddr> {
+ let mut bytes = vec![0; route_address.buffer_len()];
+ route_address.emit(&mut bytes);
+ Self::parse_ip(&bytes)
+ }
+
fn parse_ip(bytes: &[u8]) -> Result<IpAddr> {
if bytes.len() == 4 {
let mut ipv4_bytes = [0u8; 4];
@@ -566,7 +584,7 @@ impl RouteManagerImpl {
async fn delete_route_if_exists(&self, route: &Route) -> Result<()> {
if let Err(error) = self.delete_route(route).await {
if let Error::Netlink(rtnetlink::Error::NetlinkError(msg)) = &error
- && msg.code == -libc::ESRCH
+ && msg.raw_code() == -libc::ESRCH
{
return Ok(());
}
@@ -582,59 +600,61 @@ impl RouteManagerImpl {
let scope = match route.prefix {
IpNetwork::V4(v4_prefix) => {
if v4_prefix.prefix() > 0 && v4_prefix.prefix() < 32 {
- RT_SCOPE_LINK
+ RouteScope::Link // RT_SCOPE_LINK
} else {
- RT_SCOPE_UNIVERSE
+ RouteScope::Universe // RT_SCOPE_UNIVERSE
}
}
IpNetwork::V6(v6_prefix) => {
if v6_prefix.prefix() > 0 && v6_prefix.prefix() < 128 {
- RT_SCOPE_LINK
+ RouteScope::Link // RT_SCOPE_LINK
} else {
- RT_SCOPE_UNIVERSE
+ RouteScope::Universe // RT_SCOPE_UNIVERSE
}
}
};
- let mut route_message = RouteMessage {
- header: RouteHeader {
- address_family: if route.prefix.is_ipv4() {
- AF_INET as u8
- } else {
- AF_INET6 as u8
- },
- source_prefix_length: 0,
- destination_prefix_length: route.prefix.prefix(),
- tos: 0u8,
- table: compat_table,
- protocol: RTPROT_UNSPEC,
- scope,
- kind: RTN_UNSPEC,
- flags: RouteFlags::empty(),
- },
- nlas: vec![RouteNla::Destination(ip_to_bytes(route.prefix.ip()))],
+ let mut route_message = {
+ RouteMessageBuilder::<IpAddr>::new()
+ .destination_prefix(route.prefix.ip(), route.prefix.prefix())
+ // NOTE: This will only panic if the prefix length is wrong.
+ .unwrap()
+ .protocol(RouteProtocol::Unspec) // RTPROT_UNSPEC
+ .kind(RouteType::Unspec) //RTN_UNSPEC
+ .scope(scope)
+ .table_id(compat_table as u32).build()
+
+ // TODO: Are these important? v
+ //source_prefix_length: 0,
+ //tos: 0u8,
};
if compat_table == RT_TABLE_COMPAT {
- route_message.nlas.push(RouteNla::Table(route.table_id));
+ route_message
+ .attributes
+ .push(RouteAttribute::Table(route.table_id));
}
if let Some(interface_name) = route.node.get_device()
&& let Some(iface_idx) = self.find_iface_idx(interface_name)
{
- route_message.nlas.push(RouteNla::Oif(iface_idx));
+ route_message
+ .attributes
+ .push(RouteAttribute::Oif(iface_idx));
}
if let Some(gateway) = route.node.get_address() {
let gateway_nla = if route.node.get_device().is_some() {
- RouteNla::Gateway(ip_to_bytes(gateway))
+ RouteAttribute::Gateway(ip_to_route_address(gateway))
} else {
- RouteNla::Via(ip_to_bytes(gateway))
+ RouteAttribute::Via(ip_to_route_via(gateway))
};
- route_message.nlas.push(gateway_nla);
+ route_message.attributes.push(gateway_nla);
}
if let Some(metric) = route.metric {
- route_message.nlas.push(RouteNla::Priority(metric));
+ route_message
+ .attributes
+ .push(RouteAttribute::Priority(metric));
}
self.handle
@@ -646,17 +666,13 @@ impl RouteManagerImpl {
}
async fn add_route_direct(&mut self, route: Route) -> Result<()> {
- let mut add_message = match &route.prefix {
+ let add_message = match &route.prefix {
IpNetwork::V4(v4_prefix) => {
- let mut add_message = self
- .handle
- .route()
- .add()
- .v4()
+ let mut add_message = RouteMessageBuilder::<Ipv4Addr>::new()
.destination_prefix(v4_prefix.ip(), v4_prefix.prefix());
if v4_prefix.prefix() > 0 && v4_prefix.prefix() < 32 {
- add_message = add_message.scope(RT_SCOPE_LINK);
+ add_message = add_message.scope(RouteScope::Link); // RT_SCOPE_LINK
}
if let Some(IpAddr::V4(node_address)) = route.node.get_address() {
@@ -669,19 +685,36 @@ impl RouteManagerImpl {
add_message = add_message.output_interface(iface_idx);
}
- add_message.message_mut().clone()
+ // TODO: Unused ?
+ let compat_table = compat_table_id(route.table_id);
+ if compat_table == RT_TABLE_COMPAT {
+ add_message = add_message.table_id(route.table_id);
+ }
+
+ // TODO: Request support for route priority in RouteAddIpv{4,6}Request
+ if let Some(metric) = route.metric {
+ add_message = add_message.priority(metric);
+ }
+
+ let mut msg = add_message.build();
+
+ // Set route MTU
+ if let Some(mtu) = route.mtu {
+ // TODO: This can be done before calling `add_message.build()` if
+ // https://github.com/rust-netlink/rtnetlink/pull/126 is merged & released.
+ let mtu = RouteMetric::Mtu(mtu);
+ msg.attributes.push(RouteAttribute::Metrics(vec![mtu]));
+ }
+
+ self.handle.route().add(msg)
}
IpNetwork::V6(v6_prefix) => {
- let mut add_message = self
- .handle
- .route()
- .add()
- .v6()
+ let mut add_message = RouteMessageBuilder::<Ipv6Addr>::new()
.destination_prefix(v6_prefix.ip(), v6_prefix.prefix());
if v6_prefix.prefix() > 0 && v6_prefix.prefix() < 128 {
- add_message = add_message.scope(RT_SCOPE_LINK);
+ add_message = add_message.scope(RouteScope::Link); // RT_SCOPE_LINK
}
if let Some(IpAddr::V6(node_address)) = route.node.get_address() {
@@ -694,40 +727,36 @@ impl RouteManagerImpl {
add_message = add_message.output_interface(iface_idx);
}
- add_message.message_mut().clone()
- }
- };
+ let compat_table = compat_table_id(route.table_id);
+ if compat_table == RT_TABLE_COMPAT {
+ add_message = add_message.table_id(route.table_id);
+ }
- let compat_table = compat_table_id(route.table_id);
- add_message.header.table = compat_table;
- if compat_table == RT_TABLE_COMPAT {
- add_message.nlas.push(RouteNla::Table(route.table_id));
- }
+ // TODO: Request support for route priority in RouteAddIpv{4,6}Request
+ if let Some(metric) = route.metric {
+ add_message = add_message.priority(metric);
+ }
- // TODO: Request support for route priority in RouteAddIpv{4,6}Request
- if let Some(metric) = route.metric {
- add_message.nlas.push(RouteNla::Priority(metric));
- }
+ let mut msg = add_message.build();
- // Set route MTU
- if let Some(mtu) = route.mtu {
- add_message.nlas.push(RouteNla::Metrics(Metrics::Mtu(mtu)));
- }
+ // Set route MTU
+ if let Some(mtu) = route.mtu {
+ // TODO: This can be done before calling `add_message.build()` if
+ // https://github.com/rust-netlink/rtnetlink/pull/126 is merged & released.
+ let mtu = RouteMetric::Mtu(mtu);
+ msg.attributes.push(RouteAttribute::Metrics(vec![mtu]));
+ }
- // Need to modify the request in place to set the correct flags to be able to replace any
- // existing routes - self.handle.route().add_v4().execute() sets the NLM_F_EXCL flag which
- // will make the request fail if a route with the same destination already exists.
- use netlink_packet_route::constants::*;
- let mut req = NetlinkMessage::from(RtnlMessage::NewRoute(add_message));
- req.header.flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_CREATE | NLM_F_REPLACE;
+ self.handle.route().add(msg)
+ }
+ };
- let mut response = self.handle.request(req).map_err(Error::Netlink)?;
+ add_message
+ .replace()
+ .execute()
+ .await
+ .map_err(Error::Netlink)?;
- while let Some(message) = response.next().await {
- if let NetlinkPayload::Error(err) = message.payload {
- return Err(Error::Netlink(rtnetlink::Error::NetlinkError(err)));
- }
- }
Ok(())
}
@@ -805,12 +834,14 @@ impl RouteManagerImpl {
async fn get_device_mtu(&self, device: String) -> Result<u16> {
let mut links = self.handle.link().get().execute();
- let target_device = LinkNla::IfName(device);
+ let target_device = LinkAttribute::IfName(device);
while let Some(msg) = links.try_next().await.map_err(|_| Error::LinkNotFound)? {
- let found = msg.nlas.contains(&target_device);
+ let found = msg.attributes.contains(&target_device);
if found
- && let Some(LinkNla::Mtu(mtu)) =
- msg.nlas.iter().find(|e| matches!(e, LinkNla::Mtu(_)))
+ && let Some(LinkAttribute::Mtu(mtu)) = msg
+ .attributes
+ .iter()
+ .find(|e| matches!(e, LinkAttribute::Mtu(_)))
{
return Ok(
u16::try_from(*mtu).expect("MTU returned by device does not fit into a u16")
@@ -825,23 +856,40 @@ impl RouteManagerImpl {
destination: &IpAddr,
fwmark: Option<u32>,
) -> Result<Option<Route>> {
- let mut request = self.handle.route().get(get_ip_version(destination));
- let octets = match destination {
- IpAddr::V4(address) => address.octets().to_vec(),
- IpAddr::V6(address) => address.octets().to_vec(),
+ //let mut request = self.handle.route().get(route_msg);
+ let request = {
+ let mut builder = RouteMessageBuilder::<IpAddr>::new();
+ builder = {
+ let prefix_length = match destination {
+ IpAddr::V4(ipv4_addr) => 8u8 * (ipv4_addr.octets().len() as u8),
+ IpAddr::V6(ipv6_addr) => 8u8 * (ipv6_addr.octets().len() as u8),
+ };
+
+ // Note: This will only panic if `prefix_length` is wrong for the IP version.
+ builder
+ .destination_prefix(*destination, prefix_length)
+ .unwrap()
+ };
+
+ let mut request = builder.build();
+ if let Some(mark) = fwmark {
+ // TODO: This can be done before calling `builder.build()` if
+ // https://github.com/rust-netlink/rtnetlink/pull/127 is merged & released.
+ let fwmark = RouteAttribute::Mark(mark);
+ request.attributes.push(fwmark);
+ }
+
+ request.header.flags = RouteFlags::FibMatch; // RTM_F_FIB_MATCH;
+ request
};
- let message = request.message_mut();
- if let Some(mark) = fwmark {
- message.nlas.push(RouteNla::Mark(mark));
- }
- message.header.destination_prefix_length = 8u8 * (octets.len() as u8);
- message.header.flags = RouteFlags::RTM_F_FIB_MATCH;
- message.nlas.push(RouteNla::Destination(octets));
- let mut stream = execute_route_get_request(self.handle.clone(), message.clone());
+
+ let mut stream = self.handle.route().get(request).execute();
match stream.try_next().await {
Ok(Some(route_msg)) => self.parse_route_message(route_msg),
Ok(None) => Err(Error::NoRoute),
- Err(rtnetlink::Error::NetlinkError(nl_err)) if nl_err.code == -libc::ENETUNREACH => {
+ Err(rtnetlink::Error::NetlinkError(nl_err))
+ if nl_err.raw_code() == -libc::ENETUNREACH =>
+ {
Ok(None)
}
Err(err) => Err(Error::GetRoute(err)),
@@ -849,60 +897,34 @@ impl RouteManagerImpl {
}
}
-fn ip_to_bytes(addr: IpAddr) -> Vec<u8> {
+fn ip_to_route_address(addr: IpAddr) -> RouteAddress {
match addr {
- IpAddr::V4(addr) => addr.octets().to_vec(),
- IpAddr::V6(addr) => addr.octets().to_vec(),
+ IpAddr::V4(addr) => RouteAddress::Inet(addr),
+ IpAddr::V6(addr) => RouteAddress::Inet6(addr),
}
}
-fn compat_table_id(id: u32) -> u8 {
- // RT_TABLE_COMPAT must be combined with nla Table(id)
- if id > 255 { RT_TABLE_COMPAT } else { id as u8 }
-}
-
-fn get_ip_version(addr: &IpAddr) -> IpVersion {
- if addr.is_ipv4() {
- IpVersion::V4
- } else {
- IpVersion::V6
+fn ip_to_route_via(addr: IpAddr) -> RouteVia {
+ match addr {
+ IpAddr::V4(addr) => RouteVia::Inet(addr),
+ IpAddr::V6(addr) => RouteVia::Inet6(addr),
}
}
-fn execute_route_get_request(
- mut handle: Handle,
- message: RouteMessage,
-) -> impl TryStream<Ok = RouteMessage, Error = rtnetlink::Error> {
- use futures::future::{self, Either};
- use rtnetlink::Error;
-
- let mut req = NetlinkMessage::from(RtnlMessage::GetRoute(message));
- req.header.flags = NLM_F_REQUEST;
-
- match handle.request(req) {
- Ok(response) => Either::Left(response.map(move |msg| {
- let (header, payload) = msg.into_parts();
- match payload {
- NetlinkPayload::InnerMessage(RtnlMessage::NewRoute(msg)) => Ok(msg),
- NetlinkPayload::Error(err) => Err(Error::NetlinkError(err)),
- _ => Err(Error::UnexpectedMessage(NetlinkMessage::new(
- header, payload,
- ))),
- }
- })),
- Err(e) => Either::Right(future::err::<RouteMessage, Error>(e).into_stream()),
- }
+fn compat_table_id(id: u32) -> u8 {
+ // RT_TABLE_COMPAT must be combined with nla Table(id)
+ if id > 255 { RT_TABLE_COMPAT } else { id as u8 }
}
#[derive(Debug)]
struct NetworkInterface {
name: String,
- link_layer_type: u16,
+ link_layer_type: LinkLayerType,
}
impl NetworkInterface {
- fn is_loopback(&self) -> bool {
- self.link_layer_type == ARPHRD_LOOPBACK
+ const fn is_loopback(&self) -> bool {
+ matches!(self.link_layer_type, LinkLayerType::Loopback)
}
}
diff --git a/talpid-wireguard/Cargo.toml b/talpid-wireguard/Cargo.toml
index 02a37c4215..cf6e0f8acf 100644
--- a/talpid-wireguard/Cargo.toml
+++ b/talpid-wireguard/Cargo.toml
@@ -56,11 +56,10 @@ libc = "0.2.150"
talpid-net = { path = "../talpid-net" }
[target.'cfg(target_os = "linux")'.dependencies]
-rtnetlink = "0.11"
-netlink-packet-core = "0.4.2"
-netlink-packet-route = "0.13"
-netlink-packet-utils = "0.5.1"
-netlink-proto = "0.10"
+rtnetlink = { workspace = true }
+netlink-packet-core = { workspace = true }
+netlink-packet-route = { workspace = true }
+netlink-proto = { workspace = true }
talpid-dbus = { path = "../talpid-dbus" }
[target.'cfg(windows)'.dependencies]
diff --git a/talpid-wireguard/src/wireguard_kernel/mod.rs b/talpid-wireguard/src/wireguard_kernel/mod.rs
index eb2ebe0f5d..8332f00c98 100644
--- a/talpid-wireguard/src/wireguard_kernel/mod.rs
+++ b/talpid-wireguard/src/wireguard_kernel/mod.rs
@@ -1,20 +1,26 @@
use super::{Config, Tunnel, TunnelError};
use futures::future::{AbortHandle, abortable};
-use netlink_packet_core::{NetlinkDeserializable, constants::*};
-use netlink_packet_route::{
- NetlinkMessage, NetlinkPayload,
- rtnl::{
- AddressMessage, LinkMessage, RT_SCOPE_UNIVERSE, RtnlMessage,
- address::nlas::Nla as AddressNla,
- link::nlas::{Info, InfoKind, Nla as LinkNla},
- },
-};
-use netlink_packet_utils::DecodeError;
-use netlink_proto::{
- ConnectionHandle, Error as NetlinkError,
- sys::{SocketAddr, protocols::NETLINK_GENERIC},
-};
-use std::{ffi::CString, net::IpAddr};
+use netlink_packet_core::DecodeError;
+use netlink_packet_core::NLM_F_ACK;
+use netlink_packet_core::NLM_F_CREATE;
+use netlink_packet_core::NLM_F_DUMP;
+use netlink_packet_core::NLM_F_MATCH;
+use netlink_packet_core::NLM_F_REPLACE;
+use netlink_packet_core::NLM_F_REQUEST;
+use netlink_packet_core::NetlinkDeserializable;
+use netlink_packet_core::NetlinkMessage;
+use netlink_packet_core::NetlinkPayload;
+use netlink_packet_route::RouteNetlinkMessage;
+use netlink_packet_route::address::AddressMessage;
+use netlink_packet_route::link::LinkMessage;
+use netlink_proto::sys::{SocketAddr, protocols::NETLINK_GENERIC};
+use netlink_proto::{ConnectionHandle, Error as NetlinkError};
+use rtnetlink::AddressMessageBuilder;
+use rtnetlink::LinkMessageBuilder;
+use rtnetlink::LinkWireguard;
+use std::net::IpAddr;
+use std::net::Ipv4Addr;
+use std::net::Ipv6Addr;
use tokio_stream::StreamExt;
mod parsers;
@@ -60,10 +66,10 @@ pub enum Error {
NoDevice,
#[error("Failed to get config: {0}")]
- WgGetConf(netlink_packet_core::error::ErrorMessage),
+ WgGetConf(netlink_packet_core::ErrorMessage),
#[error("Failed to apply config: {0}")]
- WgSetConf(netlink_packet_core::error::ErrorMessage),
+ WgSetConf(netlink_packet_core::ErrorMessage),
#[error("Interface name too long")]
InterfaceName,
@@ -117,14 +123,14 @@ impl Handle {
}
async fn get_wireguard_message_type() -> Result<u16, Error> {
- let (conn, mut handle, _messages) =
+ let (conn, handle, _messages) =
netlink_proto::new_connection(NETLINK_GENERIC).map_err(Error::NetlinkSocket)?;
let (conn, abort_handle) = abortable(conn);
tokio::spawn(conn);
let result = async move {
let mut message: NetlinkMessage<NetlinkControlMessage> =
- NetlinkControlMessage::get_netlink_family_id(CString::new("wireguard").unwrap())
+ NetlinkControlMessage::get_netlink_family_id(c"wireguard".to_owned())
.map_err(Error::NetlinkControlMessage)?
.into();
@@ -154,54 +160,45 @@ impl Handle {
// create a wireguard device with the given name.
pub async fn create_device(&mut self, name: String, mtu: u32) -> Result<u32, Error> {
- let mut message = LinkMessage::default();
+ let message_builder = LinkMessageBuilder::<LinkWireguard>::new(&name)
+ // set link to be up
+ .up() // IFF_UP
+ // set link MTU
+ .mtu(mtu);
+ let message = message_builder.build();
- // set link to be up
- message.header.flags = netlink_packet_route::IFF_UP;
- // message.header.change_mask = netlink_packet_route::IFF_UP;
- // set link name
- message.nlas.push(LinkNla::IfName(name.clone()));
- // set link MTU
- message.nlas.push(LinkNla::Mtu(mtu));
- // set link type
- message
- .nlas
- .push(LinkNla::Info(vec![Info::Kind(InfoKind::Other(
- "wireguard".to_string(),
- ))]));
-
- let mut add_request = NetlinkMessage::from(RtnlMessage::NewLink(message));
- add_request.header.flags =
- NLM_F_REQUEST | NLM_F_ACK | NLM_F_REPLACE | NLM_F_CREATE | NLM_F_MATCH;
- let mut response = self
+ let reply = self
.route_handle
- .request(add_request)
- .map_err(Error::NetlinkCreateDevice)?;
- while let Some(response_message) = response.next().await {
- if let NetlinkPayload::Error(err) = response_message.payload {
- // if the device exists, verify that it's a wireguard device
- if -err.code != libc::EEXIST {
- return Err(Error::NetlinkCreateDevice(rtnetlink::Error::NetlinkError(
- err,
- )));
- }
- }
- }
+ .link()
+ .add(message)
+ .set_flags(NLM_F_REQUEST | NLM_F_ACK | NLM_F_REPLACE | NLM_F_CREATE | NLM_F_MATCH)
+ .execute()
+ .await;
- // fetch interface index of new device
- let new_device = self.wg_handle.get_by_name(name).await?;
- for nla in new_device.nlas {
- if let DeviceNla::IfIndex(index) = nla {
- return Ok(index);
- }
- }
+ if let Err(rtnetlink::Error::NetlinkError(err)) = reply
+ && -err.raw_code() != libc::EEXIST
+ {
+ return Err(Error::NetlinkCreateDevice(rtnetlink::Error::NetlinkError(
+ err,
+ )));
+ };
- Err(Error::NoDevice)
+ // fetch interface index of new device
+ self.wg_handle
+ .get_by_name(name)
+ .await?
+ .nlas
+ .into_iter()
+ .find_map(|nla| match nla {
+ DeviceNla::IfIndex(index) => Some(index),
+ _ => None,
+ })
+ .ok_or(Error::NoDevice)
}
pub async fn set_ip_address(&mut self, index: u32, addr: IpAddr) -> Result<(), Error> {
let address_message = add_ip_addr_message(index, addr);
- let mut request = NetlinkMessage::from(RtnlMessage::NewAddress(address_message));
+ let mut request = NetlinkMessage::from(RouteNetlinkMessage::NewAddress(address_message));
request.header.flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_CREATE | NLM_F_REPLACE;
let mut response = self
@@ -219,7 +216,7 @@ impl Handle {
let mut link_message = LinkMessage::default();
link_message.header.index = index;
- let mut request = NetlinkMessage::from(RtnlMessage::DelLink(link_message));
+ let mut request = NetlinkMessage::from(RouteNetlinkMessage::DelLink(link_message));
request.header.flags = NLM_F_REQUEST | NLM_F_ACK;
let mut response = self
@@ -273,7 +270,7 @@ impl WireguardConnection {
Some(received_message) => match received_message.payload {
NetlinkPayload::InnerMessage(inner) => Ok(inner),
NetlinkPayload::Error(err) => {
- if err.code == -libc::ENODEV {
+ if err.raw_code() == -libc::ENODEV {
Err(Error::NoDevice)
} else {
Err(Error::WgGetConf(err))
@@ -323,27 +320,15 @@ fn consume_netlink_error<
// the built-in support for adding addresses is too helpful, so a simple AddressMessage with a
// single Address nla is created
fn add_ip_addr_message(if_index: u32, addr: IpAddr) -> AddressMessage {
- let prefix_len = if addr.is_ipv4() { 32 } else { 128 };
- let mut message = AddressMessage::default();
- message.header.prefix_len = prefix_len;
- message.header.index = if_index;
- message.header.scope = RT_SCOPE_UNIVERSE;
-
+ // Note: Default scope is RT_SCOPE_UNIVERSE;
match addr {
- IpAddr::V4(ipv4) => {
- message.header.family = libc::AF_INET as u8;
- let ip_bytes = ipv4.octets().to_vec();
-
- message.nlas.push(AddressNla::Address(ip_bytes.clone()));
- message.nlas.push(AddressNla::Local(ip_bytes));
- }
- IpAddr::V6(ipv6) => {
- message.header.family = libc::AF_INET6 as u8;
- message
- .nlas
- .push(AddressNla::Address(ipv6.octets().to_vec()));
- }
- };
-
- message
+ IpAddr::V4(ipv4_addr) => AddressMessageBuilder::<Ipv4Addr>::new()
+ .address(ipv4_addr, 32)
+ .index(if_index)
+ .build(),
+ IpAddr::V6(ipv6_addr) => AddressMessageBuilder::<Ipv6Addr>::new()
+ .address(ipv6_addr, 128)
+ .index(if_index)
+ .build(),
+ }
}
diff --git a/talpid-wireguard/src/wireguard_kernel/nl_message.rs b/talpid-wireguard/src/wireguard_kernel/nl_message.rs
index 5bed6b1d45..2c77650112 100644
--- a/talpid-wireguard/src/wireguard_kernel/nl_message.rs
+++ b/talpid-wireguard/src/wireguard_kernel/nl_message.rs
@@ -1,12 +1,10 @@
use super::parsers;
use byteorder::{ByteOrder, NativeEndian};
use netlink_packet_core::{
- NetlinkDeserializable, NetlinkHeader, NetlinkPayload, NetlinkSerializable,
+ DecodeError, Emitable, Nla, NlaBuffer, NlasIterator, Parseable, parse_u16,
};
-use netlink_packet_utils::{
- DecodeError,
- nla::{Nla, NlaBuffer, NlasIterator},
- traits::{Emitable, Parseable},
+use netlink_packet_core::{
+ NetlinkDeserializable, NetlinkHeader, NetlinkPayload, NetlinkSerializable,
};
use std::{ffi::CString, io::Write, mem};
@@ -125,7 +123,7 @@ impl<'a, T: AsRef<[u8]> + 'a + ?Sized + std::fmt::Debug> Parseable<NlaBuffer<&'a
libc::CTRL_ATTR_FAMILY_NAME => {
ControlNla::FamilyName(parsers::parse_cstring(buf.value())?)
}
- libc::CTRL_ATTR_FAMILY_ID => ControlNla::FamilyId(parsers::parse_u16(buf.value())?),
+ libc::CTRL_ATTR_FAMILY_ID => ControlNla::FamilyId(parse_u16(buf.value())?),
_unknown_kind => ControlNla::Unknown(buf.kind(), buf.value().to_vec()),
};
Ok(nla)
diff --git a/talpid-wireguard/src/wireguard_kernel/parsers.rs b/talpid-wireguard/src/wireguard_kernel/parsers.rs
index f534565b96..a3a9eeffbb 100644
--- a/talpid-wireguard/src/wireguard_kernel/parsers.rs
+++ b/talpid-wireguard/src/wireguard_kernel/parsers.rs
@@ -9,8 +9,7 @@ use std::{
net::{IpAddr, SocketAddr},
};
-use netlink_packet_utils::DecodeError;
-pub use netlink_packet_utils::parsers::*;
+use netlink_packet_core::DecodeError;
pub fn parse_ip_addr(bytes: &[u8]) -> Result<IpAddr, DecodeError> {
if bytes.len() == 4 {
diff --git a/talpid-wireguard/src/wireguard_kernel/wg_message.rs b/talpid-wireguard/src/wireguard_kernel/wg_message.rs
index 5ef863aa9f..d56fe5f9fd 100644
--- a/talpid-wireguard/src/wireguard_kernel/wg_message.rs
+++ b/talpid-wireguard/src/wireguard_kernel/wg_message.rs
@@ -1,13 +1,15 @@
+use crate::wireguard_kernel::parsers::{parse_cstring, parse_inet_sockaddr, parse_ip_addr};
+
use super::{super::config::Config, Error, parsers};
use byteorder::{ByteOrder, NativeEndian};
use ipnetwork::IpNetwork;
use netlink_packet_core::{
- NetlinkDeserializable, NetlinkHeader, NetlinkPayload, NetlinkSerializable,
+ DecodeError, NLA_F_NESTED, Nla, NlaBuffer, NlasIterator, parse_u8, parse_u16, parse_u32,
+ parse_u64,
};
-use netlink_packet_utils::{
- DecodeError,
- nla::{NLA_F_NESTED, Nla, NlaBuffer, NlasIterator},
- traits::{Emitable, Parseable},
+use netlink_packet_core::{Emitable, Parseable};
+use netlink_packet_core::{
+ NetlinkDeserializable, NetlinkHeader, NetlinkPayload, NetlinkSerializable,
};
use nix::sys::{
socket::{SockaddrIn, SockaddrIn6},
@@ -269,13 +271,13 @@ impl<'a, T: AsRef<[u8]> + 'a + ?Sized + core::fmt::Debug> Parseable<NlaBuffer<&'
let value = buf.value();
let kind = buf.kind();
let nla = match kind {
- WGDEVICE_A_IFINDEX => IfIndex(parsers::parse_u32(value)?),
- WGDEVICE_A_IFNAME => IfName(parsers::parse_cstring(value)?),
+ WGDEVICE_A_IFINDEX => IfIndex(parse_u32(value)?),
+ WGDEVICE_A_IFNAME => IfName(parse_cstring(value)?),
WGDEVICE_A_PRIVATE_KEY => PrivateKey(parsers::parse_wg_key(value)?),
WGDEVICE_A_PUBLIC_KEY => PublicKey(parsers::parse_wg_key(value)?),
- WGDEVICE_A_FLAGS => Flags(parsers::parse_u32(value)?),
- WGDEVICE_A_LISTEN_PORT => ListenPort(parsers::parse_u16(value)?),
- WGDEVICE_A_FWMARK => Fwmark(parsers::parse_u32(value)?),
+ WGDEVICE_A_FLAGS => Flags(parse_u32(value)?),
+ WGDEVICE_A_LISTEN_PORT => ListenPort(parse_u16(value)?),
+ WGDEVICE_A_FWMARK => Fwmark(parse_u32(value)?),
WGDEVICE_A_PEERS => {
let peers = NlasIterator::new(value)
.map(|nla_bytes| {
@@ -437,15 +439,15 @@ impl<'a, T: AsRef<[u8]> + 'a + ?Sized> Parseable<NlaBuffer<&'a T>> for PeerNla {
let nla = match buf.kind() {
WGPEER_A_PUBLIC_KEY => PublicKey(parsers::parse_wg_key(value)?),
WGPEER_A_PRESHARED_KEY => PresharedKey(parsers::parse_wg_key(value)?),
- WGPEER_A_FLAGS => Flags(parsers::parse_u32(value)?),
- WGPEER_A_ENDPOINT => Endpoint(parsers::parse_inet_sockaddr(value)?),
+ WGPEER_A_FLAGS => Flags(parse_u32(value)?),
+ WGPEER_A_ENDPOINT => Endpoint(parse_inet_sockaddr(value)?),
WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL => {
- PersistentKeepaliveInterval(parsers::parse_u16(value)?)
+ PersistentKeepaliveInterval(parse_u16(value)?)
}
WGPEER_A_LAST_HANDSHAKE_TIME => LastHandshakeTime(parsers::parse_timespec(value)?),
- WGPEER_A_RX_BYTES => RxBytes(parsers::parse_u64(value)?),
- WGPEER_A_TX_BYTES => TxBytes(parsers::parse_u64(value)?),
+ WGPEER_A_RX_BYTES => RxBytes(parse_u64(value)?),
+ WGPEER_A_TX_BYTES => TxBytes(parse_u64(value)?),
WGPEER_A_ALLOWEDIPS => {
let nlas = NlasIterator::new(value)
.map(|nla_buffer| AllowedIpMessage::parse(&nla_buffer?))
@@ -453,7 +455,7 @@ impl<'a, T: AsRef<[u8]> + 'a + ?Sized> Parseable<NlaBuffer<&'a T>> for PeerNla {
AllowedIps(nlas)
}
- WGPEER_A_PROTOCOL_VERSION => ProtocolVersion(parsers::parse_u32(value)?),
+ WGPEER_A_PROTOCOL_VERSION => ProtocolVersion(parse_u32(value)?),
WGPEER_A_UNSPEC => Unspec(value.to_vec()),
_ => {
return Err(format!("Unexpected peer attribute kind: {}", buf.kind()).into());
@@ -561,9 +563,9 @@ impl<'a, T: AsRef<[u8]> + 'a + ?Sized> Parseable<NlaBuffer<&'a T>> for AllowedIp
use AllowedIpNla::*;
let value = buf.value();
let nla = match buf.kind() {
- WGALLOWEDIP_A_FAMILY => AddressFamily(parsers::parse_u16(value)?),
- WGALLOWEDIP_A_IPADDR => IpAddr(parsers::parse_ip_addr(value)?),
- WGALLOWEDIP_A_CIDR_MASK => CidrMask(parsers::parse_u8(value)?),
+ WGALLOWEDIP_A_FAMILY => AddressFamily(parse_u16(value)?),
+ WGALLOWEDIP_A_IPADDR => IpAddr(parse_ip_addr(value)?),
+ WGALLOWEDIP_A_CIDR_MASK => CidrMask(parse_u8(value)?),
WGALLOWEDIP_A_UNSPEC => Unspec(value.to_vec()),
_ => Err(format!(
"Unexpected allowed IP attribute kind: {}",
@@ -694,13 +696,12 @@ mod test {
// 8 bytes of WGALLOWEDIP_A_IPADDR 192.168.40.2
0x08, 0x00, 0x02, 0x00, 0xc0, 0xa8, 0x27, 0x02,
];
- let header = NetlinkHeader {
- length: payload.len() as u32,
- message_type: 0,
- flags: 0,
- sequence_number: 0,
- port_number: 0,
+ let header = {
+ let mut header = NetlinkHeader::default();
+ header.length = payload.len() as u32;
+ header
};
+
let message = DeviceMessage::deserialize(&header, &payload).unwrap();
let mut serialized_message = vec![0u8; payload.len()];
@@ -862,12 +863,10 @@ mod test {
let mut payload_buffer = vec![0u8; message.buffer_len()];
message.serialize(&mut payload_buffer);
- let header = NetlinkHeader {
- length: payload_buffer.len() as u32,
- message_type: 0,
- flags: 0,
- sequence_number: 0,
- port_number: 0,
+ let header = {
+ let mut header = NetlinkHeader::default();
+ header.length = payload_buffer.len() as u32;
+ header
};
let deserialized_device = DeviceMessage::deserialize(&header, &payload_buffer).unwrap();