aboutsummaryrefslogtreecommitdiff
path: root/src/common/IPLocation/IPLocation.cpp
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2024-11-14 00:13:18 +0100
committerOvahlord <dreadkiller@gmx.de>2024-11-14 00:30:53 +0100
commitdcc59a3d9998f033dfabab81d334382ceb7e98b0 (patch)
tree46a2dc7ce0bc26013284bc34507c297410bc2a7e /src/common/IPLocation/IPLocation.cpp
parent36bece3fc53d1535abd38217908c3042c68dfa2a (diff)
Core/Misc: Support IPv6 ip2location
(cherry picked from commit c522e5f4c22b53b349b05486fa28cdf58f4ffc26)
Diffstat (limited to 'src/common/IPLocation/IPLocation.cpp')
-rw-r--r--src/common/IPLocation/IPLocation.cpp63
1 files changed, 41 insertions, 22 deletions
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);