* 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://svn.code.sf.net/p/rathena/svn/trunk@10162 54d463be-8e91-2dee-dedb-b68131a5f0ec
This commit is contained in:
ultramage 2007-04-05 18:49:57 +00:00
parent dd818415a1
commit 8dc1b77f03
19 changed files with 1243 additions and 1391 deletions

View File

@ -3,6 +3,17 @@ Date Added
AS OF SVN REV. 5091, WE ARE NOW USING TRUNK. ALL UNTESTED BUGFIXES/FEATURES GO INTO TRUNK. AS OF SVN REV. 5091, WE ARE NOW USING TRUNK. ALL UNTESTED BUGFIXES/FEATURES GO INTO TRUNK.
IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK. IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.
2007/04/06
* 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 [ultramage]
- 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!)
2007/04/05 2007/04/05
* Cleaned @whogm. It will display the name of all gms online. If their GM * Cleaned @whogm. It will display the name of all gms online. If their GM
level is above your own, it will only display their name, otherwise level, level is above your own, it will only display their name, otherwise level,

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -215,8 +215,8 @@ struct mmo_charstatus {
short str,agi,vit,int_,dex,luk; short str,agi,vit,int_,dex,luk;
unsigned char char_num,sex; unsigned char char_num,sex;
unsigned long mapip; uint32 mapip;
unsigned int mapport; uint16 mapport;
struct point last_point,save_point,memo_point[MAX_MEMOPOINTS]; struct point last_point,save_point,memo_point[MAX_MEMOPOINTS];
struct item inventory[MAX_INVENTORY],cart[MAX_CART]; struct item inventory[MAX_INVENTORY],cart[MAX_CART];

View File

@ -242,7 +242,7 @@ int connect_client(int listen_fd)
len = sizeof(client_address); len = sizeof(client_address);
fd = accept(listen_fd,(struct sockaddr*)&client_address,&len); fd = accept(listen_fd, (struct sockaddr*)&client_address, &len);
if ( fd == INVALID_SOCKET ) { if ( fd == INVALID_SOCKET ) {
ShowError("accept failed (code %i)!\n", s_errno); ShowError("accept failed (code %i)!\n", s_errno);
return -1; return -1;
@ -258,7 +258,7 @@ int connect_client(int listen_fd)
set_nonblocking(fd, 1); set_nonblocking(fd, 1);
#ifndef MINICORE #ifndef MINICORE
if( ip_rules && !connect_check(*(uint32*)(&client_address.sin_addr)) ){ if( ip_rules && !connect_check(ntohl(client_address.sin_addr.s_addr)) ) {
do_close(fd); do_close(fd);
return -1; return -1;
} }
@ -270,13 +270,13 @@ int connect_client(int listen_fd)
fd_max = fd + 1; fd_max = fd + 1;
create_session(fd, recv_to_fifo, send_from_fifo, default_func_parse); create_session(fd, recv_to_fifo, send_from_fifo, default_func_parse);
session[fd]->client_addr = client_address; session[fd]->client_addr = ntohl(client_address.sin_addr.s_addr);
session[fd]->rdata_tick = last_tick; session[fd]->rdata_tick = last_tick;
return fd; return fd;
} }
int make_listen_bind(long ip,int port) int make_listen_bind(uint32 ip, uint16 port)
{ {
struct sockaddr_in server_address; struct sockaddr_in server_address;
int fd; int fd;
@ -293,8 +293,8 @@ int make_listen_bind(long ip,int port)
set_nonblocking(fd, 1); set_nonblocking(fd, 1);
server_address.sin_family = AF_INET; server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = ip; server_address.sin_addr.s_addr = htonl(ip);
server_address.sin_port = htons((unsigned short)port); server_address.sin_port = htons(port);
result = bind(fd, (struct sockaddr*)&server_address, sizeof(server_address)); result = bind(fd, (struct sockaddr*)&server_address, sizeof(server_address));
if( result == SOCKET_ERROR ) { if( result == SOCKET_ERROR ) {
@ -320,7 +320,7 @@ int make_listen_bind(long ip,int port)
return fd; return fd;
} }
int make_connection(long ip, int port) int make_connection(uint32 ip, uint16 port)
{ {
struct sockaddr_in server_address; struct sockaddr_in server_address;
int fd; int fd;
@ -335,12 +335,11 @@ int make_connection(long ip, int port)
setsocketopts(fd); setsocketopts(fd);
server_address.sin_family = AF_INET; server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = ip; server_address.sin_addr.s_addr = htonl(ip);
server_address.sin_port = htons((unsigned short)port); server_address.sin_port = htons(port);
ShowStatus("Connecting to %d.%d.%d.%d:%i\n", ShowStatus("Connecting to %d.%d.%d.%d:%i\n", CONVIP(ip), port);
(ip)&0xFF,(ip>>8)&0xFF,(ip>>16)&0xFF,(ip>>24)&0xFF,port);
result = connect(fd, (struct sockaddr *)(&server_address), sizeof(struct sockaddr_in)); result = connect(fd, (struct sockaddr *)(&server_address), sizeof(struct sockaddr_in));
if( result == SOCKET_ERROR ) { if( result == SOCKET_ERROR ) {
@ -389,7 +388,7 @@ int delete_session(int fd)
return 0; return 0;
} }
int realloc_fifo(int fd,unsigned int rfifo_size,unsigned int wfifo_size) int realloc_fifo(int fd, unsigned int rfifo_size, unsigned int wfifo_size)
{ {
if( !session_isValid(fd) ) if( !session_isValid(fd) )
return 0; return 0;
@ -421,7 +420,7 @@ int realloc_writefifo(int fd, size_t addition)
else if( session[fd]->max_wdata >= FIFOSIZE_SERVERLINK) { else if( session[fd]->max_wdata >= FIFOSIZE_SERVERLINK) {
//Inter-server adjust. [Skotlex] //Inter-server adjust. [Skotlex]
if ((session[fd]->wdata_size+addition)*4 < session[fd]->max_wdata) if ((session[fd]->wdata_size+addition)*4 < session[fd]->max_wdata)
newsize = session[fd]->max_wdata/2; newsize = session[fd]->max_wdata / 2;
else else
return 0; //No change return 0; //No change
} else if( session[fd]->max_wdata > wfifo_size && (session[fd]->wdata_size+addition)*4 < session[fd]->max_wdata ) } else if( session[fd]->max_wdata > wfifo_size && (session[fd]->wdata_size+addition)*4 < session[fd]->max_wdata )
@ -437,7 +436,7 @@ int realloc_writefifo(int fd, size_t addition)
return 0; return 0;
} }
int RFIFOSKIP(int fd,int len) int RFIFOSKIP(int fd, int len)
{ {
struct socket_data *s; struct socket_data *s;
@ -468,11 +467,10 @@ int WFIFOSET(int fd, int len)
// we have written len bytes to the buffer already before calling WFIFOSET // we have written len bytes to the buffer already before calling WFIFOSET
if(s->wdata_size+len > s->max_wdata) if(s->wdata_size+len > s->max_wdata)
{ // actually there was a buffer overflow already { // actually there was a buffer overflow already
unsigned char *sin_addr = (unsigned char *)&s->client_addr.sin_addr; uint32 ip = s->client_addr;
ShowFatalError("socket: Buffer Overflow. Connection %d (%d.%d.%d.%d) has written %d bytes on a %d/%d bytes buffer.\n", fd, ShowFatalError("socket: Buffer Overflow. Connection %d (%d.%d.%d.%d) has written %d bytes on a %d/%d bytes buffer.\n",
sin_addr[0], sin_addr[1], sin_addr[2], sin_addr[3], len, s->wdata_size, s->max_wdata); fd, CONVIP(ip), len, s->wdata_size, s->max_wdata);
ShowDebug("Likely command that caused it: 0x%x\n", ShowDebug("Likely command that caused it: 0x%x\n", (*(unsigned short*)(s->wdata + s->wdata_size)));
(*(unsigned short*)(s->wdata + s->wdata_size)));
// no other chance, make a better fifo model // no other chance, make a better fifo model
exit(1); exit(1);
} }
@ -645,15 +643,13 @@ static int access_order = ACO_DENY_ALLOW;
static int access_allownum = 0; static int access_allownum = 0;
static int access_denynum = 0; static int access_denynum = 0;
static int access_debug = 0; static int access_debug = 0;
static int ddos_count = 10; static int ddos_count = 10;
static int ddos_interval = 3*1000; static int ddos_interval = 3*1000;
static int ddos_autoreset = 10*60*1000; static int ddos_autoreset = 10*60*1000;
/// Connection history, an array of linked lists. /// Connection history, an array of linked lists.
/// The array's index for any ip is ip&0xFFFF /// The array's index for any ip is ip&0xFFFF
static ConnectHistory* connect_history[0x10000]; static ConnectHistory* connect_history[0x10000];
#define CONVIP(ip) ip&0xFF,(ip>>8)&0xFF,(ip>>16)&0xFF,ip>>24
static int connect_check_(uint32 ip); static int connect_check_(uint32 ip);
/// Verifies if the IP can connect. (with debug info) /// Verifies if the IP can connect. (with debug info)
@ -816,7 +812,7 @@ int access_ipmask(const char* str, AccessControl* acc)
unsigned int m[4]; unsigned int m[4];
int n; int n;
if( strcmp(str,"all") == 0 ){ if( strcmp(str,"all") == 0 ) {
ip = 0; ip = 0;
mask = 0; mask = 0;
} else { } else {
@ -856,7 +852,7 @@ int access_ipmask(const char* str, AccessControl* acc)
#endif #endif
////////////////////////////// //////////////////////////////
int socket_config_read(const char *cfgName) int socket_config_read(const char* cfgName)
{ {
char line[1024],w1[1024],w2[1024]; char line[1024],w1[1024],w2[1024];
FILE *fp; FILE *fp;
@ -960,7 +956,7 @@ void do_close(int fd)
/// Retrieve local ips in host byte order. /// Retrieve local ips in host byte order.
/// Uses loopback is no address is found. /// Uses loopback is no address is found.
int socket_getips(uint32 *ips, int max) int socket_getips(uint32* ips, int max)
{ {
int num = 0; int num = 0;
@ -986,7 +982,7 @@ int socket_getips(uint32 *ips, int max)
{ {
hent = gethostbyname(fullhost); hent = gethostbyname(fullhost);
if( hent == NULL ){ if( hent == NULL ){
ShowError("socket_getips: Cannot resolve our own hostname to a IP address\n"); ShowError("socket_getips: Cannot resolve our own hostname to an IP address\n");
return 0; return 0;
} }
a = (u_long**)hent->h_addr_list; a = (u_long**)hent->h_addr_list;
@ -1099,16 +1095,18 @@ int session_isActive(int fd)
return ( session_isValid(fd) && !session[fd]->eof ); return ( session_isValid(fd) && !session[fd]->eof );
} }
// Resolves hostname into a numeric ip.
in_addr_t host2ip(const char* hostname) uint32 host2ip(const char* hostname)
{ {
struct hostent* h = gethostbyname(hostname); struct hostent* h = gethostbyname(hostname);
return (h != NULL) ? *(in_addr_t*)h->h_addr : 0; return (h != NULL) ? ntohl(*(uint32*)h->h_addr) : 0;
} }
const char* ip2str(in_addr_t ip, char ip_str[16]) // Converts a numeric ip into a dot-formatted string.
// Result is placed either into a user-provided buffer or a static system buffer.
const char* ip2str(uint32 ip, char ip_str[16])
{ {
in_addr_t addr = ntohl(ip); struct in_addr addr;
sprintf(ip_str, "%d.%d.%d.%d", (addr>>24)&0xFF, (addr>>16)&0xFF, (addr>>8)&0xFF, (addr>>0)&0xFF); addr.s_addr = htonl(ip);
return ip_str; return (ip_str == NULL) ? inet_ntoa(addr) : strncpy(ip_str, inet_ntoa(addr), 16);
} }

View File

@ -81,7 +81,7 @@ struct socket_data {
size_t rdata_size, wdata_size; size_t rdata_size, wdata_size;
size_t rdata_pos; size_t rdata_pos;
time_t rdata_tick; // time of last receive (for detecting timeouts) time_t rdata_tick; // time of last receive (for detecting timeouts)
struct sockaddr_in client_addr; // remote client address (zero for s2s connections) uint32 client_addr; // remote client address (zero for s2s connections)
void* session_data; void* session_data;
RecvFunc func_recv; RecvFunc func_recv;
SendFunc func_send; SendFunc func_send;
@ -106,12 +106,12 @@ extern int session_isActive(int fd);
// Function prototype declaration // Function prototype declaration
int make_listen_bind(long,int); int make_listen_bind(uint32 ip, uint16 port);
int make_connection(long,int); int make_connection(uint32 ip, uint16 port);
int realloc_fifo(int fd,unsigned int rfifo_size,unsigned int wfifo_size); int realloc_fifo(int fd, unsigned int rfifo_size, unsigned int wfifo_size);
int realloc_writefifo(int fd, size_t addition); int realloc_writefifo(int fd, size_t addition);
int WFIFOSET(int fd,int len); int WFIFOSET(int fd, int len);
int RFIFOSKIP(int fd,int len); int RFIFOSKIP(int fd, int len);
int do_sendrecv(int next); int do_sendrecv(int next);
int do_parsepacket(void); int do_parsepacket(void);
@ -126,9 +126,9 @@ extern void set_nonblocking(int fd, int yes);
void set_defaultparse(ParseFunc defaultparse); void set_defaultparse(ParseFunc defaultparse);
// hostname/ip conversion functions // hostname/ip conversion functions
in_addr_t host2ip(const char* hostname); uint32 host2ip(const char* hostname);
const char* ip2str(in_addr_t ip, char ip_str[16]); const char* ip2str(uint32 ip, char ip_str[16]);
#define CONVIP(ip) (ip>>24)&0xFF,(ip>>16)&0xFF,(ip>>8)&0xFF,(ip>>0)&0xFF
int socket_getips(uint32* ips, int max); int socket_getips(uint32* ips, int max);

View File

@ -11,12 +11,15 @@
#include "../common/utils.h" #include "../common/utils.h"
#include "../common/malloc.h" #include "../common/malloc.h"
//-----------------------------------------------
// string lib. #define J_MAX_MALLOC_SIZE 65535
char* jstrescape (char* pt) {
// escapes a string in-place (' -> \' , \ -> \\ , % -> _)
char* jstrescape (char* pt)
{
//copy from here //copy from here
char *ptr; char *ptr;
int i =0, j=0; int i = 0, j = 0;
//copy string to temporary //copy string to temporary
CREATE(ptr, char, J_MAX_MALLOC_SIZE); CREATE(ptr, char, J_MAX_MALLOC_SIZE);
@ -41,10 +44,12 @@ char* jstrescape (char* pt) {
} }
pt[j++] = '\0'; pt[j++] = '\0';
aFree(ptr); aFree(ptr);
return &pt[0]; return pt;
} }
char* jstrescapecpy (char* pt, const char* spt) { // escapes a string into a provided buffer
char* jstrescapecpy (char* pt, const char* spt)
{
//copy from here //copy from here
//WARNING: Target string pt should be able to hold strlen(spt)*2, as each time //WARNING: Target string pt should be able to hold strlen(spt)*2, as each time
//a escape character is found, the target's final length increases! [Skotlex] //a escape character is found, the target's final length increases! [Skotlex]
@ -75,7 +80,10 @@ char* jstrescapecpy (char* pt, const char* spt) {
pt[j++] = '\0'; pt[j++] = '\0';
return &pt[0]; return &pt[0];
} }
int jmemescapecpy (char* pt,char* spt, int size) {
// escapes exactly 'size' bytes of a string into a provided buffer
int jmemescapecpy (char* pt, const char* spt, int size)
{
//copy from here //copy from here
int i =0, j=0; int i =0, j=0;
@ -100,11 +108,9 @@ int jmemescapecpy (char* pt,char* spt, int size) {
return j; return j;
} }
//-----------------------------------------------------
// Function to suppress control characters in a string. // Function to suppress control characters in a string.
//----------------------------------------------------- int remove_control_chars(char* str)
//int remove_control_chars(char *str) { {
int remove_control_chars(unsigned char *str) {
int i; int i;
int change = 0; int change = 0;
@ -119,11 +125,11 @@ int remove_control_chars(unsigned char *str) {
} }
//Trims a string, also removes illegal characters such as \t and reduces continous spaces to a single one. by [Foruken] //Trims a string, also removes illegal characters such as \t and reduces continous spaces to a single one. by [Foruken]
char *trim(char *str, const char *delim) char* trim(char* str, const char* delim)
{ {
char *strp = strtok(str,delim); char* strp = strtok(str,delim);
char buf[1024]; char buf[1024];
char *bufp = buf; char* bufp = buf;
memset(buf,0,sizeof buf); memset(buf,0,sizeof buf);
while(strp) { while(strp) {
@ -143,7 +149,7 @@ char *trim(char *str, const char *delim)
//stristr: Case insensitive version of strstr, code taken from //stristr: Case insensitive version of strstr, code taken from
//http://www.daniweb.com/code/snippet313.html, Dave Sinkula //http://www.daniweb.com/code/snippet313.html, Dave Sinkula
// //
const char *stristr(const char *haystack, const char *needle) const char* stristr(const char* haystack, const char* needle)
{ {
if ( !*needle ) if ( !*needle )
{ {
@ -153,9 +159,7 @@ const char *stristr(const char *haystack, const char *needle)
{ {
if ( TOUPPER(*haystack) == TOUPPER(*needle) ) if ( TOUPPER(*haystack) == TOUPPER(*needle) )
{ {
/* // matched starting char -- loop through remaining chars
* Matched starting char -- loop through remaining chars.
*/
const char *h, *n; const char *h, *n;
for ( h = haystack, n = needle; *h && *n; ++h, ++n ) for ( h = haystack, n = needle; *h && *n; ++h, ++n )
{ {
@ -164,9 +168,9 @@ const char *stristr(const char *haystack, const char *needle)
break; break;
} }
} }
if ( !*n ) /* matched all of 'needle' to null termination */ if ( !*n ) // matched all of 'needle' to null termination
{ {
return haystack; /* return the start of the match */ return haystack; // return the start of the match
} }
} }
} }
@ -174,7 +178,7 @@ const char *stristr(const char *haystack, const char *needle)
} }
#ifdef __WIN32 #ifdef __WIN32
char *_strtok_r(char *s1, const char *s2, char **lasts) char* _strtok_r(char *s1, const char *s2, char **lasts)
{ {
char *ret; char *ret;

View File

@ -4,25 +4,20 @@
#ifndef _STRLIB_H_ #ifndef _STRLIB_H_
#define _STRLIB_H_ #define _STRLIB_H_
#define J_MAX_MALLOC_SIZE 65535
// String function library.
// code by Jioh L. Jung (ziozzang@4wish.net)
// This code is under license "BSD"
char* jstrescape (char* pt); char* jstrescape (char* pt);
char* jstrescapecpy (char* pt, const char* spt); char* jstrescapecpy (char* pt, const char* spt);
int jmemescapecpy (char* pt,char* spt, int size); int jmemescapecpy (char* pt, const char* spt, int size);
int remove_control_chars(char *);
char *trim(char *str, const char *delim);
const char *stristr(const char *haystack, const char *needle);
#ifdef __WIN32 #ifdef __WIN32
#define HAVE_STRTOK_R #define HAVE_STRTOK_R
#define strtok_r(s,delim,save_ptr) _strtok_r((s),(delim),(save_ptr)) #define strtok_r(s,delim,save_ptr) _strtok_r((s),(delim),(save_ptr))
char *_strtok_r(char *s1, const char *s2, char **lasts); char* _strtok_r(char* s1, const char* s2, char** lasts);
#endif #endif
// custom functions
int remove_control_chars(unsigned char *);
char *trim(char *str, const char *delim);
const char *stristr(const char *haystack, const char *needle);
#if !defined(WIN32) || (defined(_MSC_VER) && _MSC_VER < 1400) #if !defined(WIN32) || (defined(_MSC_VER) && _MSC_VER < 1400)
size_t strnlen (const char* string, size_t maxlen); size_t strnlen (const char* string, size_t maxlen);
#endif #endif

View File

@ -20,28 +20,28 @@
#include "../common/showmsg.h" #include "../common/showmsg.h"
#include "../common/cbasetypes.h" #include "../common/cbasetypes.h"
void dump(unsigned char *buffer, int num) void dump(unsigned char* buffer, int num)
{ {
int icnt,jcnt; int icnt, jcnt;
printf(" Hex ASCII\n"); printf(" Hex ASCII\n");
printf(" ----------------------------------------------- ----------------"); printf(" ----------------------------------------------- ----------------");
for (icnt=0;icnt<num;icnt+=16) { for (icnt = 0; icnt < num; icnt += 16) {
printf("\n%p ",&buffer[icnt]); printf("\n%p ", &buffer[icnt]);
for (jcnt=icnt;jcnt<icnt+16;++jcnt) { for (jcnt = icnt; jcnt < icnt + 16; ++jcnt) {
if (jcnt < num) { if (jcnt < num) {
printf("%02hX ",buffer[jcnt]); printf("%02hX ", buffer[jcnt]);
} else } else
printf(" "); printf(" ");
} }
printf(" | "); printf(" | ");
for (jcnt=icnt;jcnt<icnt+16;++jcnt) { for (jcnt = icnt; jcnt < icnt + 16; ++jcnt) {
if (jcnt < num) { if (jcnt < num) {
if (buffer[jcnt] > 31 && buffer[jcnt] < 127) if (buffer[jcnt] > 31 && buffer[jcnt] < 127)
printf("%c",buffer[jcnt]); printf("%c", buffer[jcnt]);
else else
printf("."); printf(".");
} else } else
@ -266,30 +266,20 @@ void findfile(const char *p, const char *pat, void (func)(const char*))
unsigned char GetByte(unsigned long val, size_t num) unsigned char GetByte(unsigned long val, size_t num)
{ {
switch(num) switch(num) {
{ case 0: return (unsigned char)((val & 0x000000FF) );
case 0: case 1: return (unsigned char)((val & 0x0000FF00)>>0x08);
return (unsigned char)((val & 0x000000FF) ); case 2: return (unsigned char)((val & 0x00FF0000)>>0x10);
case 1: case 3: return (unsigned char)((val & 0xFF000000)>>0x18);
return (unsigned char)((val & 0x0000FF00)>>0x08); default: return 0; //better throw something here
case 2:
return (unsigned char)((val & 0x00FF0000)>>0x10);
case 3:
return (unsigned char)((val & 0xFF000000)>>0x18);
default:
return 0; //better throw something here
} }
} }
unsigned short GetWord(unsigned long val, size_t num) unsigned short GetWord(unsigned long val, size_t num)
{ {
switch(num) switch(num) {
{ case 0: return (unsigned short)((val & 0x0000FFFF) );
case 0: case 1: return (unsigned short)((val & 0xFFFF0000)>>0x10);
return (unsigned short)((val & 0x0000FFFF) ); default: return 0; //better throw something here
case 1:
return (unsigned short)((val & 0xFFFF0000)>>0x10);
default:
return 0; //better throw something here
} }
} }
unsigned short MakeWord(unsigned char byte0, unsigned char byte1) unsigned short MakeWord(unsigned char byte0, unsigned char byte1)

File diff suppressed because it is too large Load Diff

View File

@ -40,7 +40,7 @@
struct Login_Config { 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 unsigned short login_port; // the port to bind to
bool log_login; // whether to log login server actions or not bool log_login; // whether to log login server actions or not
char date_format[32]; // date format used in messages 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] // Advanced subnet check [LuzZza]
struct _subnet { struct _subnet {
long subnet; uint32 subnet;
long mask; uint32 mask;
long char_ip; uint32 char_ip;
long map_ip; uint32 map_ip;
} subnet[16]; } subnet[16];
int subnet_count = 0; int subnet_count = 0;
struct gm_account* gm_account_db = NULL; 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] //Account registration flood protection [Kevin]
int allowed_regs = 1; int allowed_regs = 1;
@ -118,7 +118,9 @@ char login_db_level[256] = "level";
#define AUTH_FIFO_SIZE 256 #define AUTH_FIFO_SIZE 256
struct { struct {
int account_id,login_id1,login_id2; int account_id,login_id1,login_id2;
int ip,sex,delflag; uint32 ip;
char sex;
bool delflag;
} auth_fifo[AUTH_FIFO_SIZE]; } auth_fifo[AUTH_FIFO_SIZE];
int auth_fifo_pos = 0; int auth_fifo_pos = 0;
@ -235,12 +237,13 @@ void read_gm_account(void)
//----------------------------------------------------- //-----------------------------------------------------
void send_GM_accounts(int fd) void send_GM_accounts(int fd)
{ {
int i; unsigned int i;
unsigned char buf[32767]; unsigned char buf[32767];
int len; int len;
if(!login_config.login_gm_read) if(!login_config.login_gm_read)
return; return;
len = 4; len = 4;
WBUFW(buf,0) = 0x2732; WBUFW(buf,0) = 0x2732;
for(i = 0; i < GM_num; i++) for(i = 0; i < GM_num; i++)
@ -254,16 +257,17 @@ void send_GM_accounts(int fd)
break; break;
} }
} }
WBUFW(buf,2) = len;
if (fd == -1) WBUFW(buf,2) = len;
charif_sendallwos(-1, buf, len); if (fd == -1)
else charif_sendallwos(-1, buf, len);
{ else
WFIFOHEAD(fd, len); {
memcpy(WFIFOP(fd,0), buf, len); WFIFOHEAD(fd, len);
WFIFOSET(fd, len); memcpy(WFIFOP(fd,0), buf, len);
} WFIFOSET(fd, len);
return; }
return;
} }
//--------------------------------------------------- //---------------------------------------------------
@ -497,20 +501,20 @@ int mmo_auth_new(struct mmo_account* account, char sex)
return 0; 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 charif_sendallwos(int sfd, unsigned char *buf, unsigned int len)
{ {
int i, c; int i, c, fd;
int fd;
c = 0; for(i = 0, c = 0; i < MAX_SERVERS; i++) {
for(i = 0; i < MAX_SERVERS; i++) {
if ((fd = server_fd[i]) > 0 && fd != sfd) { if ((fd = server_fd[i]) > 0 && fd != sfd) {
WFIFOHEAD(fd,len); WFIFOHEAD(fd, len);
if (WFIFOSPACE(fd) < len) //Increase buffer size. if (WFIFOSPACE(fd) < len) //Increase buffer size.
realloc_writefifo(fd, len); realloc_writefifo(fd, len);
memcpy(WFIFOP(fd,0), buf, len); memcpy(WFIFOP(fd,0), buf, len);
WFIFOSET(fd,len); WFIFOSET(fd, len);
c++; c++;
} }
} }
@ -532,8 +536,9 @@ int mmo_auth(struct mmo_account* account, int fd)
char md5str[64], md5bin[32]; char md5str[64], md5bin[32];
char ip[16]; char ip[16];
unsigned char* sin_addr = (unsigned char *)&session[fd]->client_addr.sin_addr.s_addr; uint32 ipl = session[fd]->client_addr;
sprintf(ip, "%d.%d.%d.%d", sin_addr[0], sin_addr[1], sin_addr[2], sin_addr[3]); 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 // DNS Blacklist check
if(login_config.use_dnsbl) if(login_config.use_dnsbl)
@ -543,7 +548,7 @@ int mmo_auth(struct mmo_account* account, int fd)
char *dnsbl_serv; char *dnsbl_serv;
bool matched = false; 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,",")) 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) { if (login_config.online_check) {
struct online_login_data* data = idb_get(online_db,account->account_id); struct online_login_data* data = idb_get(online_db,account->account_id);
unsigned char buf[8];
if (data && data->char_server > -1) { if (data && data->char_server > -1) {
//Request char servers to kick this account out. [Skotlex] //Request char servers to kick this account out. [Skotlex]
unsigned char buf[8];
ShowNotice("User [%s] is already online - Rejected.\n",account->userid); ShowNotice("User [%s] is already online - Rejected.\n",account->userid);
WBUFW(buf,0) = 0x2734; WBUFW(buf,0) = 0x2734;
WBUFL(buf,2) = account->account_id; WBUFL(buf,2) = account->account_id;
@ -764,19 +769,18 @@ static int online_db_setoffline(DBKey key, void* data, va_list ap)
return 0; return 0;
} }
//----------------------------------------------------- //--------------------------------
// char-server packet parse // Packet parsing for char-servers
//----------------------------------------------------- //--------------------------------
int parse_fromchar(int fd) int parse_fromchar(int fd)
{ {
int i, id; int i, id;
unsigned char *p = (unsigned char *) &session[fd]->client_addr.sin_addr.s_addr; uint32 ipl = session[fd]->client_addr;
unsigned long ipl = session[fd]->client_addr.sin_addr.s_addr;
char ip[16]; char ip[16];
RFIFOHEAD(fd); 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++) for(id = 0; id < MAX_SERVERS; id++)
if (server_fd[id] == fd) if (server_fd[id] == fd)
@ -802,14 +806,14 @@ int parse_fromchar(int fd)
return 0; return 0;
} }
while(RFIFOREST(fd) >= 2) { while (RFIFOREST(fd) >= 2) {
// printf("char_parse: %d %d packet case=%x\n", fd, RFIFOREST(fd), RFIFOW(fd, 0));
switch (RFIFOW(fd,0)) { switch (RFIFOW(fd,0)) {
case 0x2709:
case 0x2709: // request from map-server via char-server to reload GM accounts
if (login_config.log_login) 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)) { if (mysql_query(&mysql_handle, tmpsql)) {
ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); ShowSQL("DB error - %s\n",mysql_error(&mysql_handle));
ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql);
@ -821,7 +825,7 @@ int parse_fromchar(int fd)
RFIFOSKIP(fd,2); RFIFOSKIP(fd,2);
break; break;
case 0x2712: case 0x2712: // request from char-server to authenticate an account
if (RFIFOREST(fd) < 19) if (RFIFOREST(fd) < 19)
return 0; return 0;
{ {
@ -833,7 +837,7 @@ int parse_fromchar(int fd)
auth_fifo[i].login_id1 == RFIFOL(fd,6) && 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].login_id2 == RFIFOL(fd,10) && // relate to the versions higher than 18
auth_fifo[i].sex == RFIFOB(fd,14) && 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)
{ {
auth_fifo[i].delflag = 1; auth_fifo[i].delflag = 1;
@ -869,9 +873,10 @@ int parse_fromchar(int fd)
WFIFOB(fd,6) = 1; WFIFOB(fd,6) = 1;
WFIFOSET(fd,51); WFIFOSET(fd,51);
} }
}
RFIFOSKIP(fd,19); RFIFOSKIP(fd,19);
break; break;
}
case 0x2714: case 0x2714:
if (RFIFOREST(fd) < 6) if (RFIFOREST(fd) < 6)
@ -897,8 +902,7 @@ int parse_fromchar(int fd)
RFIFOSKIP(fd,6); RFIFOSKIP(fd,6);
break; break;
// We receive an e-mail/limited time request, because a player comes back from a map-server to the char-server case 0x2716: // received an e-mail/limited time request, because a player comes back from a map-server to the char-server
case 0x2716:
if (RFIFOREST(fd) < 6) if (RFIFOREST(fd) < 6)
return 0; return 0;
{ {
@ -929,10 +933,8 @@ int parse_fromchar(int fd)
RFIFOSKIP(fd,6); RFIFOSKIP(fd,6);
break; break;
case 0x2720: // GM case 0x2720: // Request to become a GM (TXT only!)
if (RFIFOREST(fd) < 4) if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2))
return 0;
if (RFIFOREST(fd) < RFIFOW(fd,2))
return 0; return 0;
//oldacc = RFIFOL(fd,4); //oldacc = RFIFOL(fd,4);
ShowWarning("change GM isn't supported in this login server version.\n"); ShowWarning("change GM isn't supported in this login server version.\n");
@ -995,7 +997,7 @@ int parse_fromchar(int fd)
break; 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) if (RFIFOREST(fd) < 10)
return 0; return 0;
{ {
@ -1029,7 +1031,7 @@ int parse_fromchar(int fd)
break; 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) if (RFIFOREST(fd) < 18)
return 0; return 0;
{ {
@ -1084,7 +1086,7 @@ int parse_fromchar(int fd)
break; break;
} }
case 0x2727: case 0x2727: // Change of sex (sex is reversed)
if (RFIFOREST(fd) < 6) if (RFIFOREST(fd) < 6)
return 0; return 0;
{ {
@ -1168,10 +1170,9 @@ int parse_fromchar(int fd)
if (buf) aFree(buf); if (buf) aFree(buf);
} }
RFIFOSKIP(fd,RFIFOW(fd,2)); RFIFOSKIP(fd,RFIFOW(fd,2));
//printf("login: save account_reg (from char)\n");
break; 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) if (RFIFOREST(fd) < 6)
return 0; return 0;
{ {
@ -1209,6 +1210,7 @@ int parse_fromchar(int fd)
remove_online_user(RFIFOL(fd,2)); remove_online_user(RFIFOL(fd,2));
RFIFOSKIP(fd,6); RFIFOSKIP(fd,6);
break; break;
case 0x272d: // Receive list of all online accounts. [Skotlex] case 0x272d: // Receive list of all online accounts. [Skotlex]
if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2)) if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2))
return 0; return 0;
@ -1270,10 +1272,8 @@ int parse_fromchar(int fd)
case 0x2736: // WAN IP update from char-server case 0x2736: // WAN IP update from char-server
if (RFIFOREST(fd) < 6) if (RFIFOREST(fd) < 6)
return 0; return 0;
ShowInfo("Updated IP of Server #%d to %d.%d.%d.%d.\n",id, server[id].ip = ntohl(RFIFOL(fd,2));
(int)RFIFOB(fd,2),(int)RFIFOB(fd,3), ShowInfo("Updated IP of Server #%d to %d.%d.%d.%d.\n",id, CONVIP(server[id].ip));
(int)RFIFOB(fd,4),(int)RFIFOB(fd,5));
server[id].ip = RFIFOL(fd,2);
RFIFOSKIP(fd,6); RFIFOSKIP(fd,6);
break; break;
@ -1284,7 +1284,7 @@ int parse_fromchar(int fd)
break; break;
default: 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; session[fd]->eof = 1;
return 0; return 0;
} }
@ -1297,12 +1297,12 @@ int parse_fromchar(int fd)
//-------------------------------------------- //--------------------------------------------
// Test to know if an IP come from LAN or WAN. // Test to know if an IP come from LAN or WAN.
//-------------------------------------------- //--------------------------------------------
int lan_subnetcheck(long p) int lan_subnetcheck(uint32 ip)
{ {
int i; int i;
for(i=0; i<subnet_count; i++) { for(i = 0; i < subnet_count; i++) {
if(subnet[i].subnet == (p & subnet[i].mask)) { if(subnet[i].subnet == (ip & subnet[i].mask)) {
return subnet[i].char_ip; return subnet[i].char_ip;
} }
} }
@ -1310,14 +1310,11 @@ int lan_subnetcheck(long p)
return 0; return 0;
} }
int login_ip_ban_check(unsigned char *p, unsigned long ipl) int login_ip_ban_check(uint32 ip)
{ {
//ip ban char* p = (char*)&ip;
//p[0], p[1], p[2], p[3]
//request DB connection
//check
sprintf(tmpsql, "SELECT count(*) FROM `ipbanlist` WHERE `list` = '%d.*.*.*' OR `list` = '%d.%d.*.*' OR `list` = '%d.%d.%d.*' OR `list` = '%d.%d.%d.%d'", 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)) { if (mysql_query(&mysql_handle, tmpsql)) {
ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); ShowSQL("DB error - %s\n",mysql_error(&mysql_handle));
ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); 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. // 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) 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 // query
if(mysql_query(&mysql_handle, tmpsql)) { if(mysql_query(&mysql_handle, tmpsql)) {
ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); ShowSQL("DB error - %s\n",mysql_error(&mysql_handle));
@ -1360,16 +1357,13 @@ int parse_login(int fd)
{ {
char t_uid[100]; char t_uid[100];
struct mmo_account account; struct mmo_account account;
long subnet_char_ip;
int packet_len;
int result, i; int result, i;
unsigned char *p = (unsigned char *) &session[fd]->client_addr.sin_addr.s_addr; uint32 ipl = session[fd]->client_addr;
unsigned long ipl = session[fd]->client_addr.sin_addr.s_addr;
char ip[16]; char ip[16];
RFIFOHEAD(fd); RFIFOHEAD(fd);
sprintf(ip, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); ip2str(ipl, ip);
memset(&account, 0, sizeof(account)); memset(&account, 0, sizeof(account));
@ -1381,9 +1375,9 @@ int parse_login(int fd)
return 0; 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. case 0x200: // New alive packet: structure: 0x200 <account.userid>.24B. used to verify if client is always alive.
if (RFIFOREST(fd) < 26) if (RFIFOREST(fd) < 26)
return 0; return 0;
@ -1399,18 +1393,22 @@ int parse_login(int fd)
case 0x277: // New login packet case 0x277: // New login packet
case 0x64: // request client login case 0x64: // request client login
case 0x01dd: // request client login with encrypt case 0x01dd: // request client login with encrypt
{
int packet_len = RFIFOREST(fd);
packet_len = RFIFOREST(fd); //Perform ip-ban check
if (login_config.ipban && login_ip_ban_check(ipl))
//Perform ip-ban check ONLY on login packets
if (login_config.ipban && login_ip_ban_check(p,ipl))
{ {
WFIFOHEAD(fd, 23);
WFIFOW(fd,0) = 0x6a;
WFIFOB(fd,2) = 3; // 3 = Rejected from Server
WFIFOSET(fd,23);
RFIFOSKIP(fd,packet_len); RFIFOSKIP(fd,packet_len);
session[fd]->eof = 1; session[fd]->eof = 1;
break; break;
} }
switch(RFIFOW(fd,0)){ switch(RFIFOW(fd, 0)){
case 0x64: case 0x64:
if(packet_len < 55) if(packet_len < 55)
return 0; return 0;
@ -1432,7 +1430,6 @@ int parse_login(int fd)
memcpy(account.passwd,RFIFOP(fd, 30),NAME_LENGTH); memcpy(account.passwd,RFIFOP(fd, 30),NAME_LENGTH);
account.passwd[23] = '\0'; 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 #ifdef PASSWORDENC
account.passwdenc= (RFIFOW(fd,0)!=0x01dd)?0:PASSWORDENC; account.passwdenc= (RFIFOW(fd,0)!=0x01dd)?0:PASSWORDENC;
#else #else
@ -1441,7 +1438,7 @@ int parse_login(int fd)
result=mmo_auth(&account, fd); result=mmo_auth(&account, fd);
jstrescapecpy(t_uid,account.userid); jstrescapecpy(t_uid,account.userid);
if(result==-1){ if(result==-1) { // auth success
if (login_config.min_level_to_connect > account.level) { if (login_config.min_level_to_connect > account.level) {
WFIFOHEAD(fd,3); WFIFOHEAD(fd,3);
WFIFOW(fd,0) = 0x81; WFIFOW(fd,0) = 0x81;
@ -1449,8 +1446,8 @@ int parse_login(int fd)
WFIFOSET(fd,3); WFIFOSET(fd,3);
} else { } else {
WFIFOHEAD(fd,47+32*MAX_SERVERS); WFIFOHEAD(fd,47+32*MAX_SERVERS);
if (p[0] != 127 && login_config.log_login) { 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, (unsigned int)ntohl(ipl), t_uid); sprintf(tmpsql,"INSERT DELAYED INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '%u', '%s','100', 'login ok')", loginlog_db, ipl, t_uid);
//query //query
if(mysql_query(&mysql_handle, tmpsql)) { if(mysql_query(&mysql_handle, tmpsql)) {
ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); 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); ShowStatus("Connection of the GM (level:%d) account '%s' accepted.\n", account.level, account.userid);
else else
ShowStatus("Connection of the account '%s' accepted.\n", account.userid); ShowStatus("Connection of the account '%s' accepted.\n", account.userid);
server_num=0;
server_num = 0;
for(i = 0; i < MAX_SERVERS; i++) { for(i = 0; i < MAX_SERVERS; i++) {
if (server_fd[i] >= 0) { if (server_fd[i] >= 0) {
// Advanced subnet check [LuzZza] // Advanced subnet check [LuzZza]
if((subnet_char_ip = lan_subnetcheck(ipl))) uint32 subnet_char_ip = lan_subnetcheck(ipl);
WFIFOL(fd,47+server_num*32) = subnet_char_ip; WFIFOL(fd,47+server_num*32) = (subnet_char_ip) ? htonl(subnet_char_ip) : htonl(server[i].ip);
else WFIFOW(fd,47+server_num*32+4) = server[i].port; // /!\ must be sent in intel host byte order /!\ (client bug)
WFIFOL(fd,47+server_num*32) = server[i].ip;
WFIFOW(fd,47+server_num*32+4) = server[i].port;
memcpy(WFIFOP(fd,47+server_num*32+6), server[i].name, 20); 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+26) = server[i].users;
WFIFOW(fd,47+server_num*32+28) = server[i].maintenance; WFIFOW(fd,47+server_num*32+28) = server[i].maintenance;
@ -1477,34 +1473,33 @@ int parse_login(int fd)
server_num++; server_num++;
} }
} }
// if at least 1 char-server if (server_num > 0) { // if at least 1 char-server
if (server_num > 0) { WFIFOW(fd,0) = 0x69;
WFIFOW(fd,0)=0x69; WFIFOW(fd,2) = 47+32*server_num;
WFIFOW(fd,2)=47+32*server_num; WFIFOL(fd,4) = account.login_id1;
WFIFOL(fd,4)=account.login_id1; WFIFOL(fd,8) = account.account_id;
WFIFOL(fd,8)=account.account_id; WFIFOL(fd,12) = account.login_id2;
WFIFOL(fd,12)=account.login_id2; WFIFOL(fd,16) = 0; // in old version, that was for ip (not more used)
WFIFOL(fd,16)=0; //memcpy(WFIFOP(fd,20), account.lastlogin, 24); // in old version, that was for name (not more used)
//memcpy(WFIFOP(fd,20),account.lastlogin,24); WFIFOB(fd,46) = account.sex;
WFIFOB(fd,46)=account.sex;
WFIFOSET(fd,47+32*server_num); WFIFOSET(fd,47+32*server_num);
if(auth_fifo_pos>=AUTH_FIFO_SIZE) if (auth_fifo_pos >= AUTH_FIFO_SIZE)
auth_fifo_pos=0; auth_fifo_pos = 0;
auth_fifo[auth_fifo_pos].account_id=account.account_id; 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_id1 = account.login_id1;
auth_fifo[auth_fifo_pos].login_id2=account.login_id2; auth_fifo[auth_fifo_pos].login_id2 = account.login_id2;
auth_fifo[auth_fifo_pos].sex=account.sex; auth_fifo[auth_fifo_pos].sex = account.sex;
auth_fifo[auth_fifo_pos].delflag=0; auth_fifo[auth_fifo_pos].delflag = 0;
auth_fifo[auth_fifo_pos].ip = session[fd]->client_addr.sin_addr.s_addr; auth_fifo[auth_fifo_pos].ip = session[fd]->client_addr;
auth_fifo_pos++; 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; WFIFOW(fd,0) = 0x81;
WFIFOB(fd,2) = 1; // 01 = Server closed WFIFOB(fd,2) = 1; // 01 = Server closed
WFIFOSET(fd,3); WFIFOSET(fd,3);
} }
} }
} else { } else { // auth failed
WFIFOHEAD(fd,23); WFIFOHEAD(fd, 23);
if (login_config.log_login) if (login_config.log_login)
{ {
const char* error; const char* error;
@ -1536,7 +1531,7 @@ int parse_login(int fd)
default : error = "Unknown Error."; break; 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 //query
if(mysql_query(&mysql_handle, tmpsql)) { 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 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", 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)) { if(mysql_query(&mysql_handle, tmpsql)) {
ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); ShowSQL("DB error - %s\n",mysql_error(&mysql_handle));
ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); 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 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 ) { 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)) { if(mysql_query(&mysql_handle, tmpsql)) {
ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); ShowSQL("DB error - %s\n",mysql_error(&mysql_handle));
ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); 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); if(sql_res) mysql_free_result(sql_res);
} }
else if (result == -2){ //dynamic banned - add ip to ban list. 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)) { if(mysql_query(&mysql_handle, tmpsql)) {
ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); ShowSQL("DB error - %s\n",mysql_error(&mysql_handle));
ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); 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_res = mysql_store_result(&mysql_handle) ;
sql_row = sql_res?mysql_fetch_row(sql_res):NULL; sql_row = sql_res?mysql_fetch_row(sql_res):NULL;
//cannot connect login failed //cannot connect login failed
memset(WFIFOP(fd,0),'\0',23); memset(WFIFOP(fd,0), '\0', 23);
WFIFOW(fd,0)=0x6a; WFIFOW(fd,0) = 0x6a;
WFIFOB(fd,2)=result; WFIFOB(fd,2) = result;
if (result == 6) { // 6 = Your are Prohibited to log in until %s if (result == 6) { // 6 = Your are Prohibited to log in until %s
char tmpstr[20]; char tmpstr[20];
time_t ban_until_time = (sql_row) ? atol(sql_row[0]) : 0; time_t ban_until_time = (sql_row) ? atol(sql_row[0]) : 0;
strftime(tmpstr, 20, login_config.date_format, localtime(&ban_until_time)); strftime(tmpstr, 20, login_config.date_format, localtime(&ban_until_time)); tmpstr[19] = '\0';
tmpstr[19] = '\0';
strncpy(WFIFOP(fd,3), tmpstr, 20); // ban timestamp goes here strncpy(WFIFOP(fd,3), tmpstr, 20); // ban timestamp goes here
} }
WFIFOSET(fd,23); WFIFOSET(fd,23);
if (sql_res) mysql_free_result(sql_res);
} }
RFIFOSKIP(fd,packet_len); RFIFOSKIP(fd,packet_len);
break; break;
}
case 0x01db: // request password key case 0x01db: // request password key
if (session[fd]->session_data) { if (session[fd]->session_data) {
@ -1606,41 +1606,39 @@ int parse_login(int fd)
return 0; 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); 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; break;
case 0x2710: // request Char-server connection case 0x2710: // Connection request of a char-server
if(RFIFOREST(fd)<86) if (RFIFOREST(fd) < 86)
return 0; return 0;
{ {
char* server_name; char* server_name;
uint32 server_ip;
uint16 server_port;
WFIFOHEAD(fd, 3); WFIFOHEAD(fd, 3);
memcpy(account.userid,RFIFOP(fd, 2),NAME_LENGTH); memcpy(account.userid,RFIFOP(fd, 2),NAME_LENGTH); account.userid[23] = '\0';
account.userid[23] = '\0'; memcpy(account.passwd,RFIFOP(fd, 26),NAME_LENGTH); account.passwd[23] = '\0';
memcpy(account.passwd,RFIFOP(fd, 26),NAME_LENGTH);
account.passwd[23] = '\0';
account.passwdenc = 0; account.passwdenc = 0;
server_name = (char*)RFIFOP(fd,60); server_name = (char*)RFIFOP(fd,60); server_name[20] = '\0';
server_name[20] = '\0'; server_ip = ntohl(RFIFOL(fd, 54));
ShowInfo("server connection request %s @ %d.%d.%d.%d:%d (%d.%d.%d.%d)\n", server_port = ntohs(RFIFOW(fd, 58));
server_name, RFIFOB(fd, 54), RFIFOB(fd, 55), RFIFOB(fd, 56), RFIFOB(fd, 57), RFIFOW(fd, 58), ShowInfo("Connection request of the char-server '%s' @ %d.%d.%d.%d:%d (ip: %s)\n",
p[0], p[1], p[2], p[3]); server_name, CONVIP(server_ip), server_port, ip);
jstrescapecpy(t_uid,server_name); jstrescapecpy(t_uid, server_name);
if (login_config.log_login) if (login_config.log_login)
{ {
char t_login[50]; char t_login[50];
jstrescapecpy(t_login,account.userid); 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')", 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), loginlog_db, ipl, t_login, t_uid, t_uid, CONVIP(server_ip), server_port);
t_login, t_uid, t_uid,
RFIFOB(fd, 54), RFIFOB(fd, 55), RFIFOB(fd, 56), RFIFOB(fd, 57),
RFIFOW(fd, 58));
//query //query
if(mysql_query(&mysql_handle, tmpsql)) { if(mysql_query(&mysql_handle, tmpsql)) {
@ -1648,19 +1646,18 @@ int parse_login(int fd)
ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); 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); ShowStatus("Connection of the char-server '%s' accepted.\n", server_name);
memset(&server[account.account_id], 0, sizeof(struct mmo_char_server)); memset(&server[account.account_id], 0, sizeof(struct mmo_char_server));
server[account.account_id].ip=RFIFOL(fd,54); server[account.account_id].ip = ntohl(RFIFOL(fd,54));
server[account.account_id].port=RFIFOW(fd,58); server[account.account_id].port = ntohs(RFIFOW(fd,58));
memcpy(server[account.account_id].name,server_name,20); memcpy(server[account.account_id].name, server_name, 20);
server[account.account_id].users=0; server[account.account_id].users = 0;
server[account.account_id].maintenance=RFIFOW(fd,82); server[account.account_id].maintenance = RFIFOW(fd,82);
server[account.account_id].new_=RFIFOW(fd,84); server[account.account_id].new_ = RFIFOW(fd,84);
server_fd[account.account_id]=fd; server_fd[account.account_id] = fd;
sprintf(tmpsql,"DELETE FROM `sstatus` WHERE `index`='%d'", account.account_id); sprintf(tmpsql,"DELETE FROM `sstatus` WHERE `index`='%d'", account.account_id);
//query //query
if(mysql_query(&mysql_handle, tmpsql)) { if(mysql_query(&mysql_handle, tmpsql)) {
@ -1675,42 +1672,43 @@ int parse_login(int fd)
ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); ShowSQL("DB error - %s\n",mysql_error(&mysql_handle));
ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql);
} }
WFIFOW(fd,0)=0x2711; WFIFOW(fd,0) = 0x2711;
WFIFOB(fd,2)=0; WFIFOB(fd,2) = 0;
WFIFOSET(fd,3); WFIFOSET(fd,3);
session[fd]->func_parse=parse_fromchar; session[fd]->func_parse = parse_fromchar;
realloc_fifo(fd,FIFOSIZE_SERVERLINK,FIFOSIZE_SERVERLINK); realloc_fifo(fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK);
// send GM account to char-server // send GM account to char-server
send_GM_accounts(fd); send_GM_accounts(fd);
} else { } else {
WFIFOW(fd, 0) =0x2711; WFIFOW(fd,0) = 0x2711;
WFIFOB(fd, 2)=3; WFIFOB(fd,2) = 3;
WFIFOSET(fd, 3); WFIFOSET(fd,3);
} }
} }
RFIFOSKIP(fd, 86); RFIFOSKIP(fd,86);
return 0; return 0;
case 0x7530: // request Athena information case 0x7530: // request Athena information
{ {
ShowInfo ("Athena version check...\n");
WFIFOHEAD(fd,10); WFIFOHEAD(fd,10);
WFIFOW(fd,0)=0x7531; WFIFOW(fd,0) = 0x7531;
WFIFOB(fd,2)=ATHENA_MAJOR_VERSION; WFIFOB(fd,2) = ATHENA_MAJOR_VERSION;
WFIFOB(fd,3)=ATHENA_MINOR_VERSION; WFIFOB(fd,3) = ATHENA_MINOR_VERSION;
WFIFOB(fd,4)=ATHENA_REVISION; WFIFOB(fd,4) = ATHENA_REVISION;
WFIFOB(fd,5)=ATHENA_RELEASE_FLAG; WFIFOB(fd,5) = ATHENA_RELEASE_FLAG;
WFIFOB(fd,6)=ATHENA_OFFICIAL_FLAG; WFIFOB(fd,6) = ATHENA_OFFICIAL_FLAG;
WFIFOB(fd,7)=ATHENA_SERVER_LOGIN; WFIFOB(fd,7) = ATHENA_SERVER_LOGIN;
WFIFOW(fd,8)=ATHENA_MOD_VERSION; WFIFOW(fd,8) = ATHENA_MOD_VERSION;
WFIFOSET(fd,10); WFIFOSET(fd,10);
RFIFOSKIP(fd,2); RFIFOSKIP(fd,2);
ShowInfo ("Athena version check...\n");
break; break;
} }
case 0x7532: case 0x7532: // Request to end connection
ShowStatus ("End of connection (ip: %s)" RETCODE, ip); ShowStatus ("End of connection (ip: %s)" RETCODE, ip);
session[fd]->eof = 1; session[fd]->eof = 1;
break; break;
default: default:
ShowStatus ("Abnormal end of connection (ip: %s): Unknown packet 0x%x " RETCODE, ip, RFIFOW(fd,0)); ShowStatus ("Abnormal end of connection (ip: %s): Unknown packet 0x%x " RETCODE, ip, RFIFOW(fd,0));
session[fd]->eof = 1; session[fd]->eof = 1;
@ -1782,7 +1780,6 @@ int config_switch(const char *str)
return atoi(str); return atoi(str);
} }
//---------------------------------- //----------------------------------
// Reading Lan Support configuration // 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') if ((line[0] == '/' && line[1] == '/') || line[0] == '\n' || line[1] == '\n')
continue; continue;
line[sizeof(line)-1] = '\0'; line[sizeof(line)-1] = '\0';
if(sscanf(line,"%[^:]: %[^:]:%[^:]:%[^\r\n]", w1, w2, w3, w4) != 4) { if(sscanf(line,"%[^:]: %[^:]:%[^:]:%[^\r\n]", w1, w2, w3, w4) != 4) {
ShowWarning("Error syntax of configuration file %s in line %d.\n", lancfgName, line_num); 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) { if(strcmpi(w1, "subnet") == 0) {
subnet[subnet_count].mask = inet_addr(w2); subnet[subnet_count].mask = ntohl(inet_addr(w2));
subnet[subnet_count].char_ip = inet_addr(w3); subnet[subnet_count].char_ip = ntohl(inet_addr(w3));
subnet[subnet_count].map_ip = inet_addr(w4); subnet[subnet_count].map_ip = ntohl(inet_addr(w4));
subnet[subnet_count].subnet = subnet[subnet_count].char_ip&subnet[subnet_count].mask; 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)) { 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); 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; return 0;
} }
//----------------------------------------------------- //-----------------------------------
// Reading main configuration file // Reading main configuration file
//----------------------------------------------------- //-----------------------------------
int login_config_read(const char* cfgName) int login_config_read(const char* cfgName)
{ {
char line[1024], w1[1024], w2[1024]; char line[1024], w1[1024], w2[1024];
@ -1867,11 +1864,12 @@ int login_config_read(const char* cfgName)
{ {
if (line[0] == '/' && line[1] == '/') if (line[0] == '/' && line[1] == '/')
continue; continue;
if (sscanf(line, "%[^:]: %[^\r\n]", w1, w2) < 2) if (sscanf(line, "%[^:]: %[^\r\n]", w1, w2) < 2)
continue; continue;
remove_control_chars((unsigned char *) w1); remove_control_chars((unsigned char *)w1);
remove_control_chars((unsigned char *) w2); remove_control_chars((unsigned char *)w2);
if(!strcmpi(w1,"timestamp_format")) { if(!strcmpi(w1,"timestamp_format")) {
strncpy(timestamp_format, w2, 20); strncpy(timestamp_format, w2, 20);
@ -1890,6 +1888,9 @@ int login_config_read(const char* cfgName)
login_config.login_port = (unsigned short)atoi(w2); login_config.login_port = (unsigned short)atoi(w2);
ShowStatus("set login_port : %s\n",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")) else if (!strcmpi(w1,"ipban"))
login_config.ipban = config_switch(w2); login_config.ipban = config_switch(w2);
else if (!strcmpi(w1,"dynamic_pass_failure_ban")) else if (!strcmpi(w1,"dynamic_pass_failure_ban"))
@ -1923,8 +1924,6 @@ int login_config_read(const char* cfgName)
time_allowed = atoi(w2); time_allowed = atoi(w2);
else if (!strcmpi(w1, "online_check")) else if (!strcmpi(w1, "online_check"))
login_config.online_check = config_switch(w2); 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")) else if (!strcmpi(w1,"use_dnsbl"))
login_config.use_dnsbl = config_switch(w2); login_config.use_dnsbl = config_switch(w2);
else if (!strcmpi(w1,"dnsbl_servers")) else if (!strcmpi(w1,"dnsbl_servers"))

View File

@ -42,8 +42,8 @@ struct mmo_account {
struct mmo_char_server { struct mmo_char_server {
char name[20]; char name[20];
long ip; uint32 ip;
short port; uint16 port;
int users; int users;
int maintenance; int maintenance;
int new_; int new_;

View File

@ -24,18 +24,14 @@
#include "status.h" #include "status.h"
#include "mercenary.h" #include "mercenary.h"
//Updated table (only doc^^) [Sirius]
//Used Packets: U->2af8
//Free Packets: F->2af8
struct dbt *auth_db; struct dbt *auth_db;
static const int packet_len_table[0x3d] = { static const int packet_len_table[0x3d] = { // U - used, F - free
60, 3,-1,27,10,-1, 6,-1, // 2af8-2aff: U->2af8, U->2af9, U->2afa, U->2afb, U->2afc, U->2afd, U->2afe, U->2aff 60, 3,-1,27,10,-1, 6,-1, // 2af8-2aff: U->2af8, U->2af9, U->2afa, U->2afb, U->2afc, U->2afd, U->2afe, U->2aff
6,-1,18, 7,-1,49,30,10, // 2b00-2b07: U->2b00, U->2b01, U->2b02, U->2b03, U->2b04, U->2b05, U->2b06, U->2b07 6,-1,18, 7,-1,49,30,10, // 2b00-2b07: U->2b00, U->2b01, U->2b02, U->2b03, U->2b04, U->2b05, U->2b06, U->2b07
6,30,-1,10,86, 7,44,34, // 2b08-2b0f: U->2b08, U->2b09, U->2b0a, U->2b0b, U->2b0c, U->2b0d, U->2b0e, U->2b0f 6,30,-1,10,86, 7,44,34, // 2b08-2b0f: U->2b08, U->2b09, U->2b0a, U->2b0b, U->2b0c, U->2b0d, U->2b0e, U->2b0f
0,-1,10, 6,11,-1, 0, 0, // 2b10-2b17: U->2b10, U->2b11, U->2b12, U->2b13, U->2b14, U->2b15, U->2b16, U->2b17 0,-1,10, 6,11,-1, 0, 0, // 2b10-2b17: U->2b10, U->2b11, U->2b12, U->2b13, U->2b14, U->2b15, U->2b16, U->2b17
-1,-1,-1,-1,-1,-1, 2, 7, // 2b18-2b1f: U->2b18, U->2b19, U->2b1a, U->2b1b, U->2b1c, U->2b1d, U->2b1e, U->2b1f -1,-1,-1,-1,-1,-1, 2, 7, // 2b18-2b1f: U->2b18, U->2b19, U->2b1a, U->2b1b, U->2b1c, U->2b1d, U->2b1e, U->2b1f
-1,10, 8,-1,-1,-1,-1,-1, // 2b20-2b27: U->2b20, U->2b21, U->2b22, U->2b23, F->2b24, F->2b25, F->2b26, F->2b27 -1,10, 8,-1,-1,-1,-1,-1, // 2b20-2b27: U->2b20, U->2b21, U->2b22, U->2b23, F->2b24, F->2b25, F->2b26, F->2b27
}; };
@ -89,8 +85,8 @@ int chrif_connected = 0;
int char_fd = 0; //Using 0 instead of -1 is safer against crashes. [Skotlex] int char_fd = 0; //Using 0 instead of -1 is safer against crashes. [Skotlex]
int srvinfo; int srvinfo;
static char char_ip_str[128]; static char char_ip_str[128];
static in_addr_t char_ip= 0; static uint32 char_ip = 0;
static int char_port = 6121; static uint16 char_port = 6121;
static char userid[NAME_LENGTH], passwd[NAME_LENGTH]; static char userid[NAME_LENGTH], passwd[NAME_LENGTH];
static int chrif_state = 0; static int chrif_state = 0;
static int char_init_done = 0; static int char_init_done = 0;
@ -103,29 +99,20 @@ int other_mapserver_count=0; //Holds count of how many other map servers are onl
//This define should spare writing the check in every function. [Skotlex] //This define should spare writing the check in every function. [Skotlex]
#define chrif_check(a) { if(!chrif_isconnect()) return a; } #define chrif_check(a) { if(!chrif_isconnect()) return a; }
// 設定ファイル読み込み関係
/*========================================== // sets char-server's user id
*
*------------------------------------------
*/
void chrif_setuserid(char *id) void chrif_setuserid(char *id)
{ {
memcpy(userid, id, NAME_LENGTH); memcpy(userid, id, NAME_LENGTH);
} }
/*========================================== // sets char-server's password
*
*------------------------------------------
*/
void chrif_setpasswd(char *pwd) void chrif_setpasswd(char *pwd)
{ {
memcpy(passwd, pwd, NAME_LENGTH); memcpy(passwd, pwd, NAME_LENGTH);
} }
/*========================================== // security check, prints warning if using default password
*
*------------------------------------------
*/
void chrif_checkdefaultlogin(void) void chrif_checkdefaultlogin(void)
{ {
if (strcmp(userid, "s1")==0 && strcmp(passwd, "p1")==0) { if (strcmp(userid, "s1")==0 && strcmp(passwd, "p1")==0) {
@ -139,11 +126,8 @@ void chrif_checkdefaultlogin(void)
} }
} }
/*========================================== // sets char-server's ip address
* int chrif_setip(const char* ip)
*------------------------------------------
*/
int chrif_setip(const char *ip)
{ {
char ip_str[16]; char ip_str[16];
char_ip = host2ip(ip); char_ip = host2ip(ip);
@ -156,30 +140,23 @@ int chrif_setip(const char *ip)
return 1; return 1;
} }
/*========================================== // sets char-server's port number
* void chrif_setport(uint16 port)
*------------------------------------------
*/
void chrif_setport(int port)
{ {
char_port = port; char_port = port;
} }
/*========================================== // says whether the char-server is connected or not
*
*------------------------------------------
*/
int chrif_isconnect(void) int chrif_isconnect(void)
{ {
return (char_fd > 0 && session[char_fd] != NULL && chrif_state == 2); return (char_fd > 0 && session[char_fd] != NULL && chrif_state == 2);
} }
/*========================================== /*==========================================
* Saves char. * Saves character data.
* Flag = 1: Character is quitting. * Flag = 1: Character is quitting
* Flag = 2: Character is changing map-servers * Flag = 2: Character is changing map-servers
*------------------------------------------ *------------------------------------------*/
*/
int chrif_save(struct map_session_data *sd, int flag) int chrif_save(struct map_session_data *sd, int flag)
{ {
nullpo_retr(-1, sd); nullpo_retr(-1, sd);
@ -226,10 +203,7 @@ int chrif_save(struct map_session_data *sd, int flag)
return 0; return 0;
} }
/*========================================== // connects to char-server (plaintext)
*
*------------------------------------------
*/
int chrif_connect(int fd) int chrif_connect(int fd)
{ {
ShowStatus("Logging in to char server...\n", char_fd); ShowStatus("Logging in to char server...\n", char_fd);
@ -238,17 +212,14 @@ int chrif_connect(int fd)
memcpy(WFIFOP(fd,2), userid, NAME_LENGTH); memcpy(WFIFOP(fd,2), userid, NAME_LENGTH);
memcpy(WFIFOP(fd,26), passwd, NAME_LENGTH); memcpy(WFIFOP(fd,26), passwd, NAME_LENGTH);
WFIFOL(fd,50) = 0; WFIFOL(fd,50) = 0;
WFIFOL(fd,54) = clif_getip_long(); WFIFOL(fd,54) = htonl(clif_getip());
WFIFOW(fd,58) = clif_getport(); // [Valaris] thanks to fov WFIFOW(fd,58) = htons(clif_getport());
WFIFOSET(fd,60); WFIFOSET(fd,60);
return 0; return 0;
} }
/*========================================== // sends maps to char-server
*
*------------------------------------------
*/
int chrif_sendmap(int fd) int chrif_sendmap(int fd)
{ {
int i; int i;
@ -263,36 +234,31 @@ int chrif_sendmap(int fd)
return 0; return 0;
} }
/*========================================== // receive maps from some other map-server (relayed via char-server)
*
*------------------------------------------
*/
int chrif_recvmap(int fd) int chrif_recvmap(int fd)
{ {
int i, j, ip, port; int i, j;
unsigned char *p = (unsigned char *)&ip; uint32 ip;
uint16 port;
RFIFOHEAD(fd); RFIFOHEAD(fd);
ip = RFIFOL(fd,4); ip = ntohl(RFIFOL(fd,4));
port = RFIFOW(fd,8); port = ntohs(RFIFOW(fd,8));
for(i = 10, j = 0; i < RFIFOW(fd,2); i += 4, j++) { for(i = 10, j = 0; i < RFIFOW(fd,2); i += 4, j++) {
map_setipport(RFIFOW(fd,i), ip, port); map_setipport(RFIFOW(fd,i), ip, port);
// if (battle_config.etc_log)
// printf("recv map %d %s\n", j, RFIFOP(fd,i));
} }
if (battle_config.etc_log) if (battle_config.etc_log)
ShowStatus("recv map on %d.%d.%d.%d:%d (%d maps)\n", p[0], p[1], p[2], p[3], port, j); ShowStatus("Received maps from %d.%d.%d.%d:%d (%d maps)\n", CONVIP(ip), port, j);
other_mapserver_count++; other_mapserver_count++;
return 0; return 0;
} }
/*========================================== // remove specified maps (used when some other map-server disconnects)
* Delete maps of other servers, (if an other mapserver is going OFF) int chrif_removemap(int fd)
*------------------------------------------ {
*/ int i, j;
int chrif_removemap(int fd){ uint32 ip;
int i, j, ip, port; uint16 port;
unsigned char *p = (unsigned char *)&ip;
RFIFOHEAD(fd); RFIFOHEAD(fd);
ip = RFIFOL(fd, 4); ip = RFIFOL(fd, 4);
@ -304,11 +270,13 @@ int chrif_removemap(int fd){
other_mapserver_count--; other_mapserver_count--;
if(battle_config.etc_log) if(battle_config.etc_log)
ShowStatus("remove map of server %d.%d.%d.%d:%d (%d maps)\n", p[0], p[1], p[2], p[3], port, j); ShowStatus("remove map of server %d.%d.%d.%d:%d (%d maps)\n", CONVIP(ip), port, j);
return 0; return 0;
} }
int chrif_save_ack(int fd) { // received after a character has been "final saved" on the char-server
int chrif_save_ack(int fd)
{
struct map_session_data *sd; struct map_session_data *sd;
RFIFOHEAD(fd); RFIFOHEAD(fd);
sd = map_id2sd(RFIFOL(fd,2)); sd = map_id2sd(RFIFOL(fd,2));
@ -318,13 +286,10 @@ int chrif_save_ack(int fd) {
return 0; return 0;
} }
/*========================================== // request to move a character between mapservers
* int chrif_changemapserver(struct map_session_data *sd, short map, int x, int y, uint32 ip, uint16 port)
*------------------------------------------
*/
int chrif_changemapserver(struct map_session_data *sd, short map, int x, int y, int ip, short port)
{ {
int s_ip; uint32 s_ip;
nullpo_retr(-1, sd); nullpo_retr(-1, sd);
@ -337,7 +302,7 @@ int chrif_changemapserver(struct map_session_data *sd, short map, int x, int y,
} }
if (sd->fd && sd->fd < fd_max && session[sd->fd]) if (sd->fd && sd->fd < fd_max && session[sd->fd])
s_ip = session[sd->fd]->client_addr.sin_addr.s_addr; s_ip = session[sd->fd]->client_addr;
else //Not connected? Can't retrieve IP else //Not connected? Can't retrieve IP
s_ip = 0; s_ip = 0;
@ -350,19 +315,16 @@ int chrif_changemapserver(struct map_session_data *sd, short map, int x, int y,
WFIFOW(char_fd,18) = map; WFIFOW(char_fd,18) = map;
WFIFOW(char_fd,20) = x; WFIFOW(char_fd,20) = x;
WFIFOW(char_fd,22) = y; WFIFOW(char_fd,22) = y;
WFIFOL(char_fd,24) = ip; WFIFOL(char_fd,24) = htonl(ip);
WFIFOW(char_fd,28) = port; WFIFOW(char_fd,28) = htons(port);
WFIFOB(char_fd,30) = sd->status.sex; WFIFOB(char_fd,30) = sd->status.sex;
WFIFOL(char_fd,31) = s_ip; WFIFOL(char_fd,31) = htonl(s_ip); // not used
WFIFOSET(char_fd,35); WFIFOSET(char_fd,35);
return 0; return 0;
} }
/*========================================== // map-server change request acknowledgement (positive or negative)
* ack
*------------------------------------------
*/
int chrif_changemapserverack(int fd) int chrif_changemapserverack(int fd)
{ {
struct map_session_data *sd; struct map_session_data *sd;
@ -380,7 +342,7 @@ int chrif_changemapserverack(int fd)
return 0; return 0;
} }
sprintf(mapname, "%s.gat", mapindex_id2name(RFIFOW(fd,18))); sprintf(mapname, "%s.gat", mapindex_id2name(RFIFOW(fd,18)));
clif_changemapserver(sd, mapname, RFIFOW(fd,20), RFIFOW(fd,22), RFIFOL(fd,24), RFIFOW(fd,28)); clif_changemapserver(sd, mapname, RFIFOW(fd,20), RFIFOW(fd,22), ntohl(RFIFOL(fd,24)), ntohs(RFIFOW(fd,28)));
//Player has been saved already, remove him from memory. [Skotlex] //Player has been saved already, remove him from memory. [Skotlex]
map_quit(sd); map_quit(sd);
@ -390,8 +352,7 @@ int chrif_changemapserverack(int fd)
/*========================================== /*==========================================
* *
*------------------------------------------ *------------------------------------------*/
*/
int chrif_connectack(int fd) int chrif_connectack(int fd)
{ {
RFIFOHEAD(fd); RFIFOHEAD(fd);
@ -568,7 +529,7 @@ int auth_db_cleanup(int tid, unsigned int tick, int id, int data) {
* *
*------------------------------------------ *------------------------------------------
*/ */
int chrif_charselectreq(struct map_session_data *sd, unsigned long s_ip) int chrif_charselectreq(struct map_session_data* sd, uint32 s_ip)
{ {
nullpo_retr(-1, sd); nullpo_retr(-1, sd);
@ -581,7 +542,7 @@ int chrif_charselectreq(struct map_session_data *sd, unsigned long s_ip)
WFIFOL(char_fd, 2) = sd->bl.id; WFIFOL(char_fd, 2) = sd->bl.id;
WFIFOL(char_fd, 6) = sd->login_id1; WFIFOL(char_fd, 6) = sd->login_id1;
WFIFOL(char_fd,10) = sd->login_id2; WFIFOL(char_fd,10) = sd->login_id2;
WFIFOL(char_fd,14) = s_ip; WFIFOL(char_fd,14) = htonl(s_ip);
WFIFOSET(char_fd,18); WFIFOSET(char_fd,18);
return 0; return 0;
@ -693,7 +654,6 @@ int chrif_changesex(int id, int sex) {
WFIFOW(char_fd,2) = 9; WFIFOW(char_fd,2) = 9;
WFIFOL(char_fd,4) = id; WFIFOL(char_fd,4) = id;
WFIFOB(char_fd,8) = sex; WFIFOB(char_fd,8) = sex;
// ShowInfo("chrif : sent 0x3000(changesex)\n");
WFIFOSET(char_fd,9); WFIFOSET(char_fd,9);
return 0; return 0;
} }
@ -1040,7 +1000,8 @@ int chrif_accountban(int fd)
//Disconnect the player out of the game, simple packet //Disconnect the player out of the game, simple packet
//packet.w AID.L WHY.B 2+4+1 = 7byte //packet.w AID.L WHY.B 2+4+1 = 7byte
int chrif_disconnectplayer(int fd){ int chrif_disconnectplayer(int fd)
{
struct map_session_data *sd; struct map_session_data *sd;
RFIFOHEAD(fd); RFIFOHEAD(fd);
@ -1419,7 +1380,7 @@ int chrif_disconnect(int fd) {
void chrif_update_ip(int fd) void chrif_update_ip(int fd)
{ {
unsigned long new_ip; uint32 new_ip;
WFIFOHEAD(fd, 6); WFIFOHEAD(fd, 6);
new_ip = host2ip(char_ip_str); new_ip = host2ip(char_ip_str);
if (new_ip && new_ip != char_ip) if (new_ip && new_ip != char_ip)
@ -1428,7 +1389,7 @@ void chrif_update_ip(int fd)
new_ip = clif_refresh_ip(); new_ip = clif_refresh_ip();
if (!new_ip) return; //No change if (!new_ip) return; //No change
WFIFOW(fd, 0) = 0x2736; WFIFOW(fd, 0) = 0x2736;
WFIFOL(fd, 2) = new_ip; WFIFOL(fd, 2) = htonl(new_ip);
WFIFOSET(fd, 6); WFIFOSET(fd, 6);
} }
@ -1452,7 +1413,7 @@ int chrif_parse(int fd)
return 0; return 0;
} }
while (RFIFOREST(fd) >= 2 && !session[fd]->eof) { //Infinite loop on broken pipe fix. [Skotlex] while (RFIFOREST(fd) >= 2) { //Infinite loop on broken pipe fix. [Skotlex]
RFIFOHEAD(fd); RFIFOHEAD(fd);
cmd = RFIFOW(fd,0); cmd = RFIFOW(fd,0);
if (cmd < 0x2af8 || cmd >= 0x2af8 + (sizeof(packet_len_table) / sizeof(packet_len_table[0])) || if (cmd < 0x2af8 || cmd >= 0x2af8 + (sizeof(packet_len_table) / sizeof(packet_len_table[0])) ||

View File

@ -12,11 +12,11 @@ struct auth_node{
unsigned int node_created; //For node auto-deleting unsigned int node_created; //For node auto-deleting
}; };
void chrif_setuserid(char*); void chrif_setuserid(char* id);
void chrif_setpasswd(char*); void chrif_setpasswd(char* pwd);
void chrif_checkdefaultlogin(void); void chrif_checkdefaultlogin(void);
int chrif_setip(const char*); int chrif_setip(const char* ip);
void chrif_setport(int); void chrif_setport(uint16 port);
int chrif_isconnect(void); int chrif_isconnect(void);
@ -27,9 +27,9 @@ void chrif_authreq(struct map_session_data *);
void chrif_authok(int fd); void chrif_authok(int fd);
int chrif_scdata_request(int account_id, int char_id); int chrif_scdata_request(int account_id, int char_id);
int chrif_save(struct map_session_data*, int flag); int chrif_save(struct map_session_data*, int flag);
int chrif_charselectreq(struct map_session_data *sd, unsigned long s_ip); int chrif_charselectreq(struct map_session_data*sd, uint32 s_ip);
void check_fake_id(int fd, struct map_session_data *sd, int target_id); void check_fake_id(int fd, struct map_session_data *sd, int target_id);
int chrif_changemapserver(struct map_session_data *sd,short map,int x,int y,int ip,short port); int chrif_changemapserver(struct map_session_data*sd, short map, int x, int y, uint32 ip, uint16 port);
int chrif_searchcharid(int char_id); int chrif_searchcharid(int char_id);
int chrif_changegm(int id,const char *pass,int len); int chrif_changegm(int id,const char *pass,int len);

View File

@ -96,9 +96,9 @@ struct packet_db packet_db[MAX_PACKET_VER + 1][MAX_PACKET_DB];
//Guarantees that the given string does not exceeds the allowed size, as well as making sure it's null terminated. [Skotlex\] //Guarantees that the given string does not exceeds the allowed size, as well as making sure it's null terminated. [Skotlex\]
#define mes_len_check(mes, len, max) if (len > max) { mes[max-1] = '\0'; len = max; } else mes[len-1] = '\0'; #define mes_len_check(mes, len, max) if (len > max) { mes[max-1] = '\0'; len = max; } else mes[len-1] = '\0';
static char map_ip_str[128]; static char map_ip_str[128];
static in_addr_t map_ip; static uint32 map_ip;
static in_addr_t bind_ip = INADDR_ANY; static uint32 bind_ip = INADDR_ANY;
static int map_port = 5121; static uint16 map_port = 5121;
int map_fd; int map_fd;
//These two will be used to verify the incoming player's validity. //These two will be used to verify the incoming player's validity.
@ -142,7 +142,7 @@ void clif_setbindip(const char* ip)
* map鯖のport設定 * map鯖のport設定
*------------------------------------------ *------------------------------------------
*/ */
void clif_setport(int port) void clif_setport(uint16 port)
{ {
map_port = port; map_port = port;
} }
@ -151,27 +151,21 @@ void clif_setport(int port)
* map鯖のip読み出し * map鯖のip読み出し
*------------------------------------------ *------------------------------------------
*/ */
in_addr_t clif_getip(void) uint32 clif_getip(void)
{ {
return map_ip; return map_ip;
} }
//Returns the ip casted as a basic type, to avoid needing to include the socket/net related libs by calling modules.
unsigned long clif_getip_long(void)
{
return (unsigned long)map_ip;
}
//Refreshes map_server ip, returns the new ip if the ip changed, otherwise it returns 0. //Refreshes map_server ip, returns the new ip if the ip changed, otherwise it returns 0.
unsigned long clif_refresh_ip(void) uint32 clif_refresh_ip(void)
{ {
in_addr_t new_ip; uint32 new_ip;
new_ip = host2ip(map_ip_str); new_ip = host2ip(map_ip_str);
if (new_ip && new_ip != map_ip) { if (new_ip && new_ip != map_ip) {
map_ip = new_ip; map_ip = new_ip;
ShowInfo("Updating IP resolution of [%s].\n",map_ip_str); ShowInfo("Updating IP resolution of [%s].\n", map_ip_str);
return (unsigned long)map_ip; return map_ip;
} }
return 0; return 0;
} }
@ -180,7 +174,7 @@ unsigned long clif_refresh_ip(void)
* map鯖のport読み出し * map鯖のport読み出し
*------------------------------------------ *------------------------------------------
*/ */
int clif_getport(void) uint16 clif_getport(void)
{ {
return map_port; return map_port;
} }
@ -1625,10 +1619,10 @@ int clif_changemap(struct map_session_data *sd, short map, int x, int y) {
} }
/*========================================== /*==========================================
* * Tells the client to connect to another map-server
*------------------------------------------ *------------------------------------------*/
*/ int clif_changemapserver(struct map_session_data* sd, const char* mapname, int x, int y, uint32 ip, uint16 port)
int clif_changemapserver(struct map_session_data* sd, const char* mapname, int x, int y, int ip, int port) { {
int fd; int fd;
nullpo_retr(0, sd); nullpo_retr(0, sd);
@ -1641,8 +1635,8 @@ int clif_changemapserver(struct map_session_data* sd, const char* mapname, int x
WFIFOB(fd,17) = 0; //Null terminator for mapname WFIFOB(fd,17) = 0; //Null terminator for mapname
WFIFOW(fd,18) = x; WFIFOW(fd,18) = x;
WFIFOW(fd,20) = y; WFIFOW(fd,20) = y;
WFIFOL(fd,22) = ip; WFIFOL(fd,22) = htonl(ip);
WFIFOW(fd,26) = port; WFIFOW(fd,26) = port; // /!\ must be sent in intel host byte order /!\ (client bug)
WFIFOSET(fd, packet_len(0x92)); WFIFOSET(fd, packet_len(0x92));
return 0; return 0;
@ -8862,7 +8856,7 @@ void clif_parse_Restart(int fd, struct map_session_data *sd) {
/* Rovert's Prevent logout option - Fixed [Valaris] */ /* Rovert's Prevent logout option - Fixed [Valaris] */
if (!battle_config.prevent_logout || DIFF_TICK(gettick(), sd->canlog_tick) > battle_config.prevent_logout) if (!battle_config.prevent_logout || DIFF_TICK(gettick(), sd->canlog_tick) > battle_config.prevent_logout)
{ //Send to char-server for character selection. { //Send to char-server for character selection.
chrif_charselectreq(sd, session[fd]->client_addr.sin_addr.s_addr); chrif_charselectreq(sd, session[fd]->client_addr);
} else { } else {
WFIFOHEAD(fd,packet_len(0x18b)); WFIFOHEAD(fd,packet_len(0x18b));
WFIFOW(fd,0)=0x18b; WFIFOW(fd,0)=0x18b;
@ -11746,7 +11740,8 @@ void clif_parse_debug(int fd,struct map_session_data *sd)
* socket.cのdo_parsepacketから呼び出される * socket.cのdo_parsepacketから呼び出される
*------------------------------------------ *------------------------------------------
*/ */
int clif_parse(int fd) { int clif_parse(int fd)
{
int packet_len = 0, cmd, packet_ver, err, dump = 0; int packet_len = 0, cmd, packet_ver, err, dump = 0;
TBL_PC *sd; TBL_PC *sd;
RFIFOHEAD(fd); RFIFOHEAD(fd);
@ -11772,8 +11767,8 @@ int clif_parse(int fd) {
map_quit(sd); map_quit(sd);
} }
} else { } else {
unsigned char *ip = (unsigned char *) &session[fd]->client_addr.sin_addr; uint32 ip = session[fd]->client_addr;
ShowInfo("Closed connection from '"CL_WHITE"%d.%d.%d.%d"CL_RESET"'.\n", ip[0],ip[1],ip[2],ip[3]); ShowInfo("Closed connection from '"CL_WHITE"%d.%d.%d.%d"CL_RESET"'.\n", CONVIP(ip));
} }
do_close(fd); do_close(fd);
return 0; return 0;
@ -12321,8 +12316,8 @@ static int packetdb_readdb(void)
* *
*------------------------------------------ *------------------------------------------
*/ */
int do_init_clif(void) { int do_init_clif(void)
{
clif_config.packet_db_ver = -1; // the main packet version of the DB clif_config.packet_db_ver = -1; // the main packet version of the DB
memset(clif_config.connect_cmd, 0, sizeof(clif_config.connect_cmd)); //The default connect command will be determined after reading the packet_db [Skotlex] memset(clif_config.connect_cmd, 0, sizeof(clif_config.connect_cmd)); //The default connect command will be determined after reading the packet_db [Skotlex]

View File

@ -52,11 +52,11 @@ extern struct packet_db packet_db[MAX_PACKET_VER + 1][MAX_PACKET_DB];
int clif_setip(const char* ip); int clif_setip(const char* ip);
void clif_setbindip(const char* ip); void clif_setbindip(const char* ip);
void clif_setport(int); void clif_setport(uint16 port);
unsigned long clif_getip_long(void); uint32 clif_getip(void);
unsigned long clif_refresh_ip(void); uint32 clif_refresh_ip(void);
int clif_getport(void); uint16 clif_getport(void);
int clif_countusers(void); int clif_countusers(void);
void clif_setwaitclose(int); void clif_setwaitclose(int);
@ -75,7 +75,7 @@ int clif_spawn(struct block_list*); //area
int clif_walkok(struct map_session_data*); // self int clif_walkok(struct map_session_data*); // self
void clif_move(struct unit_data *ud); //area void clif_move(struct unit_data *ud); //area
int clif_changemap(struct map_session_data*,short,int,int); //self int clif_changemap(struct map_session_data*,short,int,int); //self
int clif_changemapserver(struct map_session_data* sd, const char* mapname, int x, int y, int ip, int port); //self int clif_changemapserver(struct map_session_data* sd, const char* mapname, int x, int y, uint32 ip, uint16 port); //self
int clif_blown(struct block_list *); // area int clif_blown(struct block_list *); // area
int clif_slide(struct block_list *,int,int); // area int clif_slide(struct block_list *,int,int); // area
int clif_fixpos(struct block_list *); // area int clif_fixpos(struct block_list *); // area

View File

@ -2077,9 +2077,9 @@ int map_mapindex2mapid(unsigned short mapindex) {
/*========================================== /*==========================================
* map名からip,port? * map名からip,port?
*------------------------------------------ *------------------------------------------*/
*/ int map_mapname2ipport(unsigned short name, uint32* ip, uint16* port)
int map_mapname2ipport(unsigned short name,int *ip,int *port) { {
struct map_data_other_server *mdos=NULL; struct map_data_other_server *mdos=NULL;
mdos = (struct map_data_other_server*)uidb_get(map_db,(unsigned int)name); mdos = (struct map_data_other_server*)uidb_get(map_db,(unsigned int)name);
@ -2349,16 +2349,17 @@ static void* create_map_data_other_server(DBKey key, va_list args) {
} }
/*========================================== /*==========================================
* dbに追加 * dbに追加
*------------------------------------------ *------------------------------------------*/
*/
int map_setipport(unsigned short mapindex,unsigned long ip,int port) { int map_setipport(unsigned short mapindex, uint32 ip, uint16 port)
{
struct map_data_other_server *mdos=NULL; struct map_data_other_server *mdos=NULL;
mdos=(struct map_data_other_server *)uidb_ensure(map_db,(unsigned int)mapindex, create_map_data_other_server); mdos=(struct map_data_other_server *)uidb_ensure(map_db,(unsigned int)mapindex, create_map_data_other_server);
if(mdos->gat) //Local map,Do nothing. Give priority to our own local maps over ones from another server. [Skotlex] if(mdos->gat) //Local map,Do nothing. Give priority to our own local maps over ones from another server. [Skotlex]
return 0; return 0;
if(ip == clif_getip_long() && port == clif_getport()) { if(ip == clif_getip() && port == clif_getport()) {
//That's odd, we received info that we are the ones with this map, but... we don't have it. //That's odd, we received info that we are the ones with this map, but... we don't have it.
ShowFatalError("map_setipport : received info that this map-server SHOULD have map '%s', but it is not loaded.\n",mapindex_id2name(mapindex)); ShowFatalError("map_setipport : received info that this map-server SHOULD have map '%s', but it is not loaded.\n",mapindex_id2name(mapindex));
exit(1); exit(1);
@ -2388,12 +2389,10 @@ int map_eraseallipport(void) {
/*========================================== /*==========================================
* dbから削除 * dbから削除
*------------------------------------------ *------------------------------------------*/
*/ int map_eraseipport(unsigned short mapindex, uint32 ip, uint16 port)
int map_eraseipport(unsigned short mapindex,unsigned long ip,int port)
{ {
struct map_data_other_server *mdos; struct map_data_other_server *mdos;
// unsigned char *p=(unsigned char *)&ip;
mdos = uidb_get(map_db,(unsigned int)mapindex); mdos = uidb_get(map_db,(unsigned int)mapindex);
if(!mdos || mdos->gat) //Map either does not exists or is a local map. if(!mdos || mdos->gat) //Map either does not exists or is a local map.

View File

@ -1109,8 +1109,8 @@ struct map_data_other_server {
char name[MAP_NAME_LENGTH]; char name[MAP_NAME_LENGTH];
unsigned short index; //Index is the map index used by the mapindex* functions. unsigned short index; //Index is the map index used by the mapindex* functions.
unsigned char *gat; // NULL固定にして判断 unsigned char *gat; // NULL固定にして判断
unsigned long ip; uint32 ip;
unsigned int port; uint16 port;
}; };
struct flooritem_data { struct flooritem_data {
@ -1339,9 +1339,9 @@ struct map_session_data * map_id2sd(int);
struct block_list * map_id2bl(int); struct block_list * map_id2bl(int);
int map_mapindex2mapid(unsigned short mapindex); int map_mapindex2mapid(unsigned short mapindex);
int map_mapname2mapid(const char* name); int map_mapname2mapid(const char* name);
int map_mapname2ipport(unsigned short,int*,int*); int map_mapname2ipport(unsigned short name, uint32* ip, uint16* port);
int map_setipport(unsigned short map,unsigned long ip,int port); int map_setipport(unsigned short map, uint32 ip, uint16 port);
int map_eraseipport(unsigned short map,unsigned long ip,int port); int map_eraseipport(unsigned short map, uint32 ip, uint16 port);
int map_eraseallipport(void); int map_eraseallipport(void);
void map_addiddb(struct block_list *); void map_addiddb(struct block_list *);
void map_deliddb(struct block_list *bl); void map_deliddb(struct block_list *bl);

View File

@ -698,20 +698,20 @@ int pc_authok(struct map_session_data *sd, int login_id2, time_t connect_until_t
sd->state.event_kill_mob = 1; sd->state.event_kill_mob = 1;
{ //Add IP field { //Add IP field
unsigned char *ip = (unsigned char *) &session[sd->fd]->client_addr.sin_addr; uint32 ip = session[sd->fd]->client_addr;
if (pc_isGM(sd)) if (pc_isGM(sd))
ShowInfo("GM '"CL_WHITE"%s"CL_RESET"' logged in." ShowInfo("GM '"CL_WHITE"%s"CL_RESET"' logged in."
" (AID/CID: '"CL_WHITE"%d/%d"CL_RESET"'," " (AID/CID: '"CL_WHITE"%d/%d"CL_RESET"',"
" Packet Ver: '"CL_WHITE"%d"CL_RESET"', IP: '"CL_WHITE"%d.%d.%d.%d"CL_RESET"'," " Packet Ver: '"CL_WHITE"%d"CL_RESET"', IP: '"CL_WHITE"%d.%d.%d.%d"CL_RESET"',"
" GM Level '"CL_WHITE"%d"CL_RESET"').\n", " GM Level '"CL_WHITE"%d"CL_RESET"').\n",
sd->status.name, sd->status.account_id, sd->status.char_id, sd->status.name, sd->status.account_id, sd->status.char_id,
sd->packet_ver, ip[0],ip[1],ip[2],ip[3], pc_isGM(sd)); sd->packet_ver, CONVIP(ip), pc_isGM(sd));
else else
ShowInfo("'"CL_WHITE"%s"CL_RESET"' logged in." ShowInfo("'"CL_WHITE"%s"CL_RESET"' logged in."
" (AID/CID: '"CL_WHITE"%d/%d"CL_RESET"'," " (AID/CID: '"CL_WHITE"%d/%d"CL_RESET"',"
" Packet Ver: '"CL_WHITE"%d"CL_RESET"', IP: '"CL_WHITE"%d.%d.%d.%d"CL_RESET"').\n", " Packet Ver: '"CL_WHITE"%d"CL_RESET"', IP: '"CL_WHITE"%d.%d.%d.%d"CL_RESET"').\n",
sd->status.name, sd->status.account_id, sd->status.char_id, sd->status.name, sd->status.account_id, sd->status.char_id,
sd->packet_ver, ip[0],ip[1],ip[2],ip[3]); sd->packet_ver, CONVIP(ip));
} }
// Send friends list // Send friends list
@ -3371,10 +3371,11 @@ int pc_setpos(struct map_session_data *sd,unsigned short mapindex,int x,int y,in
sd->regen.state.gc = 0; sd->regen.state.gc = 0;
} }
if(m<0){ if(m<0) {
if(sd->mapindex){ if(sd->mapindex) {
int ip,port; uint32 ip;
if(map_mapname2ipport(mapindex,&ip,&port)==0){ uint16 port;
if(map_mapname2ipport(mapindex,&ip,&port)==0) {
unit_remove_map(&sd->bl,clrtype); unit_remove_map(&sd->bl,clrtype);
sd->mapindex = mapindex; sd->mapindex = mapindex;
sd->bl.x=x; sd->bl.x=x;