diff options
Diffstat (limited to 'src/transport/libp2p')
| -rw-r--r-- | src/transport/libp2p/book.rs | 28 | ||||
| -rw-r--r-- | src/transport/libp2p/tests.rs | 24 |
2 files changed, 45 insertions, 7 deletions
diff --git a/src/transport/libp2p/book.rs b/src/transport/libp2p/book.rs index 02a6b49..c2296d3 100644 --- a/src/transport/libp2p/book.rs +++ b/src/transport/libp2p/book.rs @@ -611,24 +611,38 @@ pub(super) fn ip_of(address: &Multiaddr) -> Option<std::net::IpAddr> { } } -/// Whether `ip` can be reached from the internet, as far as its range tells. +/// Whether `ip` can be reached from the internet, as far as its range tells. For IPv6, +/// only global unicast (`2000::/3`) is: other ranges in use are an overlay's +/// (Mycelium's `400::/7`), a translator's (`64:ff9b::/96`) or local, and, ranked as +/// public, would be preferred over the LAN (`preference`). pub(super) fn is_public(ip: std::net::IpAddr) -> bool { use std::net::IpAddr; match ip { IpAddr::V4(ip) => { + let [a, b, c, _] = ip.octets(); // 100.64.0.0/10: carrier-grade NAT. - let shared = ip.octets()[0] == 100 && (ip.octets()[1] & 0xc0) == 64; + let shared = a == 100 && (b & 0xc0) == 64; + // 198.18.0.0/15: benchmarking; 240.0.0.0/4: reserved (and broadcast). + let benchmarking = a == 198 && (b & 0xfe) == 18; + let reserved = a >= 240; + // 192.0.0.0/24: protocol assignments. + let protocol = a == 192 && b == 0 && c == 0; !(ip.is_private() || ip.is_loopback() || ip.is_link_local() || ip.is_unspecified() - || shared) + || ip.is_documentation() + || ip.is_multicast() + || shared + || benchmarking + || reserved + || protocol) } IpAddr::V6(ip) => { - !(ip.is_loopback() - || ip.is_unspecified() - || ip.is_unique_local() - || ip.is_unicast_link_local()) + let [first, second, ..] = ip.segments(); + // 2001:db8::/32: documentation. + let documentation = first == 0x2001 && second == 0x0db8; + (first & 0xe000) == 0x2000 && !documentation } } } diff --git a/src/transport/libp2p/tests.rs b/src/transport/libp2p/tests.rs index 801dfd3..fd607fe 100644 --- a/src/transport/libp2p/tests.rs +++ b/src/transport/libp2p/tests.rs @@ -539,6 +539,30 @@ async fn a_member_that_relays_is_picked() { /// A peer on the LAN that speaks continuum becomes a seed once, at its address. #[test] +fn public_ranges() { + let public = |ip: &str| book::is_public(ip.parse().unwrap()); + assert!(public("203.0.114.5")); + assert!(public("2a01:4f8::1")); + for not in [ + "10.1.2.3", + "100.64.0.1", + "192.0.2.1", + "198.18.0.1", + "224.0.0.1", + "255.255.255.255", + "::1", + "fd00::1", + "fe80::1", + "2001:db8::1", + "64:ff9b::1", + // Mycelium's overlay. + "45f:fa21:4bdd::1", + ] { + assert!(!public(not), "{not}"); + } +} + +#[test] fn lan_peers_become_seeds_once() { let mut book = Book::default(); let lan = peer(); |
