Эх сурвалжийг харах

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.
Thibaut Vandervelden 6 сар өмнө
parent
commit
d17d47b4c0

+ 4 - 5
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!(),
                     }
                 }
             }

+ 36 - 14
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<u8> 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<FailureType> 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})"),
         }
     }
 }