summaryrefslogtreecommitdiff
path: root/src/login_sql
diff options
context:
space:
mode:
authorultramage <ultramage@54d463be-8e91-2dee-dedb-b68131a5f0ec>2007-04-05 18:49:57 +0000
committerultramage <ultramage@54d463be-8e91-2dee-dedb-b68131a5f0ec>2007-04-05 18:49:57 +0000
commit88a5d0cdda513357496b9d53878618e1620f47e8 (patch)
tree4f3c2bedbac4b715ff783de5e1c8d1aefe4395af /src/login_sql
parenta7fd6bfe9bcce1862b554f5841d9ff1aedf473e3 (diff)
downloadhercules-88a5d0cdda513357496b9d53878618e1620f47e8.tar.gz
hercules-88a5d0cdda513357496b9d53878618e1620f47e8.tar.bz2
hercules-88a5d0cdda513357496b9d53878618e1620f47e8.tar.xz
hercules-88a5d0cdda513357496b9d53878618e1620f47e8.zip
* Made a crazy attempt to at least partially synchronize login&char code
* Major edit to the way the servers handle ip addresses, making them obey the "host byte order inside, network byte order outside" rule - hopefully covered all entry- and exit-points for IP address data - discovered several places where Gravity's client breaks the convention, will need to come up with a suitable countermeasure for that - other than that, the code should be portable, except for printing and ipban mask testing (those still assume a specific byte order) - tested both txt and sql in all usual situations; tested single- and multi-server setups, all seems to work (but watch out for hidden bugs!) git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@10162 54d463be-8e91-2dee-dedb-b68131a5f0ec
Diffstat (limited to 'src/login_sql')
-rw-r--r--src/login_sql/login.c361
-rw-r--r--src/login_sql/login.h4
2 files changed, 182 insertions, 183 deletions
diff --git a/src/login_sql/login.c b/src/login_sql/login.c
index fe92c3a96..cc50e560a 100644
--- a/src/login_sql/login.c
+++ b/src/login_sql/login.c
@@ -40,7 +40,7 @@
struct Login_Config {
- in_addr_t login_ip; // the address to bind to
+ uint32 login_ip; // the address to bind to
unsigned short login_port; // the port to bind to
bool log_login; // whether to log login server actions or not
char date_format[32]; // date format used in messages
@@ -71,17 +71,17 @@ struct mmo_char_server server[MAX_SERVERS]; // char server data
// Advanced subnet check [LuzZza]
struct _subnet {
- long subnet;
- long mask;
- long char_ip;
- long map_ip;
+ uint32 subnet;
+ uint32 mask;
+ uint32 char_ip;
+ uint32 map_ip;
} subnet[16];
int subnet_count = 0;
struct gm_account* gm_account_db = NULL;
-int GM_num = 0; // number of gm accounts
+unsigned int GM_num = 0; // number of gm accounts
//Account registration flood protection [Kevin]
int allowed_regs = 1;
@@ -118,7 +118,9 @@ char login_db_level[256] = "level";
#define AUTH_FIFO_SIZE 256
struct {
int account_id,login_id1,login_id2;
- int ip,sex,delflag;
+ uint32 ip;
+ char sex;
+ bool delflag;
} auth_fifo[AUTH_FIFO_SIZE];
int auth_fifo_pos = 0;
@@ -235,12 +237,13 @@ void read_gm_account(void)
//-----------------------------------------------------
void send_GM_accounts(int fd)
{
- int i;
+ unsigned int i;
unsigned char buf[32767];
int len;
if(!login_config.login_gm_read)
return;
+
len = 4;
WBUFW(buf,0) = 0x2732;
for(i = 0; i < GM_num; i++)
@@ -254,16 +257,17 @@ void send_GM_accounts(int fd)
break;
}
}
- WBUFW(buf,2) = len;
- if (fd == -1)
- charif_sendallwos(-1, buf, len);
- else
- {
- WFIFOHEAD(fd, len);
- memcpy(WFIFOP(fd,0), buf, len);
- WFIFOSET(fd, len);
- }
- return;
+
+ WBUFW(buf,2) = len;
+ if (fd == -1)
+ charif_sendallwos(-1, buf, len);
+ else
+ {
+ WFIFOHEAD(fd, len);
+ memcpy(WFIFOP(fd,0), buf, len);
+ WFIFOSET(fd, len);
+ }
+ return;
}
//---------------------------------------------------
@@ -497,20 +501,20 @@ int mmo_auth_new(struct mmo_account* account, char sex)
return 0;
}
-// Send to char
+//--------------------------------------------------------------------
+// Packet send to all char-servers, except one (wos: without our self)
+//--------------------------------------------------------------------
int charif_sendallwos(int sfd, unsigned char *buf, unsigned int len)
{
- int i, c;
- int fd;
+ int i, c, fd;
- c = 0;
- for(i = 0; i < MAX_SERVERS; i++) {
+ for(i = 0, c = 0; i < MAX_SERVERS; i++) {
if ((fd = server_fd[i]) > 0 && fd != sfd) {
- WFIFOHEAD(fd,len);
+ WFIFOHEAD(fd, len);
if (WFIFOSPACE(fd) < len) //Increase buffer size.
realloc_writefifo(fd, len);
memcpy(WFIFOP(fd,0), buf, len);
- WFIFOSET(fd,len);
+ WFIFOSET(fd, len);
c++;
}
}
@@ -532,8 +536,9 @@ int mmo_auth(struct mmo_account* account, int fd)
char md5str[64], md5bin[32];
char ip[16];
- unsigned char* sin_addr = (unsigned char *)&session[fd]->client_addr.sin_addr.s_addr;
- sprintf(ip, "%d.%d.%d.%d", sin_addr[0], sin_addr[1], sin_addr[2], sin_addr[3]);
+ uint32 ipl = session[fd]->client_addr;
+ uint8* sin_addr = (uint8*)&ipl;
+ sprintf(ip, "%d.%d.%d.%d", sin_addr[3], sin_addr[2], sin_addr[1], sin_addr[0]);
// DNS Blacklist check
if(login_config.use_dnsbl)
@@ -543,7 +548,7 @@ int mmo_auth(struct mmo_account* account, int fd)
char *dnsbl_serv;
bool matched = false;
- sprintf(r_ip, "%d.%d.%d.%d", sin_addr[3], sin_addr[2], sin_addr[1], sin_addr[0]);
+ sprintf(r_ip, "%d.%d.%d.%d", sin_addr[0], sin_addr[1], sin_addr[2], sin_addr[3]);
for (dnsbl_serv = strtok(login_config.dnsbl_servs,","); dnsbl_serv != NULL; dnsbl_serv = strtok(NULL,","))
{
@@ -720,9 +725,9 @@ int mmo_auth(struct mmo_account* account, int fd)
if (login_config.online_check) {
struct online_login_data* data = idb_get(online_db,account->account_id);
- unsigned char buf[8];
if (data && data->char_server > -1) {
//Request char servers to kick this account out. [Skotlex]
+ unsigned char buf[8];
ShowNotice("User [%s] is already online - Rejected.\n",account->userid);
WBUFW(buf,0) = 0x2734;
WBUFL(buf,2) = account->account_id;
@@ -764,19 +769,18 @@ static int online_db_setoffline(DBKey key, void* data, va_list ap)
return 0;
}
-//-----------------------------------------------------
-// char-server packet parse
-//-----------------------------------------------------
+//--------------------------------
+// Packet parsing for char-servers
+//--------------------------------
int parse_fromchar(int fd)
{
int i, id;
- unsigned char *p = (unsigned char *) &session[fd]->client_addr.sin_addr.s_addr;
- unsigned long ipl = session[fd]->client_addr.sin_addr.s_addr;
+ uint32 ipl = session[fd]->client_addr;
char ip[16];
RFIFOHEAD(fd);
- sprintf(ip, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
+ ip2str(ipl, ip);
for(id = 0; id < MAX_SERVERS; id++)
if (server_fd[id] == fd)
@@ -802,14 +806,14 @@ int parse_fromchar(int fd)
return 0;
}
- while(RFIFOREST(fd) >= 2) {
-// printf("char_parse: %d %d packet case=%x\n", fd, RFIFOREST(fd), RFIFOW(fd, 0));
+ while (RFIFOREST(fd) >= 2) {
switch (RFIFOW(fd,0)) {
- case 0x2709:
+
+ case 0x2709: // request from map-server via char-server to reload GM accounts
if (login_config.log_login)
{
- sprintf(tmpsql,"INSERT DELAYED INTO `%s`(`time`,`ip`,`user`,`log`) VALUES (NOW(), '%u', '%s', 'GM reload request')", loginlog_db, (unsigned int)ntohl(ipl),server[id].name);
+ sprintf(tmpsql,"INSERT DELAYED INTO `%s`(`time`,`ip`,`user`,`log`) VALUES (NOW(), '%u', '%s', 'GM reload request')", loginlog_db, ipl, server[id].name);
if (mysql_query(&mysql_handle, tmpsql)) {
ShowSQL("DB error - %s\n",mysql_error(&mysql_handle));
ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql);
@@ -821,7 +825,7 @@ int parse_fromchar(int fd)
RFIFOSKIP(fd,2);
break;
- case 0x2712:
+ case 0x2712: // request from char-server to authenticate an account
if (RFIFOREST(fd) < 19)
return 0;
{
@@ -833,7 +837,7 @@ int parse_fromchar(int fd)
auth_fifo[i].login_id1 == RFIFOL(fd,6) &&
auth_fifo[i].login_id2 == RFIFOL(fd,10) && // relate to the versions higher than 18
auth_fifo[i].sex == RFIFOB(fd,14) &&
- auth_fifo[i].ip == RFIFOL(fd,15) &&
+ auth_fifo[i].ip == ntohl(RFIFOL(fd,15)) &&
!auth_fifo[i].delflag)
{
auth_fifo[i].delflag = 1;
@@ -869,9 +873,10 @@ int parse_fromchar(int fd)
WFIFOB(fd,6) = 1;
WFIFOSET(fd,51);
}
+ }
RFIFOSKIP(fd,19);
break;
- }
+
case 0x2714:
if (RFIFOREST(fd) < 6)
@@ -897,8 +902,7 @@ int parse_fromchar(int fd)
RFIFOSKIP(fd,6);
break;
- // We receive an e-mail/limited time request, because a player comes back from a map-server to the char-server
- case 0x2716:
+ case 0x2716: // received an e-mail/limited time request, because a player comes back from a map-server to the char-server
if (RFIFOREST(fd) < 6)
return 0;
{
@@ -929,10 +933,8 @@ int parse_fromchar(int fd)
RFIFOSKIP(fd,6);
break;
- case 0x2720: // GM
- if (RFIFOREST(fd) < 4)
- return 0;
- if (RFIFOREST(fd) < RFIFOW(fd,2))
+ case 0x2720: // Request to become a GM (TXT only!)
+ if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2))
return 0;
//oldacc = RFIFOL(fd,4);
ShowWarning("change GM isn't supported in this login server version.\n");
@@ -995,7 +997,7 @@ int parse_fromchar(int fd)
break;
}
- case 0x2724: // Receiving of map-server via char-server a status change resquest (by Yor)
+ case 0x2724: // Receiving of map-server via char-server a status change resquest
if (RFIFOREST(fd) < 10)
return 0;
{
@@ -1029,7 +1031,7 @@ int parse_fromchar(int fd)
break;
}
- case 0x2725: // Receiving of map-server via char-server a ban resquest (by Yor)
+ case 0x2725: // Receiving of map-server via char-server a ban resquest
if (RFIFOREST(fd) < 18)
return 0;
{
@@ -1084,7 +1086,7 @@ int parse_fromchar(int fd)
break;
}
- case 0x2727:
+ case 0x2727: // Change of sex (sex is reversed)
if (RFIFOREST(fd) < 6)
return 0;
{
@@ -1168,10 +1170,9 @@ int parse_fromchar(int fd)
if (buf) aFree(buf);
}
RFIFOSKIP(fd,RFIFOW(fd,2));
- //printf("login: save account_reg (from char)\n");
break;
- case 0x272a: // Receiving of map-server via char-server a unban resquest (by Yor)
+ case 0x272a: // Receiving of map-server via char-server a unban resquest
if (RFIFOREST(fd) < 6)
return 0;
{
@@ -1209,6 +1210,7 @@ int parse_fromchar(int fd)
remove_online_user(RFIFOL(fd,2));
RFIFOSKIP(fd,6);
break;
+
case 0x272d: // Receive list of all online accounts. [Skotlex]
if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2))
return 0;
@@ -1270,10 +1272,8 @@ int parse_fromchar(int fd)
case 0x2736: // WAN IP update from char-server
if (RFIFOREST(fd) < 6)
return 0;
- ShowInfo("Updated IP of Server #%d to %d.%d.%d.%d.\n",id,
- (int)RFIFOB(fd,2),(int)RFIFOB(fd,3),
- (int)RFIFOB(fd,4),(int)RFIFOB(fd,5));
- server[id].ip = RFIFOL(fd,2);
+ server[id].ip = ntohl(RFIFOL(fd,2));
+ ShowInfo("Updated IP of Server #%d to %d.%d.%d.%d.\n",id, CONVIP(server[id].ip));
RFIFOSKIP(fd,6);
break;
@@ -1284,7 +1284,7 @@ int parse_fromchar(int fd)
break;
default:
- ShowError("login: unknown packet %x! (from char).\n", RFIFOW(fd,0));
+ ShowError("parse_fromchar: Unknown packet 0x%x from a char-server! Disconnecting!\n", RFIFOW(fd,0));
session[fd]->eof = 1;
return 0;
}
@@ -1297,12 +1297,12 @@ int parse_fromchar(int fd)
//--------------------------------------------
// Test to know if an IP come from LAN or WAN.
//--------------------------------------------
-int lan_subnetcheck(long p)
+int lan_subnetcheck(uint32 ip)
{
int i;
- for(i=0; i<subnet_count; i++) {
- if(subnet[i].subnet == (p & subnet[i].mask)) {
+ for(i = 0; i < subnet_count; i++) {
+ if(subnet[i].subnet == (ip & subnet[i].mask)) {
return subnet[i].char_ip;
}
}
@@ -1310,14 +1310,11 @@ int lan_subnetcheck(long p)
return 0;
}
-int login_ip_ban_check(unsigned char *p, unsigned long ipl)
+int login_ip_ban_check(uint32 ip)
{
- //ip ban
- //p[0], p[1], p[2], p[3]
- //request DB connection
- //check
+ char* p = (char*)&ip;
sprintf(tmpsql, "SELECT count(*) FROM `ipbanlist` WHERE `list` = '%d.*.*.*' OR `list` = '%d.%d.*.*' OR `list` = '%d.%d.%d.*' OR `list` = '%d.%d.%d.%d'",
- p[0], p[0], p[1], p[0], p[1], p[2], p[0], p[1], p[2], p[3]);
+ p[3], p[3], p[2], p[3], p[2], p[1], p[3], p[2], p[1], p[0]);
if (mysql_query(&mysql_handle, tmpsql)) {
ShowSQL("DB error - %s\n",mysql_error(&mysql_handle));
ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql);
@@ -1338,11 +1335,11 @@ int login_ip_ban_check(unsigned char *p, unsigned long ipl)
}
// ip ban ok.
- ShowInfo("Packet from banned ip : %d.%d.%d.%d\n" RETCODE, p[0], p[1], p[2], p[3]);
+ ShowInfo("Packet from banned ip : %d.%d.%d.%d\n" RETCODE, CONVIP(ip));
if (login_config.log_login)
{
- sprintf(tmpsql,"INSERT DELAYED INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '%u', 'unknown','-3', 'ip banned')", loginlog_db, (unsigned int)ntohl(ipl));
+ sprintf(tmpsql,"INSERT DELAYED INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '%u', 'unknown','-3', 'ip banned')", loginlog_db, ip);
// query
if(mysql_query(&mysql_handle, tmpsql)) {
ShowSQL("DB error - %s\n",mysql_error(&mysql_handle));
@@ -1360,16 +1357,13 @@ int parse_login(int fd)
{
char t_uid[100];
struct mmo_account account;
- long subnet_char_ip;
- int packet_len;
int result, i;
- unsigned char *p = (unsigned char *) &session[fd]->client_addr.sin_addr.s_addr;
- unsigned long ipl = session[fd]->client_addr.sin_addr.s_addr;
+ uint32 ipl = session[fd]->client_addr;
char ip[16];
RFIFOHEAD(fd);
- sprintf(ip, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
+ ip2str(ipl, ip);
memset(&account, 0, sizeof(account));
@@ -1381,9 +1375,9 @@ int parse_login(int fd)
return 0;
}
- while(RFIFOREST(fd)>=2 && !session[fd]->eof){
+ while(RFIFOREST(fd) >= 2) {
- switch(RFIFOW(fd,0)){
+ switch(RFIFOW(fd,0)) {
case 0x200: // New alive packet: structure: 0x200 <account.userid>.24B. used to verify if client is always alive.
if (RFIFOREST(fd) < 26)
return 0;
@@ -1399,18 +1393,22 @@ int parse_login(int fd)
case 0x277: // New login packet
case 0x64: // request client login
case 0x01dd: // request client login with encrypt
+ {
+ int packet_len = RFIFOREST(fd);
- packet_len = RFIFOREST(fd);
-
- //Perform ip-ban check ONLY on login packets
- if (login_config.ipban && login_ip_ban_check(p,ipl))
+ //Perform ip-ban check
+ if (login_config.ipban && login_ip_ban_check(ipl))
{
+ WFIFOHEAD(fd, 23);
+ WFIFOW(fd,0) = 0x6a;
+ WFIFOB(fd,2) = 3; // 3 = Rejected from Server
+ WFIFOSET(fd,23);
RFIFOSKIP(fd,packet_len);
session[fd]->eof = 1;
break;
}
- switch(RFIFOW(fd,0)){
+ switch(RFIFOW(fd, 0)){
case 0x64:
if(packet_len < 55)
return 0;
@@ -1432,7 +1430,6 @@ int parse_login(int fd)
memcpy(account.passwd,RFIFOP(fd, 30),NAME_LENGTH);
account.passwd[23] = '\0';
-// ShowDebug("client connection request %s from %d.%d.%d.%d\n", RFIFOP(fd, 6), p[0], p[1], p[2], p[3]);
#ifdef PASSWORDENC
account.passwdenc= (RFIFOW(fd,0)!=0x01dd)?0:PASSWORDENC;
#else
@@ -1441,7 +1438,7 @@ int parse_login(int fd)
result=mmo_auth(&account, fd);
jstrescapecpy(t_uid,account.userid);
- if(result==-1){
+ if(result==-1) { // auth success
if (login_config.min_level_to_connect > account.level) {
WFIFOHEAD(fd,3);
WFIFOW(fd,0) = 0x81;
@@ -1449,8 +1446,8 @@ int parse_login(int fd)
WFIFOSET(fd,3);
} else {
WFIFOHEAD(fd,47+32*MAX_SERVERS);
- if (p[0] != 127 && login_config.log_login) {
- sprintf(tmpsql,"INSERT DELAYED INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '%u', '%s','100', 'login ok')", loginlog_db, (unsigned int)ntohl(ipl), t_uid);
+ if (login_config.log_login) {
+ sprintf(tmpsql,"INSERT DELAYED INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '%u', '%s','100', 'login ok')", loginlog_db, ipl, t_uid);
//query
if(mysql_query(&mysql_handle, tmpsql)) {
ShowSQL("DB error - %s\n",mysql_error(&mysql_handle));
@@ -1461,15 +1458,14 @@ int parse_login(int fd)
ShowStatus("Connection of the GM (level:%d) account '%s' accepted.\n", account.level, account.userid);
else
ShowStatus("Connection of the account '%s' accepted.\n", account.userid);
- server_num=0;
+
+ server_num = 0;
for(i = 0; i < MAX_SERVERS; i++) {
if (server_fd[i] >= 0) {
// Advanced subnet check [LuzZza]
- if((subnet_char_ip = lan_subnetcheck(ipl)))
- WFIFOL(fd,47+server_num*32) = subnet_char_ip;
- else
- WFIFOL(fd,47+server_num*32) = server[i].ip;
- WFIFOW(fd,47+server_num*32+4) = server[i].port;
+ uint32 subnet_char_ip = lan_subnetcheck(ipl);
+ WFIFOL(fd,47+server_num*32) = (subnet_char_ip) ? htonl(subnet_char_ip) : htonl(server[i].ip);
+ WFIFOW(fd,47+server_num*32+4) = server[i].port; // /!\ must be sent in intel host byte order /!\ (client bug)
memcpy(WFIFOP(fd,47+server_num*32+6), server[i].name, 20);
WFIFOW(fd,47+server_num*32+26) = server[i].users;
WFIFOW(fd,47+server_num*32+28) = server[i].maintenance;
@@ -1477,34 +1473,33 @@ int parse_login(int fd)
server_num++;
}
}
- // if at least 1 char-server
- if (server_num > 0) {
- WFIFOW(fd,0)=0x69;
- WFIFOW(fd,2)=47+32*server_num;
- WFIFOL(fd,4)=account.login_id1;
- WFIFOL(fd,8)=account.account_id;
- WFIFOL(fd,12)=account.login_id2;
- WFIFOL(fd,16)=0;
- //memcpy(WFIFOP(fd,20),account.lastlogin,24);
- WFIFOB(fd,46)=account.sex;
+ if (server_num > 0) { // if at least 1 char-server
+ WFIFOW(fd,0) = 0x69;
+ WFIFOW(fd,2) = 47+32*server_num;
+ WFIFOL(fd,4) = account.login_id1;
+ WFIFOL(fd,8) = account.account_id;
+ WFIFOL(fd,12) = account.login_id2;
+ WFIFOL(fd,16) = 0; // in old version, that was for ip (not more used)
+ //memcpy(WFIFOP(fd,20), account.lastlogin, 24); // in old version, that was for name (not more used)
+ WFIFOB(fd,46) = account.sex;
WFIFOSET(fd,47+32*server_num);
- if(auth_fifo_pos>=AUTH_FIFO_SIZE)
- auth_fifo_pos=0;
- auth_fifo[auth_fifo_pos].account_id=account.account_id;
- auth_fifo[auth_fifo_pos].login_id1=account.login_id1;
- auth_fifo[auth_fifo_pos].login_id2=account.login_id2;
- auth_fifo[auth_fifo_pos].sex=account.sex;
- auth_fifo[auth_fifo_pos].delflag=0;
- auth_fifo[auth_fifo_pos].ip = session[fd]->client_addr.sin_addr.s_addr;
+ if (auth_fifo_pos >= AUTH_FIFO_SIZE)
+ auth_fifo_pos = 0;
+ auth_fifo[auth_fifo_pos].account_id = account.account_id;
+ auth_fifo[auth_fifo_pos].login_id1 = account.login_id1;
+ auth_fifo[auth_fifo_pos].login_id2 = account.login_id2;
+ auth_fifo[auth_fifo_pos].sex = account.sex;
+ auth_fifo[auth_fifo_pos].delflag = 0;
+ auth_fifo[auth_fifo_pos].ip = session[fd]->client_addr;
auth_fifo_pos++;
- } else {
+ } else { // if no char-server, don't send void list of servers, just disconnect the player with proper message
WFIFOW(fd,0) = 0x81;
WFIFOB(fd,2) = 1; // 01 = Server closed
WFIFOSET(fd,3);
}
}
- } else {
- WFIFOHEAD(fd,23);
+ } else { // auth failed
+ WFIFOHEAD(fd, 23);
if (login_config.log_login)
{
const char* error;
@@ -1536,7 +1531,7 @@ int parse_login(int fd)
default : error = "Unknown Error."; break;
}
- sprintf(tmpsql, "INSERT DELAYED INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '%u', '%s', '%d','login failed : %s')", loginlog_db, (unsigned int)ntohl(ipl), t_uid, result, error);
+ sprintf(tmpsql, "INSERT DELAYED INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '%u', '%s', '%d','login failed : %s')", loginlog_db, ipl, t_uid, result, error);
//query
if(mysql_query(&mysql_handle, tmpsql)) {
@@ -1547,7 +1542,7 @@ int parse_login(int fd)
if ((result == 1) && login_config.dynamic_pass_failure_ban && login_config.log_login) { // failed password
sprintf(tmpsql,"SELECT count(*) FROM `%s` WHERE `ip` = '%u' AND `rcode` = '1' AND `time` > NOW() - INTERVAL %d MINUTE",
- loginlog_db,(unsigned int)ntohl(ipl), login_config.dynamic_pass_failure_ban_interval); //how many times filed account? in one ip.
+ loginlog_db, ipl, login_config.dynamic_pass_failure_ban_interval); //how many times filed account? in one ip.
if(mysql_query(&mysql_handle, tmpsql)) {
ShowSQL("DB error - %s\n",mysql_error(&mysql_handle));
ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql);
@@ -1557,7 +1552,8 @@ int parse_login(int fd)
sql_row = sql_res?mysql_fetch_row(sql_res):NULL; //row fetching
if (sql_row && (unsigned int)atoi(sql_row[0]) >= login_config.dynamic_pass_failure_ban_limit ) {
- sprintf(tmpsql,"INSERT INTO `ipbanlist`(`list`,`btime`,`rtime`,`reason`) VALUES ('%d.%d.%d.*', NOW() , NOW() + INTERVAL %d MINUTE ,'Password error ban: %s')", p[0], p[1], p[2], login_config.dynamic_pass_failure_ban_duration, t_uid);
+ uint8* p = (uint8*)&ipl;
+ sprintf(tmpsql,"INSERT INTO `ipbanlist`(`list`,`btime`,`rtime`,`reason`) VALUES ('%d.%d.%d.*', NOW() , NOW() + INTERVAL %d MINUTE ,'Password error ban: %s')", (uint8)p[3], (uint8)p[2], (uint8)p[1], login_config.dynamic_pass_failure_ban_duration, t_uid);
if(mysql_query(&mysql_handle, tmpsql)) {
ShowSQL("DB error - %s\n",mysql_error(&mysql_handle));
ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql);
@@ -1566,7 +1562,8 @@ int parse_login(int fd)
if(sql_res) mysql_free_result(sql_res);
}
else if (result == -2){ //dynamic banned - add ip to ban list.
- sprintf(tmpsql,"INSERT INTO `ipbanlist`(`list`,`btime`,`rtime`,`reason`) VALUES ('%d.%d.%d.*', NOW() , NOW() + INTERVAL 1 MONTH ,'Dynamic banned user id : %s')", p[0], p[1], p[2], t_uid);
+ uint8* p = (uint8*)&ipl;
+ sprintf(tmpsql,"INSERT INTO `ipbanlist`(`list`,`btime`,`rtime`,`reason`) VALUES ('%d.%d.%d.*', NOW() , NOW() + INTERVAL 1 MONTH ,'Dynamic banned user id : %s')", (uint8)p[3], (uint8)p[2], (uint8)p[1], t_uid);
if(mysql_query(&mysql_handle, tmpsql)) {
ShowSQL("DB error - %s\n",mysql_error(&mysql_handle));
ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql);
@@ -1583,21 +1580,24 @@ int parse_login(int fd)
}
sql_res = mysql_store_result(&mysql_handle) ;
sql_row = sql_res?mysql_fetch_row(sql_res):NULL;
+
//cannot connect login failed
- memset(WFIFOP(fd,0),'\0',23);
- WFIFOW(fd,0)=0x6a;
- WFIFOB(fd,2)=result;
+ memset(WFIFOP(fd,0), '\0', 23);
+ WFIFOW(fd,0) = 0x6a;
+ WFIFOB(fd,2) = result;
if (result == 6) { // 6 = Your are Prohibited to log in until %s
char tmpstr[20];
time_t ban_until_time = (sql_row) ? atol(sql_row[0]) : 0;
- strftime(tmpstr, 20, login_config.date_format, localtime(&ban_until_time));
- tmpstr[19] = '\0';
+ strftime(tmpstr, 20, login_config.date_format, localtime(&ban_until_time)); tmpstr[19] = '\0';
strncpy(WFIFOP(fd,3), tmpstr, 20); // ban timestamp goes here
}
WFIFOSET(fd,23);
+
+ if (sql_res) mysql_free_result(sql_res);
}
RFIFOSKIP(fd,packet_len);
break;
+ }
case 0x01db: // request password key
if (session[fd]->session_data) {
@@ -1606,41 +1606,39 @@ int parse_login(int fd)
return 0;
}
{
- WFIFOHEAD(fd,4+md5keylen);
- WFIFOW(fd,0)=0x01dc;
- WFIFOW(fd,2)=4+md5keylen;
- memcpy(WFIFOP(fd,4),md5key,md5keylen);
- WFIFOSET(fd,WFIFOW(fd,2));
RFIFOSKIP(fd,2);
+ WFIFOHEAD(fd, 4 + md5keylen);
+ WFIFOW(fd,0) = 0x01dc;
+ WFIFOW(fd,2) = 4 + md5keylen;
+ memcpy(WFIFOP(fd,4), md5key, md5keylen);
+ WFIFOSET(fd,WFIFOW(fd,2));
}
break;
- case 0x2710: // request Char-server connection
- if(RFIFOREST(fd)<86)
+ case 0x2710: // Connection request of a char-server
+ if (RFIFOREST(fd) < 86)
return 0;
{
char* server_name;
+ uint32 server_ip;
+ uint16 server_port;
+
WFIFOHEAD(fd, 3);
- memcpy(account.userid,RFIFOP(fd, 2),NAME_LENGTH);
- account.userid[23] = '\0';
- memcpy(account.passwd,RFIFOP(fd, 26),NAME_LENGTH);
- account.passwd[23] = '\0';
+ memcpy(account.userid,RFIFOP(fd, 2),NAME_LENGTH); account.userid[23] = '\0';
+ memcpy(account.passwd,RFIFOP(fd, 26),NAME_LENGTH); account.passwd[23] = '\0';
account.passwdenc = 0;
- server_name = (char*)RFIFOP(fd,60);
- server_name[20] = '\0';
- ShowInfo("server connection request %s @ %d.%d.%d.%d:%d (%d.%d.%d.%d)\n",
- server_name, RFIFOB(fd, 54), RFIFOB(fd, 55), RFIFOB(fd, 56), RFIFOB(fd, 57), RFIFOW(fd, 58),
- p[0], p[1], p[2], p[3]);
- jstrescapecpy(t_uid,server_name);
+ server_name = (char*)RFIFOP(fd,60); server_name[20] = '\0';
+ server_ip = ntohl(RFIFOL(fd, 54));
+ server_port = ntohs(RFIFOW(fd, 58));
+ ShowInfo("Connection request of the char-server '%s' @ %d.%d.%d.%d:%d (ip: %s)\n",
+ server_name, CONVIP(server_ip), server_port, ip);
+ jstrescapecpy(t_uid, server_name);
if (login_config.log_login)
{
char t_login[50];
jstrescapecpy(t_login,account.userid);
sprintf(tmpsql,"INSERT DELAYED INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '%u', '%s@%s','100', 'charserver - %s@%d.%d.%d.%d:%d')",
- loginlog_db, (unsigned int)ntohl(ipl),
- t_login, t_uid, t_uid,
- RFIFOB(fd, 54), RFIFOB(fd, 55), RFIFOB(fd, 56), RFIFOB(fd, 57),
- RFIFOW(fd, 58));
+ loginlog_db, ipl, t_login, t_uid, t_uid, CONVIP(server_ip), server_port);
//query
if(mysql_query(&mysql_handle, tmpsql)) {
@@ -1648,19 +1646,18 @@ int parse_login(int fd)
ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql);
}
}
- result = mmo_auth(&account, fd);
- //printf("Result: %d - Sex: %d - Account ID: %d\n",result,account.sex,(int) account.account_id);
- if(result == -1 && account.sex==2 && account.account_id<MAX_SERVERS && server_fd[account.account_id]==-1){
+ result = mmo_auth(&account, fd);
+ if (result == -1 && account.sex == 2 && account.account_id < MAX_SERVERS && server_fd[account.account_id] == -1) {
ShowStatus("Connection of the char-server '%s' accepted.\n", server_name);
memset(&server[account.account_id], 0, sizeof(struct mmo_char_server));
- server[account.account_id].ip=RFIFOL(fd,54);
- server[account.account_id].port=RFIFOW(fd,58);
- memcpy(server[account.account_id].name,server_name,20);
- server[account.account_id].users=0;
- server[account.account_id].maintenance=RFIFOW(fd,82);
- server[account.account_id].new_=RFIFOW(fd,84);
- server_fd[account.account_id]=fd;
+ server[account.account_id].ip = ntohl(RFIFOL(fd,54));
+ server[account.account_id].port = ntohs(RFIFOW(fd,58));
+ memcpy(server[account.account_id].name, server_name, 20);
+ server[account.account_id].users = 0;
+ server[account.account_id].maintenance = RFIFOW(fd,82);
+ server[account.account_id].new_ = RFIFOW(fd,84);
+ server_fd[account.account_id] = fd;
sprintf(tmpsql,"DELETE FROM `sstatus` WHERE `index`='%d'", account.account_id);
//query
if(mysql_query(&mysql_handle, tmpsql)) {
@@ -1675,42 +1672,43 @@ int parse_login(int fd)
ShowSQL("DB error - %s\n",mysql_error(&mysql_handle));
ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql);
}
- WFIFOW(fd,0)=0x2711;
- WFIFOB(fd,2)=0;
+ WFIFOW(fd,0) = 0x2711;
+ WFIFOB(fd,2) = 0;
WFIFOSET(fd,3);
- session[fd]->func_parse=parse_fromchar;
- realloc_fifo(fd,FIFOSIZE_SERVERLINK,FIFOSIZE_SERVERLINK);
+ session[fd]->func_parse = parse_fromchar;
+ realloc_fifo(fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK);
// send GM account to char-server
send_GM_accounts(fd);
} else {
- WFIFOW(fd, 0) =0x2711;
- WFIFOB(fd, 2)=3;
- WFIFOSET(fd, 3);
+ WFIFOW(fd,0) = 0x2711;
+ WFIFOB(fd,2) = 3;
+ WFIFOSET(fd,3);
}
}
- RFIFOSKIP(fd, 86);
+ RFIFOSKIP(fd,86);
return 0;
case 0x7530: // request Athena information
{
+ ShowInfo ("Athena version check...\n");
WFIFOHEAD(fd,10);
- WFIFOW(fd,0)=0x7531;
- WFIFOB(fd,2)=ATHENA_MAJOR_VERSION;
- WFIFOB(fd,3)=ATHENA_MINOR_VERSION;
- WFIFOB(fd,4)=ATHENA_REVISION;
- WFIFOB(fd,5)=ATHENA_RELEASE_FLAG;
- WFIFOB(fd,6)=ATHENA_OFFICIAL_FLAG;
- WFIFOB(fd,7)=ATHENA_SERVER_LOGIN;
- WFIFOW(fd,8)=ATHENA_MOD_VERSION;
+ WFIFOW(fd,0) = 0x7531;
+ WFIFOB(fd,2) = ATHENA_MAJOR_VERSION;
+ WFIFOB(fd,3) = ATHENA_MINOR_VERSION;
+ WFIFOB(fd,4) = ATHENA_REVISION;
+ WFIFOB(fd,5) = ATHENA_RELEASE_FLAG;
+ WFIFOB(fd,6) = ATHENA_OFFICIAL_FLAG;
+ WFIFOB(fd,7) = ATHENA_SERVER_LOGIN;
+ WFIFOW(fd,8) = ATHENA_MOD_VERSION;
WFIFOSET(fd,10);
RFIFOSKIP(fd,2);
- ShowInfo ("Athena version check...\n");
break;
}
- case 0x7532:
+ case 0x7532: // Request to end connection
ShowStatus ("End of connection (ip: %s)" RETCODE, ip);
session[fd]->eof = 1;
break;
+
default:
ShowStatus ("Abnormal end of connection (ip: %s): Unknown packet 0x%x " RETCODE, ip, RFIFOW(fd,0));
session[fd]->eof = 1;
@@ -1782,7 +1780,6 @@ int config_switch(const char *str)
return atoi(str);
}
-
//----------------------------------
// Reading Lan Support configuration
//----------------------------------
@@ -1805,7 +1802,7 @@ int login_lan_config_read(const char *lancfgName)
if ((line[0] == '/' && line[1] == '/') || line[0] == '\n' || line[1] == '\n')
continue;
- line[sizeof(line)-1] = '\0';
+ line[sizeof(line)-1] = '\0';
if(sscanf(line,"%[^:]: %[^:]:%[^:]:%[^\r\n]", w1, w2, w3, w4) != 4) {
ShowWarning("Error syntax of configuration file %s in line %d.\n", lancfgName, line_num);
@@ -1819,9 +1816,9 @@ int login_lan_config_read(const char *lancfgName)
if(strcmpi(w1, "subnet") == 0) {
- subnet[subnet_count].mask = inet_addr(w2);
- subnet[subnet_count].char_ip = inet_addr(w3);
- subnet[subnet_count].map_ip = inet_addr(w4);
+ subnet[subnet_count].mask = ntohl(inet_addr(w2));
+ subnet[subnet_count].char_ip = ntohl(inet_addr(w3));
+ subnet[subnet_count].map_ip = ntohl(inet_addr(w4));
subnet[subnet_count].subnet = subnet[subnet_count].char_ip&subnet[subnet_count].mask;
if (subnet[subnet_count].subnet != (subnet[subnet_count].map_ip&subnet[subnet_count].mask)) {
ShowError("%s: Configuration Error: The char server (%s) and map server (%s) belong to different subnetworks!\n", lancfgName, w3, w4);
@@ -1851,9 +1848,9 @@ int ip_ban_flush(int tid, unsigned int tick, int id, int data)
return 0;
}
-//-----------------------------------------------------
+//-----------------------------------
// Reading main configuration file
-//-----------------------------------------------------
+//-----------------------------------
int login_config_read(const char* cfgName)
{
char line[1024], w1[1024], w2[1024];
@@ -1867,11 +1864,12 @@ int login_config_read(const char* cfgName)
{
if (line[0] == '/' && line[1] == '/')
continue;
+
if (sscanf(line, "%[^:]: %[^\r\n]", w1, w2) < 2)
continue;
- remove_control_chars((unsigned char *) w1);
- remove_control_chars((unsigned char *) w2);
+ remove_control_chars((unsigned char *)w1);
+ remove_control_chars((unsigned char *)w2);
if(!strcmpi(w1,"timestamp_format")) {
strncpy(timestamp_format, w2, 20);
@@ -1890,6 +1888,9 @@ int login_config_read(const char* cfgName)
login_config.login_port = (unsigned short)atoi(w2);
ShowStatus("set login_port : %s\n",w2);
}
+ else if (!strcmpi(w1, "log_login"))
+ login_config.log_login = config_switch(w2);
+
else if (!strcmpi(w1,"ipban"))
login_config.ipban = config_switch(w2);
else if (!strcmpi(w1,"dynamic_pass_failure_ban"))
@@ -1923,8 +1924,6 @@ int login_config_read(const char* cfgName)
time_allowed = atoi(w2);
else if (!strcmpi(w1, "online_check"))
login_config.online_check = config_switch(w2);
- else if (!strcmpi(w1, "log_login"))
- login_config.log_login = config_switch(w2);
else if (!strcmpi(w1,"use_dnsbl"))
login_config.use_dnsbl = config_switch(w2);
else if (!strcmpi(w1,"dnsbl_servers"))
diff --git a/src/login_sql/login.h b/src/login_sql/login.h
index 0115126ef..110c6a876 100644
--- a/src/login_sql/login.h
+++ b/src/login_sql/login.h
@@ -42,8 +42,8 @@ struct mmo_account {
struct mmo_char_server {
char name[20];
- long ip;
- short port;
+ uint32 ip;
+ uint16 port;
int users;
int maintenance;
int new_;