Skip to content

Commit f5286f5

Browse files
committed
fix: accept any ip for IPv6
1 parent 9bd836b commit f5286f5

File tree

3 files changed

+86
-12
lines changed

3 files changed

+86
-12
lines changed

src/iface/interface/ipv6.rs

+11-2
Original file line numberDiff line numberDiff line change
@@ -193,8 +193,17 @@ impl InterfaceInner {
193193
&& !self.has_multicast_group(ipv6_repr.dst_addr)
194194
&& !ipv6_repr.dst_addr.is_loopback()
195195
{
196-
net_trace!("packet IP address not for this interface");
197-
return None;
196+
// If AnyIP is enabled, also check if the packet is routed locally.
197+
if !self.any_ip
198+
|| !ipv6_repr.dst_addr.is_unicast()
199+
|| self
200+
.routes
201+
.lookup(&IpAddress::Ipv6(ipv6_repr.dst_addr), self.now)
202+
.map_or(true, |router_addr| !self.has_ip_addr(router_addr))
203+
{
204+
net_trace!("packet IP address not for this interface");
205+
return None;
206+
}
198207
}
199208

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

src/iface/interface/mod.rs

+1-10
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")]
@@ -221,7 +220,6 @@ impl Interface {
221220
caps,
222221
hardware_addr: config.hardware_addr,
223222
ip_addrs: Vec::new(),
224-
#[cfg(feature = "proto-ipv4")]
225223
any_ip: false,
226224
routes: Routes::new(),
227225
#[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
@@ -358,24 +356,17 @@ impl Interface {
358356
/// Enable or disable the AnyIP capability.
359357
///
360358
/// AnyIP allowins packets to be received
361-
/// locally on IPv4 addresses other than the interface's configured [ip_addrs].
359+
/// locally on IP addresses other than the interface's configured [ip_addrs].
362360
/// When AnyIP is enabled and a route prefix in [`routes`](Self::routes) specifies one of
363361
/// the interface's [`ip_addrs`](Self::ip_addrs) as its gateway, the interface will accept
364362
/// packets addressed to that prefix.
365-
///
366-
/// # IPv6
367-
///
368-
/// This option is not available or required for IPv6 as packets sent to
369-
/// the interface are not filtered by IPv6 address.
370-
#[cfg(feature = "proto-ipv4")]
371363
pub fn set_any_ip(&mut self, any_ip: bool) {
372364
self.inner.any_ip = any_ip;
373365
}
374366

375367
/// Get whether AnyIP is enabled.
376368
///
377369
/// See [`set_any_ip`](Self::set_any_ip) for details on AnyIP
378-
#[cfg(feature = "proto-ipv4")]
379370
pub fn any_ip(&self) -> bool {
380371
self.inner.any_ip
381372
}

src/iface/interface/tests/ipv6.rs

+74
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)