Bläddra i källkod

Merge pull request #887 from thvdveld/icmp-split-v4-and-v6

ICMP socket: split ICMPv4/v6 accept and process
Thibaut Vandervelden 1 år sedan
förälder
incheckning
dc895d4f67

+ 4 - 10
examples/ping.rs

@@ -187,11 +187,8 @@ fn main() {
                         remote_addr
                     );
                     icmp_repr.emit(
-                        &iface
-                            .get_source_address_ipv6(&address)
-                            .unwrap()
-                            .into_address(),
-                        &remote_addr,
+                        &iface.get_source_address_ipv6(&address).unwrap(),
+                        &address,
                         &mut icmp_packet,
                         &device_caps.checksum,
                     );
@@ -223,11 +220,8 @@ fn main() {
                 IpAddress::Ipv6(address) => {
                     let icmp_packet = Icmpv6Packet::new_checked(&payload).unwrap();
                     let icmp_repr = Icmpv6Repr::parse(
-                        &remote_addr,
-                        &iface
-                            .get_source_address_ipv6(&address)
-                            .unwrap()
-                            .into_address(),
+                        &address,
+                        &iface.get_source_address_ipv6(&address).unwrap(),
                         &icmp_packet,
                         &device_caps.checksum,
                     )

+ 8 - 15
src/iface/interface/ipv4.rs

@@ -166,16 +166,13 @@ impl InterfaceInner {
                     if udp_packet.src_port() == dhcp_socket.server_port
                         && udp_packet.dst_port() == dhcp_socket.client_port
                     {
-                        let (src_addr, dst_addr) = (ip_repr.src_addr(), ip_repr.dst_addr());
                         let udp_repr = check!(UdpRepr::parse(
                             &udp_packet,
-                            &src_addr,
-                            &dst_addr,
+                            &ipv4_repr.src_addr.into(),
+                            &ipv4_repr.dst_addr.into(),
                             &self.caps.checksum
                         ));
-                        let udp_payload = udp_packet.payload();
-
-                        dhcp_socket.process(self, &ipv4_repr, &udp_repr, udp_payload);
+                        dhcp_socket.process(self, &ipv4_repr, &udp_repr, udp_packet.payload());
                         return None;
                     }
                 }
@@ -200,7 +197,7 @@ impl InterfaceInner {
         }
 
         match ipv4_repr.next_header {
-            IpProtocol::Icmp => self.process_icmpv4(sockets, ip_repr, ip_payload),
+            IpProtocol::Icmp => self.process_icmpv4(sockets, ipv4_repr, ip_payload),
 
             #[cfg(feature = "proto-igmp")]
             IpProtocol::Igmp => self.process_igmp(ipv4_repr, ip_payload),
@@ -298,7 +295,7 @@ impl InterfaceInner {
     pub(super) fn process_icmpv4<'frame>(
         &mut self,
         _sockets: &mut SocketSet,
-        ip_repr: IpRepr,
+        ip_repr: Ipv4Repr,
         ip_payload: &'frame [u8],
     ) -> Option<Packet<'frame>> {
         let icmp_packet = check!(Icmpv4Packet::new_checked(ip_payload));
@@ -312,8 +309,8 @@ impl InterfaceInner {
             .items_mut()
             .filter_map(|i| icmp::Socket::downcast_mut(&mut i.socket))
         {
-            if icmp_socket.accepts(self, &ip_repr, &icmp_repr.into()) {
-                icmp_socket.process(self, &ip_repr, &icmp_repr.into());
+            if icmp_socket.accepts_v4(self, &ip_repr, &icmp_repr) {
+                icmp_socket.process_v4(self, &ip_repr, &icmp_repr);
                 handled_by_icmp_socket = true;
             }
         }
@@ -331,11 +328,7 @@ impl InterfaceInner {
                     seq_no,
                     data,
                 };
-                match ip_repr {
-                    IpRepr::Ipv4(ipv4_repr) => self.icmpv4_reply(ipv4_repr, icmp_reply_repr),
-                    #[allow(unreachable_patterns)]
-                    _ => unreachable!(),
-                }
+                self.icmpv4_reply(ip_repr, icmp_reply_repr)
             }
 
             // Ignore any echo replies.

+ 21 - 29
src/iface/interface/ipv6.rs

@@ -260,7 +260,7 @@ impl InterfaceInner {
         ip_payload: &'frame [u8],
     ) -> Option<Packet<'frame>> {
         match nxt_hdr {
-            IpProtocol::Icmpv6 => self.process_icmpv6(sockets, ipv6_repr.into(), ip_payload),
+            IpProtocol::Icmpv6 => self.process_icmpv6(sockets, ipv6_repr, ip_payload),
 
             #[cfg(any(feature = "socket-udp", feature = "socket-dns"))]
             IpProtocol::Udp => self.process_udp(
@@ -296,13 +296,13 @@ impl InterfaceInner {
     pub(super) fn process_icmpv6<'frame>(
         &mut self,
         _sockets: &mut SocketSet,
-        ip_repr: IpRepr,
+        ip_repr: Ipv6Repr,
         ip_payload: &'frame [u8],
     ) -> Option<Packet<'frame>> {
         let icmp_packet = check!(Icmpv6Packet::new_checked(ip_payload));
         let icmp_repr = check!(Icmpv6Repr::parse(
-            &ip_repr.src_addr(),
-            &ip_repr.dst_addr(),
+            &ip_repr.src_addr,
+            &ip_repr.dst_addr,
             &icmp_packet,
             &self.caps.checksum,
         ));
@@ -317,8 +317,8 @@ impl InterfaceInner {
                 .items_mut()
                 .filter_map(|i| IcmpSocket::downcast_mut(&mut i.socket))
             {
-                if icmp_socket.accepts(self, &ip_repr, &icmp_repr.into()) {
-                    icmp_socket.process(self, &ip_repr, &icmp_repr.into());
+                if icmp_socket.accepts_v6(self, &ip_repr, &icmp_repr) {
+                    icmp_socket.process_v6(self, &ip_repr, &icmp_repr);
                     handled_by_icmp_socket = true;
                 }
             }
@@ -330,35 +330,27 @@ impl InterfaceInner {
                 ident,
                 seq_no,
                 data,
-            } => match ip_repr {
-                IpRepr::Ipv6(ipv6_repr) => {
-                    let icmp_reply_repr = Icmpv6Repr::EchoReply {
-                        ident,
-                        seq_no,
-                        data,
-                    };
-                    self.icmpv6_reply(ipv6_repr, icmp_reply_repr)
-                }
-                #[allow(unreachable_patterns)]
-                _ => unreachable!(),
-            },
+            } => {
+                let icmp_reply_repr = Icmpv6Repr::EchoReply {
+                    ident,
+                    seq_no,
+                    data,
+                };
+                self.icmpv6_reply(ip_repr, icmp_reply_repr)
+            }
 
             // Ignore any echo replies.
             Icmpv6Repr::EchoReply { .. } => None,
 
             // Forward any NDISC packets to the ndisc packet handler
             #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
-            Icmpv6Repr::Ndisc(repr) if ip_repr.hop_limit() == 0xff => match ip_repr {
-                IpRepr::Ipv6(ipv6_repr) => match self.caps.medium {
-                    #[cfg(feature = "medium-ethernet")]
-                    Medium::Ethernet => self.process_ndisc(ipv6_repr, repr),
-                    #[cfg(feature = "medium-ieee802154")]
-                    Medium::Ieee802154 => self.process_ndisc(ipv6_repr, repr),
-                    #[cfg(feature = "medium-ip")]
-                    Medium::Ip => None,
-                },
-                #[allow(unreachable_patterns)]
-                _ => unreachable!(),
+            Icmpv6Repr::Ndisc(repr) if ip_repr.hop_limit == 0xff => match self.caps.medium {
+                #[cfg(feature = "medium-ethernet")]
+                Medium::Ethernet => self.process_ndisc(ip_repr, repr),
+                #[cfg(feature = "medium-ieee802154")]
+                Medium::Ieee802154 => self.process_ndisc(ip_repr, repr),
+                #[cfg(feature = "medium-ip")]
+                Medium::Ip => None,
             },
 
             // Don't report an error if a packet with unknown type

+ 2 - 2
src/iface/interface/sixlowpan.rs

@@ -508,8 +508,8 @@ impl InterfaceInner {
         match &mut packet.payload {
             IpPayload::Icmpv6(icmp_repr) => {
                 icmp_repr.emit(
-                    &packet.header.src_addr.into(),
-                    &packet.header.dst_addr.into(),
+                    &packet.header.src_addr,
+                    &packet.header.dst_addr,
                     &mut Icmpv6Packet::new_unchecked(&mut buffer[..icmp_repr.buffer_len()]),
                     checksum_caps,
                 );

+ 3 - 2
src/iface/interface/tests/ipv4.rs

@@ -565,7 +565,6 @@ fn test_icmpv4_socket(#[case] medium: Medium) {
         payload_len: 24,
         hop_limit: 64,
     };
-    let ip_repr = IpRepr::Ipv4(ipv4_repr);
 
     // Open a socket and ensure the packet is handled due to the listening
     // socket.
@@ -583,7 +582,9 @@ fn test_icmpv4_socket(#[case] medium: Medium) {
         ..ipv4_repr
     };
     assert_eq!(
-        iface.inner.process_icmpv4(&mut sockets, ip_repr, icmp_data),
+        iface
+            .inner
+            .process_icmpv4(&mut sockets, ipv4_repr, icmp_data),
         Some(Packet::new_ipv4(ipv4_reply, IpPayload::Icmpv4(echo_reply)))
     );
 

+ 4 - 4
src/iface/interface/tests/ipv6.rs

@@ -16,8 +16,8 @@ fn parse_ipv6(data: &[u8]) -> crate::wire::Result<Packet<'_>> {
         IpProtocol::IpSecAh => todo!(),
         IpProtocol::Icmpv6 => {
             let icmp = Icmpv6Repr::parse(
-                &ipv6.src_addr.into(),
-                &ipv6.dst_addr.into(),
+                &ipv6.src_addr,
+                &ipv6.dst_addr,
                 &Icmpv6Packet::new_checked(ipv6_header.payload())?,
                 &Default::default(),
             )?;
@@ -707,8 +707,8 @@ fn test_handle_valid_ndisc_request(#[case] medium: Medium) {
     frame.set_ethertype(EthernetProtocol::Ipv6);
     ip_repr.emit(frame.payload_mut(), &ChecksumCapabilities::default());
     solicit.emit(
-        &remote_ip_addr.into(),
-        &local_ip_addr.solicited_node().into(),
+        &remote_ip_addr,
+        &local_ip_addr.solicited_node(),
         &mut Icmpv6Packet::new_unchecked(&mut frame.payload_mut()[ip_repr.header_len()..]),
         &ChecksumCapabilities::default(),
     );

+ 35 - 32
src/iface/neighbor.rs

@@ -163,7 +163,10 @@ impl Cache {
 #[cfg(test)]
 mod test {
     use super::*;
-    use crate::wire::ip::test::{MOCK_IP_ADDR_1, MOCK_IP_ADDR_2, MOCK_IP_ADDR_3, MOCK_IP_ADDR_4};
+    #[cfg(all(feature = "proto-ipv4", not(feature = "proto-ipv6")))]
+    use crate::wire::ipv4::test::{MOCK_IP_ADDR_1, MOCK_IP_ADDR_2, MOCK_IP_ADDR_3, MOCK_IP_ADDR_4};
+    #[cfg(feature = "proto-ipv6")]
+    use crate::wire::ipv6::test::{MOCK_IP_ADDR_1, MOCK_IP_ADDR_2, MOCK_IP_ADDR_3, MOCK_IP_ADDR_4};
 
     use crate::wire::EthernetAddress;
 
@@ -177,30 +180,30 @@ mod test {
         let mut cache = Cache::new();
 
         assert!(!cache
-            .lookup(&MOCK_IP_ADDR_1, Instant::from_millis(0))
+            .lookup(&MOCK_IP_ADDR_1.into(), Instant::from_millis(0))
             .found());
         assert!(!cache
-            .lookup(&MOCK_IP_ADDR_2, Instant::from_millis(0))
+            .lookup(&MOCK_IP_ADDR_2.into(), Instant::from_millis(0))
             .found());
 
-        cache.fill(MOCK_IP_ADDR_1, HADDR_A, Instant::from_millis(0));
+        cache.fill(MOCK_IP_ADDR_1.into(), HADDR_A, Instant::from_millis(0));
         assert_eq!(
-            cache.lookup(&MOCK_IP_ADDR_1, Instant::from_millis(0)),
+            cache.lookup(&MOCK_IP_ADDR_1.into(), Instant::from_millis(0)),
             Answer::Found(HADDR_A)
         );
         assert!(!cache
-            .lookup(&MOCK_IP_ADDR_2, Instant::from_millis(0))
+            .lookup(&MOCK_IP_ADDR_2.into(), Instant::from_millis(0))
             .found());
         assert!(!cache
             .lookup(
-                &MOCK_IP_ADDR_1,
+                &MOCK_IP_ADDR_1.into(),
                 Instant::from_millis(0) + Cache::ENTRY_LIFETIME * 2
             )
             .found(),);
 
-        cache.fill(MOCK_IP_ADDR_1, HADDR_A, Instant::from_millis(0));
+        cache.fill(MOCK_IP_ADDR_1.into(), HADDR_A, Instant::from_millis(0));
         assert!(!cache
-            .lookup(&MOCK_IP_ADDR_2, Instant::from_millis(0))
+            .lookup(&MOCK_IP_ADDR_2.into(), Instant::from_millis(0))
             .found());
     }
 
@@ -208,14 +211,14 @@ mod test {
     fn test_expire() {
         let mut cache = Cache::new();
 
-        cache.fill(MOCK_IP_ADDR_1, HADDR_A, Instant::from_millis(0));
+        cache.fill(MOCK_IP_ADDR_1.into(), HADDR_A, Instant::from_millis(0));
         assert_eq!(
-            cache.lookup(&MOCK_IP_ADDR_1, Instant::from_millis(0)),
+            cache.lookup(&MOCK_IP_ADDR_1.into(), Instant::from_millis(0)),
             Answer::Found(HADDR_A)
         );
         assert!(!cache
             .lookup(
-                &MOCK_IP_ADDR_1,
+                &MOCK_IP_ADDR_1.into(),
                 Instant::from_millis(0) + Cache::ENTRY_LIFETIME * 2
             )
             .found(),);
@@ -225,14 +228,14 @@ mod test {
     fn test_replace() {
         let mut cache = Cache::new();
 
-        cache.fill(MOCK_IP_ADDR_1, HADDR_A, Instant::from_millis(0));
+        cache.fill(MOCK_IP_ADDR_1.into(), HADDR_A, Instant::from_millis(0));
         assert_eq!(
-            cache.lookup(&MOCK_IP_ADDR_1, Instant::from_millis(0)),
+            cache.lookup(&MOCK_IP_ADDR_1.into(), Instant::from_millis(0)),
             Answer::Found(HADDR_A)
         );
-        cache.fill(MOCK_IP_ADDR_1, HADDR_B, Instant::from_millis(0));
+        cache.fill(MOCK_IP_ADDR_1.into(), HADDR_B, Instant::from_millis(0));
         assert_eq!(
-            cache.lookup(&MOCK_IP_ADDR_1, Instant::from_millis(0)),
+            cache.lookup(&MOCK_IP_ADDR_1.into(), Instant::from_millis(0)),
             Answer::Found(HADDR_B)
         );
     }
@@ -241,23 +244,23 @@ mod test {
     fn test_evict() {
         let mut cache = Cache::new();
 
-        cache.fill(MOCK_IP_ADDR_1, HADDR_A, Instant::from_millis(100));
-        cache.fill(MOCK_IP_ADDR_2, HADDR_B, Instant::from_millis(50));
-        cache.fill(MOCK_IP_ADDR_3, HADDR_C, Instant::from_millis(200));
+        cache.fill(MOCK_IP_ADDR_1.into(), HADDR_A, Instant::from_millis(100));
+        cache.fill(MOCK_IP_ADDR_2.into(), HADDR_B, Instant::from_millis(50));
+        cache.fill(MOCK_IP_ADDR_3.into(), HADDR_C, Instant::from_millis(200));
         assert_eq!(
-            cache.lookup(&MOCK_IP_ADDR_2, Instant::from_millis(1000)),
+            cache.lookup(&MOCK_IP_ADDR_2.into(), Instant::from_millis(1000)),
             Answer::Found(HADDR_B)
         );
         assert!(!cache
-            .lookup(&MOCK_IP_ADDR_4, Instant::from_millis(1000))
+            .lookup(&MOCK_IP_ADDR_4.into(), Instant::from_millis(1000))
             .found());
 
-        cache.fill(MOCK_IP_ADDR_4, HADDR_D, Instant::from_millis(300));
+        cache.fill(MOCK_IP_ADDR_4.into(), HADDR_D, Instant::from_millis(300));
         assert!(!cache
-            .lookup(&MOCK_IP_ADDR_2, Instant::from_millis(1000))
+            .lookup(&MOCK_IP_ADDR_2.into(), Instant::from_millis(1000))
             .found());
         assert_eq!(
-            cache.lookup(&MOCK_IP_ADDR_4, Instant::from_millis(1000)),
+            cache.lookup(&MOCK_IP_ADDR_4.into(), Instant::from_millis(1000)),
             Answer::Found(HADDR_D)
         );
     }
@@ -267,17 +270,17 @@ mod test {
         let mut cache = Cache::new();
 
         assert_eq!(
-            cache.lookup(&MOCK_IP_ADDR_1, Instant::from_millis(0)),
+            cache.lookup(&MOCK_IP_ADDR_1.into(), Instant::from_millis(0)),
             Answer::NotFound
         );
 
         cache.limit_rate(Instant::from_millis(0));
         assert_eq!(
-            cache.lookup(&MOCK_IP_ADDR_1, Instant::from_millis(100)),
+            cache.lookup(&MOCK_IP_ADDR_1.into(), Instant::from_millis(100)),
             Answer::RateLimited
         );
         assert_eq!(
-            cache.lookup(&MOCK_IP_ADDR_1, Instant::from_millis(2000)),
+            cache.lookup(&MOCK_IP_ADDR_1.into(), Instant::from_millis(2000)),
             Answer::NotFound
         );
     }
@@ -286,21 +289,21 @@ mod test {
     fn test_flush() {
         let mut cache = Cache::new();
 
-        cache.fill(MOCK_IP_ADDR_1, HADDR_A, Instant::from_millis(0));
+        cache.fill(MOCK_IP_ADDR_1.into(), HADDR_A, Instant::from_millis(0));
         assert_eq!(
-            cache.lookup(&MOCK_IP_ADDR_1, Instant::from_millis(0)),
+            cache.lookup(&MOCK_IP_ADDR_1.into(), Instant::from_millis(0)),
             Answer::Found(HADDR_A)
         );
         assert!(!cache
-            .lookup(&MOCK_IP_ADDR_2, Instant::from_millis(0))
+            .lookup(&MOCK_IP_ADDR_2.into(), Instant::from_millis(0))
             .found());
 
         cache.flush();
         assert!(!cache
-            .lookup(&MOCK_IP_ADDR_1, Instant::from_millis(0))
+            .lookup(&MOCK_IP_ADDR_1.into(), Instant::from_millis(0))
             .found());
         assert!(!cache
-            .lookup(&MOCK_IP_ADDR_1, Instant::from_millis(0))
+            .lookup(&MOCK_IP_ADDR_1.into(), Instant::from_millis(0))
             .found());
     }
 }

+ 14 - 6
src/iface/packet.rs

@@ -84,12 +84,20 @@ impl<'p> Packet<'p> {
             #[cfg(feature = "proto-igmp")]
             IpPayload::Igmp(igmp_repr) => igmp_repr.emit(&mut IgmpPacket::new_unchecked(payload)),
             #[cfg(feature = "proto-ipv6")]
-            IpPayload::Icmpv6(icmpv6_repr) => icmpv6_repr.emit(
-                &_ip_repr.src_addr(),
-                &_ip_repr.dst_addr(),
-                &mut Icmpv6Packet::new_unchecked(payload),
-                &caps.checksum,
-            ),
+            IpPayload::Icmpv6(icmpv6_repr) => {
+                let ipv6_repr = match _ip_repr {
+                    #[cfg(feature = "proto-ipv4")]
+                    IpRepr::Ipv4(_) => unreachable!(),
+                    IpRepr::Ipv6(repr) => repr,
+                };
+
+                icmpv6_repr.emit(
+                    &ipv6_repr.src_addr,
+                    &ipv6_repr.dst_addr,
+                    &mut Icmpv6Packet::new_unchecked(payload),
+                    &caps.checksum,
+                )
+            }
             #[cfg(feature = "socket-raw")]
             IpPayload::Raw(raw_packet) => payload.copy_from_slice(raw_packet),
             #[cfg(any(feature = "socket-udp", feature = "socket-dns"))]

+ 126 - 133
src/socket/icmp.rs

@@ -412,22 +412,26 @@ impl<'a> Socket<'a> {
         Ok((length, endpoint))
     }
 
-    /// Filter determining which packets received by the interface are appended to
-    /// the given sockets received buffer.
-    pub(crate) fn accepts(&self, cx: &mut Context, ip_repr: &IpRepr, icmp_repr: &IcmpRepr) -> bool {
+    /// Fitler determining whether the socket accepts a given ICMPv4 packet.
+    /// Accepted packets are enqueued into the socket's receive buffer.
+    #[cfg(feature = "proto-ipv4")]
+    #[inline]
+    pub(crate) fn accepts_v4(
+        &self,
+        cx: &mut Context,
+        ip_repr: &Ipv4Repr,
+        icmp_repr: &Icmpv4Repr,
+    ) -> bool {
         match (&self.endpoint, icmp_repr) {
             // If we are bound to ICMP errors associated to a UDP port, only
             // accept Destination Unreachable or Time Exceeded messages with
             // the data containing a UDP packet send from the local port we
             // are bound to.
-            #[cfg(feature = "proto-ipv4")]
             (
                 &Endpoint::Udp(endpoint),
-                &IcmpRepr::Ipv4(
-                    Icmpv4Repr::DstUnreachable { data, header, .. }
-                    | Icmpv4Repr::TimeExceeded { data, header, .. },
-                ),
-            ) if endpoint.addr.is_none() || endpoint.addr == Some(ip_repr.dst_addr()) => {
+                &Icmpv4Repr::DstUnreachable { data, header, .. }
+                | &Icmpv4Repr::TimeExceeded { data, header, .. },
+            ) if endpoint.addr.is_none() || endpoint.addr == Some(ip_repr.dst_addr.into()) => {
                 let packet = UdpPacket::new_unchecked(data);
                 match UdpRepr::parse(
                     &packet,
@@ -439,14 +443,37 @@ impl<'a> Socket<'a> {
                     Err(_) => false,
                 }
             }
-            #[cfg(feature = "proto-ipv6")]
+            // If we are bound to a specific ICMP identifier value, only accept an
+            // Echo Request/Reply with the identifier field matching the endpoint
+            // port.
+            (&Endpoint::Ident(bound_ident), &Icmpv4Repr::EchoRequest { ident, .. })
+            | (&Endpoint::Ident(bound_ident), &Icmpv4Repr::EchoReply { ident, .. }) => {
+                ident == bound_ident
+            }
+            _ => false,
+        }
+    }
+
+    /// Fitler determining whether the socket accepts a given ICMPv6 packet.
+    /// Accepted packets are enqueued into the socket's receive buffer.
+    #[cfg(feature = "proto-ipv6")]
+    #[inline]
+    pub(crate) fn accepts_v6(
+        &self,
+        cx: &mut Context,
+        ip_repr: &Ipv6Repr,
+        icmp_repr: &Icmpv6Repr,
+    ) -> bool {
+        match (&self.endpoint, icmp_repr) {
+            // If we are bound to ICMP errors associated to a UDP port, only
+            // accept Destination Unreachable or Time Exceeded messages with
+            // the data containing a UDP packet send from the local port we
+            // are bound to.
             (
                 &Endpoint::Udp(endpoint),
-                &IcmpRepr::Ipv6(
-                    Icmpv6Repr::DstUnreachable { data, header, .. }
-                    | Icmpv6Repr::TimeExceeded { data, header, .. },
-                ),
-            ) if endpoint.addr.is_none() || endpoint.addr == Some(ip_repr.dst_addr()) => {
+                &Icmpv6Repr::DstUnreachable { data, header, .. }
+                | &Icmpv6Repr::TimeExceeded { data, header, .. },
+            ) if endpoint.addr.is_none() || endpoint.addr == Some(ip_repr.dst_addr.into()) => {
                 let packet = UdpPacket::new_unchecked(data);
                 match UdpRepr::parse(
                     &packet,
@@ -461,64 +488,60 @@ impl<'a> Socket<'a> {
             // If we are bound to a specific ICMP identifier value, only accept an
             // Echo Request/Reply with the identifier field matching the endpoint
             // port.
-            #[cfg(feature = "proto-ipv4")]
             (
                 &Endpoint::Ident(bound_ident),
-                &IcmpRepr::Ipv4(Icmpv4Repr::EchoRequest { ident, .. }),
-            )
-            | (
-                &Endpoint::Ident(bound_ident),
-                &IcmpRepr::Ipv4(Icmpv4Repr::EchoReply { ident, .. }),
-            ) => ident == bound_ident,
-            #[cfg(feature = "proto-ipv6")]
-            (
-                &Endpoint::Ident(bound_ident),
-                &IcmpRepr::Ipv6(Icmpv6Repr::EchoRequest { ident, .. }),
-            )
-            | (
-                &Endpoint::Ident(bound_ident),
-                &IcmpRepr::Ipv6(Icmpv6Repr::EchoReply { ident, .. }),
+                &Icmpv6Repr::EchoRequest { ident, .. } | &Icmpv6Repr::EchoReply { ident, .. },
             ) => ident == bound_ident,
             _ => false,
         }
     }
 
-    pub(crate) fn process(&mut self, _cx: &mut Context, ip_repr: &IpRepr, icmp_repr: &IcmpRepr) {
-        match icmp_repr {
-            #[cfg(feature = "proto-ipv4")]
-            IcmpRepr::Ipv4(icmp_repr) => {
-                net_trace!("icmp: receiving {} octets", icmp_repr.buffer_len());
-
-                match self
-                    .rx_buffer
-                    .enqueue(icmp_repr.buffer_len(), ip_repr.src_addr())
-                {
-                    Ok(packet_buf) => {
-                        icmp_repr.emit(
-                            &mut Icmpv4Packet::new_unchecked(packet_buf),
-                            &ChecksumCapabilities::default(),
-                        );
-                    }
-                    Err(_) => net_trace!("icmp: buffer full, dropped incoming packet"),
-                }
-            }
-            #[cfg(feature = "proto-ipv6")]
-            IcmpRepr::Ipv6(icmp_repr) => {
-                net_trace!("icmp: receiving {} octets", icmp_repr.buffer_len());
-
-                match self
-                    .rx_buffer
-                    .enqueue(icmp_repr.buffer_len(), ip_repr.src_addr())
-                {
-                    Ok(packet_buf) => icmp_repr.emit(
-                        &ip_repr.src_addr(),
-                        &ip_repr.dst_addr(),
-                        &mut Icmpv6Packet::new_unchecked(packet_buf),
-                        &ChecksumCapabilities::default(),
-                    ),
-                    Err(_) => net_trace!("icmp: buffer full, dropped incoming packet"),
-                }
+    #[cfg(feature = "proto-ipv4")]
+    pub(crate) fn process_v4(
+        &mut self,
+        _cx: &mut Context,
+        ip_repr: &Ipv4Repr,
+        icmp_repr: &Icmpv4Repr,
+    ) {
+        net_trace!("icmp: receiving {} octets", icmp_repr.buffer_len());
+
+        match self
+            .rx_buffer
+            .enqueue(icmp_repr.buffer_len(), ip_repr.src_addr.into())
+        {
+            Ok(packet_buf) => {
+                icmp_repr.emit(
+                    &mut Icmpv4Packet::new_unchecked(packet_buf),
+                    &ChecksumCapabilities::default(),
+                );
             }
+            Err(_) => net_trace!("icmp: buffer full, dropped incoming packet"),
+        }
+
+        #[cfg(feature = "async")]
+        self.rx_waker.wake();
+    }
+
+    #[cfg(feature = "proto-ipv6")]
+    pub(crate) fn process_v6(
+        &mut self,
+        _cx: &mut Context,
+        ip_repr: &Ipv6Repr,
+        icmp_repr: &Icmpv6Repr,
+    ) {
+        net_trace!("icmp: receiving {} octets", icmp_repr.buffer_len());
+
+        match self
+            .rx_buffer
+            .enqueue(icmp_repr.buffer_len(), ip_repr.src_addr.into())
+        {
+            Ok(packet_buf) => icmp_repr.emit(
+                &ip_repr.src_addr,
+                &ip_repr.dst_addr,
+                &mut Icmpv6Packet::new_unchecked(packet_buf),
+                &ChecksumCapabilities::default(),
+            ),
+            Err(_) => net_trace!("icmp: buffer full, dropped incoming packet"),
         }
 
         #[cfg(feature = "async")]
@@ -583,8 +606,8 @@ impl<'a> Socket<'a> {
                     };
                     let packet = Icmpv6Packet::new_unchecked(&*packet_buf);
                     let repr = match Icmpv6Repr::parse(
-                        &src_addr.into(),
-                        &dst_addr.into(),
+                        &src_addr,
+                        &dst_addr,
                         &packet,
                         &ChecksumCapabilities::ignored(),
                     ) {
@@ -684,13 +707,13 @@ mod test_ipv4 {
         hop_limit: 0x40,
     });
 
-    static REMOTE_IPV4_REPR: IpRepr = IpRepr::Ipv4(Ipv4Repr {
+    static REMOTE_IPV4_REPR: Ipv4Repr = Ipv4Repr {
         src_addr: REMOTE_IPV4,
         dst_addr: LOCAL_IPV4,
         next_header: IpProtocol::Icmp,
         payload_len: 24,
         hop_limit: 0x40,
-    });
+    };
 
     #[test]
     fn test_send_unaddressable() {
@@ -816,12 +839,12 @@ mod test_ipv4 {
         ECHOV4_REPR.emit(&mut packet, &checksum);
         let data = &*packet.into_inner();
 
-        assert!(socket.accepts(cx, &REMOTE_IPV4_REPR, &ECHOV4_REPR.into()));
-        socket.process(cx, &REMOTE_IPV4_REPR, &ECHOV4_REPR.into());
+        assert!(socket.accepts_v4(cx, &REMOTE_IPV4_REPR, &ECHOV4_REPR));
+        socket.process_v4(cx, &REMOTE_IPV4_REPR, &ECHOV4_REPR);
         assert!(socket.can_recv());
 
-        assert!(socket.accepts(cx, &REMOTE_IPV4_REPR, &ECHOV4_REPR.into()));
-        socket.process(cx, &REMOTE_IPV4_REPR, &ECHOV4_REPR.into());
+        assert!(socket.accepts_v4(cx, &REMOTE_IPV4_REPR, &ECHOV4_REPR));
+        socket.process_v4(cx, &REMOTE_IPV4_REPR, &ECHOV4_REPR);
 
         assert_eq!(socket.recv(), Ok((data, REMOTE_IPV4.into())));
         assert!(!socket.can_recv());
@@ -849,7 +872,7 @@ mod test_ipv4 {
 
         // Ensure that a packet with an identifier that isn't the bound
         // ID is not accepted
-        assert!(!socket.accepts(cx, &REMOTE_IPV4_REPR, &icmp_repr.into()));
+        assert!(!socket.accepts_v4(cx, &REMOTE_IPV4_REPR, &icmp_repr));
     }
 
     #[rstest]
@@ -888,20 +911,20 @@ mod test_ipv4 {
             },
             data,
         };
-        let ip_repr = IpRepr::Ipv4(Ipv4Repr {
+        let ip_repr = Ipv4Repr {
             src_addr: REMOTE_IPV4,
             dst_addr: LOCAL_IPV4,
             next_header: IpProtocol::Icmp,
             payload_len: icmp_repr.buffer_len(),
             hop_limit: 0x40,
-        });
+        };
 
         assert!(!socket.can_recv());
 
         // Ensure we can accept ICMP error response to the bound
         // UDP port
-        assert!(socket.accepts(cx, &ip_repr, &icmp_repr.into()));
-        socket.process(cx, &ip_repr, &icmp_repr.into());
+        assert!(socket.accepts_v4(cx, &ip_repr, &icmp_repr));
+        socket.process_v4(cx, &ip_repr, &icmp_repr);
         assert!(socket.can_recv());
 
         let mut bytes = [0x00; 46];
@@ -939,21 +962,21 @@ mod test_ipv6 {
         data: &[0xff; 16],
     };
 
-    static LOCAL_IPV6_REPR: IpRepr = IpRepr::Ipv6(Ipv6Repr {
+    static LOCAL_IPV6_REPR: Ipv6Repr = Ipv6Repr {
         src_addr: LOCAL_IPV6,
         dst_addr: REMOTE_IPV6,
         next_header: IpProtocol::Icmpv6,
         payload_len: 24,
         hop_limit: 0x40,
-    });
+    };
 
-    static REMOTE_IPV6_REPR: IpRepr = IpRepr::Ipv6(Ipv6Repr {
+    static REMOTE_IPV6_REPR: Ipv6Repr = Ipv6Repr {
         src_addr: REMOTE_IPV6,
         dst_addr: LOCAL_IPV6,
         next_header: IpProtocol::Icmpv6,
         payload_len: 24,
         hop_limit: 0x40,
-    });
+    };
 
     #[test]
     fn test_send_unaddressable() {
@@ -986,12 +1009,7 @@ mod test_ipv6 {
 
         let mut bytes = vec![0xff; 24];
         let mut packet = Icmpv6Packet::new_unchecked(&mut bytes);
-        ECHOV6_REPR.emit(
-            &LOCAL_IPV6.into(),
-            &REMOTE_IPV6.into(),
-            &mut packet,
-            &checksum,
-        );
+        ECHOV6_REPR.emit(&LOCAL_IPV6, &REMOTE_IPV6, &mut packet, &checksum);
 
         assert_eq!(
             socket.send_slice(&*packet.into_inner(), REMOTE_IPV6.into()),
@@ -1005,7 +1023,7 @@ mod test_ipv6 {
 
         assert_eq!(
             socket.dispatch(cx, |_, (ip_repr, icmp_repr)| {
-                assert_eq!(ip_repr, LOCAL_IPV6_REPR);
+                assert_eq!(ip_repr, LOCAL_IPV6_REPR.into());
                 assert_eq!(icmp_repr, ECHOV6_REPR.into());
                 Err(())
             }),
@@ -1016,7 +1034,7 @@ mod test_ipv6 {
 
         assert_eq!(
             socket.dispatch(cx, |_, (ip_repr, icmp_repr)| {
-                assert_eq!(ip_repr, LOCAL_IPV6_REPR);
+                assert_eq!(ip_repr, LOCAL_IPV6_REPR.into());
                 assert_eq!(icmp_repr, ECHOV6_REPR.into());
                 Ok::<_, ()>(())
             }),
@@ -1038,12 +1056,7 @@ mod test_ipv6 {
 
         let mut bytes = vec![0xff; 24];
         let mut packet = Icmpv6Packet::new_unchecked(&mut bytes);
-        ECHOV6_REPR.emit(
-            &LOCAL_IPV6.into(),
-            &REMOTE_IPV6.into(),
-            &mut packet,
-            &checksum,
-        );
+        ECHOV6_REPR.emit(&LOCAL_IPV6, &REMOTE_IPV6, &mut packet, &checksum);
 
         s.set_hop_limit(Some(0x2a));
 
@@ -1086,20 +1099,15 @@ mod test_ipv6 {
 
         let mut bytes = [0xff; 24];
         let mut packet = Icmpv6Packet::new_unchecked(&mut bytes[..]);
-        ECHOV6_REPR.emit(
-            &LOCAL_IPV6.into(),
-            &REMOTE_IPV6.into(),
-            &mut packet,
-            &checksum,
-        );
+        ECHOV6_REPR.emit(&LOCAL_IPV6, &REMOTE_IPV6, &mut packet, &checksum);
         let data = &*packet.into_inner();
 
-        assert!(socket.accepts(cx, &REMOTE_IPV6_REPR, &ECHOV6_REPR.into()));
-        socket.process(cx, &REMOTE_IPV6_REPR, &ECHOV6_REPR.into());
+        assert!(socket.accepts_v6(cx, &REMOTE_IPV6_REPR, &ECHOV6_REPR));
+        socket.process_v6(cx, &REMOTE_IPV6_REPR, &ECHOV6_REPR);
         assert!(socket.can_recv());
 
-        assert!(socket.accepts(cx, &REMOTE_IPV6_REPR, &ECHOV6_REPR.into()));
-        socket.process(cx, &REMOTE_IPV6_REPR, &ECHOV6_REPR.into());
+        assert!(socket.accepts_v6(cx, &REMOTE_IPV6_REPR, &ECHOV6_REPR));
+        socket.process_v6(cx, &REMOTE_IPV6_REPR, &ECHOV6_REPR);
 
         assert_eq!(socket.recv(), Ok((data, REMOTE_IPV6.into())));
         assert!(!socket.can_recv());
@@ -1119,19 +1127,14 @@ mod test_ipv6 {
 
         let mut bytes = [0xff; 24];
         let mut packet = Icmpv6Packet::new_unchecked(&mut bytes[..]);
-        ECHOV6_REPR.emit(
-            &LOCAL_IPV6.into(),
-            &REMOTE_IPV6.into(),
-            &mut packet,
-            &checksum,
-        );
+        ECHOV6_REPR.emit(&LOCAL_IPV6, &REMOTE_IPV6, &mut packet, &checksum);
 
-        assert!(socket.accepts(cx, &REMOTE_IPV6_REPR, &ECHOV6_REPR.into()));
-        socket.process(cx, &REMOTE_IPV6_REPR, &ECHOV6_REPR.into());
+        assert!(socket.accepts_v6(cx, &REMOTE_IPV6_REPR, &ECHOV6_REPR));
+        socket.process_v6(cx, &REMOTE_IPV6_REPR, &ECHOV6_REPR);
         assert!(socket.can_recv());
 
-        assert!(socket.accepts(cx, &REMOTE_IPV6_REPR, &ECHOV6_REPR.into()));
-        socket.process(cx, &REMOTE_IPV6_REPR, &ECHOV6_REPR.into());
+        assert!(socket.accepts_v6(cx, &REMOTE_IPV6_REPR, &ECHOV6_REPR));
+        socket.process_v6(cx, &REMOTE_IPV6_REPR, &ECHOV6_REPR);
 
         let mut buffer = [0u8; 1];
         assert_eq!(
@@ -1159,16 +1162,11 @@ mod test_ipv6 {
             seq_no: 0x5678,
             data: &[0xff; 16],
         };
-        icmp_repr.emit(
-            &LOCAL_IPV6.into(),
-            &REMOTE_IPV6.into(),
-            &mut packet,
-            &checksum,
-        );
+        icmp_repr.emit(&LOCAL_IPV6, &REMOTE_IPV6, &mut packet, &checksum);
 
         // Ensure that a packet with an identifier that isn't the bound
         // ID is not accepted
-        assert!(!socket.accepts(cx, &REMOTE_IPV6_REPR, &icmp_repr.into()));
+        assert!(!socket.accepts_v6(cx, &REMOTE_IPV6_REPR, &icmp_repr));
     }
 
     #[rstest]
@@ -1207,30 +1205,25 @@ mod test_ipv6 {
             },
             data,
         };
-        let ip_repr = IpRepr::Ipv6(Ipv6Repr {
+        let ip_repr = Ipv6Repr {
             src_addr: REMOTE_IPV6,
             dst_addr: LOCAL_IPV6,
             next_header: IpProtocol::Icmpv6,
             payload_len: icmp_repr.buffer_len(),
             hop_limit: 0x40,
-        });
+        };
 
         assert!(!socket.can_recv());
 
         // Ensure we can accept ICMP error response to the bound
         // UDP port
-        assert!(socket.accepts(cx, &ip_repr, &icmp_repr.into()));
-        socket.process(cx, &ip_repr, &icmp_repr.into());
+        assert!(socket.accepts_v6(cx, &ip_repr, &icmp_repr));
+        socket.process_v6(cx, &ip_repr, &icmp_repr);
         assert!(socket.can_recv());
 
         let mut bytes = [0x00; 66];
         let mut packet = Icmpv6Packet::new_unchecked(&mut bytes[..]);
-        icmp_repr.emit(
-            &LOCAL_IPV6.into(),
-            &REMOTE_IPV6.into(),
-            &mut packet,
-            &checksum,
-        );
+        icmp_repr.emit(&LOCAL_IPV6, &REMOTE_IPV6, &mut packet, &checksum);
         assert_eq!(
             socket.recv(),
             Ok((&*packet.into_inner(), REMOTE_IPV6.into()))

+ 19 - 10
src/wire/icmpv6.rs

@@ -9,7 +9,7 @@ use crate::wire::MldRepr;
 use crate::wire::NdiscRepr;
 #[cfg(feature = "proto-rpl")]
 use crate::wire::RplRepr;
-use crate::wire::{IpAddress, IpProtocol, Ipv6Packet, Ipv6Repr};
+use crate::wire::{IpProtocol, Ipv6Address, Ipv6Packet, Ipv6Repr};
 use crate::wire::{IPV6_HEADER_LEN, IPV6_MIN_MTU};
 
 /// Error packets must not exceed min MTU
@@ -421,14 +421,14 @@ impl<T: AsRef<[u8]>> Packet<T> {
     ///
     /// # Fuzzing
     /// This function always returns `true` when fuzzing.
-    pub fn verify_checksum(&self, src_addr: &IpAddress, dst_addr: &IpAddress) -> bool {
+    pub fn verify_checksum(&self, src_addr: &Ipv6Address, dst_addr: &Ipv6Address) -> bool {
         if cfg!(fuzzing) {
             return true;
         }
 
         let data = self.buffer.as_ref();
         checksum::combine(&[
-            checksum::pseudo_header(src_addr, dst_addr, IpProtocol::Icmpv6, data.len() as u32),
+            checksum::pseudo_header_v6(src_addr, dst_addr, IpProtocol::Icmpv6, data.len() as u32),
             checksum::data(data),
         ]) == !0
     }
@@ -535,12 +535,17 @@ impl<T: AsRef<[u8]> + AsMut<[u8]>> Packet<T> {
     }
 
     /// Compute and fill in the header checksum.
-    pub fn fill_checksum(&mut self, src_addr: &IpAddress, dst_addr: &IpAddress) {
+    pub fn fill_checksum(&mut self, src_addr: &Ipv6Address, dst_addr: &Ipv6Address) {
         self.set_checksum(0);
         let checksum = {
             let data = self.buffer.as_ref();
             !checksum::combine(&[
-                checksum::pseudo_header(src_addr, dst_addr, IpProtocol::Icmpv6, data.len() as u32),
+                checksum::pseudo_header_v6(
+                    src_addr,
+                    dst_addr,
+                    IpProtocol::Icmpv6,
+                    data.len() as u32,
+                ),
                 checksum::data(data),
             ])
         };
@@ -609,8 +614,8 @@ impl<'a> Repr<'a> {
     /// Parse an Internet Control Message Protocol version 6 packet and return
     /// a high-level representation.
     pub fn parse<T>(
-        src_addr: &IpAddress,
-        dst_addr: &IpAddress,
+        src_addr: &Ipv6Address,
+        dst_addr: &Ipv6Address,
         packet: &Packet<&'a T>,
         checksum_caps: &ChecksumCapabilities,
     ) -> Result<Repr<'a>>
@@ -725,8 +730,8 @@ impl<'a> Repr<'a> {
     /// packet.
     pub fn emit<T>(
         &self,
-        src_addr: &IpAddress,
-        dst_addr: &IpAddress,
+        src_addr: &Ipv6Address,
+        dst_addr: &Ipv6Address,
         packet: &mut Packet<&mut T>,
         checksum_caps: &ChecksumCapabilities,
     ) where
@@ -840,9 +845,13 @@ impl<'a> Repr<'a> {
 #[cfg(test)]
 mod test {
     use super::*;
-    use crate::wire::ip::test::{MOCK_IP_ADDR_1, MOCK_IP_ADDR_2};
     use crate::wire::{IpProtocol, Ipv6Address, Ipv6Repr};
 
+    const MOCK_IP_ADDR_1: Ipv6Address =
+        Ipv6Address([0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]);
+    const MOCK_IP_ADDR_2: Ipv6Address =
+        Ipv6Address([0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2]);
+
     static ECHO_PACKET_BYTES: [u8; 12] = [
         0x80, 0x00, 0x19, 0xb3, 0x12, 0x34, 0xab, 0xcd, 0xaa, 0x00, 0x00, 0xff,
     ];

+ 41 - 53
src/wire/ip.rs

@@ -753,7 +753,42 @@ pub mod checksum {
         propagate_carries(accum)
     }
 
-    /// Compute an IP pseudo header checksum.
+    #[cfg(feature = "proto-ipv4")]
+    pub fn pseudo_header_v4(
+        src_addr: &Ipv4Address,
+        dst_addr: &Ipv4Address,
+        next_header: Protocol,
+        length: u32,
+    ) -> u16 {
+        let mut proto_len = [0u8; 4];
+        proto_len[1] = next_header.into();
+        NetworkEndian::write_u16(&mut proto_len[2..4], length as u16);
+
+        combine(&[
+            data(src_addr.as_bytes()),
+            data(dst_addr.as_bytes()),
+            data(&proto_len[..]),
+        ])
+    }
+
+    #[cfg(feature = "proto-ipv6")]
+    pub fn pseudo_header_v6(
+        src_addr: &Ipv6Address,
+        dst_addr: &Ipv6Address,
+        next_header: Protocol,
+        length: u32,
+    ) -> u16 {
+        let mut proto_len = [0u8; 4];
+        proto_len[1] = next_header.into();
+        NetworkEndian::write_u16(&mut proto_len[2..4], length as u16);
+
+        combine(&[
+            data(src_addr.as_bytes()),
+            data(dst_addr.as_bytes()),
+            data(&proto_len[..]),
+        ])
+    }
+
     pub fn pseudo_header(
         src_addr: &Address,
         dst_addr: &Address,
@@ -762,32 +797,15 @@ pub mod checksum {
     ) -> u16 {
         match (src_addr, dst_addr) {
             #[cfg(feature = "proto-ipv4")]
-            (&Address::Ipv4(src_addr), &Address::Ipv4(dst_addr)) => {
-                let mut proto_len = [0u8; 4];
-                proto_len[1] = next_header.into();
-                NetworkEndian::write_u16(&mut proto_len[2..4], length as u16);
-
-                combine(&[
-                    data(src_addr.as_bytes()),
-                    data(dst_addr.as_bytes()),
-                    data(&proto_len[..]),
-                ])
+            (Address::Ipv4(src_addr), Address::Ipv4(dst_addr)) => {
+                pseudo_header_v4(src_addr, dst_addr, next_header, length)
             }
-
             #[cfg(feature = "proto-ipv6")]
-            (&Address::Ipv6(src_addr), &Address::Ipv6(dst_addr)) => {
-                let mut proto_len = [0u8; 8];
-                proto_len[7] = next_header.into();
-                NetworkEndian::write_u32(&mut proto_len[0..4], length);
-                combine(&[
-                    data(src_addr.as_bytes()),
-                    data(dst_addr.as_bytes()),
-                    data(&proto_len[..]),
-                ])
+            (Address::Ipv6(src_addr), Address::Ipv6(dst_addr)) => {
+                pseudo_header_v6(src_addr, dst_addr, next_header, length)
             }
-
             #[allow(unreachable_patterns)]
-            _ => panic!("Unexpected pseudo header addresses: {src_addr}, {dst_addr}"),
+            _ => unreachable!(),
         }
     }
 
@@ -882,36 +900,6 @@ pub fn pretty_print_ip_payload<T: Into<Repr>>(
 pub(crate) mod test {
     #![allow(unused)]
 
-    #[cfg(feature = "proto-ipv6")]
-    pub(crate) const MOCK_IP_ADDR_1: IpAddress = IpAddress::Ipv6(Ipv6Address([
-        0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
-    ]));
-    #[cfg(feature = "proto-ipv6")]
-    pub(crate) const MOCK_IP_ADDR_2: IpAddress = IpAddress::Ipv6(Ipv6Address([
-        0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2,
-    ]));
-    #[cfg(feature = "proto-ipv6")]
-    pub(crate) const MOCK_IP_ADDR_3: IpAddress = IpAddress::Ipv6(Ipv6Address([
-        0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,
-    ]));
-    #[cfg(feature = "proto-ipv6")]
-    pub(crate) const MOCK_IP_ADDR_4: IpAddress = IpAddress::Ipv6(Ipv6Address([
-        0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4,
-    ]));
-    #[cfg(feature = "proto-ipv6")]
-    pub(crate) const MOCK_UNSPECIFIED: IpAddress = IpAddress::Ipv6(Ipv6Address::UNSPECIFIED);
-
-    #[cfg(all(feature = "proto-ipv4", not(feature = "proto-ipv6")))]
-    pub(crate) const MOCK_IP_ADDR_1: IpAddress = IpAddress::Ipv4(Ipv4Address([192, 168, 1, 1]));
-    #[cfg(all(feature = "proto-ipv4", not(feature = "proto-ipv6")))]
-    pub(crate) const MOCK_IP_ADDR_2: IpAddress = IpAddress::Ipv4(Ipv4Address([192, 168, 1, 2]));
-    #[cfg(all(feature = "proto-ipv4", not(feature = "proto-ipv6")))]
-    pub(crate) const MOCK_IP_ADDR_3: IpAddress = IpAddress::Ipv4(Ipv4Address([192, 168, 1, 3]));
-    #[cfg(all(feature = "proto-ipv4", not(feature = "proto-ipv6")))]
-    pub(crate) const MOCK_IP_ADDR_4: IpAddress = IpAddress::Ipv4(Ipv4Address([192, 168, 1, 4]));
-    #[cfg(all(feature = "proto-ipv4", not(feature = "proto-ipv6")))]
-    pub(crate) const MOCK_UNSPECIFIED: IpAddress = IpAddress::Ipv4(Ipv4Address::UNSPECIFIED);
-
     use super::*;
     use crate::wire::{IpAddress, IpCidr, IpProtocol};
     #[cfg(feature = "proto-ipv4")]

+ 12 - 1
src/wire/ipv4.rs

@@ -796,9 +796,20 @@ impl<T: AsRef<[u8]>> PrettyPrint for Packet<T> {
 }
 
 #[cfg(test)]
-mod test {
+pub(crate) mod test {
     use super::*;
 
+    #[allow(unused)]
+    pub(crate) const MOCK_IP_ADDR_1: Address = Address([192, 168, 1, 1]);
+    #[allow(unused)]
+    pub(crate) const MOCK_IP_ADDR_2: Address = Address([192, 168, 1, 2]);
+    #[allow(unused)]
+    pub(crate) const MOCK_IP_ADDR_3: Address = Address([192, 168, 1, 3]);
+    #[allow(unused)]
+    pub(crate) const MOCK_IP_ADDR_4: Address = Address([192, 168, 1, 4]);
+    #[allow(unused)]
+    pub(crate) const MOCK_UNSPECIFIED: Address = Address::UNSPECIFIED;
+
     static PACKET_BYTES: [u8; 30] = [
         0x45, 0x00, 0x00, 0x1e, 0x01, 0x02, 0x62, 0x03, 0x1a, 0x01, 0xd5, 0x6e, 0x11, 0x12, 0x13,
         0x14, 0x21, 0x22, 0x23, 0x24, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,

+ 16 - 1
src/wire/ipv6.rs

@@ -897,7 +897,7 @@ impl<T: AsRef<[u8]>> PrettyPrint for Packet<T> {
 }
 
 #[cfg(test)]
-mod test {
+pub(crate) mod test {
     use super::Error;
     use super::{Address, Cidr};
     use super::{Packet, Protocol, Repr};
@@ -906,6 +906,21 @@ mod test {
     #[cfg(feature = "proto-ipv4")]
     use crate::wire::ipv4::Address as Ipv4Address;
 
+    #[allow(unused)]
+    pub(crate) const MOCK_IP_ADDR_1: Address =
+        Address([0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]);
+    #[allow(unused)]
+    pub(crate) const MOCK_IP_ADDR_2: Address =
+        Address([0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2]);
+    #[allow(unused)]
+    pub(crate) const MOCK_IP_ADDR_3: Address =
+        Address([0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3]);
+    #[allow(unused)]
+    pub(crate) const MOCK_IP_ADDR_4: Address =
+        Address([0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4]);
+    #[allow(unused)]
+    pub(crate) const MOCK_UNSPECIFIED: Address = Address::UNSPECIFIED;
+
     const LINK_LOCAL_ADDR: Address = Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1);
     const UNIQUE_LOCAL_ADDR: Address = Address::new(0xfd00, 0, 0, 201, 1, 1, 1, 1);
     const GLOBAL_UNICAST_ADDR: Address = Address::new(0x2001, 0xdb8, 0x3, 0, 0, 0, 0, 1);

+ 12 - 12
src/wire/mld.rs

@@ -476,8 +476,8 @@ mod test {
             .copy_from_slice(Ipv6Address::LINK_LOCAL_ALL_ROUTERS.as_bytes());
         packet.clear_reserved();
         packet.fill_checksum(
-            &Ipv6Address::LINK_LOCAL_ALL_NODES.into(),
-            &Ipv6Address::LINK_LOCAL_ALL_ROUTERS.into(),
+            &Ipv6Address::LINK_LOCAL_ALL_NODES,
+            &Ipv6Address::LINK_LOCAL_ALL_ROUTERS,
         );
         assert_eq!(&*packet.into_inner(), &QUERY_PACKET_BYTES[..]);
     }
@@ -519,8 +519,8 @@ mod test {
                 .copy_from_slice(Ipv6Address::LINK_LOCAL_ALL_ROUTERS.as_bytes());
         }
         packet.fill_checksum(
-            &Ipv6Address::LINK_LOCAL_ALL_NODES.into(),
-            &Ipv6Address::LINK_LOCAL_ALL_ROUTERS.into(),
+            &Ipv6Address::LINK_LOCAL_ALL_NODES,
+            &Ipv6Address::LINK_LOCAL_ALL_ROUTERS,
         );
         assert_eq!(&*packet.into_inner(), &REPORT_PACKET_BYTES[..]);
     }
@@ -529,8 +529,8 @@ mod test {
     fn test_query_repr_parse() {
         let packet = Packet::new_unchecked(&QUERY_PACKET_BYTES[..]);
         let repr = Icmpv6Repr::parse(
-            &Ipv6Address::LINK_LOCAL_ALL_NODES.into(),
-            &Ipv6Address::LINK_LOCAL_ALL_ROUTERS.into(),
+            &Ipv6Address::LINK_LOCAL_ALL_NODES,
+            &Ipv6Address::LINK_LOCAL_ALL_ROUTERS,
             &packet,
             &ChecksumCapabilities::default(),
         );
@@ -541,8 +541,8 @@ mod test {
     fn test_report_repr_parse() {
         let packet = Packet::new_unchecked(&REPORT_PACKET_BYTES[..]);
         let repr = Icmpv6Repr::parse(
-            &Ipv6Address::LINK_LOCAL_ALL_NODES.into(),
-            &Ipv6Address::LINK_LOCAL_ALL_ROUTERS.into(),
+            &Ipv6Address::LINK_LOCAL_ALL_NODES,
+            &Ipv6Address::LINK_LOCAL_ALL_ROUTERS,
             &packet,
             &ChecksumCapabilities::default(),
         );
@@ -555,8 +555,8 @@ mod test {
         let mut packet = Packet::new_unchecked(&mut bytes[..]);
         let repr = create_repr(Message::MldQuery);
         repr.emit(
-            &Ipv6Address::LINK_LOCAL_ALL_NODES.into(),
-            &Ipv6Address::LINK_LOCAL_ALL_ROUTERS.into(),
+            &Ipv6Address::LINK_LOCAL_ALL_NODES,
+            &Ipv6Address::LINK_LOCAL_ALL_ROUTERS,
             &mut packet,
             &ChecksumCapabilities::default(),
         );
@@ -569,8 +569,8 @@ mod test {
         let mut packet = Packet::new_unchecked(&mut bytes[..]);
         let repr = create_repr(Message::MldReport);
         repr.emit(
-            &Ipv6Address::LINK_LOCAL_ALL_NODES.into(),
-            &Ipv6Address::LINK_LOCAL_ALL_ROUTERS.into(),
+            &Ipv6Address::LINK_LOCAL_ALL_NODES,
+            &Ipv6Address::LINK_LOCAL_ALL_ROUTERS,
             &mut packet,
             &ChecksumCapabilities::default(),
         );

+ 2 - 2
src/wire/mod.rs

@@ -97,9 +97,9 @@ pub mod ieee802154;
 mod igmp;
 pub(crate) mod ip;
 #[cfg(feature = "proto-ipv4")]
-mod ipv4;
+pub(crate) mod ipv4;
 #[cfg(feature = "proto-ipv6")]
-mod ipv6;
+pub(crate) mod ipv6;
 #[cfg(feature = "proto-ipv6")]
 mod ipv6ext_header;
 #[cfg(feature = "proto-ipv6")]

+ 5 - 1
src/wire/ndisc.rs

@@ -459,10 +459,14 @@ impl<'a> Repr<'a> {
 mod test {
     use super::*;
     use crate::phy::ChecksumCapabilities;
-    use crate::wire::ip::test::{MOCK_IP_ADDR_1, MOCK_IP_ADDR_2};
     use crate::wire::EthernetAddress;
     use crate::wire::Icmpv6Repr;
 
+    const MOCK_IP_ADDR_1: Ipv6Address =
+        Ipv6Address([0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]);
+    const MOCK_IP_ADDR_2: Ipv6Address =
+        Ipv6Address([0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2]);
+
     static ROUTER_ADVERT_BYTES: [u8; 24] = [
         0x86, 0x00, 0xa9, 0xde, 0x40, 0x80, 0x03, 0x84, 0x00, 0x00, 0x03, 0x84, 0x00, 0x00, 0x03,
         0x84, 0x01, 0x01, 0x52, 0x54, 0x00, 0x12, 0x34, 0x56,

+ 2 - 2
src/wire/rpl.rs

@@ -2414,8 +2414,8 @@ mod tests {
             SixlowpanNextHeader::Uncompressed(IpProtocol::Icmpv6) => {
                 let icmp_packet = Icmpv6Packet::new_checked(packet.payload()).unwrap();
                 match Icmpv6Repr::parse(
-                    &IpAddress::Ipv6(repr.src_addr),
-                    &IpAddress::Ipv6(repr.dst_addr),
+                    &repr.src_addr,
+                    &repr.dst_addr,
                     &icmp_packet,
                     &ChecksumCapabilities::ignored(),
                 ) {

+ 7 - 12
src/wire/sixlowpan/nhc.rs

@@ -4,12 +4,7 @@
 use super::{Error, NextHeader, Result, DISPATCH_EXT_HEADER, DISPATCH_UDP_HEADER};
 use crate::{
     phy::ChecksumCapabilities,
-    wire::{
-        ip::{checksum, Address as IpAddress},
-        ipv6,
-        udp::Repr as UdpRepr,
-        IpProtocol,
-    },
+    wire::{ip::checksum, ipv6, udp::Repr as UdpRepr, IpProtocol},
 };
 use byteorder::{ByteOrder, NetworkEndian};
 use ipv6::Address;
@@ -708,9 +703,9 @@ impl<'a> UdpNhcRepr {
         if checksum_caps.udp.rx() {
             let payload_len = packet.payload().len();
             let chk_sum = !checksum::combine(&[
-                checksum::pseudo_header(
-                    &IpAddress::Ipv6(*src_addr),
-                    &IpAddress::Ipv6(*dst_addr),
+                checksum::pseudo_header_v6(
+                    src_addr,
+                    dst_addr,
                     crate::wire::ip::Protocol::Udp,
                     payload_len as u32 + 8,
                 ),
@@ -763,9 +758,9 @@ impl<'a> UdpNhcRepr {
 
         if checksum_caps.udp.tx() {
             let chk_sum = !checksum::combine(&[
-                checksum::pseudo_header(
-                    &IpAddress::Ipv6(*src_addr),
-                    &IpAddress::Ipv6(*dst_addr),
+                checksum::pseudo_header_v6(
+                    src_addr,
+                    dst_addr,
                     crate::wire::ip::Protocol::Udp,
                     payload_len as u32 + 8,
                 ),