@@ -200,19 +200,20 @@ impl IpFilter {
200200
201201 /// Check whether a given ip address is contained in the filter.
202202 /// Complexity: O(1)
203- pub fn is_in ( & self , addr : & IpAddr ) -> bool {
203+ pub fn is_in ( & self , addr : IpAddr ) -> bool {
204+ let addr = addr. to_canonical ( ) ;
204205 match addr {
205206 IpAddr :: V4 ( addr) => self . is_in4 ( addr) ,
206207 IpAddr :: V6 ( addr) => self . is_in6 ( addr) ,
207208 }
208209 }
209210
210- fn is_in4 ( & self , addr : & Ipv4Addr ) -> bool {
211+ fn is_in4 ( & self , addr : Ipv4Addr ) -> bool {
211212 self . ipv4_filter
212213 . lookup ( ( u32:: from_be_bytes ( addr. octets ( ) ) as u128 ) << 96 )
213214 }
214215
215- fn is_in6 ( & self , addr : & Ipv6Addr ) -> bool {
216+ fn is_in6 ( & self , addr : Ipv6Addr ) -> bool {
216217 self . ipv6_filter . lookup ( u128:: from_be_bytes ( addr. octets ( ) ) )
217218 }
218219}
@@ -229,7 +230,7 @@ pub mod fuzz {
229230 use super :: * ;
230231
231232 fn contains ( subnet : & IpSubnet , addr : & IpAddr ) -> bool {
232- match ( subnet. addr , addr) {
233+ match ( subnet. addr , addr. to_canonical ( ) ) {
233234 ( IpAddr :: V4 ( net) , IpAddr :: V4 ( addr) ) => {
234235 let net = u32:: from_be_bytes ( net. octets ( ) ) ;
235236 let addr = u32:: from_be_bytes ( addr. octets ( ) ) ;
@@ -263,13 +264,15 @@ pub mod fuzz {
263264 let filter = IpFilter :: new ( nets) ;
264265
265266 for addr in addr {
266- assert_eq ! ( filter. is_in( addr) , any_contains( nets, addr) ) ;
267+ assert_eq ! ( filter. is_in( * addr) , any_contains( nets, addr) ) ;
267268 }
268269 }
269270}
270271
271272#[ cfg( test) ]
272273mod tests {
274+ use crate :: SubnetParseError ;
275+
273276 use super :: * ;
274277
275278 #[ test]
@@ -295,31 +298,45 @@ mod tests {
295298 fn test_filter ( ) {
296299 let filter = IpFilter :: new ( & [
297300 "127.0.0.0/24" . parse ( ) . unwrap ( ) ,
298- "::FFFF:0000:0000/96 " . parse ( ) . unwrap ( ) ,
301+ "::FFFF:192.168.0.0/104 " . parse ( ) . unwrap ( ) ,
299302 ] ) ;
300- assert ! ( filter. is_in( & "127.0.0.1" . parse( ) . unwrap( ) ) ) ;
301- assert ! ( !filter. is_in( & "192.168.1.1" . parse( ) . unwrap( ) ) ) ;
302- assert ! ( filter. is_in( & "::FFFF:ABCD:0123" . parse( ) . unwrap( ) ) ) ;
303- assert ! ( !filter. is_in( & "::FEEF:ABCD:0123" . parse( ) . unwrap( ) ) ) ;
303+ assert ! ( filter. is_in( "127.0.0.1" . parse( ) . unwrap( ) ) ) ;
304+ assert ! ( !filter. is_in( "10.0.1.1" . parse( ) . unwrap( ) ) ) ;
305+ assert ! ( filter. is_in( "::FFFF:192.168.1.1" . parse( ) . unwrap( ) ) ) ;
306+ assert ! ( !filter. is_in( "::FFFF:10.0.0.5" . parse( ) . unwrap( ) ) ) ;
307+ assert ! ( !filter. is_in( "::FEEF:ABCD:1234" . parse( ) . unwrap( ) ) ) ;
308+ }
309+
310+ #[ test]
311+ fn test_subnet_mapped_ipv4_overlap ( ) {
312+ let subnet_err = "::FFFF:192.168.0.0/95" . parse :: < IpSubnet > ( ) . unwrap_err ( ) ;
313+ assert_eq ! ( subnet_err, SubnetParseError :: MaskV4Range ) ;
314+ }
315+
316+ #[ test]
317+ fn test_subnet_mapped_ipv4 ( ) {
318+ let subnet = "::FFFF:192.168.0.0/120" . parse :: < IpSubnet > ( ) . unwrap ( ) ;
319+ assert_eq ! ( subnet. addr, "192.168.0.0" . parse:: <IpAddr >( ) . unwrap( ) ) ;
320+ assert_eq ! ( subnet. mask, 24 ) ;
304321 }
305322
306323 #[ test]
307324 fn test_subnet_edgecases ( ) {
308325 let filter = IpFilter :: new ( & [ "0.0.0.0/0" . parse ( ) . unwrap ( ) , "::/0" . parse ( ) . unwrap ( ) ] ) ;
309326
310- assert ! ( filter. is_in( & "0.0.0.0" . parse( ) . unwrap( ) ) ) ;
311- assert ! ( filter. is_in( & "255.255.255.255" . parse( ) . unwrap( ) ) ) ;
312- assert ! ( filter. is_in( & "::" . parse( ) . unwrap( ) ) ) ;
313- assert ! ( filter. is_in( & "FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF" . parse( ) . unwrap( ) ) ) ;
327+ assert ! ( filter. is_in( "0.0.0.0" . parse( ) . unwrap( ) ) ) ;
328+ assert ! ( filter. is_in( "255.255.255.255" . parse( ) . unwrap( ) ) ) ;
329+ assert ! ( filter. is_in( "::" . parse( ) . unwrap( ) ) ) ;
330+ assert ! ( filter. is_in( "FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF" . parse( ) . unwrap( ) ) ) ;
314331
315332 let filter = IpFilter :: new ( & [
316333 "1.2.3.4/32" . parse ( ) . unwrap ( ) ,
317334 "10:32:54:76:98:BA:DC:FE/128" . parse ( ) . unwrap ( ) ,
318335 ] ) ;
319336
320- assert ! ( filter. is_in( & "1.2.3.4" . parse( ) . unwrap( ) ) ) ;
321- assert ! ( !filter. is_in( & "1.2.3.5" . parse( ) . unwrap( ) ) ) ;
322- assert ! ( filter. is_in( & "10:32:54:76:98:BA:DC:FE" . parse( ) . unwrap( ) ) ) ;
323- assert ! ( !filter. is_in( & "10:32:54:76:98:BA:DC:FF" . parse( ) . unwrap( ) ) ) ;
337+ assert ! ( filter. is_in( "1.2.3.4" . parse( ) . unwrap( ) ) ) ;
338+ assert ! ( !filter. is_in( "1.2.3.5" . parse( ) . unwrap( ) ) ) ;
339+ assert ! ( filter. is_in( "10:32:54:76:98:BA:DC:FE" . parse( ) . unwrap( ) ) ) ;
340+ assert ! ( !filter. is_in( "10:32:54:76:98:BA:DC:FF" . parse( ) . unwrap( ) ) ) ;
324341 }
325342}
0 commit comments