diff options
Diffstat (limited to 'src/common')
-rw-r--r-- | src/common/Asio/IpAddress.h | 1 | ||||
-rw-r--r-- | src/common/Cryptography/BigNumber.cpp | 6 | ||||
-rw-r--r-- | src/common/Cryptography/BigNumber.h | 2 | ||||
-rw-r--r-- | src/common/IPLocation/IPLocation.cpp | 63 | ||||
-rw-r--r-- | src/common/IPLocation/IPLocation.h | 13 |
5 files changed, 59 insertions, 26 deletions
diff --git a/src/common/Asio/IpAddress.h b/src/common/Asio/IpAddress.h index 22af8bbfd41..7d85b0028ac 100644 --- a/src/common/Asio/IpAddress.h +++ b/src/common/Asio/IpAddress.h @@ -28,6 +28,7 @@ namespace Trinity using boost::asio::ip::make_address; using boost::asio::ip::make_address_v4; using boost::asio::ip::make_address_v6; + using boost::asio::ip::v4_mapped_t::v4_mapped; inline uint32 address_to_uint(boost::asio::ip::address_v4 const& address) { return address.to_uint(); } } } diff --git a/src/common/Cryptography/BigNumber.cpp b/src/common/Cryptography/BigNumber.cpp index f220ca319be..66071006a7f 100644 --- a/src/common/Cryptography/BigNumber.cpp +++ b/src/common/Cryptography/BigNumber.cpp @@ -61,6 +61,12 @@ void BigNumber::SetBinary(uint8 const* bytes, int32 len, bool littleEndian) BN_bin2bn(bytes, len, _bn); } +bool BigNumber::SetDecStr(char const* str) +{ + int n = BN_dec2bn(&_bn, str); + return n > 0; +} + bool BigNumber::SetHexStr(char const* str) { int n = BN_hex2bn(&_bn, str); diff --git a/src/common/Cryptography/BigNumber.h b/src/common/Cryptography/BigNumber.h index 3ec6cc65590..3815339d9cf 100644 --- a/src/common/Cryptography/BigNumber.h +++ b/src/common/Cryptography/BigNumber.h @@ -46,6 +46,8 @@ class TC_COMMON_API BigNumber void SetBinary(uint8 const* bytes, int32 len, bool littleEndian = true); template <typename Container> auto SetBinary(Container const& c, bool littleEndian = true) -> std::enable_if_t<!std::is_pointer_v<std::decay_t<Container>>> { SetBinary(std::data(c), std::size(c), littleEndian); } + bool SetDecStr(char const* str); + bool SetDecStr(std::string const& str) { return SetDecStr(str.c_str()); } bool SetHexStr(char const* str); bool SetHexStr(std::string const& str) { return SetHexStr(str.c_str()); } diff --git a/src/common/IPLocation/IPLocation.cpp b/src/common/IPLocation/IPLocation.cpp index 7c6bb455e22..72383bd3554 100644 --- a/src/common/IPLocation/IPLocation.cpp +++ b/src/common/IPLocation/IPLocation.cpp @@ -16,22 +16,17 @@ */ #include "IPLocation.h" +#include "BigNumber.h" #include "Config.h" #include "Errors.h" #include "IpAddress.h" #include "Log.h" -#include "StringConvert.h" #include "Util.h" #include <algorithm> #include <fstream> -IpLocationStore::IpLocationStore() -{ -} - -IpLocationStore::~IpLocationStore() -{ -} +IpLocationStore::IpLocationStore() = default; +IpLocationStore::~IpLocationStore() = default; void IpLocationStore::Load() { @@ -60,6 +55,21 @@ void IpLocationStore::Load() std::string ipTo; std::string countryCode; std::string countryName; + BigNumber bnParser; + BigNumber ipv4Max(0xFFFFFFFF); + BigNumber ipv6MappedMask(0xFFFF); + ipv6MappedMask <<= 32; + + auto parseStringToIPv6 = [&](std::string const& str) -> Optional<std::array<uint8, 16>> + { + bnParser.SetDecStr(str); + if (!bnParser.SetDecStr(str)) + return {}; + // convert ipv4 to ipv6 v4 mapped value + if (bnParser <= ipv4Max) + bnParser += ipv6MappedMask; + return bnParser.ToByteArray<16>(false); + }; while (databaseFile.good()) { @@ -74,31 +84,33 @@ void IpLocationStore::Load() break; // Remove new lines and return - countryName.erase(std::remove(countryName.begin(), countryName.end(), '\r'), countryName.end()); - countryName.erase(std::remove(countryName.begin(), countryName.end(), '\n'), countryName.end()); + std::erase_if(countryName, [](char c) { return c == '\r' || c == '\n'; }); // Remove quotation marks - ipFrom.erase(std::remove(ipFrom.begin(), ipFrom.end(), '"'), ipFrom.end()); - ipTo.erase(std::remove(ipTo.begin(), ipTo.end(), '"'), ipTo.end()); - countryCode.erase(std::remove(countryCode.begin(), countryCode.end(), '"'), countryCode.end()); - countryName.erase(std::remove(countryName.begin(), countryName.end(), '"'), countryName.end()); + std::erase(ipFrom, '"'); + std::erase(ipTo, '"'); + std::erase(countryCode, '"'); + std::erase(countryName, '"'); + + if (countryCode == "-") + continue; // Convert country code to lowercase strToLower(countryCode); - Optional<uint32> from = Trinity::StringTo<uint32>(ipFrom); + Optional<std::array<uint8, 16>> from = parseStringToIPv6(ipFrom); if (!from) continue; - Optional<uint32> to = Trinity::StringTo<uint32>(ipTo); + Optional<std::array<uint8, 16>> to = parseStringToIPv6(ipTo); if (!to) continue; _ipLocationStore.emplace_back(*from, *to, std::move(countryCode), std::move(countryName)); } - std::sort(_ipLocationStore.begin(), _ipLocationStore.end(), [](IpLocationRecord const& a, IpLocationRecord const& b) { return a.IpFrom < b.IpFrom; }); - ASSERT(std::is_sorted(_ipLocationStore.begin(), _ipLocationStore.end(), [](IpLocationRecord const& a, IpLocationRecord const& b) { return a.IpFrom < b.IpTo; }), + std::ranges::sort(_ipLocationStore, {}, &IpLocationRecord::IpFrom); + ASSERT(std::ranges::is_sorted(_ipLocationStore, [](IpLocationRecord const& a, IpLocationRecord const& b) { return a.IpFrom < b.IpTo; }), "Overlapping IP ranges detected in database file"); databaseFile.close(); @@ -109,16 +121,23 @@ void IpLocationStore::Load() IpLocationRecord const* IpLocationStore::GetLocationRecord(std::string const& ipAddress) const { boost::system::error_code error; - boost::asio::ip::address_v4 address = Trinity::Net::make_address_v4(ipAddress, error); + boost::asio::ip::address address = Trinity::Net::make_address(ipAddress, error); if (error) return nullptr; - uint32 ip = Trinity::Net::address_to_uint(address); - auto itr = std::upper_bound(_ipLocationStore.begin(), _ipLocationStore.end(), ip, [](uint32 ip, IpLocationRecord const& loc) { return ip < loc.IpTo; }); + std::array<uint8, 16> bytes = [&]() -> std::array<uint8, 16> + { + if (address.is_v6()) + return address.to_v6().to_bytes(); + if (address.is_v4()) + return Trinity::Net::make_address_v6(Trinity::Net::v4_mapped, address.to_v4()).to_bytes(); + return {}; + }(); + auto itr = std::ranges::upper_bound(_ipLocationStore, bytes, {}, &IpLocationRecord::IpTo); if (itr == _ipLocationStore.end()) return nullptr; - if (ip < itr->IpFrom) + if (bytes < itr->IpFrom) return nullptr; return &(*itr); diff --git a/src/common/IPLocation/IPLocation.h b/src/common/IPLocation/IPLocation.h index ba97e5caa96..5471948586b 100644 --- a/src/common/IPLocation/IPLocation.h +++ b/src/common/IPLocation/IPLocation.h @@ -19,17 +19,18 @@ #define IPLOCATION_H #include "Define.h" +#include <array> #include <string> #include <vector> struct IpLocationRecord { - IpLocationRecord() : IpFrom(0), IpTo(0) { } - IpLocationRecord(uint32 ipFrom, uint32 ipTo, std::string countryCode, std::string countryName) + IpLocationRecord() : IpFrom(), IpTo() { } + IpLocationRecord(std::array<uint8, 16> ipFrom, std::array<uint8, 16> ipTo, std::string&& countryCode, std::string&& countryName) : IpFrom(ipFrom), IpTo(ipTo), CountryCode(std::move(countryCode)), CountryName(std::move(countryName)) { } - uint32 IpFrom; - uint32 IpTo; + std::array<uint8, 16> IpFrom; + std::array<uint8, 16> IpTo; std::string CountryCode; std::string CountryName; }; @@ -38,6 +39,10 @@ class TC_COMMON_API IpLocationStore { public: IpLocationStore(); + IpLocationStore(IpLocationStore const&) = delete; + IpLocationStore(IpLocationStore&&) = delete; + IpLocationStore& operator=(IpLocationStore const&) = delete; + IpLocationStore& operator=(IpLocationStore&&) = delete; ~IpLocationStore(); static IpLocationStore* Instance(); |