Skip to content

Commit 824bc13

Browse files
committed
Implement Any-IP feature
Any-IP is the capability to accept packets locally even when the destination address is not configured on any interface. This lets a service bind to an entire subnet of addresses and is particularly useful in anycast deployments. See also: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=4465b469008bc03b98a1b8df4e9ae501b6c69d4b https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=ab79ad14a2d51e95f0ac3cef7cd116a57089ba82 This feature is not available for IPv6 as it would be a nop: the current IPv6 handler doesn't filter packets by the interface's IP address(es).
1 parent ed8dce0 commit 824bc13

File tree

1 file changed

+36
-1
lines changed

1 file changed

+36
-1
lines changed

src/iface/ethernet.rs

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ struct InterfaceInner<'b, 'c, 'e> {
7373
neighbor_cache: NeighborCache<'b>,
7474
ethernet_addr: EthernetAddress,
7575
ip_addrs: ManagedSlice<'c, IpCidr>,
76+
#[cfg(feature = "proto-ipv4")]
77+
any_ip: bool,
7678
routes: Routes<'e>,
7779
#[cfg(feature = "proto-igmp")]
7880
ipv4_multicast_groups: ManagedMap<'e, Ipv4Address, ()>,
@@ -91,6 +93,8 @@ pub struct InterfaceBuilder <'b, 'c, 'e, DeviceT: for<'d> Device<'d>> {
9193
ethernet_addr: Option<EthernetAddress>,
9294
neighbor_cache: Option<NeighborCache<'b>>,
9395
ip_addrs: ManagedSlice<'c, IpCidr>,
96+
#[cfg(feature = "proto-ipv4")]
97+
any_ip: bool,
9498
routes: Routes<'e>,
9599
/// Does not share storage with `ipv6_multicast_groups` to avoid IPv6 size overhead.
96100
#[cfg(feature = "proto-igmp")]
@@ -132,6 +136,8 @@ impl<'b, 'c, 'e, DeviceT> InterfaceBuilder<'b, 'c, 'e, DeviceT>
132136
ethernet_addr: None,
133137
neighbor_cache: None,
134138
ip_addrs: ManagedSlice::Borrowed(&mut []),
139+
#[cfg(feature = "proto-ipv4")]
140+
any_ip: false,
135141
routes: Routes::new(ManagedMap::Borrowed(&mut [])),
136142
#[cfg(feature = "proto-igmp")]
137143
ipv4_multicast_groups: ManagedMap::Borrowed(&mut []),
@@ -169,6 +175,25 @@ impl<'b, 'c, 'e, DeviceT> InterfaceBuilder<'b, 'c, 'e, DeviceT>
169175
self
170176
}
171177

178+
/// Enable or disable the AnyIP capability, allowing packets to be received
179+
/// locally on IPv4 addresses other than the interface's configured [ip_addrs].
180+
/// When AnyIP is enabled and a route prefix in [routes] specifies one of
181+
/// the interface's [ip_addrs] as its gateway, the interface will accept
182+
/// packets addressed to that prefix.
183+
///
184+
/// # IPv6
185+
///
186+
/// This option is not available or required for IPv6 as packets sent to
187+
/// the interface are not filtered by IPv6 address.
188+
///
189+
/// [routes]: struct.EthernetInterface.html#method.routes
190+
/// [ip_addrs]: struct.EthernetInterface.html#method.ip_addrs
191+
#[cfg(feature = "proto-ipv4")]
192+
pub fn any_ip(mut self, enabled: bool) -> Self {
193+
self.any_ip = enabled;
194+
self
195+
}
196+
172197
/// Set the IP routes the interface will use. See also
173198
/// [routes].
174199
///
@@ -225,6 +250,8 @@ impl<'b, 'c, 'e, DeviceT> InterfaceBuilder<'b, 'c, 'e, DeviceT>
225250
inner: InterfaceInner {
226251
ethernet_addr, device_capabilities, neighbor_cache,
227252
ip_addrs: self.ip_addrs,
253+
#[cfg(feature = "proto-ipv4")]
254+
any_ip: self.any_ip,
228255
routes: self.routes,
229256
#[cfg(feature = "proto-igmp")]
230257
ipv4_multicast_groups: self.ipv4_multicast_groups,
@@ -916,7 +943,15 @@ impl<'b, 'c, 'e> InterfaceInner<'b, 'c, 'e> {
916943

917944
if !self.has_ip_addr(ipv4_repr.dst_addr) && !self.has_multicast_group(ipv4_repr.dst_addr) {
918945
// Ignore IP packets not directed at us or any of the multicast groups
919-
return Ok(Packet::None)
946+
// If AnyIP is enabled, also check if the packet is routed locally.
947+
if !self.any_ip {
948+
return Ok(Packet::None);
949+
} else if match self.routes.lookup(&IpAddress::Ipv4(ipv4_repr.dst_addr), timestamp) {
950+
Some(router_addr) => !self.has_ip_addr(router_addr),
951+
None => true,
952+
} {
953+
return Ok(Packet::None);
954+
}
920955
}
921956

922957
match ipv4_repr.protocol {

0 commit comments

Comments
 (0)