aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/common/Asio/IpAddress.h1
-rw-r--r--src/common/Cryptography/BigNumber.cpp6
-rw-r--r--src/common/Cryptography/BigNumber.h2
-rw-r--r--src/common/IPLocation/IPLocation.cpp63
-rw-r--r--src/common/IPLocation/IPLocation.h13
-rw-r--r--src/server/game/Server/WorldSession.cpp2
6 files changed, 60 insertions, 27 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();
diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp
index 0794ebf57dc..a70653138d6 100644
--- a/src/server/game/Server/WorldSession.cpp
+++ b/src/server/game/Server/WorldSession.cpp
@@ -827,7 +827,7 @@ void WorldSession::SendConnectToInstance(WorldPackets::Auth::ConnectToSerial ser
}
else if (v6.is_v4_mapped())
{
- memcpy(connectTo.Payload.Where.Address.V4.data(), Trinity::Net::make_address_v4(boost::asio::ip::v4_mapped, v6).to_bytes().data(), 4);
+ memcpy(connectTo.Payload.Where.Address.V4.data(), Trinity::Net::make_address_v4(Trinity::Net::v4_mapped, v6).to_bytes().data(), 4);
connectTo.Payload.Where.Type = WorldPackets::Auth::ConnectTo::IPv4;
}
else