mirror of
https://github.com/outbackdingo/firezone.git
synced 2026-01-27 10:18:54 +00:00
chore(rust): bump to Rust 1.88 (#9714)
Rust 1.88 has been released and brings with it a quite exciting feature: let-chains! It allows us to mix-and-match `if` and `let` expressions, therefore often reducing the "right-drift" of the relevant code, making it easier to read. Rust.188 also comes with a new clippy lint that warns when creating a mutable reference from an immutable pointer. Attempting to fix this revealed that this is exactly what we are doing in the eBPF kernel. Unfortunately, it doesn't seem to be possible to design this in a way that is both accepted by the borrow-checker AND by the eBPF verifier. Hence, we simply make the function `unsafe` and document for the programmer, what needs to be upheld.
This commit is contained in:
2
.github/actions/setup-rust/action.yml
vendored
2
.github/actions/setup-rust/action.yml
vendored
@@ -64,7 +64,7 @@ runs:
|
||||
- name: Install nightly Rust
|
||||
id: nightly
|
||||
run: |
|
||||
NIGHTLY="nightly-2024-12-13"
|
||||
NIGHTLY="nightly-2025-05-30"
|
||||
|
||||
rustup toolchain install $NIGHTLY
|
||||
rustup component add rust-src --toolchain $NIGHTLY
|
||||
|
||||
@@ -5,9 +5,9 @@ fn main() {
|
||||
|
||||
let bridges = vec!["src/lib.rs"];
|
||||
for path in &bridges {
|
||||
println!("cargo:rerun-if-changed={}", path);
|
||||
println!("cargo:rerun-if-changed={path}");
|
||||
}
|
||||
println!("cargo:rerun-if-env-changed={}", XCODE_CONFIGURATION_ENV);
|
||||
println!("cargo:rerun-if-env-changed={XCODE_CONFIGURATION_ENV}");
|
||||
|
||||
swift_bridge_build::parse_bridges(bridges)
|
||||
.write_all_concatenated(out_dir, env!("CARGO_PKG_NAME"));
|
||||
|
||||
@@ -35,7 +35,7 @@ pub fn logs() -> Option<PathBuf> {
|
||||
/// Runtime directory for temporary files
|
||||
pub fn runtime() -> Option<PathBuf> {
|
||||
let user = std::env::var("USER").ok()?;
|
||||
Some(PathBuf::from("/tmp").join(format!("{}-{}", BUNDLE_ID, user)))
|
||||
Some(PathBuf::from("/tmp").join(format!("{BUNDLE_ID}-{user}")))
|
||||
}
|
||||
|
||||
/// User session data directory
|
||||
|
||||
@@ -3,8 +3,5 @@ disallowed-methods = [
|
||||
{ path = "std::collections::HashMap::iter", reason = "HashMap has non-deterministic iteration order, use BTreeMap instead" },
|
||||
{ path = "std::collections::HashSet::iter", reason = "HashSet has non-deterministic iteration order, use BTreeSet instead" },
|
||||
{ path = "std::collections::HashMap::iter_mut", reason = "HashMap has non-deterministic iteration order, use BTreeMap instead" },
|
||||
{ path = "std::collections::HashSet::iter_mut", reason = "HashSet has non-deterministic iteration order, use BTreeSet instead" },
|
||||
{ path = "std::collections::HashMap::into_iter", reason = "HashMap has non-deterministic iteration order, use BTreeMap instead" },
|
||||
{ path = "std::collections::HashSet::into_iter", reason = "HashSet has non-deterministic iteration order, use BTreeSet instead" },
|
||||
{ path = "tracing::subscriber::set_global_default", reason = "Does not init `LogTracer`, use `firezone_logging::init` instead." },
|
||||
]
|
||||
|
||||
@@ -136,20 +136,20 @@ impl Server {
|
||||
}));
|
||||
}
|
||||
|
||||
if let Some(tcp_v4) = self.tcp_v4.as_mut() {
|
||||
if let Poll::Ready((stream, from)) = tcp_v4.poll_accept(cx)? {
|
||||
self.reading_tcp_queries
|
||||
.push(read_tcp_query(stream, from).boxed());
|
||||
continue;
|
||||
}
|
||||
if let Some(tcp_v4) = self.tcp_v4.as_mut()
|
||||
&& let Poll::Ready((stream, from)) = tcp_v4.poll_accept(cx)?
|
||||
{
|
||||
self.reading_tcp_queries
|
||||
.push(read_tcp_query(stream, from).boxed());
|
||||
continue;
|
||||
}
|
||||
|
||||
if let Some(tcp_v6) = self.tcp_v6.as_mut() {
|
||||
if let Poll::Ready((stream, from)) = tcp_v6.poll_accept(cx)? {
|
||||
self.reading_tcp_queries
|
||||
.push(read_tcp_query(stream, from).boxed());
|
||||
continue;
|
||||
}
|
||||
if let Some(tcp_v6) = self.tcp_v6.as_mut()
|
||||
&& let Poll::Ready((stream, from)) = tcp_v6.poll_accept(cx)?
|
||||
{
|
||||
self.reading_tcp_queries
|
||||
.push(read_tcp_query(stream, from).boxed());
|
||||
continue;
|
||||
}
|
||||
|
||||
self.waker.register(cx.waker());
|
||||
|
||||
@@ -622,13 +622,13 @@ impl ClientState {
|
||||
return Ok(Ok(()));
|
||||
};
|
||||
|
||||
if let Some(old_gateway_id) = self.resources_gateways.insert(resource_id, gateway_id) {
|
||||
if self.peers.get(&old_gateway_id).is_some() {
|
||||
assert_eq!(
|
||||
old_gateway_id, gateway_id,
|
||||
"Resources are not expected to change gateways without a previous message, resource_id = {resource_id}"
|
||||
);
|
||||
}
|
||||
if let Some(old_gateway_id) = self.resources_gateways.insert(resource_id, gateway_id)
|
||||
&& self.peers.get(&old_gateway_id).is_some()
|
||||
{
|
||||
assert_eq!(
|
||||
old_gateway_id, gateway_id,
|
||||
"Resources are not expected to change gateways without a previous message, resource_id = {resource_id}"
|
||||
)
|
||||
}
|
||||
|
||||
match self.node.upsert_connection(
|
||||
|
||||
@@ -36,11 +36,11 @@ impl NatTable {
|
||||
Protocol::Icmp(_) => ICMP_TTL,
|
||||
};
|
||||
|
||||
if now.duration_since(*e) >= ttl {
|
||||
if let Some((inside, _)) = self.table.remove_by_right(outside) {
|
||||
tracing::debug!(?inside, ?outside, ?ttl, "NAT session expired");
|
||||
self.expired.insert(*outside);
|
||||
}
|
||||
if now.duration_since(*e) >= ttl
|
||||
&& let Some((inside, _)) = self.table.remove_by_right(outside)
|
||||
{
|
||||
tracing::debug!(?inside, ?outside, ?ttl, "NAT session expired");
|
||||
self.expired.insert(*outside);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -168,8 +168,8 @@ impl ReferenceState {
|
||||
"private keys must be unique",
|
||||
|(c, gateways, _, _, _, _, _, _, _)| {
|
||||
let different_keys = gateways
|
||||
.iter()
|
||||
.map(|(_, g)| g.inner().key)
|
||||
.values()
|
||||
.map(|g| g.inner().key)
|
||||
.chain(iter::once(c.inner().key))
|
||||
.collect::<HashSet<_>>();
|
||||
|
||||
|
||||
@@ -204,20 +204,20 @@ impl SimClient {
|
||||
}
|
||||
|
||||
fn update_sent_requests(&mut self, packet: &IpPacket) {
|
||||
if let Some(icmp) = packet.as_icmpv4() {
|
||||
if let Icmpv4Type::EchoRequest(echo) = icmp.icmp_type() {
|
||||
self.sent_icmp_requests
|
||||
.insert((Seq(echo.seq), Identifier(echo.id)), packet.clone());
|
||||
return;
|
||||
}
|
||||
if let Some(icmp) = packet.as_icmpv4()
|
||||
&& let Icmpv4Type::EchoRequest(echo) = icmp.icmp_type()
|
||||
{
|
||||
self.sent_icmp_requests
|
||||
.insert((Seq(echo.seq), Identifier(echo.id)), packet.clone());
|
||||
return;
|
||||
}
|
||||
|
||||
if let Some(icmp) = packet.as_icmpv6() {
|
||||
if let Icmpv6Type::EchoRequest(echo) = icmp.icmp_type() {
|
||||
self.sent_icmp_requests
|
||||
.insert((Seq(echo.seq), Identifier(echo.id)), packet.clone());
|
||||
return;
|
||||
}
|
||||
if let Some(icmp) = packet.as_icmpv6()
|
||||
&& let Icmpv6Type::EchoRequest(echo) = icmp.icmp_type()
|
||||
{
|
||||
self.sent_icmp_requests
|
||||
.insert((Seq(echo.seq), Identifier(echo.id)), packet.clone());
|
||||
return;
|
||||
}
|
||||
|
||||
if let Some(udp) = packet.as_udp() {
|
||||
@@ -311,20 +311,20 @@ impl SimClient {
|
||||
return;
|
||||
}
|
||||
|
||||
if let Some(icmp) = packet.as_icmpv4() {
|
||||
if let Icmpv4Type::EchoReply(echo) = icmp.icmp_type() {
|
||||
self.received_icmp_replies
|
||||
.insert((Seq(echo.seq), Identifier(echo.id)), packet.clone());
|
||||
return;
|
||||
}
|
||||
if let Some(icmp) = packet.as_icmpv4()
|
||||
&& let Icmpv4Type::EchoReply(echo) = icmp.icmp_type()
|
||||
{
|
||||
self.received_icmp_replies
|
||||
.insert((Seq(echo.seq), Identifier(echo.id)), packet.clone());
|
||||
return;
|
||||
}
|
||||
|
||||
if let Some(icmp) = packet.as_icmpv6() {
|
||||
if let Icmpv6Type::EchoReply(echo) = icmp.icmp_type() {
|
||||
self.received_icmp_replies
|
||||
.insert((Seq(echo.seq), Identifier(echo.id)), packet.clone());
|
||||
return;
|
||||
}
|
||||
if let Some(icmp) = packet.as_icmpv6()
|
||||
&& let Icmpv6Type::EchoReply(echo) = icmp.icmp_type()
|
||||
{
|
||||
self.received_icmp_replies
|
||||
.insert((Seq(echo.seq), Identifier(echo.id)), packet.clone());
|
||||
return;
|
||||
}
|
||||
|
||||
tracing::error!(?packet, "Unhandled packet");
|
||||
@@ -521,12 +521,12 @@ impl RefClient {
|
||||
continue;
|
||||
}
|
||||
|
||||
if let Some(overlapping_resource) = table.exact_match(resource.address) {
|
||||
if self.is_connected_to_internet_or_cidr(*overlapping_resource) {
|
||||
tracing::debug!(%overlapping_resource, resource = %resource.id, address = %resource.address, "Already connected to resource with this exact address, retaining existing route");
|
||||
if let Some(overlapping_resource) = table.exact_match(resource.address)
|
||||
&& self.is_connected_to_internet_or_cidr(*overlapping_resource)
|
||||
{
|
||||
tracing::debug!(%overlapping_resource, resource = %resource.id, address = %resource.address, "Already connected to resource with this exact address, retaining existing route");
|
||||
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
tracing::debug!(resource = %resource.id, address = %resource.address, "Adding CIDR route");
|
||||
|
||||
@@ -187,24 +187,24 @@ impl SimGateway {
|
||||
.icmp_error_for_ip(dst_ip)
|
||||
.map(|icmp_error| icmp_error_reply(&packet, icmp_error).unwrap());
|
||||
|
||||
if let Some(icmp) = packet.as_icmpv4() {
|
||||
if let Icmpv4Type::EchoRequest(echo) = icmp.icmp_type() {
|
||||
let packet_id = u64::from_be_bytes(*icmp.payload().first_chunk().unwrap());
|
||||
tracing::debug!(%packet_id, "Received ICMP request");
|
||||
self.received_icmp_requests
|
||||
.insert(packet_id, packet.clone());
|
||||
return self.handle_icmp_request(&packet, echo, icmp.payload(), icmp_error, now);
|
||||
}
|
||||
if let Some(icmp) = packet.as_icmpv4()
|
||||
&& let Icmpv4Type::EchoRequest(echo) = icmp.icmp_type()
|
||||
{
|
||||
let packet_id = u64::from_be_bytes(*icmp.payload().first_chunk().unwrap());
|
||||
tracing::debug!(%packet_id, "Received ICMP request");
|
||||
self.received_icmp_requests
|
||||
.insert(packet_id, packet.clone());
|
||||
return self.handle_icmp_request(&packet, echo, icmp.payload(), icmp_error, now);
|
||||
}
|
||||
|
||||
if let Some(icmp) = packet.as_icmpv6() {
|
||||
if let Icmpv6Type::EchoRequest(echo) = icmp.icmp_type() {
|
||||
let packet_id = u64::from_be_bytes(*icmp.payload().first_chunk().unwrap());
|
||||
tracing::debug!(%packet_id, "Received ICMP request");
|
||||
self.received_icmp_requests
|
||||
.insert(packet_id, packet.clone());
|
||||
return self.handle_icmp_request(&packet, echo, icmp.payload(), icmp_error, now);
|
||||
}
|
||||
if let Some(icmp) = packet.as_icmpv6()
|
||||
&& let Icmpv6Type::EchoRequest(echo) = icmp.icmp_type()
|
||||
{
|
||||
let packet_id = u64::from_be_bytes(*icmp.payload().first_chunk().unwrap());
|
||||
tracing::debug!(%packet_id, "Received ICMP request");
|
||||
self.received_icmp_requests
|
||||
.insert(packet_id, packet.clone());
|
||||
return self.handle_icmp_request(&packet, echo, icmp.payload(), icmp_error, now);
|
||||
}
|
||||
|
||||
if let Some(udp) = packet.as_udp() {
|
||||
|
||||
@@ -200,16 +200,16 @@ async fn try_main(cli: Cli, telemetry: &mut Telemetry) -> Result<()> {
|
||||
}
|
||||
|
||||
async fn get_firezone_id(env_id: Option<String>) -> Result<String> {
|
||||
if let Some(id) = env_id {
|
||||
if !id.is_empty() {
|
||||
return Ok(id);
|
||||
}
|
||||
if let Some(id) = env_id
|
||||
&& !id.is_empty()
|
||||
{
|
||||
return Ok(id);
|
||||
}
|
||||
|
||||
if let Ok(id) = tokio::fs::read_to_string(ID_PATH).await {
|
||||
if !id.is_empty() {
|
||||
return Ok(id);
|
||||
}
|
||||
if let Ok(id) = tokio::fs::read_to_string(ID_PATH).await
|
||||
&& !id.is_empty()
|
||||
{
|
||||
return Ok(id);
|
||||
}
|
||||
|
||||
let device_id = device_id::get_or_create_at(Path::new(ID_PATH))?;
|
||||
|
||||
@@ -54,8 +54,7 @@ fn try_admx(attr: TokenStream, item: TokenStream) -> syn::Result<proc_macro2::To
|
||||
Err(syn::Error::new(
|
||||
span,
|
||||
format!(
|
||||
"No supported type element found for policy '{}'",
|
||||
value_name
|
||||
"No supported type element found for policy '{value_name}'"
|
||||
),
|
||||
))
|
||||
})?;
|
||||
|
||||
@@ -361,7 +361,7 @@ mod tests {
|
||||
// e.g. `\\\\?\\C:\\cygwin64\\home\\User\\projects\\firezone\\rust\\target\\debug\\deps\\firezone_windows_client-5f44800b2dafef90.exe`
|
||||
let path = tauri_utils::platform::current_exe()?.display().to_string();
|
||||
assert!(path.contains("target"));
|
||||
assert!(!path.contains('\"'), "`{}`", path);
|
||||
assert!(!path.contains('\"'), "`{path}`");
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,14 +29,14 @@ fn set_registry_values(id: &str, exe: &str) -> Result<(), io::Error> {
|
||||
let base = Path::new("Software").join("Classes").join(FZ_SCHEME);
|
||||
|
||||
let (key, _) = hkcu.create_subkey(&base)?;
|
||||
key.set_value("", &format!("URL:{}", id))?;
|
||||
key.set_value("", &format!("URL:{id}"))?;
|
||||
key.set_value("URL Protocol", &"")?;
|
||||
|
||||
let (icon, _) = hkcu.create_subkey(base.join("DefaultIcon"))?;
|
||||
icon.set_value("", &format!("{},0", &exe))?;
|
||||
icon.set_value("", &format!("{exe},0"))?;
|
||||
|
||||
let (cmd, _) = hkcu.create_subkey(base.join("shell").join("open").join("command"))?;
|
||||
cmd.set_value("", &format!("{} open-deep-link \"%1\"", &exe))?;
|
||||
cmd.set_value("", &format!("{exe} open-deep-link \"%1\""))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -169,7 +169,7 @@ fn ipc_path(id: SocketId) -> String {
|
||||
/// Public because the GUI Client reuses this for deep links. Eventually that code
|
||||
/// will be de-duped into this code.
|
||||
pub fn named_pipe_path(id: &str) -> String {
|
||||
format!(r"\\.\pipe\{}", id)
|
||||
format!(r"\\.\pipe\{id}")
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -15,7 +15,7 @@ impl fmt::Display for ErrorWithSources<'_> {
|
||||
write!(f, "{}", self.e)?;
|
||||
|
||||
for cause in anyhow::Chain::new(self.e).skip(1) {
|
||||
write!(f, ": {}", cause)?;
|
||||
write!(f, ": {cause}")?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -109,7 +109,7 @@ where
|
||||
if self.level {
|
||||
let fmt_level = FmtLevel::new(meta.level(), writer.has_ansi_escapes());
|
||||
|
||||
write!(writer, "{} ", fmt_level)?;
|
||||
write!(writer, "{fmt_level} ")?;
|
||||
}
|
||||
|
||||
let dimmed = if writer.has_ansi_escapes() {
|
||||
|
||||
@@ -10,9 +10,14 @@ pub struct ChannelData<'a> {
|
||||
}
|
||||
|
||||
impl<'a> ChannelData<'a> {
|
||||
/// # SAFETY
|
||||
///
|
||||
/// You must not create multiple [`ChannelData`] structs at same time.
|
||||
#[inline(always)]
|
||||
pub fn parse(ctx: &'a XdpContext, ip_header_length: usize) -> Result<Self, Error> {
|
||||
let hdr = ref_mut_at::<CdHdr>(ctx, EthHdr::LEN + ip_header_length + UdpHdr::LEN)?;
|
||||
pub unsafe fn parse(ctx: &'a XdpContext, ip_header_length: usize) -> Result<Self, Error> {
|
||||
// Safety: We are forwarding the constraint.
|
||||
let hdr =
|
||||
unsafe { ref_mut_at::<CdHdr>(ctx, EthHdr::LEN + ip_header_length + UdpHdr::LEN) }?;
|
||||
|
||||
if !(0x4000..0x4FFF).contains(&u16::from_be_bytes(hdr.number)) {
|
||||
return Err(Error::NotAChannelDataMessage);
|
||||
|
||||
@@ -15,10 +15,14 @@ pub struct Eth<'a> {
|
||||
}
|
||||
|
||||
impl<'a> Eth<'a> {
|
||||
/// # SAFETY
|
||||
///
|
||||
/// You must not create multiple [`Eth`] structs at same time.
|
||||
#[inline(always)]
|
||||
pub fn parse(ctx: &'a XdpContext) -> Result<Self, Error> {
|
||||
pub unsafe fn parse(ctx: &'a XdpContext) -> Result<Self, Error> {
|
||||
Ok(Self {
|
||||
inner: ref_mut_at::<EthHdr>(ctx, 0)?,
|
||||
// Safety: We are forwarding the constraint.
|
||||
inner: unsafe { ref_mut_at::<EthHdr>(ctx, 0) }?,
|
||||
ctx,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -15,9 +15,13 @@ pub struct Ip4<'a> {
|
||||
}
|
||||
|
||||
impl<'a> Ip4<'a> {
|
||||
/// # SAFETY
|
||||
///
|
||||
/// You must not create multiple [`Ip4`] structs at same time.
|
||||
#[inline(always)]
|
||||
pub fn parse(ctx: &'a XdpContext) -> Result<Self, Error> {
|
||||
let ip4_hdr = ref_mut_at::<Ipv4Hdr>(ctx, EthHdr::LEN)?;
|
||||
pub unsafe fn parse(ctx: &'a XdpContext) -> Result<Self, Error> {
|
||||
// Safety: We are forwarding the constraint.
|
||||
let ip4_hdr = unsafe { ref_mut_at::<Ipv4Hdr>(ctx, EthHdr::LEN) }?;
|
||||
|
||||
// IPv4 packets with options are handled in user-space.
|
||||
if usize::from(ip4_hdr.ihl()) * 4 != Ipv4Hdr::LEN {
|
||||
|
||||
@@ -15,11 +15,15 @@ pub struct Ip6<'a> {
|
||||
}
|
||||
|
||||
impl<'a> Ip6<'a> {
|
||||
/// # SAFETY
|
||||
///
|
||||
/// You must not create multiple [`Ip6`] structs at same time.
|
||||
#[inline(always)]
|
||||
pub fn parse(ctx: &'a XdpContext) -> Result<Self, Error> {
|
||||
pub unsafe fn parse(ctx: &'a XdpContext) -> Result<Self, Error> {
|
||||
Ok(Self {
|
||||
ctx,
|
||||
inner: ref_mut_at::<Ipv6Hdr>(ctx, EthHdr::LEN)?,
|
||||
// Safety: We are forwarding the constraint.
|
||||
inner: unsafe { ref_mut_at::<Ipv6Hdr>(ctx, EthHdr::LEN) }?,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -109,7 +109,8 @@ pub fn handle_turn(ctx: XdpContext) -> u32 {
|
||||
|
||||
#[inline(always)]
|
||||
fn try_handle_turn(ctx: &XdpContext) -> Result<u32, Error> {
|
||||
let eth = Eth::parse(ctx)?;
|
||||
// Safety: This is the only instance of `Eth`.
|
||||
let eth = unsafe { Eth::parse(ctx) }?;
|
||||
|
||||
match eth.ether_type() {
|
||||
EtherType::Ipv4 => try_handle_turn_ipv4(ctx, eth)?,
|
||||
@@ -124,7 +125,8 @@ fn try_handle_turn(ctx: &XdpContext) -> Result<u32, Error> {
|
||||
|
||||
#[inline(always)]
|
||||
fn try_handle_turn_ipv4(ctx: &XdpContext, eth: Eth) -> Result<(), Error> {
|
||||
let ipv4 = Ip4::parse(ctx)?;
|
||||
// Safety: This is the only instance of `Ip4`.
|
||||
let ipv4 = unsafe { Ip4::parse(ctx) }?;
|
||||
|
||||
eth::save_mac_for_ipv4(ipv4.src(), eth.src());
|
||||
eth::save_mac_for_ipv4(ipv4.dst(), eth.dst());
|
||||
@@ -133,7 +135,8 @@ fn try_handle_turn_ipv4(ctx: &XdpContext, eth: Eth) -> Result<(), Error> {
|
||||
return Err(Error::NotUdp);
|
||||
}
|
||||
|
||||
let udp = Udp::parse(ctx, Ipv4Hdr::LEN)?; // TODO: Change the API so we parse the UDP header _from_ the ipv4 struct?
|
||||
// Safety: This is the only instance of `Udp` in this scope.
|
||||
let udp = unsafe { Udp::parse(ctx, Ipv4Hdr::LEN) }?; // TODO: Change the API so we parse the UDP header _from_ the ipv4 struct?
|
||||
let udp_payload_len = udp.payload_len();
|
||||
|
||||
trace!(
|
||||
@@ -170,7 +173,8 @@ fn try_handle_ipv4_channel_data_to_udp(
|
||||
ipv4: Ip4,
|
||||
udp: Udp,
|
||||
) -> Result<(), Error> {
|
||||
let cd = ChannelData::parse(ctx, Ipv4Hdr::LEN)?;
|
||||
// Safety: This is the only instance of `Udp` in this scope.
|
||||
let cd = unsafe { ChannelData::parse(ctx, Ipv4Hdr::LEN) }?;
|
||||
|
||||
let key = ClientAndChannelV4::new(ipv4.src(), udp.src(), cd.number());
|
||||
|
||||
@@ -259,7 +263,8 @@ fn try_handle_ipv4_udp_to_channel_data(
|
||||
|
||||
#[inline(always)]
|
||||
fn try_handle_turn_ipv6(ctx: &XdpContext, eth: Eth) -> Result<(), Error> {
|
||||
let ipv6 = Ip6::parse(ctx)?;
|
||||
// Safety: This is the only instance of `Ip6` in this scope.
|
||||
let ipv6 = unsafe { Ip6::parse(ctx) }?;
|
||||
|
||||
eth::save_mac_for_ipv6(ipv6.src(), eth.src());
|
||||
eth::save_mac_for_ipv6(ipv6.dst(), eth.dst());
|
||||
@@ -268,7 +273,8 @@ fn try_handle_turn_ipv6(ctx: &XdpContext, eth: Eth) -> Result<(), Error> {
|
||||
return Err(Error::NotUdp);
|
||||
}
|
||||
|
||||
let udp = Udp::parse(ctx, Ipv6Hdr::LEN)?; // TODO: Change the API so we parse the UDP header _from_ the ipv6 struct?
|
||||
// Safety: This is the only instance of `Udp` in this scope.
|
||||
let udp = unsafe { Udp::parse(ctx, Ipv6Hdr::LEN) }?; // TODO: Change the API so we parse the UDP header _from_ the ipv6 struct?
|
||||
let udp_payload_len = udp.payload_len();
|
||||
|
||||
trace!(
|
||||
@@ -354,7 +360,8 @@ fn try_handle_ipv6_channel_data_to_udp(
|
||||
ipv6: Ip6,
|
||||
udp: Udp,
|
||||
) -> Result<(), Error> {
|
||||
let cd = ChannelData::parse(ctx, Ipv6Hdr::LEN)?;
|
||||
// Safety: This is the only instance of `ChannelData` in this scope.
|
||||
let cd = unsafe { ChannelData::parse(ctx, Ipv6Hdr::LEN) }?;
|
||||
|
||||
let key = ClientAndChannelV6::new(ipv6.src(), udp.src(), cd.number());
|
||||
|
||||
|
||||
@@ -6,8 +6,13 @@ use crate::error::Error;
|
||||
///
|
||||
/// The length is based on the size of `T` and the bytes at the specified offset will simply be cast into `T`.
|
||||
/// `T` should therefore most definitely be `repr(C)`.
|
||||
///
|
||||
/// # SAFETY
|
||||
///
|
||||
/// You must not obtain overlapping mutable references from the context.
|
||||
#[inline(always)]
|
||||
pub(crate) fn ref_mut_at<T>(ctx: &XdpContext, offset: usize) -> Result<&mut T, Error> {
|
||||
#[expect(clippy::mut_from_ref, reason = "The function is unsafe.")]
|
||||
pub(crate) unsafe fn ref_mut_at<T>(ctx: &XdpContext, offset: usize) -> Result<&mut T, Error> {
|
||||
let start = ctx.data();
|
||||
let end = ctx.data_end();
|
||||
let len = core::mem::size_of::<T>();
|
||||
|
||||
@@ -10,11 +10,15 @@ pub struct Udp<'a> {
|
||||
}
|
||||
|
||||
impl<'a> Udp<'a> {
|
||||
/// # SAFETY
|
||||
///
|
||||
/// You must not create multiple [`Udp`] structs at same time.
|
||||
#[inline(always)]
|
||||
pub fn parse(ctx: &'a XdpContext, ip_header_length: usize) -> Result<Self, Error> {
|
||||
pub unsafe fn parse(ctx: &'a XdpContext, ip_header_length: usize) -> Result<Self, Error> {
|
||||
Ok(Self {
|
||||
ctx,
|
||||
inner: ref_mut_at::<UdpHdr>(ctx, EthHdr::LEN + ip_header_length)?,
|
||||
// Safety: We are forwarding the constraint.
|
||||
inner: unsafe { ref_mut_at::<UdpHdr>(ctx, EthHdr::LEN + ip_header_length) }?,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ fn main() -> anyhow::Result<()> {
|
||||
|
||||
aya_build::build_ebpf(
|
||||
[package],
|
||||
aya_build::Toolchain::Custom("nightly-2024-12-13"),
|
||||
aya_build::Toolchain::Custom("nightly-2025-05-30"),
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -80,7 +80,7 @@ impl MessageIntegrityExt for MessageIntegrity {
|
||||
let password = generate_password(relay_secret, expired, salt);
|
||||
|
||||
self.check_long_term_credential(
|
||||
&Username::new(format!("{}:{}", expiry_unix_timestamp, salt))
|
||||
&Username::new(format!("{expiry_unix_timestamp}:{salt}"))
|
||||
.map_err(|_| Error::InvalidUsername)?,
|
||||
&FIREZONE,
|
||||
&password,
|
||||
@@ -109,7 +109,7 @@ impl AuthenticatedMessage {
|
||||
let (expiry_unix_timestamp, salt) = split_username(username)?;
|
||||
let expired = systemtime_from_unix(expiry_unix_timestamp);
|
||||
|
||||
let username = Username::new(format!("{}:{}", expiry_unix_timestamp, salt))
|
||||
let username = Username::new(format!("{expiry_unix_timestamp}:{salt}"))
|
||||
.map_err(|_| Error::InvalidUsername)?;
|
||||
let password = generate_password(relay_secret, expired, salt);
|
||||
|
||||
|
||||
@@ -753,7 +753,7 @@ impl TestServer {
|
||||
let Some(actual_output) = self.server.next_command() else {
|
||||
let msg = match expected_output {
|
||||
Output::SendMessage((recipient, msg)) => {
|
||||
format!("to send message {:?} to {recipient}", msg)
|
||||
format!("to send message {msg:?} to {recipient}")
|
||||
}
|
||||
CreateAllocation(port, family) => {
|
||||
format!("to create allocation on port {port} for address family {family}")
|
||||
@@ -793,8 +793,8 @@ impl TestServer {
|
||||
.unwrap();
|
||||
|
||||
if expected_bytes != payload {
|
||||
let expected_message = format!("{:?}", message);
|
||||
let actual_message = format!("{:?}", sent_message);
|
||||
let expected_message = format!("{message:?}");
|
||||
let actual_message = format!("{sent_message:?}");
|
||||
|
||||
difference::assert_diff!(&expected_message, &actual_message, "\n", 0);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
[toolchain]
|
||||
channel = "1.87.0"
|
||||
channel = "1.88.0"
|
||||
components = ["rust-src", "rust-analyzer", "clippy"]
|
||||
targets = ["x86_64-unknown-linux-musl"]
|
||||
|
||||
Reference in New Issue
Block a user