diff --git a/tdutils/td/utils/port/IPAddress.cpp b/tdutils/td/utils/port/IPAddress.cpp index 38f06736..d773ec2a 100644 --- a/tdutils/td/utils/port/IPAddress.cpp +++ b/tdutils/td/utils/port/IPAddress.cpp @@ -12,6 +12,7 @@ #include "td/utils/port/SocketFd.h" #include "td/utils/port/thread_local.h" #include "td/utils/ScopeGuard.h" +#include "td/utils/Slice.h" #include "td/utils/utf8.h" #if TD_WINDOWS @@ -23,6 +24,7 @@ #endif #include +#include namespace td { @@ -175,6 +177,38 @@ bool IPAddress::is_valid() const { return is_valid_; } +bool IPAddress::is_reserved() const { + CHECK(is_valid()); + + if (is_ipv6()) { + // TODO proper check for reserved IPv6 addresses + return true; + } + + uint32 ip = get_ipv4(); + struct IpBlock { + CSlice ip; + int mask; + IpBlock(CSlice ip, int mask) : ip(ip), mask(mask) { + } + }; + static const IpBlock blocks[] = {{"0.0.0.0", 8}, {"10.0.0.0", 8}, {"100.64.0.0", 10}, {"127.0.0.0", 8}, + {"169.254.0.0", 16}, {"172.16.0.0", 12}, {"192.0.0.0", 24}, {"192.0.2.0", 24}, + {"192.88.99.0", 24}, {"192.168.0.0", 16}, {"198.18.0.0", 15}, {"198.51.100.0", 24}, + {"203.0.113.0", 24}, {"224.0.0.0", 3}}; + for (auto &block : blocks) { + IPAddress block_ip_address; + block_ip_address.init_ipv4_port(block.ip, 80).ensure(); + uint32 range = block_ip_address.get_ipv4(); + CHECK(block.mask != 0); + uint32 mask = std::numeric_limits::max() >> (32 - block.mask) << (32 - block.mask); + if ((ip & mask) == (range & mask)) { + return true; + } + } + return false; +} + const sockaddr *IPAddress::get_sockaddr() const { CHECK(is_valid()); return &sockaddr_; diff --git a/tdutils/td/utils/port/IPAddress.h b/tdutils/td/utils/port/IPAddress.h index 9d6082e6..6e62e737 100644 --- a/tdutils/td/utils/port/IPAddress.h +++ b/tdutils/td/utils/port/IPAddress.h @@ -33,6 +33,8 @@ class IPAddress { bool is_ipv4() const; bool is_ipv6() const; + bool is_reserved() const; + int get_port() const; void set_port(int port); diff --git a/tdutils/test/misc.cpp b/tdutils/test/misc.cpp index aacebf5a..8ebcde2c 100644 --- a/tdutils/test/misc.cpp +++ b/tdutils/test/misc.cpp @@ -454,6 +454,73 @@ TEST(Misc, IPAddress_get_ipv4) { test_get_ipv4(0xFFFFFFFF); } +static void test_is_reserved(string ip, bool is_reserved) { + IPAddress ip_address; + ip_address.init_ipv4_port(ip, 80).ensure(); + ASSERT_EQ(is_reserved, ip_address.is_reserved()); +} + +TEST(Misc, IPAddress_is_reserved) { + test_is_reserved("0.0.0.0", true); + test_is_reserved("0.255.255.255", true); + test_is_reserved("1.0.0.0", false); + test_is_reserved("5.0.0.0", false); + test_is_reserved("9.255.255.255", false); + test_is_reserved("10.0.0.0", true); + test_is_reserved("10.255.255.255", true); + test_is_reserved("11.0.0.0", false); + test_is_reserved("100.63.255.255", false); + test_is_reserved("100.64.0.0", true); + test_is_reserved("100.127.255.255", true); + test_is_reserved("100.128.0.0", false); + test_is_reserved("126.255.255.255", false); + test_is_reserved("127.0.0.0", true); + test_is_reserved("127.255.255.255", true); + test_is_reserved("128.0.0.0", false); + test_is_reserved("169.253.255.255", false); + test_is_reserved("169.254.0.0", true); + test_is_reserved("169.254.255.255", true); + test_is_reserved("169.255.0.0", false); + test_is_reserved("172.15.255.255", false); + test_is_reserved("172.16.0.0", true); + test_is_reserved("172.31.255.255", true); + test_is_reserved("172.32.0.0", false); + test_is_reserved("191.255.255.255", false); + test_is_reserved("192.0.0.0", true); + test_is_reserved("192.0.0.255", true); + test_is_reserved("192.0.1.0", false); + test_is_reserved("192.0.1.255", false); + test_is_reserved("192.0.2.0", true); + test_is_reserved("192.0.2.255", true); + test_is_reserved("192.0.3.0", false); + test_is_reserved("192.88.98.255", false); + test_is_reserved("192.88.99.0", true); + test_is_reserved("192.88.99.255", true); + test_is_reserved("192.88.100.0", false); + test_is_reserved("192.167.255.255", false); + test_is_reserved("192.168.0.0", true); + test_is_reserved("192.168.255.255", true); + test_is_reserved("192.169.0.0", false); + test_is_reserved("198.17.255.255", false); + test_is_reserved("198.18.0.0", true); + test_is_reserved("198.19.255.255", true); + test_is_reserved("198.20.0.0", false); + test_is_reserved("198.51.99.255", false); + test_is_reserved("198.51.100.0", true); + test_is_reserved("198.51.100.255", true); + test_is_reserved("198.51.101.0", false); + test_is_reserved("203.0.112.255", false); + test_is_reserved("203.0.113.0", true); + test_is_reserved("203.0.113.255", true); + test_is_reserved("203.0.114.0", false); + test_is_reserved("223.255.255.255", false); + test_is_reserved("224.0.0.0", true); + test_is_reserved("239.255.255.255", true); + test_is_reserved("240.0.0.0", true); + test_is_reserved("255.255.255.254", true); + test_is_reserved("255.255.255.255", true); +} + static void test_split(Slice str, std::pair expected) { ASSERT_EQ(expected, td::split(str)); }