Skip to content

Commit 9d8dbbf

Browse files
authored
Merge pull request #377 from MabezDev/subnet-local-broadcasts
Subnet broadcasts
2 parents 43df239 + c492ed2 commit 9d8dbbf

File tree

1 file changed

+51
-2
lines changed

1 file changed

+51
-2
lines changed

src/iface/ethernet.rs

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1023,7 +1023,9 @@ impl<'b, 'c, 'e> InterfaceInner<'b, 'c, 'e> {
10231023

10241024
if !self.has_ip_addr(ipv4_repr.dst_addr) &&
10251025
!ipv4_repr.dst_addr.is_broadcast() &&
1026-
!self.has_multicast_group(ipv4_repr.dst_addr) {
1026+
!self.has_multicast_group(ipv4_repr.dst_addr) &&
1027+
!self.is_subnet_broadcast(ipv4_repr.dst_addr) {
1028+
10271029
// Ignore IP packets not directed at us, or broadcast, or any of the multicast groups.
10281030
// If AnyIP is enabled, also check if the packet is routed locally.
10291031
if !self.any_ip ||
@@ -1066,6 +1068,19 @@ impl<'b, 'c, 'e> InterfaceInner<'b, 'c, 'e> {
10661068
}
10671069
}
10681070

1071+
/// Checks if an incoming packet has a broadcast address for the interfaces
1072+
/// associated ipv4 addresses.
1073+
#[cfg(feature = "proto-ipv4")]
1074+
fn is_subnet_broadcast(&self, address: Ipv4Address) -> bool {
1075+
self.ip_addrs.iter()
1076+
.filter_map(|own_cidr| match own_cidr {
1077+
IpCidr::Ipv4(own_ip) => Some(own_ip.broadcast()?),
1078+
#[cfg(feature = "proto-ipv6")]
1079+
IpCidr::Ipv6(_) => None
1080+
})
1081+
.any(|broadcast_address| address == broadcast_address)
1082+
}
1083+
10691084
/// Host duties of the **IGMPv2** protocol.
10701085
///
10711086
/// Sets up `igmp_report_state` for responding to IGMP general/specific membership queries.
@@ -1695,7 +1710,7 @@ mod test {
16951710
use crate::wire::{EthernetAddress, EthernetFrame, EthernetProtocol};
16961711
use crate::wire::{IpAddress, IpCidr, IpProtocol, IpRepr};
16971712
#[cfg(feature = "proto-ipv4")]
1698-
use crate::wire::{Ipv4Address, Ipv4Repr};
1713+
use crate::wire::{Ipv4Address, Ipv4Repr, Ipv4Cidr};
16991714
#[cfg(feature = "proto-igmp")]
17001715
use crate::wire::Ipv4Packet;
17011716
#[cfg(feature = "proto-ipv4")]
@@ -1875,6 +1890,40 @@ mod test {
18751890
Ok(Some(expected_repr)));
18761891
}
18771892

1893+
#[test]
1894+
#[cfg(feature = "proto-ipv4")]
1895+
fn test_local_subnet_broadcasts() {
1896+
let (mut iface, _) = create_loopback();
1897+
iface.update_ip_addrs(|addrs| {
1898+
addrs.iter_mut().next().map(|addr| {
1899+
*addr = IpCidr::Ipv4(Ipv4Cidr::new(Ipv4Address([192, 168, 1, 23]), 24));
1900+
});
1901+
});
1902+
1903+
assert_eq!(iface.inner.is_subnet_broadcast(Ipv4Address([192, 168, 1, 255])), true);
1904+
assert_eq!(iface.inner.is_subnet_broadcast(Ipv4Address([192, 168, 1, 254])), false);
1905+
1906+
iface.update_ip_addrs(|addrs| {
1907+
addrs.iter_mut().next().map(|addr| {
1908+
*addr = IpCidr::Ipv4(Ipv4Cidr::new(Ipv4Address([192, 168, 23, 24]), 16));
1909+
});
1910+
});
1911+
assert_eq!(iface.inner.is_subnet_broadcast(Ipv4Address([192, 168, 23, 255])), false);
1912+
assert_eq!(iface.inner.is_subnet_broadcast(Ipv4Address([192, 168, 23, 254])), false);
1913+
assert_eq!(iface.inner.is_subnet_broadcast(Ipv4Address([192, 168, 255, 254])), false);
1914+
assert_eq!(iface.inner.is_subnet_broadcast(Ipv4Address([192, 168, 255, 255])), true);
1915+
1916+
iface.update_ip_addrs(|addrs| {
1917+
addrs.iter_mut().next().map(|addr| {
1918+
*addr = IpCidr::Ipv4(Ipv4Cidr::new(Ipv4Address([192, 168, 23, 24]), 8));
1919+
});
1920+
});
1921+
assert_eq!(iface.inner.is_subnet_broadcast(Ipv4Address([192, 23, 1, 255])), false);
1922+
assert_eq!(iface.inner.is_subnet_broadcast(Ipv4Address([192, 23, 1, 254])), false);
1923+
assert_eq!(iface.inner.is_subnet_broadcast(Ipv4Address([192, 255, 255, 254])), false);
1924+
assert_eq!(iface.inner.is_subnet_broadcast(Ipv4Address([192, 255, 255, 255])), true);
1925+
}
1926+
18781927
#[test]
18791928
#[cfg(all(feature = "socket-udp", feature = "proto-ipv4"))]
18801929
fn test_icmp_error_port_unreachable() {

0 commit comments

Comments
 (0)