aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/IPLocation/IPLocation.cpp125
-rw-r--r--src/common/IPLocation/IPLocation.h43
-rw-r--r--src/server/authserver/Main.cpp4
-rw-r--r--src/server/authserver/Server/AuthSession.cpp8
-rw-r--r--src/server/authserver/authserver.conf.dist10
-rw-r--r--src/server/database/Database/Implementation/LoginDatabase.cpp6
-rw-r--r--src/server/database/Database/Implementation/LoginDatabase.h2
-rw-r--r--src/server/game/Server/WorldSocket.cpp8
-rw-r--r--src/server/game/World/World.cpp4
-rw-r--r--src/server/scripts/Commands/cs_account.cpp18
-rw-r--r--src/server/scripts/Commands/cs_misc.cpp12
-rw-r--r--src/server/worldserver/worldserver.conf.dist10
12 files changed, 214 insertions, 36 deletions
diff --git a/src/common/IPLocation/IPLocation.cpp b/src/common/IPLocation/IPLocation.cpp
new file mode 100644
index 00000000000..3db2394fb2c
--- /dev/null
+++ b/src/common/IPLocation/IPLocation.cpp
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2008-2018 TrinityCore <https://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "IPLocation.h"
+#include "Config.h"
+#include "IpAddress.h"
+#include "Log.h"
+#include <fstream>
+#include <iostream>
+
+IpLocationStore::IpLocationStore()
+{
+}
+
+IpLocationStore::~IpLocationStore()
+{
+}
+
+void IpLocationStore::Load()
+{
+ std::string value = sConfigMgr->GetStringDefault("IPLocationFile", ".");
+ if (value.empty())
+ return;
+
+ _ipLocationStore.clear();
+ TC_LOG_INFO("server.loading", "Loading IP Location Database...");
+
+ // Default folder
+ if (!value.compare("."))
+ value.append("/IP2LOCATION-LITE-DB1.CSV");
+
+ // Check file name
+ if (value.find("IP2LOCATION-LITE-DB1.CSV") == std::string::npos)
+ {
+ TC_LOG_ERROR("server.loading", "IPLocation:: File name is not valid, must be IP2LOCATION-LITE-DB1.CSV");
+ return;
+ }
+
+ // Check if file exists
+ std::ifstream ipfile(value);
+ if (!ipfile)
+ {
+ TC_LOG_ERROR("server.loading", "IPLocation:: No database file exists.");
+ return;
+ }
+
+ if (!ipfile.is_open())
+ {
+ TC_LOG_ERROR("server.loading", "IPLocation:: The file can not be opened.");
+ return;
+ }
+
+ std::string ip_from;
+ std::string ip_to;
+ std::string country_code;
+ std::string country_name;
+
+ while (ipfile.good())
+ {
+ // Read lines
+ std::getline(ipfile, ip_from, ',');
+ std::getline(ipfile, ip_to, ',');
+ std::getline(ipfile, country_code, ',');
+ std::getline(ipfile, country_name, '\n');
+
+ // Remove new lines and return
+ country_name.erase(std::remove(country_name.begin(), country_name.end(), '\r'), country_name.end());
+ country_name.erase(std::remove(country_name.begin(), country_name.end(), '\n'), country_name.end());
+
+ // Remove quotation marks
+ ip_from.erase(std::remove(ip_from.begin(), ip_from.end(), '"'), ip_from.end());
+ ip_to.erase(std::remove(ip_to.begin(), ip_to.end(), '"'), ip_to.end());
+ country_code.erase(std::remove(country_code.begin(), country_code.end(), '"'), country_code.end());
+ country_name.erase(std::remove(country_name.begin(), country_name.end(), '"'), country_name.end());
+
+ // Convert country code to lowercase
+ std::transform(country_code.begin(), country_code.end(), country_code.begin(), ::tolower);
+
+ IpLocationRecord data;
+ data.ip_from = (uint32)atoull(ip_from.c_str());
+ data.ip_to = (uint32)atoull(ip_to.c_str());
+ data.country_code = country_code;
+ data.country_name = country_name;
+
+ _ipLocationStore.push_back(data);
+ }
+
+ std::sort(_ipLocationStore.begin(), _ipLocationStore.end(), [](IpLocationRecord const& a, IpLocationRecord const& b) { return a.ip_from < b.ip_from; });
+
+ ipfile.close();
+
+ TC_LOG_INFO("server.loading", ">> Loaded %u entries.", uint32(_ipLocationStore.size()));
+}
+
+IpLocationRecord* IpLocationStore::GetData(std::string const& ipAddress)
+{
+ if (_ipLocationStore.empty())
+ return nullptr;
+
+ uint32 ip = Trinity::Net::address_to_uint(Trinity::Net::make_address_v4(ipAddress));
+ auto itr = std::upper_bound(_ipLocationStore.begin(), _ipLocationStore.end(), ip, [](uint32 ip, IpLocationRecord const& loc) { return loc.ip_to >= ip; });
+ ASSERT(&(*itr));
+
+ return &(*itr);
+}
+
+IpLocationStore* IpLocationStore::instance()
+{
+ static IpLocationStore instance;
+ return &instance;
+}
diff --git a/src/common/IPLocation/IPLocation.h b/src/common/IPLocation/IPLocation.h
new file mode 100644
index 00000000000..00d89e1be50
--- /dev/null
+++ b/src/common/IPLocation/IPLocation.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2008-2018 TrinityCore <https://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "Define.h"
+#include <string>
+
+struct IpLocationRecord
+{
+ uint32 ip_from;
+ uint32 ip_to;
+ std::string country_code;
+ std::string country_name;
+};
+
+class TC_COMMON_API IpLocationStore
+{
+ public:
+ IpLocationStore();
+ ~IpLocationStore();
+ static IpLocationStore* instance();
+
+ void Load();
+ IpLocationRecord* GetData(std::string const& ipAddress);
+
+ private:
+ std::vector<IpLocationRecord> _ipLocationStore;
+};
+
+#define sIPLocation IpLocationStore::instance()
diff --git a/src/server/authserver/Main.cpp b/src/server/authserver/Main.cpp
index fa024d324ab..8ed74688372 100644
--- a/src/server/authserver/Main.cpp
+++ b/src/server/authserver/Main.cpp
@@ -31,6 +31,7 @@
#include "DatabaseEnv.h"
#include "DatabaseLoader.h"
#include "IoContext.h"
+#include "IPLocation.h"
#include "GitRevision.h"
#include "MySQLThreading.h"
#include "ProcessPriority.h"
@@ -137,6 +138,9 @@ int main(int argc, char** argv)
if (!StartDB())
return 1;
+ // Load IP Location Database
+ sIPLocation->Load();
+
std::shared_ptr<void> dbHandle(nullptr, [](void*) { StopDB(); });
std::shared_ptr<Trinity::Asio::IoContext> ioContext = std::make_shared<Trinity::Asio::IoContext>();
diff --git a/src/server/authserver/Server/AuthSession.cpp b/src/server/authserver/Server/AuthSession.cpp
index 8cfe4c50c1a..648296b620b 100644
--- a/src/server/authserver/Server/AuthSession.cpp
+++ b/src/server/authserver/Server/AuthSession.cpp
@@ -20,6 +20,7 @@
#include "AuthCodes.h"
#include "Config.h"
#include "Errors.h"
+#include "IPLocation.h"
#include "Log.h"
#include "DatabaseEnv.h"
#include "RealmList.h"
@@ -169,7 +170,6 @@ void AuthSession::Start()
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_IP_INFO);
stmt->setString(0, ip_address);
- stmt->setUInt32(1, inet_addr(ip_address.c_str()));
_queryProcessor.AddQuery(LoginDatabase.AsyncQuery(stmt).WithPreparedCallback(std::bind(&AuthSession::CheckIpCallback, this, std::placeholders::_1)));
}
@@ -195,9 +195,6 @@ void AuthSession::CheckIpCallback(PreparedQueryResult result)
if (fields[0].GetUInt64() != 0)
banned = true;
- if (!fields[1].GetString().empty())
- _ipCountry = fields[1].GetString();
-
} while (result->NextRow());
if (banned)
@@ -344,6 +341,9 @@ void AuthSession::LogonChallengeCallback(PreparedQueryResult result)
}
else
{
+ if (IpLocationRecord* location = sIPLocation->GetData(ipAddress))
+ _ipCountry = location->country_code;
+
TC_LOG_DEBUG("server.authserver", "[AuthChallenge] Account '%s' is not locked to ip", _accountInfo.Login.c_str());
if (_accountInfo.LockCountry.empty() || _accountInfo.LockCountry == "00")
TC_LOG_DEBUG("server.authserver", "[AuthChallenge] Account '%s' is not locked to country", _accountInfo.Login.c_str());
diff --git a/src/server/authserver/authserver.conf.dist b/src/server/authserver/authserver.conf.dist
index 1d3b48839a8..a6e3d4b8f92 100644
--- a/src/server/authserver/authserver.conf.dist
+++ b/src/server/authserver/authserver.conf.dist
@@ -158,6 +158,16 @@ SourceDirectory = ""
MySQLExecutable = ""
#
+# IPLocationFile
+# Description: The path to your IP2Location database CSV file.
+# Example: "C:/Trinity/IP2Location.csv"
+# "/home/trinity/IP2Location.csv"
+# Default: "." - (Current core directory)
+# "" - (Disabled)
+
+IPLocationFile = "."
+
+#
###################################################################################################
###################################################################################################
diff --git a/src/server/database/Database/Implementation/LoginDatabase.cpp b/src/server/database/Database/Implementation/LoginDatabase.cpp
index 2a5c6137e30..932b6c25f66 100644
--- a/src/server/database/Database/Implementation/LoginDatabase.cpp
+++ b/src/server/database/Database/Implementation/LoginDatabase.cpp
@@ -26,9 +26,7 @@ void LoginDatabaseConnection::DoPrepareStatements()
PrepareStatement(LOGIN_SEL_REALMLIST, "SELECT id, name, address, localAddress, localSubnetMask, port, icon, flag, timezone, allowedSecurityLevel, population, gamebuild FROM realmlist WHERE flag <> 3 ORDER BY name", CONNECTION_SYNCH);
PrepareStatement(LOGIN_DEL_EXPIRED_IP_BANS, "DELETE FROM ip_banned WHERE unbandate<>bandate AND unbandate<=UNIX_TIMESTAMP()", CONNECTION_ASYNC);
PrepareStatement(LOGIN_UPD_EXPIRED_ACCOUNT_BANS, "UPDATE account_banned SET active = 0 WHERE active = 1 AND unbandate<>bandate AND unbandate<=UNIX_TIMESTAMP()", CONNECTION_ASYNC);
- PrepareStatement(LOGIN_SEL_IP_INFO, "(SELECT unbandate > UNIX_TIMESTAMP() OR unbandate = bandate AS banned, NULL as country FROM ip_banned WHERE ip = ?) "
- "UNION "
- "(SELECT NULL AS banned, country FROM ip2nation WHERE INET_NTOA(ip) = ?)", CONNECTION_ASYNC);
+ PrepareStatement(LOGIN_SEL_IP_INFO, "SELECT unbandate > UNIX_TIMESTAMP() OR unbandate = bandate AS banned, NULL as country FROM ip_banned WHERE ip = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_INS_IP_AUTO_BANNED, "INSERT INTO ip_banned (ip, bandate, unbandate, bannedby, banreason) VALUES (?, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()+?, 'Trinity Auth', 'Failed login autoban')", CONNECTION_ASYNC);
PrepareStatement(LOGIN_SEL_IP_BANNED_ALL, "SELECT ip, bandate, unbandate, bannedby, banreason FROM ip_banned WHERE (bandate = unbandate OR unbandate > UNIX_TIMESTAMP()) ORDER BY unbandate", CONNECTION_SYNCH);
PrepareStatement(LOGIN_SEL_IP_BANNED_BY_IP, "SELECT ip, bandate, unbandate, bannedby, banreason FROM ip_banned WHERE (bandate = unbandate OR unbandate > UNIX_TIMESTAMP()) AND ip LIKE CONCAT('%%', ?, '%%') ORDER BY unbandate", CONNECTION_SYNCH);
@@ -44,7 +42,6 @@ void LoginDatabaseConnection::DoPrepareStatements()
PrepareStatement(LOGIN_SEL_RECONNECTCHALLENGE, "SELECT a.id, UPPER(a.username), a.locked, a.lock_country, a.last_ip, a.failed_logins, ab.unbandate > UNIX_TIMESTAMP() OR ab.unbandate = ab.bandate, "
"ab.unbandate = ab.bandate, aa.gmlevel, a.sessionKey "
"FROM account a LEFT JOIN account_access aa ON a.id = aa.id LEFT JOIN account_banned ab ON ab.id = a.id AND ab.active = 1 WHERE a.username = ?", CONNECTION_ASYNC);
- PrepareStatement(LOGIN_SEL_LOGON_COUNTRY, "SELECT country FROM ip2nation WHERE ip < ? ORDER BY ip DESC LIMIT 0,1", CONNECTION_SYNCH);
PrepareStatement(LOGIN_UPD_FAILEDLOGINS, "UPDATE account SET failed_logins = failed_logins + 1 WHERE username = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_SEL_ACCOUNT_ID_BY_NAME, "SELECT id FROM account WHERE username = ?", CONNECTION_SYNCH);
PrepareStatement(LOGIN_SEL_ACCOUNT_LIST_BY_NAME, "SELECT id, username FROM account WHERE username = ?", CONNECTION_SYNCH);
@@ -100,7 +97,6 @@ void LoginDatabaseConnection::DoPrepareStatements()
PrepareStatement(LOGIN_SEL_LAST_IP, "SELECT last_ip FROM account WHERE id = ?", CONNECTION_SYNCH);
PrepareStatement(LOGIN_SEL_REALMLIST_SECURITY_LEVEL, "SELECT allowedSecurityLevel from realmlist WHERE id = ?", CONNECTION_SYNCH);
PrepareStatement(LOGIN_DEL_ACCOUNT, "DELETE FROM account WHERE id = ?", CONNECTION_ASYNC);
- PrepareStatement(LOGIN_SEL_IP2NATION_COUNTRY, "SELECT c.country FROM ip2nationCountries c, ip2nation i WHERE i.ip < ? AND c.code = i.country ORDER BY i.ip DESC LIMIT 0,1", CONNECTION_SYNCH);
PrepareStatement(LOGIN_SEL_AUTOBROADCAST, "SELECT id, weight, text FROM autobroadcast WHERE realmid = ? OR realmid = -1", CONNECTION_SYNCH);
PrepareStatement(LOGIN_GET_EMAIL_BY_ID, "SELECT email FROM account WHERE id = ?", CONNECTION_SYNCH);
// 0: uint32, 1: uint32, 2: uint8, 3: uint32, 4: string // Complete name: "Login_Insert_AccountLoginDeLete_IP_Logging"
diff --git a/src/server/database/Database/Implementation/LoginDatabase.h b/src/server/database/Database/Implementation/LoginDatabase.h
index a6dff15dc92..1d55d343830 100644
--- a/src/server/database/Database/Implementation/LoginDatabase.h
+++ b/src/server/database/Database/Implementation/LoginDatabase.h
@@ -41,7 +41,6 @@ enum LoginDatabaseStatements : uint32
LOGIN_UPD_LOGONPROOF,
LOGIN_SEL_LOGONCHALLENGE,
LOGIN_SEL_RECONNECTCHALLENGE,
- LOGIN_SEL_LOGON_COUNTRY,
LOGIN_UPD_FAILEDLOGINS,
LOGIN_SEL_ACCOUNT_ID_BY_NAME,
LOGIN_SEL_ACCOUNT_LIST_BY_NAME,
@@ -95,7 +94,6 @@ enum LoginDatabaseStatements : uint32
LOGIN_SEL_ACCOUNT_WHOIS,
LOGIN_SEL_REALMLIST_SECURITY_LEVEL,
LOGIN_DEL_ACCOUNT,
- LOGIN_SEL_IP2NATION_COUNTRY,
LOGIN_SEL_AUTOBROADCAST,
LOGIN_SEL_LAST_ATTEMPT_IP,
LOGIN_SEL_LAST_IP,
diff --git a/src/server/game/Server/WorldSocket.cpp b/src/server/game/Server/WorldSocket.cpp
index 5cb8e056b01..7048879b9d4 100644
--- a/src/server/game/Server/WorldSocket.cpp
+++ b/src/server/game/Server/WorldSocket.cpp
@@ -20,6 +20,7 @@
#include "BigNumber.h"
#include "DatabaseEnv.h"
#include "GameTime.h"
+#include "IPLocation.h"
#include "Opcodes.h"
#include "PacketLog.h"
#include "Random.h"
@@ -55,7 +56,6 @@ void WorldSocket::Start()
std::string ip_address = GetRemoteIpAddress().to_string();
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_IP_INFO);
stmt->setString(0, ip_address);
- stmt->setUInt32(1, inet_addr(ip_address.c_str()));
_queryProcessor.AddQuery(LoginDatabase.AsyncQuery(stmt).WithPreparedCallback(std::bind(&WorldSocket::CheckIpCallback, this, std::placeholders::_1)));
}
@@ -71,9 +71,6 @@ void WorldSocket::CheckIpCallback(PreparedQueryResult result)
if (fields[0].GetUInt64() != 0)
banned = true;
- if (!fields[1].GetString().empty())
- _ipCountry = fields[1].GetString();
-
} while (result->NextRow());
if (banned)
@@ -523,6 +520,9 @@ void WorldSocket::HandleAuthSessionCallback(std::shared_ptr<AuthSession> authSes
return;
}
+ if (IpLocationRecord* location = sIPLocation->GetData(address))
+ _ipCountry = location->country_code;
+
///- Re-check ip locking (same check as in auth).
if (account.IsLockedToIP)
{
diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp
index 2fa94f57ca3..cab8c786289 100644
--- a/src/server/game/World/World.cpp
+++ b/src/server/game/World/World.cpp
@@ -48,6 +48,7 @@
#include "GroupMgr.h"
#include "GuildMgr.h"
#include "InstanceSaveMgr.h"
+#include "IPLocation.h"
#include "Language.h"
#include "LFGMgr.h"
#include "Log.h"
@@ -1555,6 +1556,9 @@ void World::SetInitialWorldSettings()
// Load cinematic cameras
LoadM2Cameras(m_dataPath);
+ // Load IP Location Database
+ sIPLocation->Load();
+
std::vector<uint32> mapIds;
for (uint32 mapId = 0; mapId < sMapStore.GetNumRows(); mapId++)
if (sMapStore.LookupEntry(mapId))
diff --git a/src/server/scripts/Commands/cs_account.cpp b/src/server/scripts/Commands/cs_account.cpp
index bd0ae263d68..1aa32fff384 100644
--- a/src/server/scripts/Commands/cs_account.cpp
+++ b/src/server/scripts/Commands/cs_account.cpp
@@ -26,6 +26,7 @@ EndScriptData */
#include "Chat.h"
#include "DatabaseEnv.h"
#include "IpAddress.h"
+#include "IPLocation.h"
#include "Language.h"
#include "Log.h"
#include "Player.h"
@@ -290,25 +291,18 @@ public:
{
if (param == "on")
{
- PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_LOGON_COUNTRY);
- uint32 ip = Trinity::Net::address_to_uint(Trinity::Net::make_address_v4(handler->GetSession()->GetRemoteAddress()));
- EndianConvertReverse(ip);
- stmt->setUInt32(0, ip);
- PreparedQueryResult result = LoginDatabase.Query(stmt);
- if (result)
+ if (IpLocationRecord* location = sIPLocation->GetData(handler->GetSession()->GetRemoteAddress()))
{
- Field* fields = result->Fetch();
- std::string country = fields[0].GetString();
- stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_ACCOUNT_LOCK_CONTRY);
- stmt->setString(0, country);
+ PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_ACCOUNT_LOCK_CONTRY);
+ stmt->setString(0, location->country_code);
stmt->setUInt32(1, handler->GetSession()->GetAccountId());
LoginDatabase.Execute(stmt);
handler->PSendSysMessage(LANG_COMMAND_ACCLOCKLOCKED);
}
else
{
- handler->PSendSysMessage("[IP2NATION] Table empty");
- TC_LOG_DEBUG("server.authserver", "[IP2NATION] Table empty");
+ handler->PSendSysMessage("IP2Location] No information");
+ TC_LOG_DEBUG("server.authserver", "IP2Location] No information");
}
}
else if (param == "off")
diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp
index 36a7a00c2da..7a1c9e8738a 100644
--- a/src/server/scripts/Commands/cs_misc.cpp
+++ b/src/server/scripts/Commands/cs_misc.cpp
@@ -28,6 +28,7 @@
#include "GroupMgr.h"
#include "InstanceSaveMgr.h"
#include "IpAddress.h"
+#include "IPLocation.h"
#include "Item.h"
#include "Language.h"
#include "LFG.h"
@@ -1688,17 +1689,10 @@ public:
lastIp = fields[4].GetString();
lastLogin = fields[5].GetString();
- uint32 ip = Trinity::Net::address_to_uint(Trinity::Net::make_address_v4(lastIp));
- EndianConvertReverse(ip);
-
- // If ip2nation table is populated, it displays the country
- stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_IP2NATION_COUNTRY);
- stmt->setUInt32(0, ip);
- if (PreparedQueryResult result2 = LoginDatabase.Query(stmt))
+ if (IpLocationRecord* location = sIPLocation->GetData(lastIp))
{
- Field* fields2 = result2->Fetch();
lastIp.append(" (");
- lastIp.append(fields2[0].GetString());
+ lastIp.append(location->country_name);
lastIp.append(")");
}
}
diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist
index 325a1bbac2d..49389b512ac 100644
--- a/src/server/worldserver/worldserver.conf.dist
+++ b/src/server/worldserver/worldserver.conf.dist
@@ -209,6 +209,16 @@ SourceDirectory = ""
MySQLExecutable = ""
#
+# IPLocationFile
+# Description: The path to your IP2Location database CSV file.
+# Example: "C:/Trinity/IP2Location.csv"
+# "/home/trinity/IP2Location.csv"
+# Default: "." - (Current core directory)
+# "" - (Disabled)
+
+IPLocationFile = "."
+
+#
###################################################################################################
###################################################################################################