From 88a5d0cdda513357496b9d53878618e1620f47e8 Mon Sep 17 00:00:00 2001 From: ultramage Date: Thu, 5 Apr 2007 18:49:57 +0000 Subject: * 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 --- src/common/socket.c | 70 ++++++++++++++++++++++++++--------------------------- 1 file changed, 34 insertions(+), 36 deletions(-) (limited to 'src/common/socket.c') 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); } -- cgit v1.2.3-70-g09d2