diff --git a/etherparse/Cargo.toml b/etherparse/Cargo.toml index c9bcc003..8d5efe35 100644 --- a/etherparse/Cargo.toml +++ b/etherparse/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "etherparse" -version = "0.19.0" +version = "0.20.0" authors = ["Julian Schmid "] edition = "2021" repository = "https://github.com/JulianSchmid/etherparse" diff --git a/etherparse/examples/read_by_slicing.rs b/etherparse/examples/read_by_slicing.rs index 1aa95be0..3422502e 100644 --- a/etherparse/examples/read_by_slicing.rs +++ b/etherparse/examples/read_by_slicing.rs @@ -75,7 +75,7 @@ fn main() { ipv4.header().source_addr(), ipv4.header().destination_addr() ); - if false == ipv4.extensions().is_empty() { + if !ipv4.extensions().is_empty() { println!(" {:?}", ipv4.extensions()); } } @@ -85,7 +85,7 @@ fn main() { ipv6.header().source_addr(), ipv6.header().destination_addr() ); - if false == ipv6.extensions().is_empty() { + if !ipv6.extensions().is_empty() { println!(" {:?}", ipv6.extensions()); } } diff --git a/etherparse/src/compositions_tests.rs b/etherparse/src/compositions_tests.rs index 42a8c010..42a19fe7 100644 --- a/etherparse/src/compositions_tests.rs +++ b/etherparse/src/compositions_tests.rs @@ -70,7 +70,7 @@ impl<'a> ComponentTest<'a> { None => {} } use std::io::Write; - buffer.write(&self.payload[..]).unwrap(); + buffer.write_all(self.payload).unwrap(); buffer } @@ -341,14 +341,14 @@ impl<'a> ComponentTest<'a> { fn assert_headers(&self, actual: PacketHeaders) { assert_eq!(self.link, actual.link); assert_eq!(self.link_exts, actual.link_exts); - assert_eq!(self.net, self.net); + assert_eq!(self.net, actual.net); assert_eq!(self.transport, actual.transport); assert_eq!(self.payload[..], actual.payload.slice()[..]); } fn assert_sliced_packet(&self, result: SlicedPacket) { //assert identity to touch the derives (code coverage hack) - assert_eq!(result, result); + assert_eq!(result.clone(), result); //ethernet & link extensions assert_eq!( diff --git a/etherparse/src/net/net_slice.rs b/etherparse/src/net/net_slice.rs index 7952bea5..849589dc 100644 --- a/etherparse/src/net/net_slice.rs +++ b/etherparse/src/net/net_slice.rs @@ -6,7 +6,7 @@ use crate::*; since = "0.14.0", note = "Deprecated use crate::NetSlice or crate::IpSlice instead" )] -pub use NetSlice as InternetSlice; +pub use self::NetSlice as InternetSlice; /// Slice containing the network headers & payloads (e.g. IPv4, IPv6, ARP). #[derive(Clone, Debug, Eq, PartialEq)] diff --git a/etherparse/src/transport/icmpv4_slice.rs b/etherparse/src/transport/icmpv4_slice.rs index 391cd8f8..0edaa927 100644 --- a/etherparse/src/transport/icmpv4_slice.rs +++ b/etherparse/src/transport/icmpv4_slice.rs @@ -38,27 +38,23 @@ impl<'a> Icmpv4Slice<'a> { // check type specific length match icmp_type { - TYPE_TIMESTAMP => { - if 0 == icmp_code && TimestampMessage::LEN != slice.len() { - return Err(err::LenError { - required_len: TimestampMessage::LEN, - len: slice.len(), - len_source: LenSource::Slice, - layer: err::Layer::Icmpv4Timestamp, - layer_start_offset: 0, - }); - } + TYPE_TIMESTAMP if 0 == icmp_code && TimestampMessage::LEN != slice.len() => { + return Err(err::LenError { + required_len: TimestampMessage::LEN, + len: slice.len(), + len_source: LenSource::Slice, + layer: err::Layer::Icmpv4Timestamp, + layer_start_offset: 0, + }); } - TYPE_TIMESTAMP_REPLY => { - if 0 == icmp_code && TimestampMessage::LEN != slice.len() { - return Err(err::LenError { - required_len: TimestampMessage::LEN, - len: slice.len(), - len_source: LenSource::Slice, - layer: err::Layer::Icmpv4TimestampReply, - layer_start_offset: 0, - }); - } + TYPE_TIMESTAMP_REPLY if 0 == icmp_code && TimestampMessage::LEN != slice.len() => { + return Err(err::LenError { + required_len: TimestampMessage::LEN, + len: slice.len(), + len_source: LenSource::Slice, + layer: err::Layer::Icmpv4TimestampReply, + layer_start_offset: 0, + }); } _ => {} } @@ -82,13 +78,7 @@ impl<'a> Icmpv4Slice<'a> { #[inline] pub fn header_len(&self) -> usize { match self.type_u8() { - TYPE_TIMESTAMP | TYPE_TIMESTAMP_REPLY => { - if 0 == self.code_u8() { - TimestampMessage::LEN - } else { - 8 - } - } + TYPE_TIMESTAMP | TYPE_TIMESTAMP_REPLY if 0 == self.code_u8() => TimestampMessage::LEN, _ => 8, } } @@ -108,10 +98,8 @@ impl<'a> Icmpv4Slice<'a> { } match self.type_u8() { - TYPE_ECHO_REPLY => { - if 0 == self.code_u8() { - return EchoReply(IcmpEchoHeader::from_bytes(self.bytes5to8())); - } + TYPE_ECHO_REPLY if 0 == self.code_u8() => { + return EchoReply(IcmpEchoHeader::from_bytes(self.bytes5to8())); } TYPE_DEST_UNREACH => { use DestUnreachableHeader::*; @@ -172,10 +160,8 @@ impl<'a> Icmpv4Slice<'a> { }); } } - TYPE_ECHO_REQUEST => { - if 0 == self.code_u8() { - return EchoRequest(IcmpEchoHeader::from_bytes(self.bytes5to8())); - } + TYPE_ECHO_REQUEST if 0 == self.code_u8() => { + return EchoRequest(IcmpEchoHeader::from_bytes(self.bytes5to8())); } TYPE_TIME_EXCEEDED => { use TimeExceededCode::*; @@ -209,24 +195,20 @@ impl<'a> Icmpv4Slice<'a> { _ => {} } } - TYPE_TIMESTAMP => { - if 0 == self.code_u8() { - // SAFETY: - // Safe as the contructor checks that the slice has - // the length of TimestampMessage::SERIALIZED_SIZE (20). - unsafe { - return TimestampRequest(timestamp_message(self.slice.as_ptr())); - } + TYPE_TIMESTAMP if 0 == self.code_u8() => { + // SAFETY: + // Safe as the contructor checks that the slice has + // the length of TimestampMessage::SERIALIZED_SIZE (20). + unsafe { + return TimestampRequest(timestamp_message(self.slice.as_ptr())); } } - TYPE_TIMESTAMP_REPLY => { - if 0 == self.code_u8() { - // SAFETY: - // Safe as the contructor checks that the slice has - // the length of TimestampMessage::SERIALIZED_SIZE (20). - unsafe { - return TimestampReply(timestamp_message(self.slice.as_ptr())); - } + TYPE_TIMESTAMP_REPLY if 0 == self.code_u8() => { + // SAFETY: + // Safe as the contructor checks that the slice has + // the length of TimestampMessage::SERIALIZED_SIZE (20). + unsafe { + return TimestampReply(timestamp_message(self.slice.as_ptr())); } } _ => {} @@ -307,13 +289,7 @@ impl<'a> Icmpv4Slice<'a> { // Length safe as the contructor checks that the slice has // the length of TimestampMessage::SERIALIZED_SIZE (20) // for the messages types TYPE_TIMESTAMP and TYPE_TIMESTAMP_REPLY. - TYPE_TIMESTAMP | TYPE_TIMESTAMP_REPLY => { - if 0 == self.code_u8() { - TimestampMessage::LEN - } else { - 8 - } - } + TYPE_TIMESTAMP | TYPE_TIMESTAMP_REPLY if 0 == self.code_u8() => TimestampMessage::LEN, // SAFETY: // Length safe as the contructor checks that the slice has // at least the length of Icmpv4Header::MIN_LEN(8) for diff --git a/etherparse/src/transport/icmpv6/icmpv6_payload/mod.rs b/etherparse/src/transport/icmpv6/icmpv6_payload/mod.rs index b4388223..99bad42f 100644 --- a/etherparse/src/transport/icmpv6/icmpv6_payload/mod.rs +++ b/etherparse/src/transport/icmpv6/icmpv6_payload/mod.rs @@ -42,6 +42,12 @@ impl Icmpv6Payload { } } + /// Returns true if the serialized payload is empty. + #[inline] + pub fn is_empty(&self) -> bool { + 0 == self.len() + } + /// Write the fixed payload bytes to the writer. #[cfg(feature = "std")] #[cfg_attr(docsrs, doc(cfg(feature = "std")))] @@ -59,6 +65,7 @@ impl Icmpv6Payload { #[cfg(test)] mod tests { use super::*; + use core::net::Ipv6Addr; use proptest::prelude::*; #[test] @@ -66,6 +73,35 @@ mod tests { assert_eq!([] as [u8; 0], RouterSolicitationPayload.to_bytes()); } + #[test] + fn payload_is_empty() { + assert!(Icmpv6Payload::RouterSolicitation(RouterSolicitationPayload).is_empty()); + assert!( + !Icmpv6Payload::RouterAdvertisement(RouterAdvertisementPayload { + reachable_time: 1, + retrans_timer: 2, + }) + .is_empty() + ); + assert!( + !Icmpv6Payload::NeighborSolicitation(NeighborSolicitationPayload { + target_address: Ipv6Addr::LOCALHOST, + }) + .is_empty() + ); + assert!( + !Icmpv6Payload::NeighborAdvertisement(NeighborAdvertisementPayload { + target_address: Ipv6Addr::LOCALHOST, + }) + .is_empty() + ); + assert!(!Icmpv6Payload::Redirect(RedirectPayload { + target_address: Ipv6Addr::LOCALHOST, + destination_address: Ipv6Addr::UNSPECIFIED, + }) + .is_empty()); + } + proptest! { #[test] fn payloads_to_bytes( diff --git a/etherparse/src/transport/icmpv6/ndp_option/prefix_information.rs b/etherparse/src/transport/icmpv6/ndp_option/prefix_information.rs index 0d116889..88a056f2 100644 --- a/etherparse/src/transport/icmpv6/ndp_option/prefix_information.rs +++ b/etherparse/src/transport/icmpv6/ndp_option/prefix_information.rs @@ -36,12 +36,7 @@ impl PrefixInformation { // Safe to unwrap because `bytes` originates from `[u8; Self::LEN]` and // the chunk sizes below exactly cover `Self::LEN` (32 bytes). let (type_and_len, rest) = bytes.split_first_chunk::<2>().unwrap(); - if *type_and_len - != [ - NdpOptionType::PREFIX_INFORMATION.0, - Self::LENGTH_UNITS, - ] - { + if *type_and_len != [NdpOptionType::PREFIX_INFORMATION.0, Self::LENGTH_UNITS] { return Err(NdpOptionReadError::UnexpectedHeader { expected_option_id: NdpOptionType::PREFIX_INFORMATION, actual_option_id: NdpOptionType(type_and_len[0]), diff --git a/etherparse/src/transport/icmpv6/ndp_option/prefix_information_option_slice.rs b/etherparse/src/transport/icmpv6/ndp_option/prefix_information_option_slice.rs index 081bbb44..aeb5c724 100644 --- a/etherparse/src/transport/icmpv6/ndp_option/prefix_information_option_slice.rs +++ b/etherparse/src/transport/icmpv6/ndp_option/prefix_information_option_slice.rs @@ -41,11 +41,13 @@ impl<'a> PrefixInformationOptionSlice<'a> { pub fn from_slice(slice: &'a [u8]) -> Result { let slice: &'a [u8; PrefixInformation::LEN] = - slice.try_into().map_err(|_| NdpOptionReadError::UnexpectedSize { - option_id: NdpOptionType::PREFIX_INFORMATION, - expected_size: PrefixInformation::LEN, - actual_size: slice.len(), - })?; + slice + .try_into() + .map_err(|_| NdpOptionReadError::UnexpectedSize { + option_id: NdpOptionType::PREFIX_INFORMATION, + expected_size: PrefixInformation::LEN, + actual_size: slice.len(), + })?; // Validate the encoded option header (`Type` and `Length`) as well. PrefixInformation::from_bytes(*slice)?; Ok(Self { slice }) diff --git a/etherparse/src/transport/icmpv6/ndp_option_read_error.rs b/etherparse/src/transport/icmpv6/ndp_option_read_error.rs index 72d49ded..2e348277 100644 --- a/etherparse/src/transport/icmpv6/ndp_option_read_error.rs +++ b/etherparse/src/transport/icmpv6/ndp_option_read_error.rs @@ -13,7 +13,8 @@ pub enum NdpOptionReadError { /// An ND option with a length value of zero was encountered. ZeroLength { option_id: NdpOptionType }, /// The option has a fixed encoded size and the received size differs. - UnexpectedSize { option_id: NdpOptionType, + UnexpectedSize { + option_id: NdpOptionType, expected_size: usize, actual_size: usize, }, diff --git a/etherparse/src/transport/icmpv6/ndp_options_iterator.rs b/etherparse/src/transport/icmpv6/ndp_options_iterator.rs index b6a3fb03..e88e2ef7 100644 --- a/etherparse/src/transport/icmpv6/ndp_options_iterator.rs +++ b/etherparse/src/transport/icmpv6/ndp_options_iterator.rs @@ -21,9 +21,7 @@ impl<'a> NdpOptionsIterator<'a> { self.options } - fn parse_next_option( - &mut self, - ) -> Result, NdpOptionReadError> { + fn parse_next_option(&mut self) -> Result, NdpOptionReadError> { use NdpOptionReadError::*; let (header, _) = NdpOptionHeader::from_slice(self.options)?; @@ -34,12 +32,14 @@ impl<'a> NdpOptionsIterator<'a> { } let option_len = header.byte_len(); - let (option, rest) = self.options.split_at_checked(option_len) - .ok_or_else(|| UnexpectedEndOfSlice { - option_id, - expected_size: option_len, - actual_size: self.options.len(), - })?; + let (option, rest) = + self.options + .split_at_checked(option_len) + .ok_or(UnexpectedEndOfSlice { + option_id, + expected_size: option_len, + actual_size: self.options.len(), + })?; let parsed = match option_id { NdpOptionType::SOURCE_LINK_LAYER_ADDRESS => { @@ -50,15 +50,11 @@ impl<'a> NdpOptionsIterator<'a> { TargetLinkLayerAddressOptionSlice::from_slice(option) .map(NdpOptionSlice::TargetLinkLayerAddress) } - NdpOptionType::PREFIX_INFORMATION => { - PrefixInformationOptionSlice::from_slice(option) - .map(NdpOptionSlice::PrefixInformation) - } + NdpOptionType::PREFIX_INFORMATION => PrefixInformationOptionSlice::from_slice(option) + .map(NdpOptionSlice::PrefixInformation), NdpOptionType::REDIRECTED_HEADER => RedirectedHeaderOptionSlice::from_slice(option) .map(NdpOptionSlice::RedirectedHeader), - NdpOptionType::MTU => { - MtuOptionSlice::from_slice(option).map(NdpOptionSlice::Mtu) - } + NdpOptionType::MTU => MtuOptionSlice::from_slice(option).map(NdpOptionSlice::Mtu), _ => UnknownNdpOptionSlice::from_slice(option).map(NdpOptionSlice::Unknown), }?; @@ -108,7 +104,6 @@ mod tests { use super::*; use crate::icmpv6::PrefixInformation; - #[test] fn from_slice_and_rest() { let buffer = [1, 1, 1, 2, 3, 4, 5, 6]; diff --git a/etherparse/src/transport/icmpv6_slice.rs b/etherparse/src/transport/icmpv6_slice.rs index 1053924b..244acf30 100644 --- a/etherparse/src/transport/icmpv6_slice.rs +++ b/etherparse/src/transport/icmpv6_slice.rs @@ -69,12 +69,10 @@ impl<'a> Icmpv6Slice<'a> { return DestinationUnreachable(code); } } - TYPE_PACKET_TOO_BIG => { - if 0 == self.code_u8() { - return PacketTooBig { - mtu: u32::from_be_bytes(self.bytes5to8()), - }; - } + TYPE_PACKET_TOO_BIG if 0 == self.code_u8() => { + return PacketTooBig { + mtu: u32::from_be_bytes(self.bytes5to8()), + }; } TYPE_TIME_EXCEEDED => { if let Some(code) = TimeExceededCode::from_u8(self.code_u8()) { @@ -89,44 +87,30 @@ impl<'a> Icmpv6Slice<'a> { }); } } - TYPE_ECHO_REQUEST => { - if 0 == self.code_u8() { - return EchoRequest(IcmpEchoHeader::from_bytes(self.bytes5to8())); - } + TYPE_ECHO_REQUEST if 0 == self.code_u8() => { + return EchoRequest(IcmpEchoHeader::from_bytes(self.bytes5to8())); } - TYPE_ECHO_REPLY => { - if 0 == self.code_u8() { - return EchoReply(IcmpEchoHeader::from_bytes(self.bytes5to8())); - } + TYPE_ECHO_REPLY if 0 == self.code_u8() => { + return EchoReply(IcmpEchoHeader::from_bytes(self.bytes5to8())); } - TYPE_ROUTER_SOLICITATION => { - if 0 == self.code_u8() { - return RouterSolicitation; - } + TYPE_ROUTER_SOLICITATION if 0 == self.code_u8() => { + return RouterSolicitation; } - TYPE_ROUTER_ADVERTISEMENT => { - if 0 == self.code_u8() { - return RouterAdvertisement(RouterAdvertisementHeader::from_bytes( - self.bytes5to8(), - )); - } + TYPE_ROUTER_ADVERTISEMENT if 0 == self.code_u8() => { + return RouterAdvertisement(RouterAdvertisementHeader::from_bytes( + self.bytes5to8(), + )); } - TYPE_NEIGHBOR_SOLICITATION => { - if 0 == self.code_u8() { - return NeighborSolicitation; - } + TYPE_NEIGHBOR_SOLICITATION if 0 == self.code_u8() => { + return NeighborSolicitation; } - TYPE_NEIGHBOR_ADVERTISEMENT => { - if 0 == self.code_u8() { - return NeighborAdvertisement(NeighborAdvertisementHeader::from_bytes( - self.bytes5to8(), - )); - } + TYPE_NEIGHBOR_ADVERTISEMENT if 0 == self.code_u8() => { + return NeighborAdvertisement(NeighborAdvertisementHeader::from_bytes( + self.bytes5to8(), + )); } - TYPE_REDIRECT_MESSAGE => { - if 0 == self.code_u8() { - return Redirect; - } + TYPE_REDIRECT_MESSAGE if 0 == self.code_u8() => { + return Redirect; } _ => {} } diff --git a/etherparse/tests/transport/icmpv4.rs b/etherparse/tests/transport/icmpv4.rs index c86a8c14..a6c42b23 100644 --- a/etherparse/tests/transport/icmpv4.rs +++ b/etherparse/tests/transport/icmpv4.rs @@ -190,7 +190,7 @@ mod icmpv4_regression { let offset = 14 + 20 + 1; // ethernet + iphdr + icmp_type // test all of the unreachable codes to make sure the maps are right for code_u8 in 0..icmpv4::CODE_DST_UNREACH_PRECEDENCE_CUTOFF { - let mut pkt = ICMP4_PORT_UNREACHABLE_BYTES.clone(); + let mut pkt = ICMP4_PORT_UNREACHABLE_BYTES; pkt[offset] = code_u8; // over write the code let parsed = PacketHeaders::from_ethernet_slice(&pkt).unwrap(); let icmp4 = parsed.transport.unwrap().icmpv4().unwrap(); diff --git a/etherparse_proptest_generators/Cargo.toml b/etherparse_proptest_generators/Cargo.toml index 1a00b89b..d2da7438 100644 --- a/etherparse_proptest_generators/Cargo.toml +++ b/etherparse_proptest_generators/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "etherparse_proptest_generators" -version = "0.19.0" +version = "0.20.0" authors = ["Julian Schmid "] edition = "2021" repository = "https://github.com/JulianSchmid/etherparse"