diff --git a/Cargo.lock b/Cargo.lock index 8bf05db..ca423c4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -862,14 +862,15 @@ dependencies = [ [[package]] name = "netlink-packet-route" -version = "0.17.1" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "053998cea5a306971f88580d0829e90f270f940befd7cf928da179d4187a5a66" +checksum = "483325d4bfef65699214858f097d504eb812c38ce7077d165f301ec406c3066e" dependencies = [ "anyhow", - "bitflags 1.3.2", + "bitflags 2.5.0", "byteorder", "libc", + "log", "netlink-packet-core", "netlink-packet-utils", ] diff --git a/netlink-request/Cargo.toml b/netlink-request/Cargo.toml index 7eda69b..95e1eae 100644 --- a/netlink-request/Cargo.toml +++ b/netlink-request/Cargo.toml @@ -14,7 +14,7 @@ version = "1.6.1" netlink-sys = "0.8.5" netlink-packet-core = "0.7" netlink-packet-generic = "0.3.3" -netlink-packet-route = "0.17" +netlink-packet-route = "0.21" netlink-packet-utils = "0.5.2" nix = { version = "0.25", features = ["feature"] } once_cell = "1" diff --git a/netlink-request/src/lib.rs b/netlink-request/src/lib.rs index 1baf446..a5611c3 100644 --- a/netlink-request/src/lib.rs +++ b/netlink-request/src/lib.rs @@ -9,7 +9,7 @@ mod linux { ctrl::{nlas::GenlCtrlAttrs, GenlCtrl, GenlCtrlCmd}, GenlFamily, GenlHeader, GenlMessage, }; - use netlink_packet_route::RtnlMessage; + use netlink_packet_route::RouteNetlinkMessage; use netlink_packet_utils::{Emitable, ParseableParametrized}; use netlink_sys::{constants::NETLINK_GENERIC, protocols::NETLINK_ROUTE, Socket}; use nix::unistd::{sysconf, SysconfVar}; @@ -86,9 +86,9 @@ mod linux { } pub fn netlink_request_rtnl( - message: RtnlMessage, + message: RouteNetlinkMessage, flags: Option, - ) -> Result>, io::Error> { + ) -> Result>, io::Error> { netlink_request(message, flags, NETLINK_ROUTE) } diff --git a/shared/Cargo.toml b/shared/Cargo.toml index 402b261..3d90a9c 100644 --- a/shared/Cargo.toml +++ b/shared/Cargo.toml @@ -31,7 +31,7 @@ wireguard-control = { path = "../wireguard-control" } [target.'cfg(target_os = "linux")'.dependencies] netlink-packet-core = "0.7" -netlink-packet-route = "0.17" +netlink-packet-route = "0.21" netlink-request = { path = "../netlink-request" } netlink-sys = "0.8.5" diff --git a/shared/src/netlink.rs b/shared/src/netlink.rs index 5dcfc67..940075d 100644 --- a/shared/src/netlink.rs +++ b/shared/src/netlink.rs @@ -4,11 +4,10 @@ use netlink_packet_core::{ NLM_F_REQUEST, }; use netlink_packet_route::{ - address, - constants::*, - link::{self, nlas::State}, - route, AddressHeader, AddressMessage, LinkHeader, LinkMessage, RouteHeader, RouteMessage, - RtnlMessage, RTN_UNICAST, RT_SCOPE_LINK, RT_TABLE_MAIN, + address::{self, AddressHeader, AddressMessage}, + link::{self, LinkFlags, LinkHeader, LinkMessage, State}, + route::{self, RouteHeader, RouteMessage}, + AddressFamily, RouteNetlinkMessage, }; use netlink_request::netlink_request_rtnl; use std::{io, net::IpAddr}; @@ -28,13 +27,13 @@ pub fn set_up(interface: &InterfaceName, mtu: u32) -> Result<(), io::Error> { let index = if_nametoindex(interface)?; let header = LinkHeader { index, - flags: IFF_UP, + flags: LinkFlags::Up, ..Default::default() }; let mut message = LinkMessage::default(); message.header = header; - message.nlas = vec![link::nlas::Nla::Mtu(mtu)]; - netlink_request_rtnl(RtnlMessage::SetLink(message), None)?; + message.attributes = vec![link::LinkAttribute::Mtu(mtu)]; + netlink_request_rtnl(RouteNetlinkMessage::SetLink(message), None)?; log::debug!("set interface {} up with mtu {}", interface, mtu); Ok(()) } @@ -43,33 +42,35 @@ pub fn set_addr(interface: &InterfaceName, addr: IpNet) -> Result<(), io::Error> let index = if_nametoindex(interface)?; let (family, nlas) = match addr { IpNet::V4(network) => { - let addr_bytes = network.addr().octets().to_vec(); + let addr = IpAddr::V4(network.addr()); ( - AF_INET as u8, + AddressFamily::Inet, vec![ - address::Nla::Local(addr_bytes.clone()), - address::Nla::Address(addr_bytes), + address::AddressAttribute::Local(addr), + address::AddressAttribute::Address(addr), ], ) }, IpNet::V6(network) => ( - AF_INET6 as u8, - vec![address::Nla::Address(network.addr().octets().to_vec())], + AddressFamily::Inet6, + vec![address::AddressAttribute::Address(IpAddr::V6( + network.addr(), + ))], ), }; let header = AddressHeader { index, family, prefix_len: addr.prefix_len(), - scope: RT_SCOPE_UNIVERSE, + scope: address::AddressScope::Universe, ..Default::default() }; let mut message = AddressMessage::default(); message.header = header; - message.nlas = nlas; + message.attributes = nlas; netlink_request_rtnl( - RtnlMessage::NewAddress(message), + RouteNetlinkMessage::NewAddress(message), Some(NLM_F_REQUEST | NLM_F_ACK | NLM_F_REPLACE | NLM_F_CREATE), )?; log::debug!("set address {} on interface {}", addr, interface); @@ -79,23 +80,29 @@ pub fn set_addr(interface: &InterfaceName, addr: IpNet) -> Result<(), io::Error> pub fn add_route(interface: &InterfaceName, cidr: IpNet) -> Result { let if_index = if_nametoindex(interface)?; let (address_family, dst) = match cidr { - IpNet::V4(network) => (AF_INET as u8, network.network().octets().to_vec()), - IpNet::V6(network) => (AF_INET6 as u8, network.network().octets().to_vec()), + IpNet::V4(network) => ( + AddressFamily::Inet, + route::RouteAttribute::Destination(route::RouteAddress::Inet(network.network())), + ), + IpNet::V6(network) => ( + AddressFamily::Inet6, + route::RouteAttribute::Destination(route::RouteAddress::Inet6(network.network())), + ), }; let header = RouteHeader { - table: RT_TABLE_MAIN, - protocol: RTPROT_BOOT, - scope: RT_SCOPE_LINK, - kind: RTN_UNICAST, + table: RouteHeader::RT_TABLE_MAIN, + protocol: route::RouteProtocol::Boot, + scope: route::RouteScope::Link, + kind: route::RouteType::Unicast, destination_prefix_length: cidr.prefix_len(), address_family, ..Default::default() }; let mut message = RouteMessage::default(); message.header = header; - message.nlas = vec![route::Nla::Destination(dst), route::Nla::Oif(if_index)]; + message.attributes = vec![dst, route::RouteAttribute::Oif(if_index)]; - match netlink_request_rtnl(RtnlMessage::NewRoute(message), None) { + match netlink_request_rtnl(RouteNetlinkMessage::NewRoute(message), None) { Ok(_) => { log::debug!("added route {} to interface {}", cidr, interface); Ok(true) @@ -110,7 +117,7 @@ pub fn add_route(interface: &InterfaceName, cidr: IpNet) -> Result Result, io::Error> { let link_responses = netlink_request_rtnl( - RtnlMessage::GetLink(LinkMessage::default()), + RouteNetlinkMessage::GetLink(LinkMessage::default()), Some(NLM_F_DUMP | NLM_F_REQUEST), )?; let links = link_responses @@ -118,21 +125,21 @@ fn get_links() -> Result, io::Error> { // Filter out non-link messages .filter_map(|response| match response { NetlinkMessage { - payload: NetlinkPayload::InnerMessage(RtnlMessage::NewLink(link)), + payload: NetlinkPayload::InnerMessage(RouteNetlinkMessage::NewLink(link)), .. } => Some(link), _ => None, }) // Filter out loopback links - .filter_map(|link| if link.header.flags & IFF_LOOPBACK == 0 { - Some(link.nlas) + .filter_map(|link| if link.header.flags.contains(LinkFlags::Loopback) { + Some(link.attributes) } else { None }) // Find and filter out addresses for interfaces - .filter(|nlas| nlas.iter().any(|nla| nla == &link::nlas::Nla::OperState(State::Up))) + .filter(|nlas| nlas.iter().any(|nla| nla == &link::LinkAttribute::OperState(State::Up))) .filter_map(|nlas| nlas.iter().find_map(|nla| match nla { - link::nlas::Nla::IfName(name) => Some(name.clone()), + link::LinkAttribute::IfName(name) => Some(name.clone()), _ => None, })) .collect::>(); @@ -143,7 +150,7 @@ fn get_links() -> Result, io::Error> { pub fn get_local_addrs() -> Result, io::Error> { let links = get_links()?; let addr_responses = netlink_request_rtnl( - RtnlMessage::GetAddress(AddressMessage::default()), + RouteNetlinkMessage::GetAddress(AddressMessage::default()), Some(NLM_F_DUMP | NLM_F_REQUEST), )?; let addrs = addr_responses @@ -151,33 +158,25 @@ pub fn get_local_addrs() -> Result, io::Error> { // Filter out non-link messages .filter_map(|response| match response { NetlinkMessage { - payload: NetlinkPayload::InnerMessage(RtnlMessage::NewAddress(addr)), + payload: NetlinkPayload::InnerMessage(RouteNetlinkMessage::NewAddress(addr)), .. } => Some(addr), _ => None, }) // Filter out non-global-scoped addresses - .filter_map(|link| if link.header.scope == RT_SCOPE_UNIVERSE { - Some(link.nlas) + .filter_map(|link| if link.header.scope == address::AddressScope::Universe { + Some(link.attributes) } else { None }) // Only select addresses for helpful links .filter(move |nlas| nlas.iter().any(|nla| { - matches!(nla, address::nlas::Nla::Label(label) if links.contains(label)) - || matches!(nla, address::nlas::Nla::Address(name) if name.len() == 16) + matches!(nla, address::AddressAttribute::Label(label) if links.contains(label)) + || matches!(nla, address::AddressAttribute::Address(IpAddr::V6(_addr))) })) .filter_map(|nlas| nlas.iter().find_map(|nla| match nla { - address::nlas::Nla::Address(name) if name.len() == 4 => { - let mut addr = [0u8; 4]; - addr.copy_from_slice(name); - Some(IpAddr::V4(addr.into())) - }, - address::nlas::Nla::Address(name) if name.len() == 16 => { - let mut addr = [0u8; 16]; - addr.copy_from_slice(name); - Some(IpAddr::V6(addr.into())) - }, + address::AddressAttribute::Address(IpAddr::V4(addr)) => Some(IpAddr::V4(*addr)), + address::AddressAttribute::Address(IpAddr::V6(addr)) => Some(IpAddr::V6(*addr)), _ => None, })); Ok(addrs) diff --git a/wireguard-control/Cargo.toml b/wireguard-control/Cargo.toml index c718699..411b747 100644 --- a/wireguard-control/Cargo.toml +++ b/wireguard-control/Cargo.toml @@ -21,7 +21,7 @@ x25519-dalek = { version = "2.0.1", features = ["static_secrets"] } [target.'cfg(target_os = "linux")'.dependencies] netlink-packet-core = "0.7" netlink-packet-generic = "0.3.3" -netlink-packet-route = "0.17" +netlink-packet-route = "0.21" netlink-packet-utils = "0.5.2" netlink-packet-wireguard = "0.2.3" netlink-request = { path = "../netlink-request", version = "1.6.1" } diff --git a/wireguard-control/src/backends/kernel.rs b/wireguard-control/src/backends/kernel.rs index 71837b1..9b4ac0b 100644 --- a/wireguard-control/src/backends/kernel.rs +++ b/wireguard-control/src/backends/kernel.rs @@ -7,17 +7,16 @@ use netlink_packet_core::{ }; use netlink_packet_generic::GenlMessage; use netlink_packet_route::{ - constants::*, - link::{ - self, - nlas::{Info, InfoKind}, - }, - LinkMessage, RtnlMessage, + link::{self, InfoKind, LinkInfo, LinkMessage}, + RouteNetlinkMessage, }; use netlink_packet_utils::traits::Emitable; use netlink_packet_wireguard::{ self, - constants::{WGDEVICE_F_REPLACE_PEERS, WGPEER_F_REMOVE_ME, WGPEER_F_REPLACE_ALLOWEDIPS}, + constants::{ + AF_INET, AF_INET6, WGDEVICE_F_REPLACE_PEERS, WGPEER_F_REMOVE_ME, + WGPEER_F_REPLACE_ALLOWEDIPS, + }, nlas::{WgAllowedIp, WgAllowedIpAttrs, WgDeviceAttrs, WgPeer, WgPeerAttrs}, Wireguard, WireguardCmd, }; @@ -166,7 +165,7 @@ impl<'a> TryFrom<&'a [WgDeviceAttrs]> for Device { pub fn enumerate() -> Result, io::Error> { let link_responses = netlink_request_rtnl( - RtnlMessage::GetLink(LinkMessage::default()), + RouteNetlinkMessage::GetLink(LinkMessage::default()), Some(NLM_F_DUMP | NLM_F_REQUEST), )?; let links = link_responses @@ -174,21 +173,21 @@ pub fn enumerate() -> Result, io::Error> { // Filter out non-link messages .filter_map(|response| match response { NetlinkMessage { - payload: NetlinkPayload::InnerMessage(RtnlMessage::NewLink(link)), + payload: NetlinkPayload::InnerMessage(RouteNetlinkMessage::NewLink(link)), .. } => Some(link), _ => None, }) .filter(|link| { - for nla in link.nlas.iter() { - if let link::nlas::Nla::Info(infos) = nla { - return infos.iter().any(|info| info == &Info::Kind(InfoKind::Wireguard)) + for nla in link.attributes.iter() { + if let link::LinkAttribute::LinkInfo(infos) = nla { + return infos.iter().any(|info| info == &LinkInfo::Kind(InfoKind::Wireguard)) } } false }) - .filter_map(|link| link.nlas.iter().find_map(|nla| match nla { - link::nlas::Nla::IfName(name) => Some(name.clone()), + .filter_map(|link| link.attributes.iter().find_map(|nla| match nla { + link::LinkAttribute::IfName(name) => Some(name.clone()), _ => None, })) .filter_map(|name| name.parse().ok()) @@ -199,17 +198,19 @@ pub fn enumerate() -> Result, io::Error> { fn add_del(iface: &InterfaceName, add: bool) -> io::Result<()> { let mut message = LinkMessage::default(); + message.attributes.push(link::LinkAttribute::IfName( + iface.as_str_lossy().to_string(), + )); message - .nlas - .push(link::nlas::Nla::IfName(iface.as_str_lossy().to_string())); - message.nlas.push(link::nlas::Nla::Info(vec![Info::Kind( - link::nlas::InfoKind::Wireguard, - )])); + .attributes + .push(link::LinkAttribute::LinkInfo(vec![LinkInfo::Kind( + link::InfoKind::Wireguard, + )])); let extra_flags = if add { NLM_F_CREATE | NLM_F_EXCL } else { 0 }; let rtnl_message = if add { - RtnlMessage::NewLink(message) + RouteNetlinkMessage::NewLink(message) } else { - RtnlMessage::DelLink(message) + RouteNetlinkMessage::DelLink(message) }; match netlink_request_rtnl(rtnl_message, Some(NLM_F_REQUEST | NLM_F_ACK | extra_flags)) { Err(e) if e.kind() != io::ErrorKind::AlreadyExists => Err(e),