From 555d1a164699dff072e9925bab020a82012a2546 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 20 Jul 2023 14:55:16 -0400 Subject: [PATCH] Log common errors instead of panic --- src/nat/mod.rs | 28 +++++++++++++++++----------- src/nat/utils.rs | 32 ++++++++++++++++++++++++++++++++ src/packet/error.rs | 2 +- src/packet/protocols/icmp.rs | 5 ++--- src/packet/protocols/icmpv6.rs | 4 ++-- src/packet/protocols/ipv4.rs | 2 +- src/packet/protocols/ipv6.rs | 2 +- src/packet/protocols/tcp.rs | 4 ++-- src/packet/protocols/udp.rs | 4 ++-- 9 files changed, 60 insertions(+), 23 deletions(-) diff --git a/src/nat/mod.rs b/src/nat/mod.rs index 9ff65cf..f79fb1b 100644 --- a/src/nat/mod.rs +++ b/src/nat/mod.rs @@ -9,7 +9,7 @@ use crate::{ use self::{ error::Nat64Error, table::Nat64Table, - utils::{embed_address, extract_address}, + utils::{embed_address, extract_address, unwrap_log}, }; use ipnet::{Ipv4Net, Ipv6Net}; use protomask_tun::TunDevice; @@ -99,11 +99,14 @@ impl Nat64 { // Spawn a task to process the packet tokio::spawn(async move { - let output = - translate_ipv4_to_ipv6(packet, new_source, new_destination) - .unwrap(); - tx.send(output.into()).await.unwrap(); - PACKET_COUNTER.with_label_values(&["ipv6", "sent"]).inc(); + if let Some(output) = unwrap_log(translate_ipv4_to_ipv6( + packet, + new_source, + new_destination, + )) { + tx.send(output.into()).await.unwrap(); + PACKET_COUNTER.with_label_values(&["ipv6", "sent"]).inc(); + } }); } 6 => { @@ -145,11 +148,14 @@ impl Nat64 { // Spawn a task to process the packet tokio::spawn(async move { - let output = - translate_ipv6_to_ipv4(packet, new_source, new_destination) - .unwrap(); - tx.send(output.into()).await.unwrap(); - PACKET_COUNTER.with_label_values(&["ipv4", "sent"]).inc(); + if let Some(output) = unwrap_log(translate_ipv6_to_ipv4( + packet, + new_source, + new_destination, + )) { + tx.send(output.into()).await.unwrap(); + PACKET_COUNTER.with_label_values(&["ipv4", "sent"]).inc(); + } }); } n => { diff --git a/src/nat/utils.rs b/src/nat/utils.rs index 47b15f6..44d1f18 100644 --- a/src/nat/utils.rs +++ b/src/nat/utils.rs @@ -2,6 +2,8 @@ use std::net::{Ipv4Addr, Ipv6Addr}; use ipnet::Ipv6Net; +use crate::packet::error::PacketError; + /// Embed an IPv4 address in an IPv6 prefix pub fn embed_address(ipv4_address: Ipv4Addr, ipv6_prefix: Ipv6Net) -> Ipv6Addr { let v4_octets = ipv4_address.octets(); @@ -23,3 +25,33 @@ pub fn extract_address(ipv6_address: Ipv6Addr) -> Ipv4Addr { let octets = ipv6_address.octets(); Ipv4Addr::new(octets[12], octets[13], octets[14], octets[15]) } + +/// Logs errors instead of crashing out of them +pub fn unwrap_log(result: Result) -> Option { + match result { + Ok(value) => Some(value), + Err(err) => match err { + PacketError::MismatchedAddressFamily(addr_a, addr_b) => { + log::error!( + "Mismatched address family between {} and {}", + addr_a, + addr_b + ); + None + } + PacketError::TooShort(len, data) => { + log::warn!("Received packet that's too short to parse. Length {}", len); + log::debug!("Short packet: {:?}", data); + None + } + PacketError::UnsupportedIcmpType(icmp_type) => { + log::warn!("Unsupported ICMP type {}", icmp_type); + None + } + PacketError::UnsupportedIcmpv6Type(icmp_type) => { + log::warn!("Unsupported ICMPv6 type {}", icmp_type); + None + } + }, + } +} diff --git a/src/packet/error.rs b/src/packet/error.rs index fc65fcd..ec2ffe9 100644 --- a/src/packet/error.rs +++ b/src/packet/error.rs @@ -5,7 +5,7 @@ pub enum PacketError { #[error("Mismatched source and destination address family: source={0:?}, destination={1:?}")] MismatchedAddressFamily(IpAddr, IpAddr), #[error("Packet too short: {0}")] - TooShort(usize), + TooShort(usize, Vec), #[error("Unsupported ICMP type: {0}")] UnsupportedIcmpType(u8), #[error("Unsupported ICMPv6 type: {0}")] diff --git a/src/packet/protocols/icmp.rs b/src/packet/protocols/icmp.rs index dce1f92..6553ff3 100644 --- a/src/packet/protocols/icmp.rs +++ b/src/packet/protocols/icmp.rs @@ -31,8 +31,8 @@ where fn try_from(bytes: Vec) -> Result { // Parse the packet - let packet = - pnet_packet::icmp::IcmpPacket::new(&bytes).ok_or(PacketError::TooShort(bytes.len()))?; + let packet = pnet_packet::icmp::IcmpPacket::new(&bytes) + .ok_or(PacketError::TooShort(bytes.len(), bytes.to_vec()))?; // Return the packet Ok(Self { @@ -43,7 +43,6 @@ where } } - impl Into> for IcmpPacket where T: Into>, diff --git a/src/packet/protocols/icmpv6.rs b/src/packet/protocols/icmpv6.rs index 6242c8b..08d75e4 100644 --- a/src/packet/protocols/icmpv6.rs +++ b/src/packet/protocols/icmpv6.rs @@ -50,7 +50,7 @@ where ) -> Result { // Parse the packet let packet = pnet_packet::icmpv6::Icmpv6Packet::new(bytes) - .ok_or(PacketError::TooShort(bytes.len()))?; + .ok_or(PacketError::TooShort(bytes.len(), bytes.to_vec()))?; // Return the packet Ok(Self { @@ -72,7 +72,7 @@ impl Icmpv6Packet { ) -> Result { // Parse the packet let packet = pnet_packet::icmpv6::Icmpv6Packet::new(bytes) - .ok_or(PacketError::TooShort(bytes.len()))?; + .ok_or(PacketError::TooShort(bytes.len(), bytes.to_vec()))?; // Return the packet Ok(Self { diff --git a/src/packet/protocols/ipv4.rs b/src/packet/protocols/ipv4.rs index 9728084..b83c65d 100644 --- a/src/packet/protocols/ipv4.rs +++ b/src/packet/protocols/ipv4.rs @@ -71,7 +71,7 @@ where fn try_from(bytes: Vec) -> Result { // Parse the packet let packet = - pnet_packet::ipv4::Ipv4Packet::new(&bytes).ok_or(PacketError::TooShort(bytes.len()))?; + pnet_packet::ipv4::Ipv4Packet::new(&bytes).ok_or(PacketError::TooShort(bytes.len(), bytes.to_vec()))?; // Return the packet Ok(Self { diff --git a/src/packet/protocols/ipv6.rs b/src/packet/protocols/ipv6.rs index 8d28375..253958b 100644 --- a/src/packet/protocols/ipv6.rs +++ b/src/packet/protocols/ipv6.rs @@ -47,7 +47,7 @@ where fn try_from(bytes: Vec) -> Result { // Parse the packet let packet = - pnet_packet::ipv6::Ipv6Packet::new(&bytes).ok_or(PacketError::TooShort(bytes.len()))?; + pnet_packet::ipv6::Ipv6Packet::new(&bytes).ok_or(PacketError::TooShort(bytes.len(), bytes.to_vec()))?; // Return the packet Ok(Self { diff --git a/src/packet/protocols/tcp.rs b/src/packet/protocols/tcp.rs index 5c0244a..ca71159 100644 --- a/src/packet/protocols/tcp.rs +++ b/src/packet/protocols/tcp.rs @@ -131,7 +131,7 @@ where // Parse the packet let parsed = pnet_packet::tcp::TcpPacket::new(bytes) - .ok_or_else(|| PacketError::TooShort(bytes.len()))?; + .ok_or_else(|| PacketError::TooShort(bytes.len(), bytes.to_vec()))?; // Build the struct Ok(Self { @@ -165,7 +165,7 @@ impl TcpPacket { // Parse the packet let parsed = pnet_packet::tcp::TcpPacket::new(bytes) - .ok_or_else(|| PacketError::TooShort(bytes.len()))?; + .ok_or_else(|| PacketError::TooShort(bytes.len(), bytes.to_vec()))?; // Build the struct Ok(Self { diff --git a/src/packet/protocols/udp.rs b/src/packet/protocols/udp.rs index dfe7c7e..56200a7 100644 --- a/src/packet/protocols/udp.rs +++ b/src/packet/protocols/udp.rs @@ -102,7 +102,7 @@ where // Parse the packet let parsed = pnet_packet::udp::UdpPacket::new(bytes) - .ok_or_else(|| PacketError::TooShort(bytes.len()))?; + .ok_or_else(|| PacketError::TooShort(bytes.len(), bytes.to_vec()))?; // Build the struct Ok(Self { @@ -130,7 +130,7 @@ impl UdpPacket { // Parse the packet let parsed = pnet_packet::udp::UdpPacket::new(bytes) - .ok_or_else(|| PacketError::TooShort(bytes.len()))?; + .ok_or_else(|| PacketError::TooShort(bytes.len(), bytes.to_vec()))?; // Build the struct Ok(Self {