Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update netlink-packet-route to 0.21 #324

Merged
merged 1 commit into from
Oct 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion netlink-request/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
6 changes: 3 additions & 3 deletions netlink-request/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -86,9 +86,9 @@ mod linux {
}

pub fn netlink_request_rtnl(
message: RtnlMessage,
message: RouteNetlinkMessage,
flags: Option<u16>,
) -> Result<Vec<NetlinkMessage<RtnlMessage>>, io::Error> {
) -> Result<Vec<NetlinkMessage<RouteNetlinkMessage>>, io::Error> {
netlink_request(message, flags, NETLINK_ROUTE)
}

Expand Down
2 changes: 1 addition & 1 deletion shared/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down
93 changes: 46 additions & 47 deletions shared/src/netlink.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand All @@ -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(())
}
Expand All @@ -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);
Expand All @@ -79,23 +80,29 @@ pub fn set_addr(interface: &InterfaceName, addr: IpNet) -> Result<(), io::Error>
pub fn add_route(interface: &InterfaceName, cidr: IpNet) -> Result<bool, io::Error> {
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)
Expand All @@ -110,29 +117,29 @@ pub fn add_route(interface: &InterfaceName, cidr: IpNet) -> Result<bool, io::Err

fn get_links() -> Result<Vec<String>, 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
.into_iter()
// 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::<Vec<_>>();
Expand All @@ -143,41 +150,33 @@ fn get_links() -> Result<Vec<String>, io::Error> {
pub fn get_local_addrs() -> Result<impl Iterator<Item = IpAddr>, 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
.into_iter()
// 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)
Expand Down
2 changes: 1 addition & 1 deletion wireguard-control/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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" }
Expand Down
43 changes: 22 additions & 21 deletions wireguard-control/src/backends/kernel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};
Expand Down Expand Up @@ -166,29 +165,29 @@ impl<'a> TryFrom<&'a [WgDeviceAttrs]> for Device {

pub fn enumerate() -> Result<Vec<InterfaceName>, 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
.into_iter()
// 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())
Expand All @@ -199,17 +198,19 @@ pub fn enumerate() -> Result<Vec<InterfaceName>, 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),
Expand Down
Loading