Browse Source

wire: use own Error type.

Dario Nieuwenhuis 2 years ago
parent
commit
78f92bcea6

+ 10 - 7
examples/multicast.rs

@@ -82,13 +82,16 @@ fn main() {
         if socket.can_recv() {
             // For display purposes only - normally we wouldn't process incoming IGMP packets
             // in the application layer
-            socket
-                .recv()
-                .and_then(Ipv4Packet::new_checked)
-                .and_then(|ipv4_packet| IgmpPacket::new_checked(ipv4_packet.payload()))
-                .and_then(|igmp_packet| IgmpRepr::parse(&igmp_packet))
-                .map(|igmp_repr| println!("IGMP packet: {:?}", igmp_repr))
-                .unwrap_or_else(|e| println!("Recv IGMP error: {:?}", e));
+            match socket.recv() {
+                Err(e) => println!("Recv IGMP error: {:?}", e),
+                Ok(buf) => {
+                    Ipv4Packet::new_checked(buf)
+                        .and_then(|ipv4_packet| IgmpPacket::new_checked(ipv4_packet.payload()))
+                        .and_then(|igmp_packet| IgmpRepr::parse(&igmp_packet))
+                        .map(|igmp_repr| println!("IGMP packet: {:?}", igmp_repr))
+                        .unwrap_or_else(|e| println!("parse IGMP error: {:?}", e));
+                }
+            }
         }
 
         let socket = iface.get_socket::<UdpSocket>(udp_handle);

+ 6 - 0
src/lib.rs

@@ -252,3 +252,9 @@ impl fmt::Display for Error {
         }
     }
 }
+
+impl From<wire::Error> for Error {
+    fn from(_: wire::Error) -> Self {
+        Error::Malformed
+    }
+}

+ 5 - 5
src/socket/dns.rs

@@ -7,7 +7,7 @@ use managed::ManagedSlice;
 use crate::socket::{Context, PollAt, Socket};
 use crate::time::{Duration, Instant};
 use crate::wire::dns::{Flags, Opcode, Packet, Question, Rcode, Record, RecordData, Repr, Type};
-use crate::wire::{IpAddress, IpProtocol, IpRepr, UdpRepr};
+use crate::wire::{self, IpAddress, IpProtocol, IpRepr, UdpRepr};
 use crate::{Error, Result};
 
 #[cfg(feature = "async")]
@@ -509,9 +509,9 @@ impl<'a> From<DnsSocket<'a>> for Socket<'a> {
 }
 
 fn eq_names<'a>(
