From d17d47b4c0eea66ed664a7748c5391ae56e130de Mon Sep 17 00:00:00 2001 From: Thibaut Vandervelden Date: Fri, 27 Sep 2024 09:07:51 +0200 Subject: [PATCH 1/2] fix: enter unreachable HBH Discard multicast addr It was previously possible to enter an unreachable path when the HBH option type was 0b11 and the destination address was multicast. This is now fixed in the interface. I also changed the way an HBH option type is parsed. The option type is only 2 bits, meaning that we can't have an unknown state. --- src/iface/interface/ipv6.rs | 9 +++---- src/wire/ipv6option.rs | 50 ++++++++++++++++++++++++++----------- 2 files changed, 40 insertions(+), 19 deletions(-) diff --git a/src/iface/interface/ipv6.rs b/src/iface/interface/ipv6.rs index a8d29e48c..926f80a0c 100644 --- a/src/iface/interface/ipv6.rs +++ b/src/iface/interface/ipv6.rs @@ -288,12 +288,11 @@ impl InterfaceInner { Ipv6OptionFailureType::DiscardSendAll => { return HopByHopResponse::Discard(param_problem()); } - Ipv6OptionFailureType::DiscardSendUnicast - if !ipv6_repr.dst_addr.is_multicast() => - { - return HopByHopResponse::Discard(param_problem()); + Ipv6OptionFailureType::DiscardSendUnicast => { + if !ipv6_repr.dst_addr.is_multicast() { + return HopByHopResponse::Discard(param_problem()); + } } - _ => unreachable!(), } } } diff --git a/src/wire/ipv6option.rs b/src/wire/ipv6option.rs index 998df887a..ffa2a14de 100644 --- a/src/wire/ipv6option.rs +++ b/src/wire/ipv6option.rs @@ -51,19 +51,42 @@ impl RouterAlert { pub const DATA_LEN: u8 = 2; } -enum_with_unknown! { - /// Action required when parsing the given IPv6 Extension - /// Header Option Type fails - pub enum FailureType(u8) { - /// Skip this option and continue processing the packet - Skip = 0b00000000, - /// Discard the containing packet - Discard = 0b01000000, - /// Discard the containing packet and notify the sender - DiscardSendAll = 0b10000000, - /// Discard the containing packet and only notify the sender - /// if the sender is a unicast address - DiscardSendUnicast = 0b11000000, +/// Action required when parsing the given IPv6 Extension +/// Header Option Type fails +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum FailureType { + /// Skip this option and continue processing the packet + Skip = 0b00000000, + /// Discard the containing packet + Discard = 0b01000000, + /// Discard the containing packet and notify the sender + DiscardSendAll = 0b10000000, + /// Discard the containing packet and only notify the sender + /// if the sender is a unicast address + DiscardSendUnicast = 0b11000000, +} + +impl From for FailureType { + fn from(value: u8) -> FailureType { + match value & 0b11000000 { + 0b00000000 => FailureType::Skip, + 0b01000000 => FailureType::Discard, + 0b10000000 => FailureType::DiscardSendAll, + 0b11000000 => FailureType::DiscardSendUnicast, + _ => unreachable!(), + } + } +} + +impl From for u8 { + fn from(value: FailureType) -> Self { + match value { + FailureType::Skip => 0b00000000, + FailureType::Discard => 0b01000000, + FailureType::DiscardSendAll => 0b10000000, + FailureType::DiscardSendUnicast => 0b11000000, + } } } @@ -74,7 +97,6 @@ impl fmt::Display for FailureType { FailureType::Discard => write!(f, "discard"), FailureType::DiscardSendAll => write!(f, "discard and send error"), FailureType::DiscardSendUnicast => write!(f, "discard and send error if unicast"), - FailureType::Unknown(id) => write!(f, "Unknown({id})"), } } } From 32f81a77f5dd67676668c04a3a29812a9942382f Mon Sep 17 00:00:00 2001 From: Thibaut Vandervelden Date: Fri, 27 Sep 2024 10:52:00 +0200 Subject: [PATCH 2/2] fix: IPv6-hbb: discard as indicated by hbh type Discard the packet if the Hop-by-Hop header type is 0b11 and the packet destination address is multicast. --- src/iface/interface/ipv6.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/iface/interface/ipv6.rs b/src/iface/interface/ipv6.rs index 926f80a0c..7a378b7c2 100644 --- a/src/iface/interface/ipv6.rs +++ b/src/iface/interface/ipv6.rs @@ -291,6 +291,8 @@ impl InterfaceInner { Ipv6OptionFailureType::DiscardSendUnicast => { if !ipv6_repr.dst_addr.is_multicast() { return HopByHopResponse::Discard(param_problem()); + } else { + return HopByHopResponse::Discard(None); } } }