Skip to content

Commit

Permalink
fix: accept any ip for IPv6
Browse files Browse the repository at this point in the history
  • Loading branch information
thvdveld committed Jan 22, 2024
1 parent 9bd836b commit f5286f5
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 12 deletions.
13 changes: 11 additions & 2 deletions src/iface/interface/ipv6.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,8 +193,17 @@ impl InterfaceInner {
&& !self.has_multicast_group(ipv6_repr.dst_addr)
&& !ipv6_repr.dst_addr.is_loopback()
{
net_trace!("packet IP address not for this interface");
return None;
// If AnyIP is enabled, also check if the packet is routed locally.
if !self.any_ip
|| !ipv6_repr.dst_addr.is_unicast()
|| self
.routes
.lookup(&IpAddress::Ipv6(ipv6_repr.dst_addr), self.now)
.map_or(true, |router_addr| !self.has_ip_addr(router_addr))
{
net_trace!("packet IP address not for this interface");
return None;
}
}

#[cfg(feature = "socket-raw")]
Expand Down
11 changes: 1 addition & 10 deletions src/iface/interface/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,6 @@ pub struct InterfaceInner {
#[cfg(feature = "proto-sixlowpan-fragmentation")]
tag: u16,
ip_addrs: Vec<IpCidr, IFACE_MAX_ADDR_COUNT>,
#[cfg(feature = "proto-ipv4")]
any_ip: bool,
routes: Routes,
#[cfg(feature = "proto-igmp")]
Expand Down Expand Up @@ -221,7 +220,6 @@ impl Interface {
caps,
hardware_addr: config.hardware_addr,
ip_addrs: Vec::new(),
#[cfg(feature = "proto-ipv4")]
any_ip: false,
routes: Routes::new(),
#[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
Expand Down Expand Up @@ -358,24 +356,17 @@ impl Interface {
/// Enable or disable the AnyIP capability.
///
/// AnyIP allowins packets to be received
/// locally on IPv4 addresses other than the interface's configured [ip_addrs].
/// locally on IP addresses other than the interface's configured [ip_addrs].
/// When AnyIP is enabled and a route prefix in [`routes`](Self::routes) specifies one of
/// the interface's [`ip_addrs`](Self::ip_addrs) as its gateway, the interface will accept
/// packets addressed to that prefix.
///
/// # IPv6
///
/// This option is not available or required for IPv6 as packets sent to
/// the interface are not filtered by IPv6 address.
#[cfg(feature = "proto-ipv4")]
pub fn set_any_ip(&mut self, any_ip: bool) {
self.inner.any_ip = any_ip;
}

/// Get whether AnyIP is enabled.
///
/// See [`set_any_ip`](Self::set_any_ip) for details on AnyIP
#[cfg(feature = "proto-ipv4")]
pub fn any_ip(&self) -> bool {
self.inner.any_ip
}
Expand Down
74 changes: 74 additions & 0 deletions src/iface/interface/tests/ipv6.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,80 @@ fn parse_ipv6(data: &[u8]) -> crate::wire::Result<Packet<'_>> {
}
}

#[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);

// Add a route to the interface, otherwise, we don't know if the packet is routed localy.
iface.routes_mut().update(|routes| {
routes
.push(crate::iface::Route {
cidr: IpCidr::Ipv6(Ipv6Cidr::new(
Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 0),
64,
)),
via_router: IpAddress::Ipv6(Ipv6Address::from_parts(&[
0xfdbe, 0, 0, 0, 0, 0, 0, 0x0001,
])),
preferred_until: None,
expires_at: None,
})
.unwrap();
});

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")]
Expand Down

0 comments on commit f5286f5

Please sign in to comment.