-    mut a: impl Iterator<Item = Result<&'a [u8]>>,
-    mut b: impl Iterator<Item = Result<&'a [u8]>>,
-) -> Result<bool> {
+    mut a: impl Iterator<Item = wire::Result<&'a [u8]>>,
+    mut b: impl Iterator<Item = wire::Result<&'a [u8]>>,
+) -> wire::Result<bool> {
     loop {
         match (a.next(), b.next()) {
             // Handle errors
@@ -537,7 +537,7 @@ fn eq_names<'a>(
 
 fn copy_name<'a, const N: usize>(
     dest: &mut Vec<u8, N>,
-    name: impl Iterator<Item = Result<&'a [u8]>>,
+    name: impl Iterator<Item = wire::Result<&'a [u8]>>,
 ) -> Result<()> {
     dest.truncate(0);
 

+ 6 - 6
src/wire/arp.rs

@@ -1,7 +1,7 @@
 use byteorder::{ByteOrder, NetworkEndian};
 use core::fmt;
 
-use crate::{Error, Result};
+use super::{Error, Result};
 
 pub use super::EthernetProtocol as Protocol;
 
@@ -80,7 +80,7 @@ impl<T: AsRef<[u8]>> Packet<T> {
     }
 
     /// Ensure that no accessor method will panic if called.
-    /// Returns `Err(Error::Truncated)` if the buffer is too short.
+    /// Returns `Err(Error)` if the buffer is too short.
     ///
     /// The result of this check is invalidated by calling [set_hardware_len] or
     /// [set_protocol_len].
@@ -91,9 +91,9 @@ impl<T: AsRef<[u8]>> Packet<T> {
     pub fn check_len(&self) -> Result<()> {
         let len = self.buffer.as_ref().len();
         if len < field::OPER.end {
-            Err(Error::Truncated)
+            Err(Error)
         } else if len < field::TPA(self.hardware_len(), self.protocol_len()).end {
-            Err(Error::Truncated)
+            Err(Error)
         } else {
             Ok(())
         }
@@ -269,7 +269,7 @@ pub enum Repr {
 
 impl Repr {
     /// Parse an Address Resolution Protocol packet and return a high-level representation,
-    /// or return `Err(Error::Unrecognized)` if the packet is not recognized.
+    /// or return `Err(Error)` if the packet is not recognized.
     pub fn parse<T: AsRef<[u8]>>(packet: &Packet<T>) -> Result<Repr> {
         match (
             packet.hardware_type(),
@@ -284,7 +284,7 @@ impl Repr {
                 target_hardware_addr: EthernetAddress::from_bytes(packet.target_hardware_addr()),
                 target_protocol_addr: Ipv4Address::from_bytes(packet.target_protocol_addr()),
             }),
-            _ => Err(Error::Unrecognized),
+            _ => Err(Error),
         }
     }
 

+ 14 - 14
src/wire/dhcpv4.rs

@@ -3,9 +3,9 @@
 use bitflags::bitflags;
 use byteorder::{ByteOrder, NetworkEndian};
 
+use super::{Error, Result};
 use crate::wire::arp::Hardware;
 use crate::wire::{EthernetAddress, Ipv4Address};
-use crate::{Error, Result};
 
 pub const SERVER_PORT: u16 = 67;
 pub const CLIENT_PORT: u16 = 68;
@@ -77,7 +77,7 @@ impl<'a> DhcpOption<'a> {
         // See https://tools.ietf.org/html/rfc2132 for all possible DHCP options.
 
         let (skip_len, option);
-        match *buffer.get(0).ok_or(Error::Truncated)? {
+        match *buffer.get(0).ok_or(Error)? {
             field::OPT_END => {
                 skip_len = 1;
                 option = DhcpOption::EndOfList;
@@ -87,9 +87,9 @@ impl<'a> DhcpOption<'a> {
                 option = DhcpOption::Pad;
             }
             kind => {
-                let length = *buffer.get(1).ok_or(Error::Truncated)? as usize;
+                let length = *buffer.get(1).ok_or(Error)? as usize;
                 skip_len = length + 2;
-                let data = buffer.get(2..skip_len).ok_or(Error::Truncated)?;
+                let data = buffer.get(2..skip_len).ok_or(Error)?;
                 match (kind, length) {
                     (field::OPT_END, _) | (field::OPT_PAD, _) => unreachable!(),
                     (field::OPT_DHCP_MESSAGE_TYPE, 1) => {
@@ -101,7 +101,7 @@ impl<'a> DhcpOption<'a> {
                     (field::OPT_CLIENT_ID, 7) => {
                         let hardware_type = Hardware::from(u16::from(data[0]));
                         if hardware_type != Hardware::Ethernet {
-                            return Err(Error::Unrecognized);
+                            return Err(Error);
                         }
                         option =
                             DhcpOption::ClientIdentifier(EthernetAddress::from_bytes(&data[1..]));
@@ -354,13 +354,13 @@ impl<T: AsRef<[u8]>> Packet<T> {
     }
 
     /// Ensure that no accessor method will panic if called.
-    /// Returns `Err(Error::Truncated)` if the buffer is too short.
+    /// Returns `Err(Error)` if the buffer is too short.
     ///
     /// [set_header_len]: #method.set_header_len
     pub fn check_len(&self) -> Result<()> {
         let len = self.buffer.as_ref().len();
         if len < field::MAGIC_NUMBER.end {
-            Err(Error::Truncated)
+            Err(Error)
         } else {
             Ok(())
         }
@@ -470,7 +470,7 @@ impl<'a, T: AsRef<[u8]> + ?Sized> Packet<&'a T> {
     #[inline]
     pub fn options(&self) -> Result<&'a [u8]> {
         let data = self.buffer.as_ref();
-        data.get(field::OPTIONS).ok_or(Error::Malformed)
+        data.get(field::OPTIONS).ok_or(Error)
     }
 }
 
@@ -593,7 +593,7 @@ impl<'a, T: AsRef<[u8]> + AsMut<[u8]> + ?Sized> Packet<&'a mut T> {
     #[inline]
     pub fn options_mut(&mut self) -> Result<&mut [u8]> {
         let data = self.buffer.as_mut();
-        data.get_mut(field::OPTIONS).ok_or(Error::Truncated)
+        data.get_mut(field::OPTIONS).ok_or(Error)
     }
 }
 
@@ -760,17 +760,17 @@ impl<'a> Repr<'a> {
         match packet.hardware_type() {
             Hardware::Ethernet => {
                 if packet.hardware_len() != 6 {
-                    return Err(Error::Malformed);
+                    return Err(Error);
                 }
             }
-            Hardware::Unknown(_) => return Err(Error::Unrecognized), // unimplemented
+            Hardware::Unknown(_) => return Err(Error), // unimplemented
         }
 
         if packet.magic_number() != DHCP_MAGIC_NUMBER {
-            return Err(Error::Malformed);
+            return Err(Error);
         }
 
-        let mut message_type = Err(Error::Malformed);
+        let mut message_type = Err(Error);
         let mut requested_ip = None;
         let mut client_identifier = None;
         let mut server_identifier = None;
@@ -827,7 +827,7 @@ impl<'a> Repr<'a> {
                     let chunk_size = 4;
                     for (server, chunk) in servers.iter_mut().zip(data.chunks(chunk_size)) {
                         if chunk.len() != chunk_size {
-                            return Err(Error::Malformed);
+                            return Err(Error);
                         }
                         *server = Some(Ipv4Address::from_bytes(chunk));
                     }

+ 19 - 19
src/wire/dns.rs

@@ -5,11 +5,11 @@ use byteorder::{ByteOrder, NetworkEndian};
 use core::iter;
 use core::iter::Iterator;
 
+use super::{Error, Result};
 #[cfg(feature = "proto-ipv4")]
 use crate::wire::Ipv4Address;
 #[cfg(feature = "proto-ipv6")]
 use crate::wire::Ipv6Address;
-use crate::{Error, Result};
 
 enum_with_unknown! {
     /// DNS OpCodes
@@ -98,12 +98,12 @@ impl<T: AsRef<[u8]>> Packet<T> {
     }
 
     /// Ensure that no accessor method will panic if called.
-    /// Returns `Err(Error::Malformed)` if the buffer is smaller than
+    /// Returns `Err(Error)` if the buffer is smaller than
     /// the header length.
     pub fn check_len(&self) -> Result<()> {
         let len = self.buffer.as_ref().len();
         if len < field::HEADER_END {
-            Err(Error::Malformed)
+            Err(Error)
         } else {
             Ok(())
         }
@@ -166,14 +166,14 @@ impl<T: AsRef<[u8]>> Packet<T> {
 
         iter::from_fn(move || loop {
             if bytes.is_empty() {
-                return Some(Err(Error::Malformed));
+                return Some(Err(Error));
             }
             match bytes[0] {
                 0x00 => return None,
                 x if x & 0xC0 == 0x00 => {
                     let len = (x & 0x3F) as usize;
                     if bytes.len() < 1 + len {
-                        return Some(Err(Error::Malformed));
+                        return Some(Err(Error));
                     }
                     let label = &bytes[1..1 + len];
                     bytes = &bytes[1 + len..];
@@ -181,12 +181,12 @@ impl<T: AsRef<[u8]>> Packet<T> {
                 }
                 x if x & 0xC0 == 0xC0 => {
                     if bytes.len() < 2 {
-                        return Some(Err(Error::Malformed));
+                        return Some(Err(Error));
                     }
                     let y = bytes[1];
                     let ptr = ((x & 0x3F) as usize) << 8 | (y as usize);
                     if packet.len() <= ptr {
-                        return Some(Err(Error::Malformed));
+                        return Some(Err(Error));
                     }
 
                     // RFC1035 says: "In this scheme, an entire domain name or a list of labels at
@@ -204,7 +204,7 @@ impl<T: AsRef<[u8]>> Packet<T> {
                     bytes = &packet[ptr..];
                     packet = &packet[..ptr];
                 }
-                _ => return Some(Err(Error::Malformed)),
+                _ => return Some(Err(Error)),
             }
         })
     }
@@ -262,24 +262,24 @@ fn parse_name_part<'a>(
     mut f: impl FnMut(&'a [u8]),
 ) -> Result<(&'a [u8], Option<usize>)> {
     loop {
-        let x = *bytes.get(0).ok_or(Error::Malformed)?;
+        let x = *bytes.get(0).ok_or(Error)?;
         bytes = &bytes[1..];
         match x {
             0x00 => return Ok((bytes, None)),
             x if x & 0xC0 == 0x00 => {
                 let len = (x & 0x3F) as usize;
-                let label = bytes.get(..len).ok_or(Error::Malformed)?;
+                let label = bytes.get(..len).ok_or(Error)?;
                 bytes = &bytes[len..];
                 f(label);
             }
             x if x & 0xC0 == 0xC0 => {
-                let y = *bytes.get(0).ok_or(Error::Malformed)?;
+                let y = *bytes.get(0).ok_or(Error)?;
                 bytes = &bytes[1..];
 
                 let ptr = ((x & 0x3F) as usize) << 8 | (y as usize);
                 return Ok((bytes, Some(ptr)));
             }
-            _ => return Err(Error::Malformed),
+            _ => return Err(Error),
         }
     }
 }
@@ -297,14 +297,14 @@ impl<'a> Question<'a> {
         let name = &buffer[..buffer.len() - rest.len()];
 
         if rest.len() < 4 {
-            return Err(Error::Malformed);
+            return Err(Error);
         }
         let type_ = NetworkEndian::read_u16(&rest[0..2]).into();
         let class = NetworkEndian::read_u16(&rest[2..4]);
         let rest = &rest[4..];
 
         if class != CLASS_IN {
-            return Err(Error::Malformed);
+            return Err(Error);
         }
 
         Ok((rest, Question { name, type_ }))
@@ -338,14 +338,14 @@ impl<'a> RecordData<'a> {
             #[cfg(feature = "proto-ipv4")]
             Type::A => {
                 if data.len() != 4 {
-                    return Err(Error::Malformed);
+                    return Err(Error);
                 }
                 Ok(RecordData::A(Ipv4Address::from_bytes(data)))
             }
             #[cfg(feature = "proto-ipv6")]
             Type::Aaaa => {
                 if data.len() != 16 {
-                    return Err(Error::Malformed);
+                    return Err(Error);
                 }
                 Ok(RecordData::Aaaa(Ipv6Address::from_bytes(data)))
             }
@@ -372,7 +372,7 @@ impl<'a> Record<'a> {
         let name = &buffer[..buffer.len() - rest.len()];
 
         if rest.len() < 10 {
-            return Err(Error::Malformed);
+            return Err(Error);
         }
         let type_ = NetworkEndian::read_u16(&rest[0..2]).into();
         let class = NetworkEndian::read_u16(&rest[2..4]);
@@ -381,10 +381,10 @@ impl<'a> Record<'a> {
         let rest = &rest[10..];
 
         if class != CLASS_IN {
-            return Err(Error::Malformed);
+            return Err(Error);
         }
 
-        let data = rest.get(..len).ok_or(Error::Malformed)?;
+        let data = rest.get(..len).ok_or(Error)?;
         let rest = &rest[len..];
 
         Ok((

+ 3 - 3
src/wire/ethernet.rs

@@ -1,7 +1,7 @@
 use byteorder::{ByteOrder, NetworkEndian};
 use core::fmt;
 
-use crate::{Error, Result};
+use super::{Error, Result};
 
 enum_with_unknown! {
     /// Ethernet protocol type.
@@ -115,11 +115,11 @@ impl<T: AsRef<[u8]>> Frame<T> {
     }
 
     /// Ensure that no accessor method will panic if called.
-    /// Returns `Err(Error::Truncated)` if the buffer is too short.
+    /// Returns `Err(Error)` if the buffer is too short.
     pub fn check_len(&self) -> Result<()> {
         let len = self.buffer.as_ref().len();
         if len < HEADER_LEN {
-            Err(Error::Truncated)
+            Err(Error)
         } else {
             Ok(())
         }

+ 8 - 8
src/wire/icmpv4.rs

@@ -1,10 +1,10 @@
 use byteorder::{ByteOrder, NetworkEndian};
 use core::{cmp, fmt};
 
+use super::{Error, Result};
 use crate::phy::ChecksumCapabilities;
 use crate::wire::ip::checksum;
 use crate::wire::{Ipv4Packet, Ipv4Repr};
-use crate::{Error, Result};
 
 enum_with_unknown! {
     /// Internet protocol control message type.
@@ -189,7 +189,7 @@ impl<T: AsRef<[u8]>> Packet<T> {
     }
 
     /// Ensure that no accessor method will panic if called.
-    /// Returns `Err(Error::Truncated)` if the buffer is too short.
+    /// Returns `Err(Error)` if the buffer is too short.
     ///
     /// The result of this check is invalidated by calling [set_header_len].
     ///
@@ -197,7 +197,7 @@ impl<T: AsRef<[u8]>> Packet<T> {
     pub fn check_len(&self) -> Result<()> {
         let len = self.buffer.as_ref().len();
         if len < field::HEADER_END {
-            Err(Error::Truncated)
+            Err(Error)
         } else {
             Ok(())
         }
@@ -386,7 +386,7 @@ impl<'a> Repr<'a> {
     {
         // Valid checksum is expected.
         if checksum_caps.icmpv4.rx() && !packet.verify_checksum() {
-            return Err(Error::Checksum);
+            return Err(Error);
         }
 
         match (packet.msg_type(), packet.msg_code()) {
@@ -409,7 +409,7 @@ impl<'a> Repr<'a> {
                 // RFC 792 requires exactly eight bytes to be returned.
                 // We allow more, since there isn't a reason not to, but require at least eight.
                 if payload.len() < 8 {
-                    return Err(Error::Truncated);
+                    return Err(Error);
                 }
 
                 Ok(Repr::DstUnreachable {
@@ -424,7 +424,7 @@ impl<'a> Repr<'a> {
                     data: payload,
                 })
             }
-            _ => Err(Error::Unrecognized),
+            _ => Err(Error),
         }
     }
 
@@ -635,8 +635,8 @@ mod test {
     #[test]
     fn test_check_len() {
         let bytes = [0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];
-        assert_eq!(Packet::new_checked(&[]), Err(Error::Truncated));
-        assert_eq!(Packet::new_checked(&bytes[..4]), Err(Error::Truncated));
+        assert_eq!(Packet::new_checked(&[]), Err(Error));
+        assert_eq!(Packet::new_checked(&bytes[..4]), Err(Error));
         assert!(Packet::new_checked(&bytes[..]).is_ok());
     }
 }

+ 6 - 6
src/wire/icmpv6.rs

@@ -1,13 +1,13 @@
 use byteorder::{ByteOrder, NetworkEndian};
 use core::{cmp, fmt};
 
+use super::{Error, Result};
 use crate::phy::ChecksumCapabilities;
 use crate::wire::ip::checksum;
 use crate::wire::MldRepr;
 #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
 use crate::wire::NdiscRepr;
 use crate::wire::{IpAddress, IpProtocol, Ipv6Packet, Ipv6Repr};
-use crate::{Error, Result};
 
 enum_with_unknown! {
     /// Internet protocol control message type.
@@ -262,11 +262,11 @@ impl<T: AsRef<[u8]>> Packet<T> {
     }
 
     /// Ensure that no accessor method will panic if called.
-    /// Returns `Err(Error::Truncated)` if the buffer is too short.
+    /// Returns `Err(Error)` if the buffer is too short.
     pub fn check_len(&self) -> Result<()> {
         let len = self.buffer.as_ref().len();
         if len < field::HEADER_END || len < self.header_len() {
-            Err(Error::Truncated)
+            Err(Error)
         } else {
             Ok(())
         }
@@ -557,7 +557,7 @@ impl<'a> Repr<'a> {
 
             let payload = &packet.payload()[ip_packet.header_len() as usize..];
             if payload.len() < 8 {
-                return Err(Error::Truncated);
+                return Err(Error);
             }
             let repr = Ipv6Repr {
                 src_addr: ip_packet.src_addr(),
@@ -570,7 +570,7 @@ impl<'a> Repr<'a> {
         }
         // Valid checksum is expected.
         if checksum_caps.icmpv6.rx() && !packet.verify_checksum(src_addr, dst_addr) {
-            return Err(Error::Checksum);
+            return Err(Error);
         }
 
         match (packet.msg_type(), packet.msg_code()) {
@@ -620,7 +620,7 @@ impl<'a> Repr<'a> {
             #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
             (msg_type, 0) if msg_type.is_ndisc() => NdiscRepr::parse(packet).map(Repr::Ndisc),
             (msg_type, 0) if msg_type.is_mld() => MldRepr::parse(packet).map(Repr::Mld),
-            _ => Err(Error::Unrecognized),
+            _ => Err(Error),
         }
     }
 

+ 6 - 7
src/wire/ieee802154.rs

@@ -2,9 +2,8 @@ use core::fmt;
 
 use byteorder::{ByteOrder, LittleEndian};
 
+use super::{Error, Result};
 use crate::wire::ipv6::Address as Ipv6Address;
-use crate::Error;
-use crate::Result;
 
 enum_with_unknown! {
     /// IEEE 802.15.4 frame type.
@@ -238,22 +237,22 @@ impl<T: AsRef<[u8]>> Frame<T> {
         packet.check_len()?;
 
         if matches!(packet.dst_addressing_mode(), AddressingMode::Unknown(_)) {
-            return Err(Error::Malformed);
+            return Err(Error);
         }
 
         if matches!(packet.src_addressing_mode(), AddressingMode::Unknown(_)) {
-            return Err(Error::Malformed);
+            return Err(Error);
         }
 
         Ok(packet)
     }
 
     /// Ensure that no accessor method will panic if called.
-    /// Returns `Err(Error::Truncated)` if the buffer is too short.
+    /// Returns `Err(Error)` if the buffer is too short.
     pub fn check_len(&self) -> Result<()> {
         // We need at least 3 bytes
         if self.buffer.as_ref().len() < 3 {
-            return Err(Error::Truncated);
+            return Err(Error);
         }
 
         let mut offset = field::ADDRESSING.start + 2;
@@ -267,7 +266,7 @@ impl<T: AsRef<[u8]>> Frame<T> {
         }
 
         if offset > self.buffer.as_ref().len() {
-            return Err(Error::Truncated);
+            return Err(Error);
         }
 
         Ok(())

+ 5 - 5
src/wire/igmp.rs

@@ -1,9 +1,9 @@
 use byteorder::{ByteOrder, NetworkEndian};
 use core::fmt;
 
+use super::{Error, Result};
 use crate::time::Duration;
 use crate::wire::ip::checksum;
-use crate::{Error, Result};
 
 use crate::wire::Ipv4Address;
 
@@ -69,11 +69,11 @@ impl<T: AsRef<[u8]>> Packet<T> {
     }
 
     /// Ensure that no accessor method will panic if called.
-    /// Returns `Err(Error::Truncated)` if the buffer is too short.
+    /// Returns `Err(Error)` if the buffer is too short.
     pub fn check_len(&self) -> Result<()> {
         let len = self.buffer.as_ref().len();
         if len < field::GROUP_ADDRESS.end as usize {
-            Err(Error::Truncated)
+            Err(Error)
         } else {
             Ok(())
         }
@@ -208,7 +208,7 @@ impl Repr {
         // Check if the address is 0.0.0.0 or multicast
         let addr = packet.group_addr();
         if !addr.is_unspecified() && !addr.is_multicast() {
-            return Err(Error::Malformed);
+            return Err(Error);
         }
 
         // construct a packet based on the Type field
@@ -241,7 +241,7 @@ impl Repr {
                     version: IgmpVersion::Version1,
                 })
             }
-            _ => Err(Error::Unrecognized),
+            _ => Err(Error),
         }
     }
 

+ 3 - 3
src/wire/ip.rs

@@ -1,12 +1,12 @@
 use core::convert::From;
 use core::fmt;
 
+use super::{Error, Result};
 use crate::phy::ChecksumCapabilities;
 #[cfg(feature = "proto-ipv4")]
 use crate::wire::{Ipv4Address, Ipv4Cidr, Ipv4Packet, Ipv4Repr};
 #[cfg(feature = "proto-ipv6")]
 use crate::wire::{Ipv6Address, Ipv6Cidr, Ipv6Packet, Ipv6Repr};
-use crate::{Error, Result};
 
 /// Internet protocol version.
 #[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
@@ -22,14 +22,14 @@ impl Version {
     /// Return the version of an IP packet stored in the provided buffer.
     ///
     /// This function never returns `Ok(IpVersion::Unspecified)`; instead,
-    /// unknown versions result in `Err(Error::Unrecognized)`.
+    /// unknown versions result in `Err(Error)`.
     pub fn of_packet(data: &[u8]) -> Result<Version> {
         match data[0] >> 4 {
             #[cfg(feature = "proto-ipv4")]
             4 => Ok(Version::Ipv4),
             #[cfg(feature = "proto-ipv6")]
             6 => Ok(Version::Ipv6),
-            _ => Err(Error::Unrecognized),
+            _ => Err(Error),
         }
     }
 }

+ 15 - 15
src/wire/ipv4.rs

@@ -1,9 +1,9 @@
 use byteorder::{ByteOrder, NetworkEndian};
 use core::fmt;
 
+use super::{Error, Result};
 use crate::phy::ChecksumCapabilities;
 use crate::wire::ip::{checksum, pretty_print_ip_payload};
-use crate::{Error, Result};
 
 pub use super::IpProtocol as Protocol;
 
@@ -164,7 +164,7 @@ impl Cidr {
                 prefix_len: netmask.count_ones() as u8,
             })
         } else {
-            Err(Error::Illegal)
+            Err(Error)
         }
     }
 
@@ -305,8 +305,8 @@ impl<T: AsRef<[u8]>> Packet<T> {
     }
 
     /// Ensure that no accessor method will panic if called.
-    /// Returns `Err(Error::Truncated)` if the buffer is too short.
-    /// Returns `Err(Error::Malformed)` if the header length is greater
+    /// Returns `Err(Error)` if the buffer is too short.
+    /// Returns `Err(Error)` if the header length is greater
     /// than total length.
     ///
     /// The result of this check is invalidated by calling [set_header_len]
@@ -318,13 +318,13 @@ impl<T: AsRef<[u8]>> Packet<T> {
     pub fn check_len(&self) -> Result<()> {
         let len = self.buffer.as_ref().len();
         if len < field::DST_ADDR.end {
-            Err(Error::Truncated)
+            Err(Error)
         } else if len < self.header_len() as usize {
-            Err(Error::Truncated)
+            Err(Error)
         } else if self.header_len() as u16 > self.total_len() {
-            Err(Error::Malformed)
+            Err(Error)
         } else if len < self.total_len() as usize {
-            Err(Error::Truncated)
+            Err(Error)
         } else {
             Ok(())
         }
@@ -611,20 +611,20 @@ impl Repr {
     ) -> Result<Repr> {
         // Version 4 is expected.
         if packet.version() != 4 {
-            return Err(Error::Malformed);
+            return Err(Error);
         }
         // Valid checksum is expected.
         if checksum_caps.ipv4.rx() && !packet.verify_checksum() {
-            return Err(Error::Checksum);
+            return Err(Error);
         }
         // We do not support fragmentation.
         if packet.more_frags() || packet.frag_offset() != 0 {
-            return Err(Error::Fragmented);
+            return Err(Error);
         }
         // Since the packet is not fragmented, it must include the entire payload.
         let payload_len = packet.total_len() as usize - packet.header_len() as usize;
         if packet.payload().len() < payload_len {
-            return Err(Error::Truncated);
+            return Err(Error);
         }
 
         // All DSCP values are acceptable, since they are of no concern to receiving endpoint.
@@ -837,7 +837,7 @@ mod test {
         bytes.extend(&PACKET_BYTES[..]);
         Packet::new_unchecked(&mut bytes).set_total_len(128);
 
-        assert_eq!(Packet::new_checked(&bytes).unwrap_err(), Error::Truncated);
+        assert_eq!(Packet::new_checked(&bytes).unwrap_err(), Error);
     }
 
     static REPR_PACKET_BYTES: [u8; 24] = [
@@ -874,7 +874,7 @@ mod test {
         let packet = Packet::new_unchecked(&*packet.into_inner());
         assert_eq!(
             Repr::parse(&packet, &ChecksumCapabilities::default()),
-            Err(Error::Malformed)
+            Err(Error)
         );
     }
 
@@ -882,7 +882,7 @@ mod test {
     fn test_parse_total_len_less_than_header_len() {
         let mut bytes = vec![0; 40];
         bytes[0] = 0x09;
-        assert_eq!(Packet::new_checked(&mut bytes), Err(Error::Malformed));
+        assert_eq!(Packet::new_checked(&mut bytes), Err(Error));
     }
 
     #[test]

+ 9 - 9
src/wire/ipv6.rs

@@ -3,10 +3,10 @@
 use byteorder::{ByteOrder, NetworkEndian};
 use core::fmt;
 
+use super::{Error, Result};
 use crate::wire::ip::pretty_print_ip_payload;
 #[cfg(feature = "proto-ipv4")]
 use crate::wire::ipv4;
-use crate::{Error, Result};
 
 pub use super::IpProtocol as Protocol;
 
@@ -422,7 +422,7 @@ impl<T: AsRef<[u8]>> Packet<T> {
     }
 
     /// Ensure that no accessor method will panic if called.
-    /// Returns `Err(Error::Truncated)` if the buffer is too short.
+    /// Returns `Err(Error)` if the buffer is too short.
     ///
     /// The result of this check is invalidated by calling [set_payload_len].
     ///
@@ -431,7 +431,7 @@ impl<T: AsRef<[u8]>> Packet<T> {
     pub fn check_len(&self) -> Result<()> {
         let len = self.buffer.as_ref().len();
         if len < field::DST_ADDR.end || len < self.total_len() {
-            Err(Error::Truncated)
+            Err(Error)
         } else {
             Ok(())
         }
@@ -639,7 +639,7 @@ impl Repr {
         // Ensure basic accessors will work
         packet.check_len()?;
         if packet.version() != 6 {
-            return Err(Error::Malformed);
+            return Err(Error);
         }
         Ok(Repr {
             src_addr: packet.src_addr(),
@@ -708,10 +708,10 @@ impl<T: AsRef<[u8]>> PrettyPrint for Packet<T> {
 
 #[cfg(test)]
 mod test {
+    use super::Error;
     use super::{Address, Cidr};
     use super::{Packet, Protocol, Repr};
     use crate::wire::pretty_print::PrettyPrinter;
-    use crate::Error;
 
     #[cfg(feature = "proto-ipv4")]
     use crate::wire::ipv4::Address as Ipv4Address;
@@ -1128,7 +1128,7 @@ mod test {
         bytes.extend(&REPR_PACKET_BYTES[..]);
         Packet::new_unchecked(&mut bytes).set_payload_len(0x80);
 
-        assert_eq!(Packet::new_checked(&bytes).unwrap_err(), Error::Truncated);
+        assert_eq!(Packet::new_checked(&bytes).unwrap_err(), Error);
     }
 
     #[test]
@@ -1145,7 +1145,7 @@ mod test {
         packet.set_version(4);
         packet.set_payload_len(0);
         let packet = Packet::new_unchecked(&*packet.into_inner());
-        assert_eq!(Repr::parse(&packet), Err(Error::Malformed));
+        assert_eq!(Repr::parse(&packet), Err(Error));
     }
 
     #[test]
@@ -1155,7 +1155,7 @@ mod test {
         packet.set_version(6);
         packet.set_payload_len(39);
         let packet = Packet::new_unchecked(&*packet.into_inner());
-        assert_eq!(Repr::parse(&packet), Err(Error::Truncated));
+        assert_eq!(Repr::parse(&packet), Err(Error));
     }
 
     #[test]
@@ -1165,7 +1165,7 @@ mod test {
         packet.set_version(6);
         packet.set_payload_len(1);
         let packet = Packet::new_unchecked(&*packet.into_inner());
-        assert_eq!(Repr::parse(&packet), Err(Error::Truncated));
+        assert_eq!(Repr::parse(&packet), Err(Error));
     }
 
     #[test]

+ 4 - 4
src/wire/ipv6fragment.rs

@@ -1,4 +1,4 @@
-use crate::{Error, Result};
+use super::{Error, Result};
 use core::fmt;
 
 use byteorder::{ByteOrder, NetworkEndian};
@@ -51,13 +51,13 @@ impl<T: AsRef<[u8]>> Header<T> {
     }
 
     /// Ensure that no accessor method will panic if called.
-    /// Returns `Err(Error::Truncated)` if the buffer is too short.
+    /// Returns `Err(Error)` if the buffer is too short.
     pub fn check_len(&self) -> Result<()> {
         let data = self.buffer.as_ref();
         let len = data.len();
 
         if len < field::IDENT.end {
-            Err(Error::Truncated)
+            Err(Error)
         } else {
             Ok(())
         }
@@ -226,7 +226,7 @@ mod test {
     fn test_check_len() {
         // less than 8 bytes
         assert_eq!(
-            Err(Error::Truncated),
+            Err(Error),
             Header::new_unchecked(&BYTES_HEADER_MORE_FRAG[..7]).check_len()
         );
         // valid

+ 10 - 13
src/wire/ipv6hopbyhop.rs

@@ -1,4 +1,4 @@
-use crate::{Error, Result};
+use super::{Error, Result};
 use core::fmt;
 
 pub use super::IpProtocol as Protocol;
@@ -65,7 +65,7 @@ impl<T: AsRef<[u8]>> Header<T> {
     }
 
     /// Ensure that no accessor method will panic if called.
-    /// Returns `Err(Error::Truncated)` if the buffer is too short.
+    /// Returns `Err(Error)` if the buffer is too short.
     ///
     /// The result of this check is invalidated by calling [set_header_len].
     ///
@@ -75,13 +75,13 @@ impl<T: AsRef<[u8]>> Header<T> {
         let len = data.len();
 
         if len < field::MIN_HEADER_SIZE {
-            return Err(Error::Truncated);
+            return Err(Error);
         }
 
         let of = field::OPTIONS(data[field::LENGTH]);
 
         if len < of.end {
-            return Err(Error::Truncated);
+            return Err(Error);
         }
 
         Ok(())
@@ -226,17 +226,17 @@ mod test {
     fn test_check_len() {
         // zero byte buffer
         assert_eq!(
-            Err(Error::Truncated),
+            Err(Error),
             Header::new_unchecked(&REPR_PACKET_PAD4[..0]).check_len()
         );
         // no length field
         assert_eq!(
-            Err(Error::Truncated),
+            Err(Error),
             Header::new_unchecked(&REPR_PACKET_PAD4[..1]).check_len()
         );
         // less than 8 bytes
         assert_eq!(
-            Err(Error::Truncated),
+            Err(Error),
             Header::new_unchecked(&REPR_PACKET_PAD4[..7]).check_len()
         );
         // valid
@@ -248,10 +248,7 @@ mod test {
         );
         // length field value greater than number of bytes
         let header: [u8; 8] = [0x06, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0];
-        assert_eq!(
-            Err(Error::Truncated),
-            Header::new_unchecked(&header).check_len()
-        );
+        assert_eq!(Err(Error), Header::new_unchecked(&header).check_len());
     }
 
     #[test]
@@ -303,14 +300,14 @@ mod test {
         let len = bytes.len() as u8;
         Header::new_unchecked(&mut bytes).set_header_len(len + 1);
 
-        assert_eq!(Header::new_checked(&bytes).unwrap_err(), Error::Truncated);
+        assert_eq!(Header::new_checked(&bytes).unwrap_err(), Error);
 
         let mut bytes = vec![];
         bytes.extend(&REPR_PACKET_PAD12);
         let len = bytes.len() as u8;
         Header::new_unchecked(&mut bytes).set_header_len(len + 1);
 
-        assert_eq!(Header::new_checked(&bytes).unwrap_err(), Error::Truncated);
+        assert_eq!(Header::new_checked(&bytes).unwrap_err(), Error);
     }
 
     #[test]

+ 11 - 11
src/wire/ipv6option.rs

@@ -1,4 +1,4 @@
-use crate::{Error, Result};
+use super::{Error, Result};
 use core::fmt;
 
 enum_with_unknown! {
@@ -103,7 +103,7 @@ impl<T: AsRef<[u8]>> Ipv6Option<T> {
     }
 
     /// Ensure that no accessor method will panic if called.
-    /// Returns `Err(Error::Truncated)` if the buffer is too short.
+    /// Returns `Err(Error)` if the buffer is too short.
     ///
     /// The result of this check is invalidated by calling [set_data_len].
     ///
@@ -113,7 +113,7 @@ impl<T: AsRef<[u8]>> Ipv6Option<T> {
         let len = data.len();
 
         if len < field::LENGTH {
-            return Err(Error::Truncated);
+            return Err(Error);
         }
 
         if self.option_type() == Type::Pad1 {
@@ -121,13 +121,13 @@ impl<T: AsRef<[u8]>> Ipv6Option<T> {
         }
 
         if len == field::LENGTH {
-            return Err(Error::Truncated);
+            return Err(Error);
         }
 
         let df = field::DATA(data[field::LENGTH]);
 
         if len < df.end {
-            return Err(Error::Truncated);
+            return Err(Error);
         }
 
         Ok(())
@@ -362,7 +362,7 @@ mod test {
         let bytes = [0u8];
         // zero byte buffer
         assert_eq!(
-            Err(Error::Truncated),
+            Err(Error),
             Ipv6Option::new_unchecked(&bytes[..0]).check_len()
         );
         // pad1
@@ -373,7 +373,7 @@ mod test {
 
         // padn with truncated data
         assert_eq!(
-            Err(Error::Truncated),
+            Err(Error),
             Ipv6Option::new_unchecked(&IPV6OPTION_BYTES_PADN[..2]).check_len()
         );
         // padn
@@ -384,11 +384,11 @@ mod test {
 
         // unknown option type with truncated data
         assert_eq!(
-            Err(Error::Truncated),
+            Err(Error),
             Ipv6Option::new_unchecked(&IPV6OPTION_BYTES_UNKNOWN[..4]).check_len()
         );
         assert_eq!(
-            Err(Error::Truncated),
+            Err(Error),
             Ipv6Option::new_unchecked(&IPV6OPTION_BYTES_UNKNOWN[..1]).check_len()
         );
         // unknown type
@@ -436,7 +436,7 @@ mod test {
         assert_eq!(opt.option_type(), Type::Unknown(255));
 
         // unrecognized option without length and data
-        assert_eq!(Ipv6Option::new_checked(&bytes), Err(Error::Truncated));
+        assert_eq!(Ipv6Option::new_checked(&bytes), Err(Error));
     }
 
     #[test]
@@ -533,7 +533,7 @@ mod test {
                         ..
                     }),
                 ) => continue,
-                (6, Err(Error::Truncated)) => continue,
+                (6, Err(Error)) => continue,
                 (i, res) => panic!("Unexpected option `{:?}` at index {}", res, i),
             }
         }

+ 11 - 29
src/wire/ipv6routing.rs

@@ -1,4 +1,4 @@
-use crate::{Error, Result};
+use super::{Error, Result};
 use core::fmt;
 
 use crate::wire::IpProtocol as Protocol;
@@ -158,7 +158,7 @@ impl<T: AsRef<[u8]>> Header<T> {
     }
 
     /// Ensure that no accessor method will panic if called.
-    /// Returns `Err(Error::Truncated)` if the buffer is too short.
+    /// Returns `Err(Error)` if the buffer is too short.
     ///
     /// The result of this check is invalidated by calling [set_header_len].
     ///
@@ -166,11 +166,11 @@ impl<T: AsRef<[u8]>> Header<T> {
     pub fn check_len(&self) -> Result<()> {
         let len = self.buffer.as_ref().len();
         if len < field::MIN_HEADER_SIZE {
-            return Err(Error::Truncated);
+            return Err(Error);
         }
 
         if len < field::DATA(self.header_len()).end as usize {
-            return Err(Error::Truncated);
+            return Err(Error);
         }
 
         Ok(())
@@ -444,7 +444,7 @@ impl<'a> Repr<'a> {
                 addresses: header.addresses(),
             }),
 
-            _ => Err(Error::Unrecognized),
+            _ => Err(Error),
         }
     }
 
@@ -588,31 +588,13 @@ mod test {
     #[test]
     fn test_check_len() {
         // less than min header size
-        assert_eq!(
-            Err(Error::Truncated),
-            Header::new(&BYTES_TYPE2[..3]).check_len()
-        );
-        assert_eq!(
-            Err(Error::Truncated),
-            Header::new(&BYTES_SRH_FULL[..3]).check_len()
-        );
-        assert_eq!(
-            Err(Error::Truncated),
-            Header::new(&BYTES_SRH_ELIDED[..3]).check_len()
-        );
+        assert_eq!(Err(Error), Header::new(&BYTES_TYPE2[..3]).check_len());
+        assert_eq!(Err(Error), Header::new(&BYTES_SRH_FULL[..3]).check_len());
+        assert_eq!(Err(Error), Header::new(&BYTES_SRH_ELIDED[..3]).check_len());
         // less than specified length field
-        assert_eq!(
-            Err(Error::Truncated),
-            Header::new(&BYTES_TYPE2[..23]).check_len()
-        );
-        assert_eq!(
-            Err(Error::Truncated),
-            Header::new(&BYTES_SRH_FULL[..39]).check_len()
-        );
-        assert_eq!(
-            Err(Error::Truncated),
-            Header::new(&BYTES_SRH_ELIDED[..11]).check_len()
-        );
+        assert_eq!(Err(Error), Header::new(&BYTES_TYPE2[..23]).check_len());
+        assert_eq!(Err(Error), Header::new(&BYTES_SRH_FULL[..39]).check_len());
+        assert_eq!(Err(Error), Header::new(&BYTES_SRH_ELIDED[..11]).check_len());
         // valid
         assert_eq!(Ok(()), Header::new(&BYTES_TYPE2[..]).check_len());
         assert_eq!(Ok(()), Header::new(&BYTES_SRH_FULL[..]).check_len());

+ 3 - 3
src/wire/mld.rs

@@ -6,9 +6,9 @@
 
 use byteorder::{ByteOrder, NetworkEndian};
 
+use super::{Error, Result};
 use crate::wire::icmpv6::{field, Message, Packet};
 use crate::wire::Ipv6Address;
-use crate::{Error, Result};
 
 enum_with_unknown! {
     /// MLDv2 Multicast Listener Report Record Type. See [RFC 3810 § 5.2.12] for
@@ -192,7 +192,7 @@ impl<T: AsRef<[u8]>> AddressRecord<T> {
     pub fn check_len(&self) -> Result<()> {
         let len = self.buffer.as_ref().len();
         if len < field::RECORD_MCAST_ADDR.end {
-            Err(Error::Truncated)
+            Err(Error)
         } else {
             Ok(())
         }
@@ -333,7 +333,7 @@ impl<'a> Repr<'a> {
                 nr_mcast_addr_rcrds: packet.nr_mcast_addr_rcrds(),
                 data: packet.payload(),
             }),
-            _ => Err(Error::Unrecognized),
+            _ => Err(Error),
         }
     }
 

+ 24 - 4
src/wire/mod.rs

@@ -125,7 +125,9 @@ mod sixlowpan;
 mod tcp;
 mod udp;
 
-use crate::{phy::Medium, Error};
+use core::fmt;
+
+use crate::phy::Medium;
 
 pub use self::pretty_print::PrettyPrinter;
 
@@ -245,6 +247,24 @@ pub use self::dhcpv4::{
     SERVER_PORT as DHCP_SERVER_PORT,
 };
 
+/// Parsing a packet failed.
+///
+/// Either it is malformed, or it is not supported by smoltcp.
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+#[cfg_attr(feature = "defmt", derive(defmt::Format))]
+pub struct Error;
+
+#[cfg(feature = "std")]
+impl std::error::Error for Error {}
+
+impl fmt::Display for Error {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "wire::Error")
+    }
+}
+
+pub type Result<T> = core::result::Result<T, Error>;
+
 /// Representation of an hardware address, such as an Ethernet address or an IEEE802.15.4 address.
 #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
@@ -354,12 +374,12 @@ impl RawHardwareAddress {
         self.len == 0
     }
 
-    pub fn parse(&self, medium: Medium) -> Result<HardwareAddress, Error> {
+    pub fn parse(&self, medium: Medium) -> Result<HardwareAddress> {
         match medium {
             #[cfg(feature = "medium-ethernet")]
             Medium::Ethernet => {
                 if self.len() < 6 {
-                    return Err(Error::Malformed);
+                    return Err(Error);
                 }
                 Ok(HardwareAddress::Ethernet(EthernetAddress::from_bytes(
                     self.as_bytes(),
@@ -368,7 +388,7 @@ impl RawHardwareAddress {
             #[cfg(feature = "medium-ieee802154")]
             Medium::Ieee802154 => {
                 if self.len() < 8 {
-                    return Err(Error::Malformed);
+                    return Err(Error);
                 }
                 Ok(HardwareAddress::Ieee802154(Ieee802154Address::from_bytes(
                     self.as_bytes(),

+ 8 - 8
src/wire/ndisc.rs

@@ -1,6 +1,7 @@
 use bitflags::bitflags;
 use byteorder::{ByteOrder, NetworkEndian};
 
+use super::{Error, Result};
 use crate::time::Duration;
 use crate::wire::icmpv6::{field, Message, Packet};
 use crate::wire::Ipv6Address;
@@ -8,7 +9,6 @@ use crate::wire::RawHardwareAddress;
 use crate::wire::{Ipv6Packet, Ipv6Repr};
 use crate::wire::{NdiscOption, NdiscOptionRepr, NdiscOptionType};
 use crate::wire::{NdiscPrefixInformation, NdiscRedirectedHeader};
-use crate::{Error, Result};
 
 bitflags! {
     #[cfg_attr(feature = "defmt", derive(defmt::Format))]
@@ -237,7 +237,7 @@ impl<'a> Repr<'a> {
                     match opt.option_type() {
                         NdiscOptionType::SourceLinkLayerAddr => Some(opt.link_layer_addr()),
                         _ => {
-                            return Err(Error::Unrecognized);
+                            return Err(Error);
                         }
                     }
                 } else {
@@ -256,7 +256,7 @@ impl<'a> Repr<'a> {
                         NdiscOptionRepr::Mtu(val) => mtu = Some(val),
                         NdiscOptionRepr::PrefixInformation(info) => prefix_info = Some(info),
                         _ => {
-                            return Err(Error::Unrecognized);
+                            return Err(Error);
                         }
                     }
                     offset += opt.buffer_len();
@@ -278,7 +278,7 @@ impl<'a> Repr<'a> {
                     match opt.option_type() {
                         NdiscOptionType::SourceLinkLayerAddr => Some(opt.link_layer_addr()),
                         _ => {
-                            return Err(Error::Unrecognized);
+                            return Err(Error);
                         }
                     }
                 } else {
@@ -295,7 +295,7 @@ impl<'a> Repr<'a> {
                     match opt.option_type() {
                         NdiscOptionType::TargetLinkLayerAddr => Some(opt.link_layer_addr()),
                         _ => {
-                            return Err(Error::Unrecognized);
+                            return Err(Error);
                         }
                     }
                 } else {
@@ -319,7 +319,7 @@ impl<'a> Repr<'a> {
                         }
                         NdiscOptionType::RedirectedHeader => {
                             if opt.data_len() < 6 {
-                                return Err(Error::Truncated);
+                                return Err(Error);
                             } else {
                                 let ip_packet =
                                     Ipv6Packet::new_unchecked(&opt.data()[offset + 8..]);
@@ -333,7 +333,7 @@ impl<'a> Repr<'a> {
                             }
                         }
                         _ => {
-                            return Err(Error::Unrecognized);
+                            return Err(Error);
                         }
                     }
                 }
@@ -344,7 +344,7 @@ impl<'a> Repr<'a> {
                     redirected_hdr,
                 })
             }
-            _ => Err(Error::Unrecognized),
+            _ => Err(Error),
         }
     }
 

+ 13 - 16
src/wire/ndiscoption.rs

@@ -2,9 +2,9 @@ use bitflags::bitflags;
 use byteorder::{ByteOrder, NetworkEndian};
 use core::fmt;
 
+use super::{Error, Result};
 use crate::time::Duration;
 use crate::wire::{Ipv6Address, Ipv6Packet, Ipv6Repr, MAX_HARDWARE_ADDRESS_LEN};
-use crate::{Error, Result};
 
 use crate::wire::RawHardwareAddress;
 
@@ -162,7 +162,7 @@ impl<T: AsRef<[u8]>> NdiscOption<T> {
     }
 
     /// Ensure that no accessor method will panic if called.
-    /// Returns `Err(Error::Truncated)` if the buffer is too short.
+    /// Returns `Err(Error)` if the buffer is too short.
     ///
     /// The result of this check is invalidated by calling [set_data_len].
     ///
@@ -172,18 +172,18 @@ impl<T: AsRef<[u8]>> NdiscOption<T> {
         let len = data.len();
 
         if len < field::MIN_OPT_LEN {
-            Err(Error::Truncated)
+            Err(Error)
         } else {
             let data_range = field::DATA(data[field::LENGTH]);
             if len < data_range.end {
-                Err(Error::Truncated)
+                Err(Error)
             } else {
                 match self.option_type() {
                     Type::SourceLinkLayerAddr | Type::TargetLinkLayerAddr | Type::Mtu => Ok(()),
                     Type::PrefixInformation if data_range.end >= field::PREFIX.end => Ok(()),
                     Type::RedirectedHeader if data_range.end >= field::REDIR_MIN_SZ => Ok(()),
                     Type::Unknown(_) => Ok(()),
-                    _ => Err(Error::Truncated),
+                    _ => Err(Error),
                 }
             }
         }
@@ -432,14 +432,14 @@ impl<'a> Repr<'a> {
                 if opt.data_len() == 1 {
                     Ok(Repr::SourceLinkLayerAddr(opt.link_layer_addr()))
                 } else {
-                    Err(Error::Malformed)
+                    Err(Error)
                 }
             }
             Type::TargetLinkLayerAddr => {
                 if opt.data_len() == 1 {
                     Ok(Repr::TargetLinkLayerAddr(opt.link_layer_addr()))
                 } else {
-                    Err(Error::Malformed)
+                    Err(Error)
                 }
             }
             Type::PrefixInformation => {
@@ -452,7 +452,7 @@ impl<'a> Repr<'a> {
                         prefix: opt.prefix(),
                     }))
                 } else {
-                    Err(Error::Malformed)
+                    Err(Error)
                 }
             }
             Type::RedirectedHeader => {
@@ -460,7 +460,7 @@ impl<'a> Repr<'a> {
                 // does not have enough data to fill out the IP header
                 // and common option fields.
                 if opt.data_len() < 6 {
-                    Err(Error::Truncated)
+                    Err(Error)
                 } else {
                     let ip_packet = Ipv6Packet::new_unchecked(&opt.data()[field::IP_DATA..]);
                     let ip_repr = Ipv6Repr::parse(&ip_packet)?;
@@ -474,7 +474,7 @@ impl<'a> Repr<'a> {
                 if opt.data_len() == 1 {
                     Ok(Repr::Mtu(opt.mtu()))
                 } else {
-                    Err(Error::Malformed)
+                    Err(Error)
                 }
             }
             Type::Unknown(id) => Ok(Repr::Unknown {
@@ -617,10 +617,10 @@ impl<T: AsRef<[u8]>> PrettyPrint for NdiscOption<T> {
 
 #[cfg(test)]
 mod test {
+    use super::Error;
     use super::{NdiscOption, PrefixInfoFlags, PrefixInformation, Repr, Type};
     use crate::time::Duration;
     use crate::wire::{EthernetAddress, Ipv6Address};
-    use crate::Error;
 
     static PREFIX_OPT_BYTES: [u8; 32] = [
         0x03, 0x04, 0x40, 0xc0, 0x00, 0x00, 0x03, 0x84, 0x00, 0x00, 0x03, 0xe8, 0x00, 0x00, 0x00,
@@ -659,12 +659,9 @@ mod test {
 
     #[test]
     fn test_short_packet() {
-        assert_eq!(
-            NdiscOption::new_checked(&[0x00, 0x00]),
-            Err(Error::Truncated)
-        );
+        assert_eq!(NdiscOption::new_checked(&[0x00, 0x00]), Err(Error));
         let bytes = [0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];
-        assert_eq!(NdiscOption::new_checked(&bytes), Err(Error::Truncated));
+        assert_eq!(NdiscOption::new_checked(&bytes), Err(Error));
     }
 
     #[test]

+ 27 - 30
src/wire/sixlowpan.rs

@@ -1,12 +1,11 @@
-/// Implementation of [RFC 6282] which specifies a compression format for IPv6 datagrams over
-/// IEEE802.154-based networks.
-///
-/// [RFC 6282]: https://datatracker.ietf.org/doc/html/rfc6282
+//! Implementation of [RFC 6282] which specifies a compression format for IPv6 datagrams over
+//! IEEE802.154-based networks.
+//!
+//! [RFC 6282]: https://datatracker.ietf.org/doc/html/rfc6282
+use super::{Error, Result};
 use crate::wire::ieee802154::Address as LlAddress;
 use crate::wire::ipv6;
 use crate::wire::IpProtocol;
-use crate::Error;
-use crate::Result;
 
 #[derive(Debug, PartialEq, Eq, Clone, Copy)]
 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
@@ -46,23 +45,22 @@ impl<'a> Address<'a> {
                     Some(LlAddress::Extended(ll)) => {
                         bytes[8..].copy_from_slice(&LlAddress::Extended(ll).as_eui_64().unwrap());
                     }
-                    _ => return Err(Error::Malformed),
+                    _ => return Err(Error),
                 }
 
                 Ok(ipv6::Address::from_bytes(&bytes))
             }
-            Address::WithContext(_) => Err(Error::NotSupported),
-            Address::Reserved => Err(Error::Malformed),
+            Address::WithContext(_) => Err(Error),
+            Address::Reserved => Err(Error),
         }
     }
 }
 
 pub mod iphc {
+    use super::{Error, Result};
     use crate::wire::ieee802154::Address as LlAddress;
     use crate::wire::ipv6;
     use crate::wire::IpProtocol;
-    use crate::Error;
-    use crate::Result;
     use byteorder::{ByteOrder, NetworkEndian};
 
     use super::Address;
@@ -124,11 +122,11 @@ pub mod iphc {
         }
 
         /// Ensure that no accessor method will panic if called.
-        /// Returns `Err(Error::Truncated)` if the buffer is too short.
+        /// Returns `Err(Error)` if the buffer is too short.
         pub fn check_len(&self) -> Result<()> {
             let buffer = self.buffer.as_ref();
             if buffer.len() < 2 {
-                return Err(Error::Truncated);
+                return Err(Error);
             }
 
             let mut offset = self.ip_fields_start()
@@ -139,7 +137,7 @@ pub mod iphc {
             offset += self.dst_address_size();
 
             if offset as usize > buffer.len() {
-                return Err(Error::Truncated);
+                return Err(Error);
             }
 
             Ok(())
@@ -290,7 +288,7 @@ pub mod iphc {
                     // Any remaining bits are zero.
                     Ok(Address::WithContext(&[]))
                 }
-                _ => Err(Error::Malformed),
+                _ => Err(Error),
             }
         }
 
@@ -428,10 +426,10 @@ pub mod iphc {
                     // P are octets used to encode the prefix itself.
                     // L are octets used to encode the prefix length.
                     // The prefix information P and L is taken from the specified context.
-                    Err(Error::NotSupported)
+                    Err(Error)
                 }
                 (1, 1, 0b01 | 0b10 | 0b11) => Ok(Address::Reserved),
-                _ => Err(Error::Malformed),
+                _ => Err(Error),
             }
         }
 
@@ -781,7 +779,7 @@ pub mod iphc {
 
             if packet.dispatch_field() != DISPATCH {
                 // This is not an LOWPAN_IPHC packet.
-                return Err(Error::Malformed);
+                return Err(Error);
             }
 
             let src_addr = packet.src_addr()?.resolve(ll_src_addr)?;
@@ -975,13 +973,12 @@ pub mod iphc {
 }
 
 pub mod nhc {
+    use super::{Error, Result};
     use crate::wire::ip::checksum;
     use crate::wire::ip::Address as IpAddress;
     use crate::wire::ipv6;
     use crate::wire::udp::Repr as UdpRepr;
     use crate::wire::IpProtocol;
-    use crate::Error;
-    use crate::Result;
     use byteorder::{ByteOrder, NetworkEndian};
     use ipv6::Address;
 
@@ -1032,7 +1029,7 @@ pub mod nhc {
                 // We have a compressed UDP header.
                 Ok(Packet::UdpHeader(UdpPacket::new_checked(buffer)?))
             } else {
-                Err(Error::Unrecognized)
+                Err(Error)
             }
         }
     }
@@ -1089,11 +1086,11 @@ pub mod nhc {
         }
 
         /// Ensure that no accessor method will panic if called.
-        /// Returns `Err(Error::Truncated)` if the buffer is too short.
+        /// Returns `Err(Error)` if the buffer is too short.
         pub fn check_len(&self) -> Result<()> {
             let buffer = self.buffer.as_ref();
             if buffer.is_empty() {
-                Err(Error::Truncated)
+                Err(Error)
             } else {
                 Ok(())
             }
@@ -1235,7 +1232,7 @@ pub mod nhc {
             packet.check_len()?;
 
             if packet.dispatch_field() != EXT_HEADER_DISPATCH {
-                return Err(Error::Malformed);
+                return Err(Error);
             }
 
             Ok(ExtensionHeaderRepr {
@@ -1293,17 +1290,17 @@ pub mod nhc {
         }
 
         /// Ensure that no accessor method will panic if called.
-        /// Returns `Err(Error::Truncated)` if the buffer is too short.
+        /// Returns `Err(Error)` if the buffer is too short.
         pub fn check_len(&self) -> Result<()> {
             let buffer = self.buffer.as_ref();
 
             if buffer.is_empty() {
-                return Err(Error::Truncated);
+                return Err(Error);
             }
 
             let index = 1 + self.ports_size() + self.checksum_size();
             if index > buffer.len() {
-                return Err(Error::Truncated);
+                return Err(Error);
             }
 
             Ok(())
@@ -1507,7 +1504,7 @@ pub mod nhc {
             packet.check_len()?;
 
             if packet.dispatch_field() != UDP_DISPATCH {
-                return Err(Error::Malformed);
+                return Err(Error);
             }
 
             let payload_len = packet.payload().len();
@@ -1526,11 +1523,11 @@ pub mod nhc {
 
             if let Some(checksum) = packet.checksum() {
                 if chk_sum != checksum {
-                    return Err(Error::Checksum);
+                    return Err(Error);
                 }
             } else {
                 net_trace!("Currently we do not support elided checksums.");
-                return Err(Error::Unrecognized);
+                return Err(Error);
             };
 
             Ok(UdpNhcRepr(UdpRepr {

+ 25 - 30
src/wire/tcp.rs

@@ -1,10 +1,10 @@
 use byteorder::{ByteOrder, NetworkEndian};
 use core::{cmp, fmt, i32, ops};
 
+use super::{Error, Result};
 use crate::phy::ChecksumCapabilities;
 use crate::wire::ip::checksum;
 use crate::wire::{IpAddress, IpProtocol};
-use crate::{Error, Result};
 
 /// A TCP sequence number.
 ///
@@ -128,8 +128,8 @@ impl<T: AsRef<[u8]>> Packet<T> {
     }
 
     /// Ensure that no accessor method will panic if called.
-    /// Returns `Err(Error::Truncated)` if the buffer is too short.
-    /// Returns `Err(Error::Malformed)` if the header length field has a value smaller
+    /// Returns `Err(Error)` if the buffer is too short.
+    /// Returns `Err(Error)` if the header length field has a value smaller
     /// than the minimal header length.
     ///
     /// The result of this check is invalidated by calling [set_header_len].
@@ -138,13 +138,11 @@ impl<T: AsRef<[u8]>> Packet<T> {
     pub fn check_len(&self) -> Result<()> {
         let len = self.buffer.as_ref().len();
         if len < field::URGENT.end {
-            Err(Error::Truncated)
+            Err(Error)
         } else {
             let header_len = self.header_len() as usize;
-            if len < header_len {
-                Err(Error::Truncated)
-            } else if header_len < field::URGENT.end {
-                Err(Error::Malformed)
+            if len < header_len || header_len < field::URGENT.end {
+                Err(Error)
             } else {
                 Ok(())
             }
@@ -608,7 +606,7 @@ pub enum TcpOption<'a> {
 impl<'a> TcpOption<'a> {
     pub fn parse(buffer: &'a [u8]) -> Result<(&'a [u8], TcpOption<'a>)> {
         let (length, option);
-        match *buffer.get(0).ok_or(Error::Truncated)? {
+        match *buffer.get(0).ok_or(Error)? {
             field::OPT_END => {
                 length = 1;
                 option = TcpOption::EndOfList;
@@ -618,21 +616,21 @@ impl<'a> TcpOption<'a> {
                 option = TcpOption::NoOperation;
             }
             kind => {
-                length = *buffer.get(1).ok_or(Error::Truncated)? as usize;
-                let data = buffer.get(2..length).ok_or(Error::Truncated)?;
+                length = *buffer.get(1).ok_or(Error)? as usize;
+                let data = buffer.get(2..length).ok_or(Error)?;
                 match (kind, length) {
                     (field::OPT_END, _) | (field::OPT_NOP, _) => unreachable!(),
                     (field::OPT_MSS, 4) => {
                         option = TcpOption::MaxSegmentSize(NetworkEndian::read_u16(data))
                     }
-                    (field::OPT_MSS, _) => return Err(Error::Malformed),
+                    (field::OPT_MSS, _) => return Err(Error),
                     (field::OPT_WS, 3) => option = TcpOption::WindowScale(data[0]),
-                    (field::OPT_WS, _) => return Err(Error::Malformed),
+                    (field::OPT_WS, _) => return Err(Error),
                     (field::OPT_SACKPERM, 2) => option = TcpOption::SackPermitted,
-                    (field::OPT_SACKPERM, _) => return Err(Error::Malformed),
+                    (field::OPT_SACKPERM, _) => return Err(Error),
                     (field::OPT_SACKRNG, n) => {
                         if n < 10 || (n - 2) % 8 != 0 {
-                            return Err(Error::Malformed);
+                            return Err(Error);
                         }
                         if n > 26 {
                             // It's possible for a remote to send 4 SACK blocks, but extremely rare.
@@ -801,14 +799,14 @@ impl<'a> Repr<'a> {
     {
         // Source and destination ports must be present.
         if packet.src_port() == 0 {
-            return Err(Error::Malformed);
+            return Err(Error);
         }
         if packet.dst_port() == 0 {
-            return Err(Error::Malformed);
+            return Err(Error);
         }
         // Valid checksum is expected.
         if checksum_caps.tcp.rx() && !packet.verify_checksum(src_addr, dst_addr) {
-            return Err(Error::Checksum);
+            return Err(Error);
         }
 
         let control = match (packet.syn(), packet.fin(), packet.rst(), packet.psh()) {
@@ -817,7 +815,7 @@ impl<'a> Repr<'a> {
             (true, false, false, _) => Control::Syn,
             (false, true, false, _) => Control::Fin,
             (false, false, true, _) => Control::Rst,
-            _ => return Err(Error::Malformed),
+            _ => return Err(Error),
         };
         let ack_number = match packet.ack() {
             true => Some(packet.ack_number()),
@@ -1157,7 +1155,7 @@ mod test {
     #[cfg(feature = "proto-ipv4")]
     fn test_truncated() {
         let packet = Packet::new_unchecked(&PACKET_BYTES[..23]);
-        assert_eq!(packet.check_len(), Err(Error::Truncated));
+        assert_eq!(packet.check_len(), Err(Error));
     }
 
     #[test]
@@ -1165,7 +1163,7 @@ mod test {
         let mut bytes = vec![0; 20];
         let mut packet = Packet::new_unchecked(&mut bytes);
         packet.set_header_len(10);
-        assert_eq!(packet.check_len(), Err(Error::Malformed));
+        assert_eq!(packet.check_len(), Err(Error));
     }
 
     #[cfg(feature = "proto-ipv4")]
@@ -1277,14 +1275,11 @@ mod test {
 
     #[test]
     fn test_malformed_tcp_options() {
-        assert_eq!(TcpOption::parse(&[]), Err(Error::Truncated));
-        assert_eq!(TcpOption::parse(&[0xc]), Err(Error::Truncated));
-        assert_eq!(
-            TcpOption::parse(&[0xc, 0x05, 0x01, 0x02]),
-            Err(Error::Truncated)
-        );
-        assert_eq!(TcpOption::parse(&[0xc, 0x01]), Err(Error::Truncated));
-        assert_eq!(TcpOption::parse(&[0x2, 0x02]), Err(Error::Malformed));
-        assert_eq!(TcpOption::parse(&[0x3, 0x02]), Err(Error::Malformed));
+        assert_eq!(TcpOption::parse(&[]), Err(Error));
+        assert_eq!(TcpOption::parse(&[0xc]), Err(Error));
+        assert_eq!(TcpOption::parse(&[0xc, 0x05, 0x01, 0x02]), Err(Error));
+        assert_eq!(TcpOption::parse(&[0xc, 0x01]), Err(Error));
+        assert_eq!(TcpOption::parse(&[0x2, 0x02]), Err(Error));
+        assert_eq!(TcpOption::parse(&[0x3, 0x02]), Err(Error));
     }
 }

+ 9 - 11
src/wire/udp.rs

@@ -1,10 +1,10 @@
 use byteorder::{ByteOrder, NetworkEndian};
 use core::fmt;
 
+use super::{Error, Result};
 use crate::phy::ChecksumCapabilities;
 use crate::wire::ip::checksum;
 use crate::wire::{IpAddress, IpProtocol};
-use crate::{Error, Result};
 
 /// A read/write wrapper around an User Datagram Protocol packet buffer.
 #[derive(Debug, PartialEq, Clone)]
@@ -48,8 +48,8 @@ impl<T: AsRef<[u8]>> Packet<T> {
     }
 
     /// Ensure that no accessor method will panic if called.
-    /// Returns `Err(Error::Truncated)` if the buffer is too short.
-    /// Returns `Err(Error::Malformed)` if the length field has a value smaller
+    /// Returns `Err(Error)` if the buffer is too short.
+    /// Returns `Err(Error)` if the length field has a value smaller
     /// than the header length.
     ///
     /// The result of this check is invalidated by calling [set_len].
@@ -58,13 +58,11 @@ impl<T: AsRef<[u8]>> Packet<T> {
     pub fn check_len(&self) -> Result<()> {
         let buffer_len = self.buffer.as_ref().len();
         if buffer_len < HEADER_LEN {
-            Err(Error::Truncated)
+            Err(Error)
         } else {
             let field_len = self.len() as usize;
-            if buffer_len < field_len {
-                Err(Error::Truncated)
-            } else if field_len < HEADER_LEN {
-                Err(Error::Malformed)
+            if buffer_len < field_len || field_len < HEADER_LEN {
+                Err(Error)
             } else {
                 Ok(())
             }
@@ -221,7 +219,7 @@ impl Repr {
     {
         // Destination port cannot be omitted (but source port can be).
         if packet.dst_port() == 0 {
-            return Err(Error::Malformed);
+            return Err(Error);
         }
         // Valid checksum is expected...
         if checksum_caps.udp.rx() && !packet.verify_checksum(src_addr, dst_addr) {
@@ -229,7 +227,7 @@ impl Repr {
                 // ... except on UDP-over-IPv4, where it can be omitted.
                 #[cfg(feature = "proto-ipv4")]
                 (&IpAddress::Ipv4(_), &IpAddress::Ipv4(_)) if packet.checksum() == 0 => (),
-                _ => return Err(Error::Checksum),
+                _ => return Err(Error),
             }
         }
 
@@ -360,7 +358,7 @@ mod test {
         let mut bytes = vec![0; 12];
         let mut packet = Packet::new_unchecked(&mut bytes);
         packet.set_len(4);
-        assert_eq!(packet.check_len(), Err(Error::Malformed));
+        assert_eq!(packet.check_len(), Err(Error));
     }
 
     #[test]