diff options
author | ultramage <ultramage@54d463be-8e91-2dee-dedb-b68131a5f0ec> | 2007-04-05 18:49:57 +0000 |
---|---|---|
committer | ultramage <ultramage@54d463be-8e91-2dee-dedb-b68131a5f0ec> | 2007-04-05 18:49:57 +0000 |
commit | 88a5d0cdda513357496b9d53878618e1620f47e8 (patch) | |
tree | 4f3c2bedbac4b715ff783de5e1c8d1aefe4395af /src/common | |
parent | a7fd6bfe9bcce1862b554f5841d9ff1aedf473e3 (diff) | |
download | hercules-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/common')
-rw-r--r-- | src/common/mmo.h | 4 | ||||
-rw-r--r-- | src/common/socket.c | 70 | ||||
-rw-r--r-- | src/common/socket.h | 18 | ||||
-rw-r--r-- | src/common/strlib.c | 46 | ||||
-rw-r--r-- | src/common/strlib.h | 17 | ||||
-rw-r--r-- | src/common/utils.c | 46 |
6 files changed, 94 insertions, 107 deletions
diff --git a/src/common/mmo.h b/src/common/mmo.h index 03c3d7484..f07876115 100644 --- a/src/common/mmo.h +++ b/src/common/mmo.h @@ -215,8 +215,8 @@ struct mmo_charstatus { short str,agi,vit,int_,dex,luk; unsigned char char_num,sex; - unsigned long mapip; - unsigned int mapport; + uint32 mapip; + uint16 mapport; struct point last_point,save_point,memo_point[MAX_MEMOPOINTS]; struct item inventory[MAX_INVENTORY],cart[MAX_CART]; diff --git a/src/common/socket.c b/src/common/socket.c index f7b5ebc2f..b2c9810b4 100644 --- a/src/common/socket.c +++ b/src/common/socket.c @@ -242,7 +242,7 @@ int connect_client(int listen_fd) 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 ) { ShowError("accept failed (code %i)!\n", s_errno); return -1; @@ -258,7 +258,7 @@ int connect_client(int listen_fd) set_nonblocking(fd, 1); #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); return -1; } @@ -270,13 +270,13 @@ int connect_client(int listen_fd) fd_max = fd + 1; 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; return fd; } -int make_listen_bind(long ip,int port) +int make_listen_bind(uint32 ip, uint16 port) { struct sockaddr_in server_address; int fd; @@ -293,8 +293,8 @@ int make_listen_bind(long ip,int port) set_nonblocking(fd, 1); server_address.sin_family = AF_INET; - server_address.sin_addr.s_addr = ip; - server_address.sin_port = htons((unsigned short)port); + server_address.sin_addr.s_addr = htonl(ip); + server_address.sin_port = htons(port); result = bind(fd, (struct sockaddr*)&server_address, sizeof(server_address)); if( result == SOCKET_ERROR ) { @@ -320,7 +320,7 @@ int make_listen_bind(long ip,int port) return fd; } -int make_connection(long ip, int port) +int make_connection(uint32 ip, uint16 port) { struct sockaddr_in server_address; int fd; @@ -335,12 +335,11 @@ int make_connection(long ip, int port) setsocketopts(fd); - server_address.sin_family = AF_INET; - server_address.sin_addr.s_addr = ip; - server_address.sin_port = htons((unsigned short)port); + server_address.sin_family = AF_INET; + server_address.sin_addr.s_addr = htonl(ip); + server_address.sin_port = htons(port); - ShowStatus("Connecting to %d.%d.%d.%d:%i\n", - (ip)&0xFF,(ip>>8)&0xFF,(ip>>16)&0xFF,(ip>>24)&0xFF,port); + ShowStatus("Connecting to %d.%d.%d.%d:%i\n", CONVIP(ip), port); result = connect(fd, (struct sockaddr *)(&server_address), sizeof(struct sockaddr_in)); if( result == SOCKET_ERROR ) { @@ -389,7 +388,7 @@ int delete_session(int fd) 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) ) return 0; @@ -421,7 +420,7 @@ int realloc_writefifo(int fd, size_t addition) else if( session[fd]->max_wdata >= FIFOSIZE_SERVERLINK) { //Inter-server adjust. [Skotlex] if ((session[fd]->wdata_size+addition)*4 < session[fd]->max_wdata) - newsize = session[fd]->max_wdata/2; + newsize = session[fd]->max_wdata / 2; else return 0; //No change } 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; } -int RFIFOSKIP(int fd,int len) +int RFIFOSKIP(int fd, int len) { 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 if(s->wdata_size+len > s->max_wdata) { // actually there was a buffer overflow already - unsigned char *sin_addr = (unsigned char *)&s->client_addr.sin_addr; - ShowFatalError("socket: Buffer Overflow. Connection %d (%d.%d.%d.%d) has written %d bytes on a %d/%d bytes buffer.\n", fd, - sin_addr[0], sin_addr[1], sin_addr[2], sin_addr[3], len, s->wdata_size, s->max_wdata); - ShowDebug("Likely command that caused it: 0x%x\n", - (*(unsigned short*)(s->wdata + s->wdata_size))); + 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, CONVIP(ip), len, s->wdata_size, s->max_wdata); + ShowDebug("Likely command that caused it: 0x%x\n", (*(unsigned short*)(s->wdata + s->wdata_size))); // no other chance, make a better fifo model exit(1); } @@ -645,15 +643,13 @@ static int access_order = ACO_DENY_ALLOW; static int access_allownum = 0; static int access_denynum = 0; static int access_debug = 0; -static int ddos_count = 10; -static int ddos_interval = 3*1000; -static int ddos_autoreset = 10*60*1000; +static int ddos_count = 10; +static int ddos_interval = 3*1000; +static int ddos_autoreset = 10*60*1000; /// Connection history, an array of linked lists. /// The array's index for any ip is ip&0xFFFF static ConnectHistory* connect_history[0x10000]; -#define CONVIP(ip) ip&0xFF,(ip>>8)&0xFF,(ip>>16)&0xFF,ip>>24 - static int connect_check_(uint32 ip); /// 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]; int n; - if( strcmp(str,"all") == 0 ){ + if( strcmp(str,"all") == 0 ) { ip = 0; mask = 0; } else { @@ -856,7 +852,7 @@ int access_ipmask(const char* str, AccessControl* acc) #endif ////////////////////////////// -int socket_config_read(const char *cfgName) +int socket_config_read(const char* cfgName) { char line[1024],w1[1024],w2[1024]; FILE *fp; @@ -960,7 +956,7 @@ void do_close(int fd) /// Retrieve local ips in host byte order. /// Uses loopback is no address is found. -int socket_getips(uint32 *ips, int max) +int socket_getips(uint32* ips, int max) { int num = 0; @@ -986,7 +982,7 @@ int socket_getips(uint32 *ips, int max) { hent = gethostbyname(fullhost); 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; } a = (u_long**)hent->h_addr_list; @@ -1099,16 +1095,18 @@ int session_isActive(int fd) return ( session_isValid(fd) && !session[fd]->eof ); } - -in_addr_t host2ip(const char* hostname) +// Resolves hostname into a numeric ip. +uint32 host2ip(const char* 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); - sprintf(ip_str, "%d.%d.%d.%d", (addr>>24)&0xFF, (addr>>16)&0xFF, (addr>>8)&0xFF, (addr>>0)&0xFF); - return ip_str; + struct in_addr addr; + addr.s_addr = htonl(ip); + return (ip_str == NULL) ? inet_ntoa(addr) : strncpy(ip_str, inet_ntoa(addr), 16); } diff --git a/src/common/socket.h b/src/common/socket.h index b7b8ce839..ba984eb3a 100644 --- a/src/common/socket.h +++ b/src/common/socket.h @@ -81,7 +81,7 @@ struct socket_data { size_t rdata_size, wdata_size; size_t rdata_pos; 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; RecvFunc func_recv; SendFunc func_send; @@ -106,12 +106,12 @@ extern int session_isActive(int fd); // Function prototype declaration -int make_listen_bind(long,int); -int make_connection(long,int); -int realloc_fifo(int fd,unsigned int rfifo_size,unsigned int wfifo_size); +int make_listen_bind(uint32 ip, uint16 port); +int make_connection(uint32 ip, uint16 port); +int realloc_fifo(int fd, unsigned int rfifo_size, unsigned int wfifo_size); int realloc_writefifo(int fd, size_t addition); -int WFIFOSET(int fd,int len); -int RFIFOSKIP(int fd,int len); +int WFIFOSET(int fd, int len); +int RFIFOSKIP(int fd, int len); int do_sendrecv(int next); int do_parsepacket(void); @@ -126,9 +126,9 @@ extern void set_nonblocking(int fd, int yes); void set_defaultparse(ParseFunc defaultparse); // hostname/ip conversion functions -in_addr_t host2ip(const char* hostname); -const char* ip2str(in_addr_t ip, char ip_str[16]); - +uint32 host2ip(const char* hostname); +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); diff --git a/src/common/strlib.c b/src/common/strlib.c index 9d79e2745..327b2daf1 100644 --- a/src/common/strlib.c +++ b/src/common/strlib.c @@ -11,12 +11,15 @@ #include "../common/utils.h" #include "../common/malloc.h" -//----------------------------------------------- -// string lib. -char* jstrescape (char* pt) { + +#define J_MAX_MALLOC_SIZE 65535 + +// escapes a string in-place (' -> \' , \ -> \\ , % -> _) +char* jstrescape (char* pt) +{ //copy from here char *ptr; - int i =0, j=0; + int i = 0, j = 0; //copy string to temporary CREATE(ptr, char, J_MAX_MALLOC_SIZE); @@ -41,10 +44,12 @@ char* jstrescape (char* pt) { } pt[j++] = '\0'; 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 //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] @@ -75,7 +80,10 @@ char* jstrescapecpy (char* pt, const char* spt) { pt[j++] = '\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 int i =0, j=0; @@ -100,11 +108,9 @@ int jmemescapecpy (char* pt,char* spt, int size) { return j; } -//----------------------------------------------------- // Function to suppress control characters in a string. -//----------------------------------------------------- -//int remove_control_chars(char *str) { -int remove_control_chars(unsigned char *str) { +int remove_control_chars(char* str) +{ int i; 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] -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 *bufp = buf; + char* bufp = buf; memset(buf,0,sizeof buf); while(strp) { @@ -143,7 +149,7 @@ char *trim(char *str, const char *delim) //stristr: Case insensitive version of strstr, code taken from //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 ) { @@ -153,9 +159,7 @@ const char *stristr(const char *haystack, const char *needle) { if ( TOUPPER(*haystack) == TOUPPER(*needle) ) { - /* - * Matched starting char -- loop through remaining chars. - */ + // matched starting char -- loop through remaining chars const char *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; } } - 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 -char *_strtok_r(char *s1, const char *s2, char **lasts) +char* _strtok_r(char *s1, const char *s2, char **lasts) { char *ret; diff --git a/src/common/strlib.h b/src/common/strlib.h index f9a6e41a3..332e823b9 100644 --- a/src/common/strlib.h +++ b/src/common/strlib.h @@ -4,25 +4,20 @@ #ifndef _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* 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 #define HAVE_STRTOK_R #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 -// 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) size_t strnlen (const char* string, size_t maxlen); #endif diff --git a/src/common/utils.c b/src/common/utils.c index c06e57083..2f5cf8705 100644 --- a/src/common/utils.c +++ b/src/common/utils.c @@ -20,28 +20,28 @@ #include "../common/showmsg.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(" ----------------------------------------------- ----------------"); - for (icnt=0;icnt<num;icnt+=16) { - printf("\n%p ",&buffer[icnt]); - for (jcnt=icnt;jcnt<icnt+16;++jcnt) { + for (icnt = 0; icnt < num; icnt += 16) { + printf("\n%p ", &buffer[icnt]); + for (jcnt = icnt; jcnt < icnt + 16; ++jcnt) { if (jcnt < num) { - printf("%02hX ",buffer[jcnt]); + printf("%02hX ", buffer[jcnt]); } else printf(" "); } printf(" | "); - for (jcnt=icnt;jcnt<icnt+16;++jcnt) { + for (jcnt = icnt; jcnt < icnt + 16; ++jcnt) { if (jcnt < num) { if (buffer[jcnt] > 31 && buffer[jcnt] < 127) - printf("%c",buffer[jcnt]); + printf("%c", buffer[jcnt]); else printf("."); } 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) { - switch(num) - { - case 0: - return (unsigned char)((val & 0x000000FF) ); - case 1: - return (unsigned char)((val & 0x0000FF00)>>0x08); - case 2: - return (unsigned char)((val & 0x00FF0000)>>0x10); - case 3: - return (unsigned char)((val & 0xFF000000)>>0x18); - default: - return 0; //better throw something here + switch(num) { + case 0: return (unsigned char)((val & 0x000000FF) ); + case 1: return (unsigned char)((val & 0x0000FF00)>>0x08); + 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) { - switch(num) - { - case 0: - return (unsigned short)((val & 0x0000FFFF) ); - case 1: - return (unsigned short)((val & 0xFFFF0000)>>0x10); - default: - return 0; //better throw something here + switch(num) { + case 0: return (unsigned short)((val & 0x0000FFFF) ); + case 1: return (unsigned short)((val & 0xFFFF0000)>>0x10); + default: return 0; //better throw something here } } unsigned short MakeWord(unsigned char byte0, unsigned char byte1) |