diff --git a/rust/connlib/tunnel/src/tests/strategies.rs b/rust/connlib/tunnel/src/tests/strategies.rs index a5418f60e..721754ffa 100644 --- a/rust/connlib/tunnel/src/tests/strategies.rs +++ b/rust/connlib/tunnel/src/tests/strategies.rs @@ -135,19 +135,11 @@ pub(crate) fn relays( /// We make sure to always have at least 1 IPv4 and 1 IPv6 DNS server. pub(crate) fn dns_servers() -> impl Strategy> { let ip4_dns_servers = collection::btree_set( - non_reserved_ipv4() - .prop_filter("must be addressable IP", |ip| { - !ip.is_unspecified() && !ip.is_multicast() && !ip.is_broadcast() - }) - .prop_map(|ip| SocketAddr::from((ip, 53))), + non_reserved_ipv4().prop_map(|ip| SocketAddr::from((ip, 53))), 1..4, ); let ip6_dns_servers = collection::btree_set( - non_reserved_ipv6() - .prop_filter("must be addressable IP", |ip| { - !ip.is_unspecified() && !ip.is_multicast() - }) - .prop_map(|ip| SocketAddr::from((ip, 53))), + non_reserved_ipv6().prop_map(|ip| SocketAddr::from((ip, 53))), 1..4, ); @@ -165,23 +157,42 @@ pub(crate) fn non_reserved_ip() -> impl Strategy { } fn non_reserved_ipv4() -> impl Strategy { - any::() - .prop_filter("must not be in sentinel IP range", |ip| { - !DNS_SENTINELS_V4.contains(*ip) - }) - .prop_filter("must not be in IPv4 resources range", |ip| { - !IPV4_RESOURCES.contains(*ip) - }) + let undesired_ranges = [ + Ipv4Network::new(Ipv4Addr::BROADCAST, 32).unwrap(), + Ipv4Network::new(Ipv4Addr::UNSPECIFIED, 32).unwrap(), + Ipv4Network::new(Ipv4Addr::new(224, 0, 0, 0), 4).unwrap(), // Multicast + DNS_SENTINELS_V4, + IPV4_RESOURCES, + ]; + + any::().prop_map(move |mut ip| { + while let Some(range) = undesired_ranges.iter().find(|range| range.contains(ip)) { + ip = Ipv4Addr::from(u32::from(range.broadcast_address()).wrapping_add(1)); + } + + debug_assert!(undesired_ranges.iter().all(|range| !range.contains(ip))); + + ip + }) } fn non_reserved_ipv6() -> impl Strategy { - any::() - .prop_filter("must not be in sentinel IP range", |ip| { - !DNS_SENTINELS_V6.contains(*ip) - }) - .prop_filter("must not be in IPv6 resources range", |ip| { - !IPV6_RESOURCES.contains(*ip) - }) + let undesired_ranges = [ + Ipv6Network::new(Ipv6Addr::UNSPECIFIED, 32).unwrap(), + DNS_SENTINELS_V6, + IPV6_RESOURCES, + Ipv6Network::new(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0), 8).unwrap(), // Multicast + ]; + + any::().prop_map(move |mut ip| { + while let Some(range) = undesired_ranges.iter().find(|range| range.contains(ip)) { + ip = Ipv6Addr::from(u128::from(range.last_address()).wrapping_add(1)); + } + + debug_assert!(undesired_ranges.iter().all(|range| !range.contains(ip))); + + ip + }) } fn any_site(sites: BTreeSet) -> impl Strategy {