Skip to content

Commit ef67e7b

Browse files
authored
Merge pull request #900 from thvdveld/ipv6-any-ip
fix: accept any ip for IPv6
2 parents 35bb01a + f5286f5 commit ef67e7b

File tree

3 files changed

+86
-12
lines changed

3 files changed

+86
-12
lines changed

src/iface/interface/ipv6.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -210,8 +210,17 @@ impl InterfaceInner {
210210
&& !self.has_multicast_group(ipv6_repr.dst_addr)
211211
&& !ipv6_repr.dst_addr.is_loopback()
212212
{
213-
net_trace!("packet IP address not for this interface");
214-
return None;
213+
// If AnyIP is enabled, also check if the packet is routed locally.
214+
if !self.any_ip
215+
|| !ipv6_repr.dst_addr.is_unicast()
216+
|| self
217+
.routes
218+
.lookup(&IpAddress::Ipv6(ipv6_repr.dst_addr), self.now)
219+
.map_or(true, |router_addr| !self.has_ip_addr(router_addr))
220+
{
221+
net_trace!("packet IP address not for this interface");
222+
return None;
223+
}
215224
}
216225

217226
#[cfg(feature = "socket-raw")]

src/iface/interface/mod.rs

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,6 @@ pub struct InterfaceInner {
109109
#[cfg(feature = "proto-sixlowpan-fragmentation")]
110110
tag: u16,
111111
ip_addrs: Vec<IpCidr, IFACE_MAX_ADDR_COUNT>,
112-
#[cfg(feature = "proto-ipv4")]
113112
any_ip: bool,
114113
routes: Routes,
115114
#[cfg(feature = "proto-igmp")]
@@ -223,7 +222,6 @@ impl Interface {
223222
caps,
224223
hardware_addr: config.hardware_addr,
225224
ip_addrs: Vec::new(),
226-
#[cfg(feature = "proto-ipv4")]
227225
any_ip: false,
228226
routes: Routes::new(),
229227
#[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
@@ -362,24 +360,17 @@ impl Interface {
362360
/// Enable or disable the AnyIP capability.
363361
///
364362
/// AnyIP allowins packets to be received
365-
/// locally on IPv4 addresses other than the interface's configured [ip_addrs].
363+
/// locally on IP addresses other than the interface's configured [ip_addrs].
366364
/// When AnyIP is enabled and a route prefix in [`routes`](Self::routes) specifies one of
367365
/// the interface's [`ip_addrs`](Self::ip_addrs) as its gateway, the interface will accept
368366
/// packets addressed to that prefix.
369-
///
370-
/// # IPv6
371-
///
372-
/// This option is not available or required for IPv6 as packets sent to
373-
/// the interface are not filtered by IPv6 address.
374-
#[cfg(feature = "proto-ipv4")]
375367
pub fn set_any_ip(&mut self, any_ip: bool) {
376368
self.inner.any_ip = any_ip;
377369
}
378370

379371
/// Get whether AnyIP is enabled.
380372
///
381373
/// See [`set_any_ip`](Self::set_any_ip) for details on AnyIP
382-
#[cfg(feature = "proto-ipv4")]
383374
pub fn any_ip(&self) -> bool {
384375
self.inner.any_ip
385376
}

src/iface/interface/tests/ipv6.rs

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,80 @@ fn parse_ipv6(data: &[u8]) -> crate::wire::Result<Packet<'_>> {
2929
}
3030
}
3131

32+
#[rstest]
33+
#[case::ip(Medium::Ip)]
34+
#[cfg(feature = "medium-ip")]
35+
#[case::ethernet(Medium::Ethernet)]
36+
#[cfg(feature = "medium-ethernet")]
37+
#[case::ieee802154(Medium::Ieee802154)]
38+
#[cfg(feature = "medium-ieee802154")]
39+
fn any_ip(#[case] medium: Medium) {
40+
// An empty echo request with destination address fdbe::3, which is not part of the interface
41+
// address list.
42+
let data = [
43+
0x60, 0x0, 0x0, 0x0, 0x0, 0x8, 0x3a, 0x40, 0xfd, 0xbe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
44+
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0xfd, 0xbe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
45+
0x0, 0x0, 0x0, 0x0, 0x3, 0x80, 0x0, 0x84, 0x3a, 0x0, 0x0, 0x0, 0x0,
46+
];
47+
48+
assert_eq!(
49+
parse_ipv6(&data),
50+
Ok(Packet::new_ipv6(
51+
Ipv6Repr {
52+
src_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002]),
53+
dst_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0003]),
54+
hop_limit: 64,
55+
next_header: IpProtocol::Icmpv6,
56+
payload_len: 8,
57+
},
58+
IpPayload::Icmpv6(Icmpv6Repr::EchoRequest {
59+
ident: 0,
60+
seq_no: 0,
61+
data: b"",
62+
})
63+
))
64+
);
65+
66+
let (mut iface, mut sockets, _device) = setup(medium);
67+
68+
// Add a route to the interface, otherwise, we don't know if the packet is routed localy.
69+
iface.routes_mut().update(|routes| {
70+
routes
71+
.push(crate::iface::Route {
72+
cidr: IpCidr::Ipv6(Ipv6Cidr::new(
73+
Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 0),
74+
64,
75+
)),
76+
via_router: IpAddress::Ipv6(Ipv6Address::from_parts(&[
77+
0xfdbe, 0, 0, 0, 0, 0, 0, 0x0001,
78+
])),
79+
preferred_until: None,
80+
expires_at: None,
81+
})
82+
.unwrap();
83+
});
84+
85+
assert_eq!(
86+
iface.inner.process_ipv6(
87+
&mut sockets,
88+
PacketMeta::default(),
89+
&Ipv6Packet::new_checked(&data[..]).unwrap()
90+
),
91+
None
92+
);
93+
94+
// Accept any IP:
95+
iface.set_any_ip(true);
96+
assert!(iface
97+
.inner
98+
.process_ipv6(
99+
&mut sockets,
100+
PacketMeta::default(),
101+
&Ipv6Packet::new_checked(&data[..]).unwrap()
102+
)
103+
.is_some());
104+
}
105+
32106
#[rstest]
33107
#[case::ip(Medium::Ip)]
34108
#[cfg(feature = "medium-ip")]

0 commit comments

Comments
 (0)