diff --git a/src/iface/interface/ipv6.rs b/src/iface/interface/ipv6.rs index 490fdee15..8c52757f6 100644 --- a/src/iface/interface/ipv6.rs +++ b/src/iface/interface/ipv6.rs @@ -189,7 +189,8 @@ impl InterfaceInner { (ipv6_repr.next_header, ipv6_packet.payload()) }; - if !self.has_ip_addr(ipv6_repr.dst_addr) + if !self.any_ip + && !self.has_ip_addr(ipv6_repr.dst_addr) && !self.has_multicast_group(ipv6_repr.dst_addr) && !ipv6_repr.dst_addr.is_loopback() { diff --git a/src/iface/interface/tests/ipv6.rs b/src/iface/interface/tests/ipv6.rs index f7debda9f..83eec2281 100644 --- a/src/iface/interface/tests/ipv6.rs +++ b/src/iface/interface/tests/ipv6.rs @@ -29,6 +29,63 @@ fn parse_ipv6(data: &[u8]) -> crate::wire::Result> { } } +#[rstest] +#[case::ip(Medium::Ip)] +#[cfg(feature = "medium-ip")] +#[case::ethernet(Medium::Ethernet)] +#[cfg(feature = "medium-ethernet")] +#[case::ieee802154(Medium::Ieee802154)] +#[cfg(feature = "medium-ieee802154")] +fn any_ip(#[case] medium: Medium) { + // An empty echo request with destination address fdbe::3, which is not part of the interface + // address list. + let data = [ + 0x60, 0x0, 0x0, 0x0, 0x0, 0x8, 0x3a, 0x40, 0xfd, 0xbe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0xfd, 0xbe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x3, 0x80, 0x0, 0x84, 0x3a, 0x0, 0x0, 0x0, 0x0, + ]; + + assert_eq!( + parse_ipv6(&data), + Ok(Packet::new_ipv6( + Ipv6Repr { + src_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002]), + dst_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0003]), + hop_limit: 64, + next_header: IpProtocol::Icmpv6, + payload_len: 8, + }, + IpPayload::Icmpv6(Icmpv6Repr::EchoRequest { + ident: 0, + seq_no: 0, + data: b"", + }) + )) + ); + + let (mut iface, mut sockets, _device) = setup(medium); + + assert_eq!( + iface.inner.process_ipv6( + &mut sockets, + PacketMeta::default(), + &Ipv6Packet::new_checked(&data[..]).unwrap() + ), + None + ); + + // Accept any IP: + iface.set_any_ip(true); + assert!(iface + .inner + .process_ipv6( + &mut sockets, + PacketMeta::default(), + &Ipv6Packet::new_checked(&data[..]).unwrap() + ) + .is_some()); +} + #[rstest] #[case::ip(Medium::Ip)] #[cfg(feature = "medium-ip")]