@@ -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