diff options
| author | Markus Pettersson <markus.pettersson@mullvad.net> | 2025-09-17 13:26:29 +0200 |
|---|---|---|
| committer | Markus Pettersson <markus.pettersson@mullvad.net> | 2025-09-17 13:26:29 +0200 |
| commit | 8b7d65c2e0083076a1ccf65d49079f050a4bfe36 (patch) | |
| tree | 39af70d05324434a5059829b213adb1b6f762ebc | |
| parent | 5a4f45316c2da3da02bb2fc3f4e3e89df227e654 (diff) | |
| parent | c9baf1ed9f051fcd3e70050d7539bcf199426e0d (diff) | |
| download | mullvadvpn-8b7d65c2e0083076a1ccf65d49079f050a4bfe36.tar.xz mullvadvpn-8b7d65c2e0083076a1ccf65d49079f050a4bfe36.zip | |
Merge branch 'use-pastey'
| -rw-r--r-- | Cargo.lock | 71 | ||||
| -rw-r--r-- | Cargo.toml | 6 | ||||
| -rw-r--r-- | talpid-routing/Cargo.toml | 7 | ||||
| -rw-r--r-- | talpid-routing/src/lib.rs | 5 | ||||
| -rw-r--r-- | talpid-routing/src/unix/linux.rs | 436 | ||||
| -rw-r--r-- | talpid-wireguard/Cargo.toml | 9 | ||||
| -rw-r--r-- | talpid-wireguard/src/wireguard_kernel/mod.rs | 151 | ||||
| -rw-r--r-- | talpid-wireguard/src/wireguard_kernel/nl_message.rs | 10 | ||||
| -rw-r--r-- | talpid-wireguard/src/wireguard_kernel/parsers.rs | 3 | ||||
| -rw-r--r-- | talpid-wireguard/src/wireguard_kernel/wg_message.rs | 61 |
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(); |
