Skip to content

Commit 58f9dc6

Browse files
committed
iface: add support for sending subnet-local broadcast addrs (like 192.168.1.255).
1 parent 8f4820f commit 58f9dc6

File tree

3 files changed

+45
-24
lines changed

3 files changed

+45
-24
lines changed

src/iface/interface/mod.rs

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1312,10 +1312,25 @@ impl InterfaceInner {
13121312
handled_by_raw_socket
13131313
}
13141314

1315-
/// Checks if an incoming packet has a broadcast address for the interfaces
1316-
/// associated ipv4 addresses.
1315+
/// Checks if an address is broadcast, taking into account ipv4 subnet-local
1316+
/// broadcast addresses.
1317+
pub(crate) fn is_broadcast(&self, address: &IpAddress) -> bool {
1318+
match address {
1319+
#[cfg(feature = "proto-ipv4")]
1320+
IpAddress::Ipv4(address) => self.is_broadcast_v4(*address),
1321+
#[cfg(feature = "proto-ipv6")]
1322+
IpAddress::Ipv6(_) => false,
1323+
}
1324+
}
1325+
1326+
/// Checks if an address is broadcast, taking into account ipv4 subnet-local
1327+
/// broadcast addresses.
13171328
#[cfg(feature = "proto-ipv4")]
1318-
fn is_subnet_broadcast(&self, address: Ipv4Address) -> bool {
1329+
pub(crate) fn is_broadcast_v4(&self, address: Ipv4Address) -> bool {
1330+
if address.is_broadcast() {
1331+
return true;
1332+
}
1333+
13191334
self.ip_addrs
13201335
.iter()
13211336
.filter_map(|own_cidr| match own_cidr {
@@ -1326,16 +1341,10 @@ impl InterfaceInner {
13261341
.any(|broadcast_address| address == broadcast_address)
13271342
}
13281343

1329-
/// Checks if an ipv4 address is broadcast, taking into account subnet broadcast addresses
1330-
#[cfg(feature = "proto-ipv4")]
1331-
fn is_broadcast_v4(&self, address: Ipv4Address) -> bool {
1332-
address.is_broadcast() || self.is_subnet_broadcast(address)
1333-
}
1334-
13351344
/// Checks if an ipv4 address is unicast, taking into account subnet broadcast addresses
13361345
#[cfg(feature = "proto-ipv4")]
13371346
fn is_unicast_v4(&self, address: Ipv4Address) -> bool {
1338-
address.is_unicast() && !self.is_subnet_broadcast(address)
1347+
address.is_unicast() && !self.is_broadcast_v4(address)
13391348
}
13401349

13411350
#[cfg(any(feature = "socket-udp", feature = "socket-dns"))]
@@ -1475,6 +1484,8 @@ impl InterfaceInner {
14751484

14761485
fn route(&self, addr: &IpAddress, timestamp: Instant) -> Option<IpAddress> {
14771486
// Send directly.
1487+
// note: no need to use `self.is_broadcast()` to check for subnet-local broadcast addrs
1488+
// here because `in_same_network` will already return true.
14781489
if self.in_same_network(addr) || addr.is_broadcast() {
14791490
return Some(*addr);
14801491
}
@@ -1508,7 +1519,7 @@ impl InterfaceInner {
15081519
where
15091520
Tx: TxToken,
15101521
{
1511-
if dst_addr.is_broadcast() {
1522+
if self.is_broadcast(dst_addr) {
15121523
let hardware_addr = match self.caps.medium {
15131524
#[cfg(feature = "medium-ethernet")]
15141525
Medium::Ethernet => HardwareAddress::Ethernet(EthernetAddress::BROADCAST),

src/iface/interface/tests.rs

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -268,46 +268,56 @@ fn test_local_subnet_broadcasts() {
268268

269269
assert!(iface
270270
.inner
271-
.is_subnet_broadcast(Ipv4Address([192, 168, 1, 255])),);
271+
.is_broadcast_v4(Ipv4Address([255, 255, 255, 255])));
272272
assert!(!iface
273273
.inner
274-
.is_subnet_broadcast(Ipv4Address([192, 168, 1, 254])),);
274+
.is_broadcast_v4(Ipv4Address([255, 255, 255, 254])));
275+
assert!(iface.inner.is_broadcast_v4(Ipv4Address([192, 168, 1, 255])));
276+
assert!(!iface.inner.is_broadcast_v4(Ipv4Address([192, 168, 1, 254])));
275277

276278
iface.update_ip_addrs(|addrs| {
277279
addrs.iter_mut().next().map(|addr| {
278280
*addr = IpCidr::Ipv4(Ipv4Cidr::new(Ipv4Address([192, 168, 23, 24]), 16));
279281
});
280282
});
283+
assert!(iface
284+
.inner
285+
.is_broadcast_v4(Ipv4Address([255, 255, 255, 255])));
286+
assert!(!iface
287+
.inner
288+
.is_broadcast_v4(Ipv4Address([255, 255, 255, 254])));
281289
assert!(!iface
282290
.inner
283-
.is_subnet_broadcast(Ipv4Address([192, 168, 23, 255])),);
291+
.is_broadcast_v4(Ipv4Address([192, 168, 23, 255])));
284292
assert!(!iface
285293
.inner
286-
.is_subnet_broadcast(Ipv4Address([192, 168, 23, 254])),);
294+
.is_broadcast_v4(Ipv4Address([192, 168, 23, 254])));
287295
assert!(!iface
288296
.inner
289-
.is_subnet_broadcast(Ipv4Address([192, 168, 255, 254])),);
297+
.is_broadcast_v4(Ipv4Address([192, 168, 255, 254])));
290298
assert!(iface
291299
.inner
292-
.is_subnet_broadcast(Ipv4Address([192, 168, 255, 255])),);
300+
.is_broadcast_v4(Ipv4Address([192, 168, 255, 255])));
293301

294302
iface.update_ip_addrs(|addrs| {
295303
addrs.iter_mut().next().map(|addr| {
296304
*addr = IpCidr::Ipv4(Ipv4Cidr::new(Ipv4Address([192, 168, 23, 24]), 8));
297305
});
298306
});
299-
assert!(!iface
307+
assert!(iface
300308
.inner
301-
.is_subnet_broadcast(Ipv4Address([192, 23, 1, 255])),);
309+
.is_broadcast_v4(Ipv4Address([255, 255, 255, 255])));
302310
assert!(!iface
303311
.inner
304-
.is_subnet_broadcast(Ipv4Address([192, 23, 1, 254])),);
312+
.is_broadcast_v4(Ipv4Address([255, 255, 255, 254])));
313+
assert!(!iface.inner.is_broadcast_v4(Ipv4Address([192, 23, 1, 255])));
314+
assert!(!iface.inner.is_broadcast_v4(Ipv4Address([192, 23, 1, 254])));
305315
assert!(!iface
306316
.inner
307-
.is_subnet_broadcast(Ipv4Address([192, 255, 255, 254])),);
317+
.is_broadcast_v4(Ipv4Address([192, 255, 255, 254])));
308318
assert!(iface
309319
.inner
310-
.is_subnet_broadcast(Ipv4Address([192, 255, 255, 255])),);
320+
.is_broadcast_v4(Ipv4Address([192, 255, 255, 255])));
311321
}
312322

313323
#[test]

src/socket/udp.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -405,13 +405,13 @@ impl<'a> Socket<'a> {
405405
Ok((length, endpoint))
406406
}
407407

408-
pub(crate) fn accepts(&self, _cx: &mut Context, ip_repr: &IpRepr, repr: &UdpRepr) -> bool {
408+
pub(crate) fn accepts(&self, cx: &mut Context, ip_repr: &IpRepr, repr: &UdpRepr) -> bool {
409409
if self.endpoint.port != repr.dst_port {
410410
return false;
411411
}
412412
if self.endpoint.addr.is_some()
413413
&& self.endpoint.addr != Some(ip_repr.dst_addr())
414-
&& !ip_repr.dst_addr().is_broadcast()
414+
&& !cx.is_broadcast(&ip_repr.dst_addr())
415415
&& !ip_repr.dst_addr().is_multicast()
416416
{
417417
return false;

0 commit comments

Comments
 (0)