diff --git a/src/iface/interface/ethernet.rs b/src/iface/interface/ethernet.rs index 4d29faa11..da2d01229 100644 --- a/src/iface/interface/ethernet.rs +++ b/src/iface/interface/ethernet.rs @@ -25,13 +25,19 @@ impl InterfaceInner { EthernetProtocol::Ipv4 => { let ipv4_packet = check!(Ipv4Packet::new_checked(eth_frame.payload())); - self.process_ipv4(sockets, meta, &ipv4_packet, fragments) - .map(EthernetPacket::Ip) + self.process_ipv4( + sockets, + meta, + eth_frame.src_addr().into(), + &ipv4_packet, + fragments, + ) + .map(EthernetPacket::Ip) } #[cfg(feature = "proto-ipv6")] EthernetProtocol::Ipv6 => { let ipv6_packet = check!(Ipv6Packet::new_checked(eth_frame.payload())); - self.process_ipv6(sockets, meta, &ipv6_packet) + self.process_ipv6(sockets, meta, eth_frame.src_addr().into(), &ipv6_packet) .map(EthernetPacket::Ip) } // Drop all other traffic. diff --git a/src/iface/interface/ipv4.rs b/src/iface/interface/ipv4.rs index 84b265c5e..e75159ea2 100644 --- a/src/iface/interface/ipv4.rs +++ b/src/iface/interface/ipv4.rs @@ -91,6 +91,7 @@ impl InterfaceInner { &mut self, sockets: &mut SocketSet, meta: PacketMeta, + source_hardware_addr: HardwareAddress, ipv4_packet: &Ipv4Packet<&'a [u8]>, frag: &'a mut FragmentsBuffer, ) -> Option> { @@ -197,8 +198,13 @@ impl InterfaceInner { } #[cfg(feature = "medium-ethernet")] - self.neighbor_cache - .reset_expiry_if_existing(IpAddress::Ipv4(ipv4_repr.src_addr), self.now); + if self.is_unicast_v4(ipv4_repr.dst_addr) { + self.neighbor_cache.reset_expiry_if_existing( + IpAddress::Ipv4(ipv4_repr.src_addr), + source_hardware_addr, + self.now, + ); + } match ipv4_repr.next_header { IpProtocol::Icmp => self.process_icmpv4(sockets, ipv4_repr, ip_payload), diff --git a/src/iface/interface/ipv6.rs b/src/iface/interface/ipv6.rs index 28c446304..a8d29e48c 100644 --- a/src/iface/interface/ipv6.rs +++ b/src/iface/interface/ipv6.rs @@ -187,6 +187,7 @@ impl InterfaceInner { &mut self, sockets: &mut SocketSet, meta: PacketMeta, + source_hardware_addr: HardwareAddress, ipv6_packet: &Ipv6Packet<&'frame [u8]>, ) -> Option> { let ipv6_repr = check!(Ipv6Repr::parse(ipv6_packet)); @@ -229,8 +230,13 @@ impl InterfaceInner { let handled_by_raw_socket = false; #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))] - self.neighbor_cache - .reset_expiry_if_existing(IpAddress::Ipv6(ipv6_repr.src_addr), self.now); + if ipv6_repr.dst_addr.is_unicast() { + self.neighbor_cache.reset_expiry_if_existing( + IpAddress::Ipv6(ipv6_repr.src_addr), + source_hardware_addr, + self.now, + ); + } self.process_nxt_hdr( sockets, diff --git a/src/iface/interface/mod.rs b/src/iface/interface/mod.rs index f8c8afb69..7eed974e8 100644 --- a/src/iface/interface/mod.rs +++ b/src/iface/interface/mod.rs @@ -785,12 +785,12 @@ impl InterfaceInner { Ok(IpVersion::Ipv4) => { let ipv4_packet = check!(Ipv4Packet::new_checked(ip_payload)); - self.process_ipv4(sockets, meta, &ipv4_packet, frag) + self.process_ipv4(sockets, meta, HardwareAddress::Ip, &ipv4_packet, frag) } #[cfg(feature = "proto-ipv6")] Ok(IpVersion::Ipv6) => { let ipv6_packet = check!(Ipv6Packet::new_checked(ip_payload)); - self.process_ipv6(sockets, meta, &ipv6_packet) + self.process_ipv6(sockets, meta, HardwareAddress::Ip, &ipv6_packet) } // Drop all other traffic. _ => None, diff --git a/src/iface/interface/sixlowpan.rs b/src/iface/interface/sixlowpan.rs index 3caa446f5..a89934f1f 100644 --- a/src/iface/interface/sixlowpan.rs +++ b/src/iface/interface/sixlowpan.rs @@ -99,7 +99,15 @@ impl InterfaceInner { } }; - self.process_ipv6(sockets, meta, &check!(Ipv6Packet::new_checked(payload))) + self.process_ipv6( + sockets, + meta, + match ieee802154_repr.src_addr { + Some(s) => HardwareAddress::Ieee802154(s), + None => HardwareAddress::Ieee802154(Ieee802154Address::Absent), + }, + &check!(Ipv6Packet::new_checked(payload)), + ) } #[cfg(feature = "proto-sixlowpan-fragmentation")] diff --git a/src/iface/interface/tests/ipv4.rs b/src/iface/interface/tests/ipv4.rs index 475911bed..e8b667fbc 100644 --- a/src/iface/interface/tests/ipv4.rs +++ b/src/iface/interface/tests/ipv4.rs @@ -91,6 +91,7 @@ fn test_no_icmp_no_unicast(#[case] medium: Medium) { iface.inner.process_ipv4( &mut sockets, PacketMeta::default(), + EthernetAddress([0x02, 0x02, 0x02, 0x02, 0x02, 0x02]).into(), &frame, &mut iface.fragments ), @@ -152,6 +153,7 @@ fn test_icmp_error_no_payload(#[case] medium: Medium) { iface.inner.process_ipv4( &mut sockets, PacketMeta::default(), + EthernetAddress([0x02, 0x02, 0x02, 0x02, 0x02, 0x02]).into(), &frame, &mut iface.fragments ), @@ -397,6 +399,7 @@ fn test_handle_ipv4_broadcast(#[case] medium: Medium) { iface.inner.process_ipv4( &mut sockets, PacketMeta::default(), + EthernetAddress([0x02, 0x02, 0x02, 0x02, 0x02, 0x02]).into(), &frame, &mut iface.fragments ), @@ -828,6 +831,7 @@ fn test_raw_socket_no_reply(#[case] medium: Medium) { iface.inner.process_ipv4( &mut sockets, PacketMeta::default(), + EthernetAddress([0x02, 0x02, 0x02, 0x02, 0x02, 0x02]).into(), &frame, &mut iface.fragments ), @@ -925,6 +929,7 @@ fn test_raw_socket_with_udp_socket(#[case] medium: Medium) { iface.inner.process_ipv4( &mut sockets, PacketMeta::default(), + EthernetAddress([0x02, 0x02, 0x02, 0x02, 0x02, 0x02]).into(), &frame, &mut iface.fragments ), diff --git a/src/iface/interface/tests/ipv6.rs b/src/iface/interface/tests/ipv6.rs index c891ecc34..2522aa1c8 100644 --- a/src/iface/interface/tests/ipv6.rs +++ b/src/iface/interface/tests/ipv6.rs @@ -86,6 +86,7 @@ fn any_ip(#[case] medium: Medium) { iface.inner.process_ipv6( &mut sockets, PacketMeta::default(), + EthernetAddress([0x02, 0x02, 0x02, 0x02, 0x02, 0x02]).into(), &Ipv6Packet::new_checked(&data[..]).unwrap() ), None @@ -98,6 +99,7 @@ fn any_ip(#[case] medium: Medium) { .process_ipv6( &mut sockets, PacketMeta::default(), + EthernetAddress([0x02, 0x02, 0x02, 0x02, 0x02, 0x02]).into(), &Ipv6Packet::new_checked(&data[..]).unwrap() ) .is_some()); @@ -125,6 +127,7 @@ fn multicast_source_address(#[case] medium: Medium) { iface.inner.process_ipv6( &mut sockets, PacketMeta::default(), + EthernetAddress([0x02, 0x02, 0x02, 0x02, 0x02, 0x02]).into(), &Ipv6Packet::new_checked(&data[..]).unwrap() ), response @@ -173,6 +176,7 @@ fn hop_by_hop_skip_with_icmp(#[case] medium: Medium) { iface.inner.process_ipv6( &mut sockets, PacketMeta::default(), + EthernetAddress([0x02, 0x02, 0x02, 0x02, 0x02, 0x02]).into(), &Ipv6Packet::new_checked(&data[..]).unwrap() ), response @@ -208,6 +212,7 @@ fn hop_by_hop_discard_with_icmp(#[case] medium: Medium) { iface.inner.process_ipv6( &mut sockets, PacketMeta::default(), + EthernetAddress([0x02, 0x02, 0x02, 0x02, 0x02, 0x02]).into(), &Ipv6Packet::new_checked(&data[..]).unwrap() ), response @@ -262,6 +267,7 @@ fn hop_by_hop_discard_param_problem(#[case] medium: Medium) { iface.inner.process_ipv6( &mut sockets, PacketMeta::default(), + EthernetAddress([0x02, 0x02, 0x02, 0x02, 0x02, 0x02]).into(), &Ipv6Packet::new_checked(&data[..]).unwrap() ), response @@ -319,6 +325,7 @@ fn hop_by_hop_discard_with_multicast(#[case] medium: Medium) { iface.inner.process_ipv6( &mut sockets, PacketMeta::default(), + EthernetAddress([0x02, 0x02, 0x02, 0x02, 0x02, 0x02]).into(), &Ipv6Packet::new_checked(&data[..]).unwrap() ), response @@ -378,6 +385,7 @@ fn imcp_empty_echo_request(#[case] medium: Medium) { iface.inner.process_ipv6( &mut sockets, PacketMeta::default(), + EthernetAddress([0x02, 0x02, 0x02, 0x02, 0x02, 0x02]).into(), &Ipv6Packet::new_checked(&data[..]).unwrap() ), response @@ -438,6 +446,7 @@ fn icmp_echo_request(#[case] medium: Medium) { iface.inner.process_ipv6( &mut sockets, PacketMeta::default(), + EthernetAddress([0x02, 0x02, 0x02, 0x02, 0x02, 0x02]).into(), &Ipv6Packet::new_checked(&data[..]).unwrap() ), response @@ -485,6 +494,7 @@ fn icmp_echo_reply_as_input(#[case] medium: Medium) { iface.inner.process_ipv6( &mut sockets, PacketMeta::default(), + EthernetAddress([0x02, 0x02, 0x02, 0x02, 0x02, 0x02]).into(), &Ipv6Packet::new_checked(&data[..]).unwrap() ), response @@ -533,6 +543,7 @@ fn unknown_proto_with_multicast_dst_address(#[case] medium: Medium) { iface.inner.process_ipv6( &mut sockets, PacketMeta::default(), + EthernetAddress([0x02, 0x02, 0x02, 0x02, 0x02, 0x02]).into(), &Ipv6Packet::new_checked(&data[..]).unwrap() ), response @@ -582,6 +593,7 @@ fn unknown_proto(#[case] medium: Medium) { iface.inner.process_ipv6( &mut sockets, PacketMeta::default(), + EthernetAddress([0x02, 0x02, 0x02, 0x02, 0x02, 0x02]).into(), &Ipv6Packet::new_checked(&data[..]).unwrap() ), response @@ -626,6 +638,7 @@ fn ndsic_neighbor_advertisement_ethernet(#[case] medium: Medium) { iface.inner.process_ipv6( &mut sockets, PacketMeta::default(), + EthernetAddress([0x02, 0x02, 0x02, 0x02, 0x02, 0x02]).into(), &Ipv6Packet::new_checked(&data[..]).unwrap() ), response @@ -682,6 +695,7 @@ fn ndsic_neighbor_advertisement_ethernet_multicast_addr(#[case] medium: Medium) iface.inner.process_ipv6( &mut sockets, PacketMeta::default(), + EthernetAddress([0x02, 0x02, 0x02, 0x02, 0x02, 0x02]).into(), &Ipv6Packet::new_checked(&data[..]).unwrap() ), response @@ -734,6 +748,7 @@ fn ndsic_neighbor_advertisement_ieee802154(#[case] medium: Medium) { iface.inner.process_ipv6( &mut sockets, PacketMeta::default(), + EthernetAddress([0x02, 0x02, 0x02, 0x02, 0x02, 0x02]).into(), &Ipv6Packet::new_checked(&data[..]).unwrap() ), response diff --git a/src/iface/neighbor.rs b/src/iface/neighbor.rs index 543d78c98..dcef2bb87 100644 --- a/src/iface/neighbor.rs +++ b/src/iface/neighbor.rs @@ -63,13 +63,20 @@ impl Cache { } } - pub fn reset_expiry_if_existing(&mut self, protocol_addr: IpAddress, timestamp: Instant) { + pub fn reset_expiry_if_existing( + &mut self, + protocol_addr: IpAddress, + source_hardware_addr: HardwareAddress, + timestamp: Instant, + ) { if let Some(Neighbor { expires_at, - hardware_addr: _, + hardware_addr, }) = self.storage.get_mut(&protocol_addr) { - *expires_at = timestamp + Self::ENTRY_LIFETIME; + if source_hardware_addr == *hardware_addr { + *expires_at = timestamp + Self::ENTRY_LIFETIME; + } } }