· 9 years ago · Jan 24, 2017, 03:56 PM
1// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
2// For more information, see LICENCE in the main folder
3
4#include "../common/cbasetypes.h"
5#include "../common/mmo.h"
6#include "../common/timer.h"
7#include "../common/malloc.h"
8#include "../common/showmsg.h"
9#include "../common/strlib.h"
10#include "socket.h"
11
12#include <stdlib.h>
13
14#ifdef WIN32
15 #include "../common/winapi.h"
16#else
17 #include <errno.h>
18#include <netinet/tcp.h>
19 #include <net/if.h>
20 #include <unistd.h>
21#include <sys/ioctl.h>
22 #include <netdb.h>
23 #include <arpa/inet.h>
24
25 #ifndef SIOCGIFCONF
26 #include <sys/sockio.h> // SIOCGIFCONF on Solaris, maybe others? [Shinomori]
27 #endif
28 #ifndef FIONBIO
29 #include <sys/filio.h> // FIONBIO on Solaris [FlavioJS]
30 #endif
31
32 #ifdef HAVE_SETRLIMIT
33 #include <sys/resource.h>
34 #endif
35#endif
36
37/////////////////////////////////////////////////////////////////////
38#if defined(WIN32)
39/////////////////////////////////////////////////////////////////////
40// windows portability layer
41
42typedef int socklen_t;
43
44#define sErrno WSAGetLastError()
45#define S_ENOTSOCK WSAENOTSOCK
46#define S_EWOULDBLOCK WSAEWOULDBLOCK
47#define S_EINTR WSAEINTR
48#define S_ECONNABORTED WSAECONNABORTED
49
50#define SHUT_RD SD_RECEIVE
51#define SHUT_WR SD_SEND
52#define SHUT_RDWR SD_BOTH
53
54// global array of sockets (emulating linux)
55// fd is the position in the array
56static SOCKET sock_arr[FD_SETSIZE];
57static int sock_arr_len = 0;
58
59/// Returns the socket associated with the target fd.
60///
61/// @param fd Target fd.
62/// @return Socket
63#define fd2sock(fd) sock_arr[fd]
64
65/// Returns the first fd associated with the socket.
66/// Returns -1 if the socket is not found.
67///
68/// @param s Socket
69/// @return Fd or -1
70int sock2fd(SOCKET s)
71{
72 int fd;
73
74 // search for the socket
75 for( fd = 1; fd < sock_arr_len; ++fd )
76 if( sock_arr[fd] == s )
77 break;// found the socket
78 if( fd == sock_arr_len )
79 return -1;// not found
80 return fd;
81}
82
83
84/// Inserts the socket into the global array of sockets.
85/// Returns a new fd associated with the socket.
86/// If there are too many sockets it closes the socket, sets an error and
87// returns -1 instead.
88/// Since fd 0 is reserved, it returns values in the range [1,FD_SETSIZE[.
89///
90/// @param s Socket
91/// @return New fd or -1
92int sock2newfd(SOCKET s)
93{
94 int fd;
95
96 // find an empty position
97 for( fd = 1; fd < sock_arr_len; ++fd )
98 if( sock_arr[fd] == INVALID_SOCKET )
99 break;// empty position
100 if( fd == ARRAYLENGTH(sock_arr) )
101 {// too many sockets
102 closesocket(s);
103 WSASetLastError(WSAEMFILE);
104 return -1;
105 }
106 sock_arr[fd] = s;
107 if( sock_arr_len <= fd )
108 sock_arr_len = fd+1;
109 return fd;
110}
111
112int sAccept(int fd, struct sockaddr* addr, int* addrlen)
113{
114 SOCKET s;
115
116 // accept connection
117 s = accept(fd2sock(fd), addr, addrlen);
118 if( s == INVALID_SOCKET )
119 return -1;// error
120 return sock2newfd(s);
121}
122
123int sClose(int fd)
124{
125 int ret = closesocket(fd2sock(fd));
126 fd2sock(fd) = INVALID_SOCKET;
127 return ret;
128}
129
130int sSocket(int af, int type, int protocol)
131{
132 SOCKET s;
133
134 // create socket
135 s = socket(af,type,protocol);
136 if( s == INVALID_SOCKET )
137 return -1;// error
138 return sock2newfd(s);
139}
140
141char* sErr(int code)
142{
143 static char sbuf[512];
144 // strerror does not handle socket codes
145 if( FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, NULL,
146 code, MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT), (LPTSTR)&sbuf, sizeof(sbuf), NULL) == 0 )
147 snprintf(sbuf, sizeof(sbuf), "unknown error");
148 return sbuf;
149}
150
151#define sBind(fd,name,namelen) bind(fd2sock(fd),name,namelen)
152#define sConnect(fd,name,namelen) connect(fd2sock(fd),name,namelen)
153#define sIoctl(fd,cmd,argp) ioctlsocket(fd2sock(fd),cmd,argp)
154#define sListen(fd,backlog) listen(fd2sock(fd),backlog)
155#define sRecv(fd,buf,len,flags) recv(fd2sock(fd),buf,len,flags)
156#define sSelect select
157#define sSend(fd,buf,len,flags) send(fd2sock(fd),buf,len,flags)
158#define sSetsockopt(fd,level,optname,optval,optlen) setsockopt(fd2sock(fd),level,optname,optval,optlen)
159#define sShutdown(fd,how) shutdown(fd2sock(fd),how)
160#define sFD_SET(fd,set) FD_SET(fd2sock(fd),set)
161#define sFD_CLR(fd,set) FD_CLR(fd2sock(fd),set)
162#define sFD_ISSET(fd,set) FD_ISSET(fd2sock(fd),set)
163#define sFD_ZERO FD_ZERO
164
165/////////////////////////////////////////////////////////////////////
166#else
167/////////////////////////////////////////////////////////////////////
168// nix portability layer
169
170#define SOCKET_ERROR (-1)
171
172#define sErrno errno
173#define S_ENOTSOCK EBADF
174#define S_EWOULDBLOCK EAGAIN
175#define S_EINTR EINTR
176#define S_ECONNABORTED ECONNABORTED
177
178#define sAccept accept
179#define sClose close
180#define sSocket socket
181#define sErr strerror
182
183#define sBind bind
184#define sConnect connect
185#define sIoctl ioctl
186#define sListen listen
187#define sRecv recv
188#define sSelect select
189#define sSend send
190#define sSetsockopt setsockopt
191#define sShutdown shutdown
192#define sFD_SET FD_SET
193#define sFD_CLR FD_CLR
194#define sFD_ISSET FD_ISSET
195#define sFD_ZERO FD_ZERO
196
197/////////////////////////////////////////////////////////////////////
198#endif
199/////////////////////////////////////////////////////////////////////
200
201#ifndef MSG_NOSIGNAL
202 #define MSG_NOSIGNAL 0
203#endif
204
205fd_set readfds;
206int fd_max;
207time_t last_tick;
208time_t stall_time = 60;
209
210uint32 addr_[16]; // ip addresses of local host (host byte order)
211int naddr_ = 0; // # of ip addresses
212
213// Maximum packet size in bytes, which the client is able to handle.
214// Larger packets cause a buffer overflow and stack corruption.
215static size_t socket_max_client_packet = 24576;
216
217#ifdef SHOW_SERVER_STATS
218// Data I/O statistics
219static size_t socket_data_i = 0, socket_data_ci = 0, socket_data_qi = 0;
220static size_t socket_data_o = 0, socket_data_co = 0, socket_data_qo = 0;
221static time_t socket_data_last_tick = 0;
222#endif
223
224// initial recv buffer size (this will also be the max. size)
225// biggest known packet: S 0153 <len>.w <emblem data>.?B -> 24x24 256 color .bmp (0153 + len.w + 1618/1654/1756 bytes)
226#define RFIFO_SIZE (2*1024)
227// initial send buffer size (will be resized as needed)
228#define WFIFO_SIZE (16*1024)
229
230// Maximum size of pending data in the write fifo. (for non-server connections)
231// The connection is closed if it goes over the limit.
232#define WFIFO_MAX (1*1024*1024)
233
234struct socket_data* session[FD_SETSIZE];
235
236#ifdef SEND_SHORTLIST
237int send_shortlist_array[FD_SETSIZE];// we only support FD_SETSIZE sockets, limit the array to that
238int send_shortlist_count = 0;// how many fd's are in the shortlist
239uint32 send_shortlist_set[(FD_SETSIZE+31)/32];// to know if specific fd's are already in the shortlist
240#endif
241
242static int create_session(int fd, RecvFunc func_recv, SendFunc func_send, ParseFunc func_parse);
243
244#ifndef MINICORE
245 int ip_rules = 1;
246 static int connect_check(uint32 ip);
247#endif
248
249const char* error_msg(void)
250{
251 static char buf[512];
252 int code = sErrno;
253 snprintf(buf, sizeof(buf), "error %d: %s", code, sErr(code));
254 return buf;
255}
256
257/*======================================
258 * CORE : Default processing functions
259 *--------------------------------------*/
260int null_recv(int fd) { return 0; }
261int null_send(int fd) { return 0; }
262int null_parse(int fd) { return 0; }
263
264ParseFunc default_func_parse = null_parse;
265
266void set_defaultparse(ParseFunc defaultparse)
267{
268 default_func_parse = defaultparse;
269}
270
271
272/*======================================
273 * CORE : Socket options
274 *--------------------------------------*/
275void set_nonblocking(int fd, unsigned long yes)
276{
277 // FIONBIO Use with a nonzero argp parameter to enable the nonblocking mode of socket s.
278 // The argp parameter is zero if nonblocking is to be disabled.
279 if( sIoctl(fd, FIONBIO, &yes) != 0 )
280 ShowError("set_nonblocking: Failed to set socket #%d to non-blocking mode (%s) - Please report this!!!\n", fd, error_msg());
281}
282
283void setsocketopts(int fd,int delay_timeout){
284 int yes = 1; // reuse fix
285
286#if !defined(WIN32)
287 // set SO_REAUSEADDR to true, unix only. on windows this option causes
288 // the previous owner of the socket to give up, which is not desirable
289 // in most cases, neither compatible with unix.
290 sSetsockopt(fd,SOL_SOCKET,SO_REUSEADDR,(char *)&yes,sizeof(yes));
291#ifdef SO_REUSEPORT
292 sSetsockopt(fd,SOL_SOCKET,SO_REUSEPORT,(char *)&yes,sizeof(yes));
293#endif
294#endif
295
296 // Set the socket into no-delay mode; otherwise packets get delayed for up to 200ms, likely creating server-side lag.
297 // The RO protocol is mainly single-packet request/response, plus the FIFO model already does packet grouping anyway.
298 sSetsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&yes, sizeof(yes));
299
300 // force the socket into no-wait, graceful-close mode (should be the default, but better make sure)
301 //(http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winsock/winsock/closesocket_2.asp)
302 {
303 struct linger opt;
304 opt.l_onoff = 0; // SO_DONTLINGER
305 opt.l_linger = 0; // Do not care
306 if( sSetsockopt(fd, SOL_SOCKET, SO_LINGER, (char*)&opt, sizeof(opt)) )
307 ShowWarning("setsocketopts: Unable to set SO_LINGER mode for connection #%d!\n", fd);
308 }
309 if(delay_timeout){
310 struct timeval timeout;
311 timeout.tv_sec = delay_timeout;
312 timeout.tv_usec = 0;
313
314 if (sSetsockopt (fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout,sizeof(timeout)) < 0)
315 ShowError("setsocketopts: Unable to set SO_RCVTIMEO timeout for connection #%d!\n");
316 if (sSetsockopt (fd, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout,sizeof(timeout)) < 0)
317 ShowError("setsocketopts: Unable to set SO_SNDTIMEO timeout for connection #%d!\n");
318 }
319}
320
321/*======================================
322 * CORE : Socket Sub Function
323 *--------------------------------------*/
324void set_eof(int fd)
325{
326 if( session_isActive(fd) )
327 {
328#ifdef SEND_SHORTLIST
329 // Add this socket to the shortlist for eof handling.
330 send_shortlist_add_fd(fd);
331#endif
332 session[fd]->flag.eof = 1;
333 }
334}
335
336int recv_to_fifo(int fd)
337{
338 int len;
339
340 if( !session_isActive(fd) )
341 return -1;
342
343 len = sRecv(fd, (char *) session[fd]->rdata + session[fd]->rdata_size, (int)RFIFOSPACE(fd), 0);
344
345 if( len == SOCKET_ERROR )
346 {//An exception has occured
347 if( sErrno != S_EWOULDBLOCK ) {
348 //ShowDebug("recv_to_fifo: %s, closing connection #%d\n", error_msg(), fd);
349 set_eof(fd);
350 }
351 return 0;
352 }
353
354 if( len == 0 )
355 {//Normal connection end.
356 set_eof(fd);
357 return 0;
358 }
359
360 session[fd]->rdata_size += len;
361 session[fd]->rdata_tick = last_tick;
362#ifdef SHOW_SERVER_STATS
363 socket_data_i += len;
364 socket_data_qi += len;
365 if (!session[fd]->flag.server)
366 {
367 socket_data_ci += len;
368 }
369#endif
370 return 0;
371}
372
373int send_from_fifo(int fd)
374{
375 int len;
376
377 if( !session_isValid(fd) )
378 return -1;
379
380 if( session[fd]->wdata_size == 0 )
381 return 0; // nothing to send
382
383 len = sSend(fd, (const char *) session[fd]->wdata, (int)session[fd]->wdata_size, MSG_NOSIGNAL);
384
385 if( len == SOCKET_ERROR )
386 {//An exception has occured
387 if( sErrno != S_EWOULDBLOCK ) {
388 //ShowDebug("send_from_fifo: %s, ending connection #%d\n", error_msg(), fd);
389#ifdef SHOW_SERVER_STATS
390 socket_data_qo -= session[fd]->wdata_size;
391#endif
392 session[fd]->wdata_size = 0; //Clear the send queue as we can't send anymore. [Skotlex]
393 set_eof(fd);
394 }
395 return 0;
396 }
397
398 if( len > 0 )
399 {
400 // some data could not be transferred?
401 // shift unsent data to the beginning of the queue
402 if( (size_t)len < session[fd]->wdata_size )
403 memmove(session[fd]->wdata, session[fd]->wdata + len, session[fd]->wdata_size - len);
404
405 session[fd]->wdata_size -= len;
406#ifdef SHOW_SERVER_STATS
407 socket_data_o += len;
408 socket_data_qo -= len;
409 if (!session[fd]->flag.server)
410 {
411 socket_data_co += len;
412 }
413#endif
414 }
415
416 return 0;
417}
418
419/// Best effort - there's no warranty that the data will be sent.
420void flush_fifo(int fd)
421{
422 if(session[fd] != NULL)
423 session[fd]->func_send(fd);
424}
425
426void flush_fifos(void)
427{
428 int i;
429 for(i = 1; i < fd_max; i++)
430 flush_fifo(i);
431}
432
433/*======================================
434 * CORE : Connection functions
435 *--------------------------------------*/
436int connect_client(int listen_fd)
437{
438 int fd;
439 struct sockaddr_in client_address;
440 socklen_t len;
441
442 len = sizeof(client_address);
443
444 fd = sAccept(listen_fd, (struct sockaddr*)&client_address, &len);
445 if ( fd == -1 ) {
446 ShowError("connect_client: accept failed (%s)!\n", error_msg());
447 return -1;
448 }
449 if( fd == 0 )
450 {// reserved
451 ShowError("connect_client: Socket #0 is reserved - Please report this!!!\n");
452 sClose(fd);
453 return -1;
454 }
455 if( fd >= FD_SETSIZE )
456 {// socket number too big
457 ShowError("connect_client: New socket #%d is greater than can we handle! Increase the value of FD_SETSIZE (currently %d) for your OS to fix this!\n", fd, FD_SETSIZE);
458 sClose(fd);
459 return -1;
460 }
461
462 setsocketopts(fd,0);
463 set_nonblocking(fd, 1);
464
465#ifndef MINICORE
466 if( ip_rules && !connect_check(ntohl(client_address.sin_addr.s_addr)) ) {
467 do_close(fd);
468 return -1;
469 }
470#endif
471
472 if( fd_max <= fd ) fd_max = fd + 1;
473 sFD_SET(fd,&readfds);
474
475 create_session(fd, recv_to_fifo, send_from_fifo, default_func_parse);
476 session[fd]->client_addr = ntohl(client_address.sin_addr.s_addr);
477
478 return fd;
479}
480
481int make_listen_bind(uint32 ip, uint16 port)
482{
483 struct sockaddr_in server_address;
484 int fd;
485 int result;
486
487 fd = sSocket(AF_INET, SOCK_STREAM, 0);
488
489 if( fd == -1 )
490 {
491 ShowError("make_listen_bind: socket creation failed (%s)!\n", error_msg());
492 exit(EXIT_FAILURE);
493 }
494 if( fd == 0 )
495 {// reserved
496 ShowError("make_listen_bind: Socket #0 is reserved - Please report this!!!\n");
497 sClose(fd);
498 return -1;
499 }
500 if( fd >= FD_SETSIZE )
501 {// socket number too big
502 ShowError("make_listen_bind: New socket #%d is greater than can we handle! Increase the value of FD_SETSIZE (currently %d) for your OS to fix this!\n", fd, FD_SETSIZE);
503 sClose(fd);
504 return -1;
505 }
506
507 setsocketopts(fd,0);
508 set_nonblocking(fd, 1);
509
510 server_address.sin_family = AF_INET;
511 server_address.sin_addr.s_addr = htonl(ip);
512 server_address.sin_port = htons(port);
513
514 result = sBind(fd, (struct sockaddr*)&server_address, sizeof(server_address));
515 if( result == SOCKET_ERROR ) {
516 ShowError("make_listen_bind: bind failed (socket #%d, %s)!\n", fd, error_msg());
517 exit(EXIT_FAILURE);
518 }
519 result = sListen(fd,5);
520 if( result == SOCKET_ERROR ) {
521 ShowError("make_listen_bind: listen failed (socket #%d, %s)!\n", fd, error_msg());
522 exit(EXIT_FAILURE);
523 }
524
525 if(fd_max <= fd) fd_max = fd + 1;
526 sFD_SET(fd, &readfds);
527
528 create_session(fd, connect_client, null_send, null_parse);
529 session[fd]->client_addr = 0; // just listens
530 session[fd]->rdata_tick = 0; // disable timeouts on this socket
531
532 return fd;
533}
534
535int make_connection(uint32 ip, uint16 port, bool silent,int timeout) {
536 struct sockaddr_in remote_address;
537 int fd;
538 int result;
539
540 fd = sSocket(AF_INET, SOCK_STREAM, 0);
541
542 if (fd == -1) {
543 ShowError("make_connection: socket creation failed (%s)!\n", error_msg());
544 return -1;
545 }
546 if( fd == 0 )
547 {// reserved
548 ShowError("make_connection: Socket #0 is reserved - Please report this!!!\n");
549 sClose(fd);
550 return -1;
551 }
552 if( fd >= FD_SETSIZE )
553 {// socket number too big
554 ShowError("make_connection: New socket #%d is greater than can we handle! Increase the value of FD_SETSIZE (currently %d) for your OS to fix this!\n", fd, FD_SETSIZE);
555 sClose(fd);
556 return -1;
557 }
558
559 setsocketopts(fd,timeout);
560
561 remote_address.sin_family = AF_INET;
562 remote_address.sin_addr.s_addr = htonl(ip);
563 remote_address.sin_port = htons(port);
564
565 if( !silent )
566 ShowStatus("Connecting to %d.%d.%d.%d:%i\n", CONVIP(ip), port);
567
568 result = sConnect(fd, (struct sockaddr *)(&remote_address), sizeof(struct sockaddr_in));
569 if( result == SOCKET_ERROR ) {
570 if( !silent )
571 ShowError("make_connection: connect failed (socket #%d, %s)!\n", fd, error_msg());
572 do_close(fd);
573 return -1;
574 }
575 //Now the socket can be made non-blocking. [Skotlex]
576 set_nonblocking(fd, 1);
577
578 if (fd_max <= fd) fd_max = fd + 1;
579 sFD_SET(fd,&readfds);
580
581 create_session(fd, recv_to_fifo, send_from_fifo, default_func_parse);
582 session[fd]->client_addr = ntohl(remote_address.sin_addr.s_addr);
583
584 return fd;
585}
586
587static int create_session(int fd, RecvFunc func_recv, SendFunc func_send, ParseFunc func_parse)
588{
589 CREATE(session[fd], struct socket_data, 1);
590 CREATE(session[fd]->rdata, unsigned char, RFIFO_SIZE);
591 CREATE(session[fd]->wdata, unsigned char, WFIFO_SIZE);
592 session[fd]->max_rdata = RFIFO_SIZE;
593 session[fd]->max_wdata = WFIFO_SIZE;
594 session[fd]->func_recv = func_recv;
595 session[fd]->func_send = func_send;
596 session[fd]->func_parse = func_parse;
597 session[fd]->rdata_tick = last_tick;
598 return 0;
599}
600
601static void delete_session(int fd)
602{
603 if( session_isValid(fd) )
604 {
605#ifdef SHOW_SERVER_STATS
606 socket_data_qi -= session[fd]->rdata_size - session[fd]->rdata_pos;
607 socket_data_qo -= session[fd]->wdata_size;
608#endif
609 aFree(session[fd]->rdata);
610 aFree(session[fd]->wdata);
611 aFree(session[fd]->session_data);
612 aFree(session[fd]);
613 session[fd] = NULL;
614 }
615}
616
617int realloc_fifo(int fd, unsigned int rfifo_size, unsigned int wfifo_size)
618{
619 if( !session_isValid(fd) )
620 return 0;
621
622 if( session[fd]->max_rdata != rfifo_size && session[fd]->rdata_size < rfifo_size) {
623 RECREATE(session[fd]->rdata, unsigned char, rfifo_size);
624 session[fd]->max_rdata = rfifo_size;
625 }
626
627 if( session[fd]->max_wdata != wfifo_size && session[fd]->wdata_size < wfifo_size) {
628 RECREATE(session[fd]->wdata, unsigned char, wfifo_size);
629 session[fd]->max_wdata = wfifo_size;
630 }
631 return 0;
632}
633
634int realloc_writefifo(int fd, size_t addition)
635{
636 size_t newsize;
637
638 if( !session_isValid(fd) ) // might not happen
639 return 0;
640
641 if( session[fd]->wdata_size + addition > session[fd]->max_wdata )
642 { // grow rule; grow in multiples of WFIFO_SIZE
643 newsize = WFIFO_SIZE;
644 while( session[fd]->wdata_size + addition > newsize ) newsize += WFIFO_SIZE;
645 }
646 else
647 if( session[fd]->max_wdata >= (size_t)2*(session[fd]->flag.server?FIFOSIZE_SERVERLINK:WFIFO_SIZE)
648 && (session[fd]->wdata_size+addition)*4 < session[fd]->max_wdata )
649 { // shrink rule, shrink by 2 when only a quarter of the fifo is used, don't shrink below nominal size.
650 newsize = session[fd]->max_wdata / 2;
651 }
652 else // no change
653 return 0;
654
655 RECREATE(session[fd]->wdata, unsigned char, newsize);
656 session[fd]->max_wdata = newsize;
657
658 return 0;
659}
660
661/// advance the RFIFO cursor (marking 'len' bytes as processed)
662int RFIFOSKIP(int fd, size_t len)
663{
664 struct socket_data *s;
665
666 if ( !session_isActive(fd) )
667 return 0;
668
669 s = session[fd];
670
671 if ( s->rdata_size < s->rdata_pos + len ) {
672 ShowError("RFIFOSKIP: skipped past end of read buffer! Adjusting from %d to %d (session #%d)\n", len, RFIFOREST(fd), fd);
673 len = RFIFOREST(fd);
674 }
675
676 s->rdata_pos = s->rdata_pos + len;
677#ifdef SHOW_SERVER_STATS
678 socket_data_qi -= len;
679#endif
680 return 0;
681}
682
683/// advance the WFIFO cursor (marking 'len' bytes for sending)
684int WFIFOSET(int fd, size_t len)
685{
686 size_t newreserve;
687 struct socket_data* s = session[fd];
688
689 if( !session_isValid(fd) || s->wdata == NULL )
690 return 0;
691
692 // we have written len bytes to the buffer already before calling WFIFOSET
693 if(s->wdata_size+len > s->max_wdata)
694 { // actually there was a buffer overflow already
695 uint32 ip = s->client_addr;
696 ShowFatalError("WFIFOSET: Write Buffer Overflow. Connection %d (%d.%d.%d.%d) has written %u bytes on a %u/%u bytes buffer.\n", fd, CONVIP(ip), (unsigned int)len, (unsigned int)s->wdata_size, (unsigned int)s->max_wdata);
697 ShowDebug("Likely command that caused it: 0x%x\n", (*(uint16*)(s->wdata + s->wdata_size)));
698 // no other chance, make a better fifo model
699 exit(EXIT_FAILURE);
700 }
701
702 if( len > 0xFFFF )
703 {
704 // dynamic packets allow up to UINT16_MAX bytes (<packet_id>.W <packet_len>.W ...)
705 // all known fixed-size packets are within this limit, so use the same limit
706 ShowFatalError("WFIFOSET: Packet 0x%x is too big. (len=%u, max=%u)\n", (*(uint16*)(s->wdata + s->wdata_size)), (unsigned int)len, 0xFFFF);
707 exit(EXIT_FAILURE);
708 }
709 else if( len == 0 )
710 {
711 // abuses the fact, that the code that did WFIFOHEAD(fd,0), already wrote
712 // the packet type into memory, even if it could have overwritten vital data
713 // this can happen when a new packet was added on map-server, but packet len table was not updated
714 ShowWarning("WFIFOSET: Attempted to send zero-length packet, most likely 0x%04x (please report this).\n", WFIFOW(fd,0));
715 return 0;
716 }
717
718 if( !s->flag.server ) {
719
720 if( len > socket_max_client_packet ) {// see declaration of socket_max_client_packet for details
721 ShowError("WFIFOSET: Dropped too large client packet 0x%04x (length=%u, max=%u).\n", WFIFOW(fd,0), len, socket_max_client_packet);
722 return 0;
723 }
724
725 if( s->wdata_size+len > WFIFO_MAX ) {// reached maximum write fifo size
726 ShowError("WFIFOSET: Maximum write buffer size for client connection %d exceeded, most likely caused by packet 0x%04x (len=%u, ip=%lu.%lu.%lu.%lu).\n", fd, WFIFOW(fd,0), len, CONVIP(s->client_addr));
727 set_eof(fd);
728 return 0;
729 }
730
731 }
732 s->wdata_size += len;
733 // Gepard Shield
734 if (is_gepard_active == true)
735 {
736 gepard_process_packet(fd, s->wdata + s->wdata_size, len, &s->send_crypt);
737 }
738 // Gepard Shield
739#ifdef SHOW_SERVER_STATS
740 socket_data_qo += len;
741#endif
742 //If the interserver has 200% of its normal size full, flush the data.
743 if( s->flag.server && s->wdata_size >= 2*FIFOSIZE_SERVERLINK )
744 flush_fifo(fd);
745
746 // always keep a WFIFO_SIZE reserve in the buffer
747 // For inter-server connections, let the reserve be 1/4th of the link size.
748 newreserve = s->flag.server ? FIFOSIZE_SERVERLINK / 4 : WFIFO_SIZE;
749
750 // readjust the buffer to include the chosen reserve
751 realloc_writefifo(fd, newreserve);
752
753#ifdef SEND_SHORTLIST
754 send_shortlist_add_fd(fd);
755#endif
756
757 return 0;
758}
759
760int do_sockets(int next)
761{
762 fd_set rfd;
763 struct timeval timeout;
764 int ret,i;
765
766 // PRESEND Timers are executed before do_sendrecv and can send packets and/or set sessions to eof.
767 // Send remaining data and process client-side disconnects here.
768#ifdef SEND_SHORTLIST
769 send_shortlist_do_sends();
770#else
771 for (i = 1; i < fd_max; i++)
772 {
773 if(!session[i])
774 continue;
775
776 if(session[i]->wdata_size)
777 session[i]->func_send(i);
778 }
779#endif
780
781 // can timeout until the next tick
782 timeout.tv_sec = next/1000;
783 timeout.tv_usec = next%1000*1000;
784
785 memcpy(&rfd, &readfds, sizeof(rfd));
786 ret = sSelect(fd_max, &rfd, NULL, NULL, &timeout);
787
788 if( ret == SOCKET_ERROR )
789 {
790 if( sErrno != S_EINTR )
791 {
792 ShowFatalError("do_sockets: select() failed, %s!\n", error_msg());
793 exit(EXIT_FAILURE);
794 }
795 return 0; // interrupted by a signal, just loop and try again
796 }
797
798 last_tick = time(NULL);
799
800#if defined(WIN32)
801 // on windows, enumerating all members of the fd_set is way faster if we access the internals
802 for( i = 0; i < (int)rfd.fd_count; ++i )
803 {
804 int fd = sock2fd(rfd.fd_array[i]);
805 if( session[fd] )
806 session[fd]->func_recv(fd);
807 }
808#else
809 // otherwise assume that the fd_set is a bit-array and enumerate it in a standard way
810 for( i = 1; ret && i < fd_max; ++i )
811 {
812 if(sFD_ISSET(i,&rfd) && session[i])
813 {
814 session[i]->func_recv(i);
815 --ret;
816 }
817 }
818#endif
819
820 // POSTSEND Send remaining data and handle eof sessions.
821#ifdef SEND_SHORTLIST
822 send_shortlist_do_sends();
823#else
824 for (i = 1; i < fd_max; i++)
825 {
826 if(!session[i])
827 continue;
828
829 if(session[i]->wdata_size)
830 session[i]->func_send(i);
831
832 if(session[i]->flag.eof) //func_send can't free a session, this is safe.
833 { //Finally, even if there is no data to parse, connections signalled eof should be closed, so we call parse_func [Skotlex]
834 session[i]->func_parse(i); //This should close the session immediately.
835 }
836 }
837#endif
838
839 // parse input data on each socket
840 for(i = 1; i < fd_max; i++)
841 {
842 if(!session[i])
843 continue;
844
845 if (session[i]->rdata_tick && DIFF_TICK(last_tick, session[i]->rdata_tick) > stall_time) {
846 if( session[i]->flag.server ) {/* server is special */
847 if( session[i]->flag.ping != 2 )/* only update if necessary otherwise it'd resend the ping unnecessarily */
848 session[i]->flag.ping = 1;
849 } else {
850 ShowInfo("Session #%d timed out\n", i);
851 set_eof(i);
852 }
853 }
854
855 session[i]->func_parse(i);
856
857 if(!session[i])
858 continue;
859
860 // after parse, check client's RFIFO size to know if there is an invalid packet (too big and not parsed)
861 if (session[i]->rdata_size == RFIFO_SIZE && session[i]->max_rdata == RFIFO_SIZE) {
862 set_eof(i);
863 continue;
864 }
865 RFIFOFLUSH(i);
866 }
867
868#ifdef SHOW_SERVER_STATS
869 if (last_tick != socket_data_last_tick)
870 {
871 char buf[1024];
872
873 sprintf(buf, "In: %.03f kB/s (%.03f kB/s, Q: %.03f kB) | Out: %.03f kB/s (%.03f kB/s, Q: %.03f kB) | RAM: %.03f MB", socket_data_i/1024., socket_data_ci/1024., socket_data_qi/1024., socket_data_o/1024., socket_data_co/1024., socket_data_qo/1024., malloc_usage()/1024.);
874#ifdef _WIN32
875 SetConsoleTitle(buf);
876#else
877 ShowMessage("\033[s\033[1;1H\033[2K%s\033[u", buf);
878#endif
879 socket_data_last_tick = last_tick;
880 socket_data_i = socket_data_ci = 0;
881 socket_data_o = socket_data_co = 0;
882 }
883#endif
884
885 return 0;
886}
887
888//////////////////////////////
889#ifndef MINICORE
890//////////////////////////////
891// IP rules and DDoS protection
892
893typedef struct _connect_history {
894 struct _connect_history* next;
895 uint32 ip;
896 uint32 tick;
897 int count;
898 unsigned ddos : 1;
899} ConnectHistory;
900
901typedef struct _access_control {
902 uint32 ip;
903 uint32 mask;
904} AccessControl;
905
906enum _aco {
907 ACO_DENY_ALLOW,
908 ACO_ALLOW_DENY,
909 ACO_MUTUAL_FAILURE
910};
911
912static AccessControl* access_allow = NULL;
913static AccessControl* access_deny = NULL;
914static int access_order = ACO_DENY_ALLOW;
915static int access_allownum = 0;
916static int access_denynum = 0;
917static int access_debug = 0;
918static int ddos_count = 10;
919static int ddos_interval = 3*1000;
920static int ddos_autoreset = 10*60*1000;
921/// Connection history, an array of linked lists.
922/// The array's index for any ip is ip&0xFFFF
923static ConnectHistory* connect_history[0x10000];
924
925static int connect_check_(uint32 ip);
926
927/// Verifies if the IP can connect. (with debug info)
928/// @see connect_check_()
929static int connect_check(uint32 ip)
930{
931 int result = connect_check_(ip);
932 if( access_debug ) {
933 ShowInfo("connect_check: Connection from %d.%d.%d.%d %s\n", CONVIP(ip),result ? "allowed." : "denied!");
934 }
935 return result;
936}
937
938/// Verifies if the IP can connect.
939/// 0 : Connection Rejected
940/// 1 or 2 : Connection Accepted
941static int connect_check_(uint32 ip)
942{
943 ConnectHistory* hist = connect_history[ip&0xFFFF];
944 int i;
945 int is_allowip = 0;
946 int is_denyip = 0;
947 int connect_ok = 0;
948
949 // Search the allow list
950 for( i=0; i < access_allownum; ++i ){
951 if( (ip & access_allow[i].mask) == (access_allow[i].ip & access_allow[i].mask) ){
952 if( access_debug ){
953 ShowInfo("connect_check: Found match from allow list:%d.%d.%d.%d IP:%d.%d.%d.%d Mask:%d.%d.%d.%d\n",
954 CONVIP(ip),
955 CONVIP(access_allow[i].ip),
956 CONVIP(access_allow[i].mask));
957 }
958 is_allowip = 1;
959 break;
960 }
961 }
962 // Search the deny list
963 for( i=0; i < access_denynum; ++i ){
964 if( (ip & access_deny[i].mask) == (access_deny[i].ip & access_deny[i].mask) ){
965 if( access_debug ){
966 ShowInfo("connect_check: Found match from deny list:%d.%d.%d.%d IP:%d.%d.%d.%d Mask:%d.%d.%d.%d\n",
967 CONVIP(ip),
968 CONVIP(access_deny[i].ip),
969 CONVIP(access_deny[i].mask));
970 }
971 is_denyip = 1;
972 break;
973 }
974 }
975 // Decide connection status
976 // 0 : Reject
977 // 1 : Accept
978 // 2 : Unconditional Accept (accepts even if flagged as DDoS)
979 switch(access_order) {
980 case ACO_DENY_ALLOW:
981 default:
982 if( is_denyip )
983 connect_ok = 0; // Reject
984 else if( is_allowip )
985 connect_ok = 2; // Unconditional Accept
986 else
987 connect_ok = 1; // Accept
988 break;
989 case ACO_ALLOW_DENY:
990 if( is_allowip )
991 connect_ok = 2; // Unconditional Accept
992 else if( is_denyip )
993 connect_ok = 0; // Reject
994 else
995 connect_ok = 1; // Accept
996 break;
997 case ACO_MUTUAL_FAILURE:
998 if( is_allowip && !is_denyip )
999 connect_ok = 2; // Unconditional Accept
1000 else
1001 connect_ok = 0; // Reject
1002 break;
1003 }
1004
1005 // Inspect connection history
1006 while( hist ) {
1007 if( ip == hist->ip )
1008 {// IP found
1009 if( hist->ddos )
1010 {// flagged as DDoS
1011 return (connect_ok == 2 ? 1 : 0);
1012 } else if( DIFF_TICK(gettick(),hist->tick) < ddos_interval )
1013 {// connection within ddos_interval
1014 hist->tick = gettick();
1015 if( hist->count++ >= ddos_count )
1016 {// DDoS attack detected
1017 hist->ddos = 1;
1018 ShowWarning("connect_check: DDoS Attack detected from %d.%d.%d.%d!\n", CONVIP(ip));
1019 return (connect_ok == 2 ? 1 : 0);
1020 }
1021 return connect_ok;
1022 } else
1023 {// not within ddos_interval, clear data
1024 hist->tick = gettick();
1025 hist->count = 0;
1026 return connect_ok;
1027 }
1028 }
1029 hist = hist->next;
1030 }
1031 // IP not found, add to history
1032 CREATE(hist, ConnectHistory, 1);
1033 memset(hist, 0, sizeof(ConnectHistory));
1034 hist->ip = ip;
1035 hist->tick = gettick();
1036 hist->next = connect_history[ip&0xFFFF];
1037 connect_history[ip&0xFFFF] = hist;
1038 return connect_ok;
1039}
1040
1041/// Timer function.
1042/// Deletes old connection history records.
1043static int connect_check_clear(int tid, unsigned int tick, int id, intptr_t data)
1044{
1045 int i;
1046 int clear = 0;
1047 int list = 0;
1048 ConnectHistory root;
1049 ConnectHistory* prev_hist;
1050 ConnectHistory* hist;
1051
1052 for( i=0; i < 0x10000 ; ++i ){
1053 prev_hist = &root;
1054 root.next = hist = connect_history[i];
1055 while( hist ){
1056 if( (!hist->ddos && DIFF_TICK(tick,hist->tick) > ddos_interval*3) ||
1057 (hist->ddos && DIFF_TICK(tick,hist->tick) > ddos_autoreset) )
1058 {// Remove connection history
1059 prev_hist->next = hist->next;
1060 aFree(hist);
1061 hist = prev_hist->next;
1062 clear++;
1063 } else {
1064 prev_hist = hist;
1065 hist = hist->next;
1066 }
1067 list++;
1068 }
1069 connect_history[i] = root.next;
1070 }
1071 if( access_debug ){
1072 ShowInfo("connect_check_clear: Cleared %d of %d from IP list.\n", clear, list);
1073 }
1074 return list;
1075}
1076
1077/// Parses the ip address and mask and puts it into acc.
1078/// Returns 1 is successful, 0 otherwise.
1079int access_ipmask(const char* str, AccessControl* acc)
1080{
1081 uint32 ip;
1082 uint32 mask;
1083
1084 if( strcmp(str,"all") == 0 ) {
1085 ip = 0;
1086 mask = 0;
1087 } else {
1088 unsigned int a[4];
1089 unsigned int m[4];
1090 int n;
1091 if( ((n=sscanf(str,"%3u.%3u.%3u.%3u/%3u.%3u.%3u.%3u",a,a+1,a+2,a+3,m,m+1,m+2,m+3)) != 8 && // not an ip + standard mask
1092 (n=sscanf(str,"%3u.%3u.%3u.%3u/%3u",a,a+1,a+2,a+3,m)) != 5 && // not an ip + bit mask
1093 (n=sscanf(str,"%3u.%3u.%3u.%3u",a,a+1,a+2,a+3)) != 4 ) || // not an ip
1094 a[0] > 255 || a[1] > 255 || a[2] > 255 || a[3] > 255 || // invalid ip
1095 (n == 8 && (m[0] > 255 || m[1] > 255 || m[2] > 255 || m[3] > 255)) || // invalid standard mask
1096 (n == 5 && m[0] > 32) ){ // invalid bit mask
1097 return 0;
1098 }
1099 ip = MAKEIP(a[0],a[1],a[2],a[3]);
1100 if( n == 8 )
1101 {// standard mask
1102 mask = MAKEIP(m[0],m[1],m[2],m[3]);
1103 } else if( n == 5 )
1104 {// bit mask
1105 mask = 0;
1106 while( m[0] ){
1107 mask = (mask >> 1) | 0x80000000;
1108 --m[0];
1109 }
1110 } else
1111 {// just this ip
1112 mask = 0xFFFFFFFF;
1113 }
1114 }
1115 if( access_debug ){
1116 ShowInfo("access_ipmask: Loaded IP:%d.%d.%d.%d mask:%d.%d.%d.%d\n", CONVIP(ip), CONVIP(mask));
1117 }
1118 acc->ip = ip;
1119 acc->mask = mask;
1120 return 1;
1121}
1122//////////////////////////////
1123#endif
1124//////////////////////////////
1125
1126int socket_config_read(const char* cfgName)
1127{
1128 char line[1024],w1[1024],w2[1024];
1129 FILE *fp;
1130
1131 fp = fopen(cfgName, "r");
1132 if(fp == NULL) {
1133 ShowError("File not found: %s\n", cfgName);
1134 return 1;
1135 }
1136
1137 while(fgets(line, sizeof(line), fp))
1138 {
1139 if(line[0] == '/' && line[1] == '/')
1140 continue;
1141 if(sscanf(line, "%1023[^:]: %1023[^\r\n]", w1, w2) != 2)
1142 continue;
1143
1144 if (!strcmpi(w1, "stall_time")) {
1145 stall_time = atoi(w2);
1146 if( stall_time < 3 )
1147 stall_time = 3;/* a minimum is required to refrain it from killing itself */
1148 }
1149#ifndef MINICORE
1150 else if (!strcmpi(w1, "enable_ip_rules")) {
1151 ip_rules = config_switch(w2);
1152 } else if (!strcmpi(w1, "order")) {
1153 if (!strcmpi(w2, "deny,allow"))
1154 access_order = ACO_DENY_ALLOW;
1155 else if (!strcmpi(w2, "allow,deny"))
1156 access_order = ACO_ALLOW_DENY;
1157 else if (!strcmpi(w2, "mutual-failure"))
1158 access_order = ACO_MUTUAL_FAILURE;
1159 } else if (!strcmpi(w1, "allow")) {
1160 RECREATE(access_allow, AccessControl, access_allownum+1);
1161 if (access_ipmask(w2, &access_allow[access_allownum]))
1162 ++access_allownum;
1163 else
1164 ShowError("socket_config_read: Invalid ip or ip range '%s'!\n", line);
1165 } else if (!strcmpi(w1, "deny")) {
1166 RECREATE(access_deny, AccessControl, access_denynum+1);
1167 if (access_ipmask(w2, &access_deny[access_denynum]))
1168 ++access_denynum;
1169 else
1170 ShowError("socket_config_read: Invalid ip or ip range '%s'!\n", line);
1171 }
1172 else if (!strcmpi(w1,"ddos_interval"))
1173 ddos_interval = atoi(w2);
1174 else if (!strcmpi(w1,"ddos_count"))
1175 ddos_count = atoi(w2);
1176 else if (!strcmpi(w1,"ddos_autoreset"))
1177 ddos_autoreset = atoi(w2);
1178 else if (!strcmpi(w1,"debug"))
1179 access_debug = config_switch(w2);
1180 else if (!strcmpi(w1,"socket_max_client_packet"))
1181 socket_max_client_packet = strtoul(w2, NULL, 0);
1182#endif
1183 else if (!strcmpi(w1, "import"))
1184 socket_config_read(w2);
1185 else
1186 ShowWarning("Unknown setting '%s' in file %s\n", w1, cfgName);
1187 }
1188
1189 fclose(fp);
1190 return 0;
1191}
1192
1193
1194void socket_final(void)
1195{
1196 int i;
1197#ifndef MINICORE
1198 ConnectHistory* hist;
1199 ConnectHistory* next_hist;
1200
1201 for( i=0; i < 0x10000; ++i ){
1202 hist = connect_history[i];
1203 while( hist ){
1204 next_hist = hist->next;
1205 aFree(hist);
1206 hist = next_hist;
1207 }
1208 }
1209 if( access_allow )
1210 aFree(access_allow);
1211 if( access_deny )
1212 aFree(access_deny);
1213#endif
1214
1215 for( i = 1; i < fd_max; i++ )
1216 if(session[i])
1217 do_close(i);
1218
1219 // session[0]
1220 aFree(session[0]->rdata);
1221 aFree(session[0]->wdata);
1222 aFree(session[0]->session_data);
1223 aFree(session[0]);
1224 session[0] = NULL;
1225}
1226
1227/// Closes a socket.
1228void do_close(int fd)
1229{
1230 if( fd <= 0 ||fd >= FD_SETSIZE )
1231 return;// invalid
1232
1233 flush_fifo(fd); // Try to send what's left (although it might not succeed since it's a nonblocking socket)
1234 sFD_CLR(fd, &readfds);// this needs to be done before closing the socket
1235 sShutdown(fd, SHUT_RDWR); // Disallow further reads/writes
1236 sClose(fd); // We don't really care if these closing functions return an error, we are just shutting down and not reusing this socket.
1237 if (session[fd]) delete_session(fd);
1238}
1239
1240/// Retrieve local ips in host byte order.
1241/// Uses loopback is no address is found.
1242int socket_getips(uint32* ips, int max)
1243{
1244 int num = 0;
1245
1246 if( ips == NULL || max <= 0 )
1247 return 0;
1248
1249#ifdef WIN32
1250 {
1251 char fullhost[255];
1252
1253 // XXX This should look up the local IP addresses in the registry
1254 // instead of calling gethostbyname. However, the way IP addresses
1255 // are stored in the registry is annoyingly complex, so I'll leave
1256 // this as T.B.D. [Meruru]
1257 if( gethostname(fullhost, sizeof(fullhost)) == SOCKET_ERROR )
1258 {
1259 ShowError("socket_getips: No hostname defined!\n");
1260 return 0;
1261 }
1262 else
1263 {
1264 u_long** a;
1265 struct hostent* hent;
1266 hent = gethostbyname(fullhost);
1267 if( hent == NULL ){
1268 ShowError("socket_getips: Cannot resolve our own hostname to an IP address\n");
1269 return 0;
1270 }
1271 a = (u_long**)hent->h_addr_list;
1272 for( ;num < max && a[num] != NULL; ++num)
1273 ips[num] = (uint32)ntohl(*a[num]);
1274 }
1275 }
1276#else // not WIN32
1277 {
1278 int fd;
1279 char buf[2*16*sizeof(struct ifreq)];
1280 struct ifconf ic;
1281 u_long ad;
1282
1283 fd = sSocket(AF_INET, SOCK_STREAM, 0);
1284
1285 memset(buf, 0x00, sizeof(buf));
1286
1287 // The ioctl call will fail with Invalid Argument if there are more
1288 // interfaces than will fit in the buffer
1289 ic.ifc_len = sizeof(buf);
1290 ic.ifc_buf = buf;
1291 if( sIoctl(fd, SIOCGIFCONF, &ic) == -1 )
1292 {
1293 ShowError("socket_getips: SIOCGIFCONF failed!\n");
1294 return 0;
1295 }
1296 else
1297 {
1298 int pos;
1299 for( pos=0; pos < ic.ifc_len && num < max; )
1300 {
1301 struct ifreq* ir = (struct ifreq*)(buf+pos);
1302 struct sockaddr_in*a = (struct sockaddr_in*) &(ir->ifr_addr);
1303 if( a->sin_family == AF_INET ){
1304 ad = ntohl(a->sin_addr.s_addr);
1305 if( ad != INADDR_LOOPBACK && ad != INADDR_ANY )
1306 ips[num++] = (uint32)ad;
1307 }
1308 #if (defined(BSD) && BSD >= 199103) || defined(_AIX) || defined(__APPLE__)
1309 pos += ir->ifr_addr.sa_len + sizeof(ir->ifr_name);
1310 #else// not AIX or APPLE
1311 pos += sizeof(struct ifreq);
1312 #endif//not AIX or APPLE
1313 }
1314 }
1315 sClose(fd);
1316 }
1317#endif // not W32
1318
1319 // Use loopback if no ips are found
1320 if( num == 0 )
1321 ips[num++] = (uint32)INADDR_LOOPBACK;
1322
1323 return num;
1324}
1325
1326void socket_init(void)
1327{
1328 char *SOCKET_CONF_FILENAME = "conf/packet_athena.conf";
1329 unsigned int rlim_cur = FD_SETSIZE;
1330
1331#ifdef WIN32
1332 {// Start up windows networking
1333 WSADATA wsaData;
1334 WORD wVersionRequested = MAKEWORD(2, 0);
1335 if( WSAStartup(wVersionRequested, &wsaData) != 0 )
1336 {
1337 ShowError("socket_init: WinSock not available!\n");
1338 return;
1339 }
1340 if( LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 0 )
1341 {
1342 ShowError("socket_init: WinSock version mismatch (2.0 or compatible required)!\n");
1343 return;
1344 }
1345 }
1346#elif defined(HAVE_SETRLIMIT) && !defined(CYGWIN)
1347 // NOTE: getrlimit and setrlimit have bogus behaviour in cygwin.
1348 // "Number of fds is virtually unlimited in cygwin" (sys/param.h)
1349 {// set socket limit to FD_SETSIZE
1350 struct rlimit rlp;
1351 if( 0 == getrlimit(RLIMIT_NOFILE, &rlp) )
1352 {
1353 rlp.rlim_cur = FD_SETSIZE;
1354 if( 0 != setrlimit(RLIMIT_NOFILE, &rlp) )
1355 {// failed, try setting the maximum too (permission to change system limits is required)
1356 rlp.rlim_max = FD_SETSIZE;
1357 if( 0 != setrlimit(RLIMIT_NOFILE, &rlp) )
1358 {// failed
1359 const char *errmsg = error_msg();
1360 int rlim_ori;
1361 // set to maximum allowed
1362 getrlimit(RLIMIT_NOFILE, &rlp);
1363 rlim_ori = (int)rlp.rlim_cur;
1364 rlp.rlim_cur = rlp.rlim_max;
1365 setrlimit(RLIMIT_NOFILE, &rlp);
1366 // report limit
1367 getrlimit(RLIMIT_NOFILE, &rlp);
1368 rlim_cur = rlp.rlim_cur;
1369 ShowWarning("socket_init: failed to set socket limit to %d, setting to maximum allowed (original limit=%d, current limit=%d, maximum allowed=%d, %s).\n", FD_SETSIZE, rlim_ori, (int)rlp.rlim_cur, (int)rlp.rlim_max, errmsg);
1370 }
1371 }
1372 }
1373 }
1374#endif
1375
1376 // Get initial local ips
1377 naddr_ = socket_getips(addr_,16);
1378
1379 sFD_ZERO(&readfds);
1380#if defined(SEND_SHORTLIST)
1381 memset(send_shortlist_set, 0, sizeof(send_shortlist_set));
1382#endif
1383
1384 socket_config_read(SOCKET_CONF_FILENAME);
1385
1386 // Gepard Shield
1387 gepard_config_read();
1388 // Gepard Shield
1389
1390 // initialise last send-receive tick
1391 last_tick = time(NULL);
1392
1393 // session[0] is now currently used for disconnected sessions of the map server, and as such,
1394 // should hold enough buffer (it is a vacuum so to speak) as it is never flushed. [Skotlex]
1395 create_session(0, null_recv, null_send, null_parse); //FIXME this is causing leak
1396
1397#ifndef MINICORE
1398 // Delete old connection history every 5 minutes
1399 memset(connect_history, 0, sizeof(connect_history));
1400 add_timer_func_list(connect_check_clear, "connect_check_clear");
1401 add_timer_interval(gettick()+1000, connect_check_clear, 0, 0, 5*60*1000);
1402#endif
1403
1404 ShowInfo("Server supports up to '"CL_WHITE"%u"CL_RESET"' concurrent connections.\n", rlim_cur);
1405}
1406
1407
1408bool session_isValid(int fd)
1409{
1410 return ( fd > 0 && fd < FD_SETSIZE && session[fd] != NULL );
1411}
1412
1413bool session_isActive(int fd)
1414{
1415 return ( session_isValid(fd) && !session[fd]->flag.eof );
1416}
1417
1418// Resolves hostname into a numeric ip.
1419uint32 host2ip(const char* hostname)
1420{
1421 struct hostent* h = gethostbyname(hostname);
1422 return (h != NULL) ? ntohl(*(uint32*)h->h_addr) : 0;
1423}
1424
1425// Converts a numeric ip into a dot-formatted string.
1426// Result is placed either into a user-provided buffer or a static system buffer.
1427const char* ip2str(uint32 ip, char ip_str[16])
1428{
1429 struct in_addr addr;
1430 addr.s_addr = htonl(ip);
1431 return (ip_str == NULL) ? inet_ntoa(addr) : strncpy(ip_str, inet_ntoa(addr), 16);
1432}
1433
1434// Converts a dot-formatted ip string into a numeric ip.
1435uint32 str2ip(const char* ip_str)
1436{
1437 return ntohl(inet_addr(ip_str));
1438}
1439
1440// Reorders bytes from network to little endian (Windows).
1441// Neccessary for sending port numbers to the RO client until Gravity notices that they forgot ntohs() calls.
1442uint16 ntows(uint16 netshort)
1443{
1444 return ((netshort & 0xFF) << 8) | ((netshort & 0xFF00) >> 8);
1445}
1446
1447#ifdef SEND_SHORTLIST
1448// Add a fd to the shortlist so that it'll be recognized as a fd that needs
1449// sending or eof handling.
1450void send_shortlist_add_fd(int fd)
1451{
1452 int i;
1453 int bit;
1454
1455 if( !session_isValid(fd) )
1456 return;// out of range
1457
1458 i = fd/32;
1459 bit = fd%32;
1460
1461 if( (send_shortlist_set[i]>>bit)&1 )
1462 return;// already in the list
1463
1464 if( send_shortlist_count >= ARRAYLENGTH(send_shortlist_array) )
1465 {
1466 ShowDebug("send_shortlist_add_fd: shortlist is full, ignoring... (fd=%d shortlist.count=%d shortlist.length=%d)\n", fd, send_shortlist_count, ARRAYLENGTH(send_shortlist_array));
1467 return;
1468 }
1469
1470 // set the bit
1471 send_shortlist_set[i] |= 1<<bit;
1472 // Add to the end of the shortlist array.
1473 send_shortlist_array[send_shortlist_count++] = fd;
1474}
1475
1476// Do pending network sends and eof handling from the shortlist.
1477void send_shortlist_do_sends()
1478{
1479 int i;
1480
1481 for( i = send_shortlist_count-1; i >= 0; --i )
1482 {
1483 int fd = send_shortlist_array[i];
1484 int idx = fd/32;
1485 int bit = fd%32;
1486
1487 // Remove fd from shortlist, move the last fd to the current position
1488 --send_shortlist_count;
1489 send_shortlist_array[i] = send_shortlist_array[send_shortlist_count];
1490 send_shortlist_array[send_shortlist_count] = 0;
1491
1492 if( fd <= 0 || fd >= FD_SETSIZE )
1493 {
1494 ShowDebug("send_shortlist_do_sends: fd is out of range, corrupted memory? (fd=%d)\n", fd);
1495 continue;
1496 }
1497 if( ((send_shortlist_set[idx]>>bit)&1) == 0 )
1498 {
1499 ShowDebug("send_shortlist_do_sends: fd is not set, why is it in the shortlist? (fd=%d)\n", fd);
1500 continue;
1501 }
1502 send_shortlist_set[idx]&=~(1<<bit);// unset fd
1503 // If this session still exists, perform send operations on it and
1504 // check for the eof state.
1505 if( session[fd] )
1506 {
1507 // Send data
1508 if( session[fd]->wdata_size )
1509 session[fd]->func_send(fd);
1510
1511 // If it's been marked as eof, call the parse func on it so that
1512 // the socket will be immediately closed.
1513 if( session[fd]->flag.eof )
1514 session[fd]->func_parse(fd);
1515
1516 // If the session still exists, is not eof and has things left to
1517 // be sent from it we'll re-add it to the shortlist.
1518 if( session[fd] && !session[fd]->flag.eof && session[fd]->wdata_size )
1519 send_shortlist_add_fd(fd);
1520 }
1521 }
1522}
1523#endif
1524
1525bool is_gepard_active;
1526uint32 gepard_rand_seed;
1527uint32 min_allowed_gepard_version;
1528
1529const unsigned char* shield_matrix = (const unsigned char*)
1530
1531 "\x50\xa0\xc4\xc1\x57\xc5\x9e\x52\xc1\xc7\x1d\x83\x07\xd4\xa0\x9e"
1532 "\x44\x6e\xee\x41\x99\x8d\x47\x6d\x7f\x7d\x65\xcc\x9c\xa8\x32\x78"
1533 "\x75\x58\x08\x73\x08\xb8\x46\xc1\xa2\x10\x2a\xab\x9a\x05\x1c\xaf"
1534 "\xa0\x61\xe8\xa0\x53\x2c\x11\x7b\x66\x06\x3b\xfe\x6b\xa2\xd6\xeb"
1535 "\x90\xd5\x0f\x21\x70\x79\x9a\x61\xbd\xb6\xf7\x7e\x65\x72\x3c\xb5"
1536 "\x76\xdb\x6d\x73\xed\xee\x17\x61\xa8\x5a\x1b\x51\x9c\x25\xd6\x80"
1537 "\xb2\x03\x3a\x47\x3d\x28\x5a\x9c\xfd\x9a\x89\x95\x38\x44\x30\xc4"
1538 "\x29\xd2\x41\x90\x07\x20\x19\x7e\x42\xa2\x28\xf7\x37\xbc\xa1\x04"
1539 "\x11\xdd\xaf\x17\x7b\xbb\x46\x4b\xf1\xae\xa4\x3e\xcb\xf3\xa8\x64"
1540 "\x41\xce\x6a\x83\x1e\xde\x59\xa9\x55\x1d\xca\x5a\x24\x50\xad\x39"
1541 "\x86\x79\xd7\x74\x1c\xfa\xa4\xbd\xcc\xfa\x53\xf9\xbb\xce\x5d\x92"
1542 "\xea\x6b\xb4\x89\x98\x1d\xa0\x2c\xa5\x19\xb0\x93\x30\x94\x72\xd3"
1543 "\x10\x7a\xdf\xf7\x78\x03\x3e\x36\xe5\x9a\xe3\x7d\x08\xf7\x09\xbd"
1544 "\x75\xd8\x2e\x95\x3d\x24\x39\x42\x9d\xfe\x49\x74\x8b\x17\x6d\x80"
1545 "\x50\x9d\x38\xed\xc9\xc5\x62\x6c\x37\xbb\x69\x33\x92\xe3\xea\xca"
1546 "\xd5\x5b\xab\xce\x3a\x8b\x74\x1c\x48\x45\xc8\xfe\x4e\x36\x1f\x5b"
1547 "\x0d\xae\x98\xd7\xad\x07\xe1\x8b\x5f\x23\xb7\x39\x23\x5c\xc4\x11"
1548 "\x22\xcb\x44\x8e\x1e\xc3\xa4\x5f\xd6\xfb\xa5\xeb\xf0\x28\x0b\xf6"
1549 "\x30\x91\xf6\x69\xa7\xde\x91\x32\x23\x27\x6b\xdf\x66\x80\xdd\x5c"
1550 "\x17\x16\x51\xe3\x5f\x8f\xa2\xa5\x20\xc1\x9e\xa5\x50\x72\xba\x5a"
1551 "\x48\xba\x13\x0c\x1d\x3b\x4c\xf2\xe6\xb3\x61\x2d\xea\xc0\x7f\x6d"
1552 "\x15\xba\xf2\x12\xd3\x85\xc9\x7b\x9a\xcb\xb2\x4d\xae\xf1\xba\x7e"
1553 "\x05\x37\x6c\x5b\x59\xdc\xee\xd5\x38\x48\xbb\xd9\x23\xe2\x7a\x78"
1554 "\x20\x4d\x8c\x8e\xba\x10\xf8\xe1\x65\xe5\x25\x34\x30\x56\x9c\x52"
1555 "\x3e\x23\x48\xa7\x0b\x58\x5b\x55\xc4\x77\x61\x55\x68\x82\xa0\xa4"
1556 "\xde\xf6\xc5\x04\x33\xed\x93\x4e\x40\x6c\x80\x64\xde\x23\x73\xb5"
1557 "\x6e\x31\x30\xf5\xc2\x96\xf6\x60\xdd\xe7\x7c\xc0\xf4\x0b\x47\x0e"
1558 "\x9d\x73\x08\xd1\x40\xb3\x83\xa8\x8f\x4f\x8d\x17\x28\xaf\x59\x81"
1559 "\x31\x28\x72\xfe\x78\xd3\x2c\xda\xfc\x56\xf9\x6f\x68\x3f\xca\xc5"
1560 "\xcd\x93\x84\x0a\xcc\x45\xb1\x50\x5c\x94\xdf\xbd\xde\x29\x6a\x7e"
1561 "\xca\x62\x1e\x2f\x07\x22\xe8\x9a\xbb\x11\x8c\x6d\xc5\x34\x09\x4f"
1562 "\x02\xbb\x2e\x72\xa3\x5f\x10\x13\x54\xd5\xc8\x7a\x35\x0e\xc6\xe9"
1563 "\x1f\x4e\x89\xa6\xaa\x64\x1d\x6b\x59\x7c\xaa\xf6\xf3\xd5\xe3\xa1"
1564 "\x71\x62\xba\x06\xf5\x11\x90\xb8\x48\xc0\xe2\xa4\xc7\xb2\x13\xf6"
1565 "\xb9\x6c\xcd\xba\x88\x54\x40\x0b\xb8\x8e\x0f\x7e\x41\x5f\x44\xaa"
1566 "\xf9\x17\x25\xf3\xd7\x3b\x2b\xf8\xac\x94\x09\xc9\x91\xbe\x78\xca"
1567 "\xc7\xd4\xc7\x73\x24\x7f\xca\xae\xe0\xd2\xb6\x28\xd9\x65\x13\x48"
1568 "\x1a\xf6\x2e\x1e\x41\x16\x5c\x81\x9a\xa8\xda\x27\xf5\xad\x24\x01"
1569 "\x1b\xb1\x98\x0d\x6a\xc4\xba\xfb\xfb\xe8\x64\xce\x52\xca\xbe\x51"
1570 "\xf5\xb7\xd8\x1c\x0f\x2c\x24\xf2\xce\xe6\x3d\xb1\x39\x50\x45\x26"
1571 "\xa9\xc0\xa5\xf8\x28\x5b\x11\x8e\x59\x84\x9d\x7e\xa1\xca\xba\x8a"
1572 "\xd5\xa1\xea\x37\x82\x5c\x84\xe1\xab\x49\x59\x8f\x04\xc8\x12\xbb"
1573 "\x8d\xd4\x98\xda\x90\xc9\x55\xf3\x6c\x6c\x2e\x7a\x24\xf1\x7e\xb2"
1574 "\x25\x10\xf0\xed\x3e\x59\x05\xd7\x33\x64\x19\x1e\x65\x90\x42\x39"
1575 "\x04\xd2\xdd\x0b\x3a\x6e\x8e\x32\x4c\xfb\x23\xb7\x99\xa4\x03\x78"
1576 "\xf3\x75\x3a\xf2\x4b\x29\x34\xd1\x10\xdc\xae\x6c\x4e\x72\x92\x08"
1577 "\xef\x37\xa5\x17\x1f\x79\xcc\x3d\x32\x22\xcd\x5e\x23\x95\xc6\x01"
1578 "\xf5\xd3\x57\xad\x97\xa7\x9e\x41\x0f\xe9\x8c\xbc\x14\x8e\x44\x86"
1579 "\xd6\x8e\xe7\x3e\x9d\xee\x21\x02\x7e\xe2\xc4\x4e\xca\xd0\xce\xe1"
1580 "\x83\x44\x23\xb7\xf0\x83\x59\x0a\xa1\xda\x6c\x08\x6f\xd7\x9b\x07"
1581 "\xe1\x7b\xda\xf6\x78\x29\xa0\x5e\x34\xd4\x64\x97\xf9\x33\x9e\x2a"
1582 "\x98\x73\x36\x5f\x8e\xbe\x7b\x07\x5b\x90\xc9\x78\x7e\x17\xdf\xce"
1583 "\xdf\x34\xfd\x67\x55\xd3\xe4\xa5\xf8\xa3\x47\x22\x81\xee\x44\x57"
1584 "\x54\xa0\x70\xa8\x85\x31\xa0\x83\xf6\x22\x64\x6e\x42\xe8\xdf\x97"
1585 "\xc3\x04\x11\x6e\x3f\xef\x0c\x9f\x19\x8d\xd2\x81\x13\x09\xcb\x5f"
1586 "\xfb\x22\xf4\xc8\x55\x84\x69\xc0\xcf\x33\x40\xfd\xa0\x3a\xeb\x10"
1587 "\xa0\xc7\x98\x9a\x24\x52\x37\x07\x03\xe7\x2a\xc8\x48\x5b\x48\xa9"
1588 "\xf5\xdd\xab\xaa\x5d\xb8\x79\xf4\x66\xc5\xa6\x6d\x63\x51\xd7\x5a"
1589 "\x32\x72\x5f\x31\xd7\xa4\x8c\x89\x48\x18\x3a\xb7\x1b\x95\x51\x11"
1590 "\xcf\xd0\x3e\xeb\xe1\x9f\xf6\x48\x61\x6b\xa3\x3a\xb6\xc5\x7c\x0c"
1591 "\x57\x8a\x72\x2b\x8e\x61\xb5\xcb\x22\x9a\xaf\x64\x6b\x37\x81\x67"
1592 "\x37\x8c\x9c\x61\x8a\xdf\x0f\xd7\x88\x67\x06\x90\x2c\x02\xb7\x2f"
1593 "\x0f\x2a\xa1\xb4\xe3\x5b\x60\x64\x6a\xfd\xfb\x17\x7c\x16\x76\xef"
1594 "\x82\x33\xf9\x0f\xe3\xf3\xef\xb3\x49\x93\xe2\x57\x3a\xc6\xe6\xc2"
1595 "\x82\x22\x83\x2e\x57\xb6\xbd\x5e\x9f\x66\xd6\x4f\x75\x5d\xd3\xe1"
1596 "\x27\x7f\xcd\xb1\x5f\xac\xce\x63\x34\x5c\x12\x25\x39\xa7\xf2\xb7"
1597 "\x79\xcc\xef\xac\xc8\x6c\x04\x39\xe4\x8a\x3a\x3c\xe1\x0a\x3f\xea"
1598 "\x43\x3b\xd2\xb6\x51\x2b\xe2\x5d\xfd\x45\xb0\xc3\x67\x0d\xc1\xf3"
1599 "\x62\xe7\x05\x78\x80\x49\xeb\x67\x81\xb4\x63\x45\xb1\xee\x64\x29"
1600 "\x95\xc8\x88\xbf\x72\xe5\x67\x11\x7f\xe1\x1e\xb4\xe4\xb1\x41\xd1"
1601 "\x4e\x3c\x23\x0d\x29\xed\x34\x4f\xdf\x45\xd5\x03\x37\xaf\xf0\x33"
1602 "\x82\x1b\xb1\xa4\x5d\x29\x9b\x5d\x36\xdb\xfd\xab\xb8\xa5\xe0\x20"
1603 "\xf4\x47\x70\x1d\xce\xce\x1e\xcc\x0f\x31\xd6\x43\x2b\x47\x98\x8e"
1604 "\x11\xbb\x55\x6f\x93\x92\xc3\x18\xc2\x70\xb9\x0e\xcb\xcc\x16\x20"
1605 "\x2f\x9b\x56\x0b\x66\x35\xee\x2f\x42\x7b\xee\x87\xa7\x04\x12\xb8"
1606 "\x6e\xc5\x3f\xde\x79\x95\x28\x0a\xe9\x71\x7c\xf8\x6b\xde\x59\x88"
1607 "\x7b\xde\x22\x70\x45\x3d\x70\xb8\xd0\x43\xef\x85\x2e\x87\x17\xa0"
1608 "\x69\x69\x7d\x66\xd7\x77\x13\x71\x94\x44\xb6\xbb\x47\x68\xa7\x82"
1609 "\x7a\xcc\xdf\x1a\x26\xd8\xf1\xa1\xb3\xb6\xe8\x27\x1f\xc6\xe6\x2c"
1610 "\x76\x6b\x64\xa9\x5a\xd4\xd5\x7d\xd0\x60\x1c\xda\x77\xc8\x80\x2c"
1611 "\xf2\x32\x2c\x86\xa6\x4c\x42\x92\x8b\x18\xb1\x08\xc4\x0c\x43\xb0"
1612 "\x2d\x24\x8a\x06\x12\x9b\x43\x54\xcd\x54\xa5\x0c\x74\x32\x6a\x97"
1613 "\x50\xf1\x5b\xed\x4a\xaf\xb8\x2d\x9b\x3f\xe2\xfb\x48\xf4\x74\x7d"
1614 "\xc9\x22\x4c\x89\x72\x0f\x31\x0f\xe1\xc1\x8e\xbb\x1b\x2f\xec\x4b"
1615 "\x1d\x01\x2d\xb5\x76\xf0\x2f\x04\xc8\x18\xdb\x08\xba\xf3\x43\x4f"
1616 "\xac\x7f\x46\xf4\x55\xc5\x7e\x3a\x04\xdd\x58\x09\x2e\x99\x15\x41"
1617 "\x0d\x6c\xa1\x7b\xf5\xcf\x82\x1c\x20\x22\x3f\xe3\x8d\xcd\x22\x5c"
1618 "\x58\x35\x5d\xc0\x75\xa9\x88\x57\x53\xf1\xc6\x48\xd0\xa1\xf2\xe6"
1619 "\x77\x50\x7d\x8f\x77\x60\x15\x72\xcf\x6e\x72\x7f\x9a\x1c\xfc\xcb"
1620 "\x75\x4b\x39\x16\xf4\x7b\xb4\x5b\x8f\xd9\xe0\x22\x0e\xcb\x9b\x1f"
1621 "\x53\x5f\xca\x76\x0d\x0e\x4c\x75\x29\x27\x9e\xfa\x1c\x4f\x10\x39"
1622 "\xd0\x7d\x43\x55\xd6\xcb\xe8\xae\x1d\x88\xf3\x6d\xd2\xed\xa7\x3f"
1623 "\x41\x60\xd6\xe9\x2e\x93\x11\x88\xa5\x85\xb3\xac\x31\x25\x93\x36"
1624 "\xd8\x1c\x2c\x8f\x84\x82\x12\xae\x06\x82\x0f\xfc\x71\xb6\x33\x11"
1625 "\x01\xad\xb1\xd4\x33\x02\x51\x82\xde\xd9\x63\x9d\xdd\x36\x67\xc5"
1626 "\xa2\x8b\x67\x8b\xc9\xd9\x9e\x2d\xf6\xe1\x87\x55\x9d\x23\xdf\xd3"
1627 "\xf9\x35\xb1\xd8\xdc\xbe\x7f\xad\x93\x06\xa2\x0b\x88\xeb\xed\x5f"
1628 "\x65\xc3\x2a\x44\x57\xe1\x83\xec\xc0\xd2\xf4\x4d\x72\x88\x52\xb8"
1629 "\xb4\x78\x6e\xc8\xca\x02\x11\xca\x27\x04\xac\x66\xfd\x03\x8d\xef"
1630 "\x7c\xd0\x70\x66\xc0\x7b\x37\xaa\xd7\x18\xb3\xee\x6b\x8d\xb2\x65"
1631 "\xe0\x0f\xc6\x2f\x86\xd8\xfe\x0a\x20\x5c\x80\xd6\x6c\x0e\x31\x57"
1632 "\xe8\x53\xf9\x57\x7f\xdf\xb6\x8f\xd5\x84\xe3\xfa\xeb\x30\xad\xf4"
1633 "\x4f\xa2\x5a\xc7\x77\x23\xc7\x16\xa9\xb0\x5d\x34\x67\xf2\xc7\x6a"
1634 "\xce\x7f\x4a\x2c\x6f\x96\x81\x3f\xf6\x83\x69\xe4\xb8\xbe\x73\xf4"
1635 "\xf5\xf1\x10\x03\x6e\x18\xeb\x07\x92\x32\x4d\x0d\xe6\x6b\x43\x6f"
1636 "\xf4\x1e\x27\xaf\x51\x81\x1a\xcd\x1c\x91\xeb\x54\xf9\x5c\xb9\x66"
1637 "\x6e\xce\x10\x06\x1d\xbd\x72\x6d\xcd\xa9\x97\x21\x46\x05\x99\xa3"
1638 "\xc7\x0a\x9c\xdf\x4a\x52\x09\xc3\xcb\xc0\xd9\xa4\xbe\x81\xb7\x40"
1639 "\x77\x9e\x47\x28\x19\x72\xe4\x4b\xf1\x70\xca\xe8\x45\xa0\xc6\x36"
1640 "\xd6\xb5\x79\xee\x60\x8e\xd8\x9f\x2c\x34\x60\x64\x78\x7a\xab\xec"
1641 "\xf1\x5e\xe5\xf6\xdd\x66\xcf\x18\x3b\x78\x3a\x0b\x06\x76\xc9\xcc"
1642 "\xd6\xa3\x51\xc4\x02\x93\x1b\x51\x0c\xa8\xf5\x59\xfa\x65\x55\x4a"
1643 "\xe4\x99\x64\xb2\xc7\x1e\xc4\xbf\x86\xc2\x7b\xe6\x91\x0e\xa3\xfc"
1644 "\x9e\xec\x7b\x7b\x7f\x0e\x61\xbe\x5c\xe7\xd1\xf8\x01\xb8\x79\x2a"
1645 "\xf8\x73\xf7\x4f\x1d\x73\xda\x20\xd8\xe7\x68\x8d\x51\xc5\x5c\xd4"
1646 "\x2b\x3d\x12\x60\x8b\x22\x45\xbe\xb0\x55\xee\xee\xa7\xb9\xe1\xd1"
1647 "\x7e\xa1\xa1\x75\x80\x12\x2b\x0c\x56\x13\x9f\xc3\x96\xce\xfd\x54"
1648 "\x1c\xd4\xf4\xf7\x41\x43\x61\xa0\x44\xe5\x8f\x9b\xef\x05\x59\xfc"
1649 "\xe3\xf0\x9f\x03\xfd\x7b\xd2\x4c\x4d\x03\x82\x03\x13\x31\x97\x6e"
1650 "\xb4\x89\x47\x77\x1b\x01\x55\xa5\xf0\xa1\x37\x92\x3f\x0b\xb1\xd7"
1651 "\x41\x3c\x77\x07\x04\x04\xf3\x1a\x29\x8a\x38\x7a\x60\xc3\x3c\x0b"
1652 "\x5d\xc1\xef\x49\xf8\xb6\x44\x80\x3a\x28\x2d\x9a\xe0\x8f\xbe\x06"
1653 "\xd0\xf7\xf2\xc6\x64\xd4\xb4\x25\x22\x13\xa9\x8b\xf7\xb6\x01\x07"
1654 "\x22\x7a\x1a\x0d\xa1\xb8\x57\x5c\xc3\x28\xfd\xaf\xfe\xa9\x5a\x9c"
1655 "\x6e\x2a\x20\xba\xd6\xe9\x3d\x11\x07\x95\x06\x49\x3a\x8a\x02\xb2"
1656 "\x33\xc4\xb5\x93\xbb\x2e\xb9\xd4\xd6\xe8\xfa\x02\xac\xc4\x5f\x25"
1657 "\x9e\xec\xce\x0f\x73\x16\xbb\x73\x19\xa2\xbf\x7f\x6a\x95\xdc\x51"
1658 "\xe2\xc3\x74\xe5\xd3\x11\x9a\x7c\x5f\xc2\x37\xf3\x60\x21\xb0\x9f";
1659
1660void gepard_config_read()
1661{
1662 char* conf_name = "conf/gepard_shield.conf";
1663 char line[1024], w1[1024], w2[1024];
1664
1665 FILE* fp = fopen(conf_name, "r");
1666
1667 is_gepard_active = false;
1668
1669 if (fp == NULL)
1670 {
1671 ShowError("Gepard configuration file (%s) not found. Shield disabled.\n", conf_name);
1672 return;
1673 }
1674
1675 while(fgets(line, sizeof(line), fp))
1676 {
1677 if (line[0] == '/' && line[1] == '/')
1678 continue;
1679
1680 if (sscanf(line, "%[^:]: %[^\r\n]", w1, w2) < 2)
1681 continue;
1682
1683 if (!strcmpi(w1, "gepard_shield_enabled"))
1684 {
1685 is_gepard_active = (bool)config_switch(w2);
1686 }
1687 }
1688
1689 fclose(fp);
1690
1691 conf_name = "conf/gepard_version.txt";
1692
1693 if ((fp = fopen(conf_name, "r")) == NULL)
1694 {
1695 min_allowed_gepard_version = 0;
1696 ShowError("Gepard version file (%s) not found.\n", conf_name);
1697 return;
1698 }
1699
1700 fscanf(fp, "%u", &min_allowed_gepard_version);
1701
1702 fclose(fp);
1703}
1704
1705bool gepard_process_packet(int fd, uint8* packet_data, uint32 packet_size, struct gepard_crypt_link* link)
1706{
1707 uint16 packet_id = RBUFW(packet_data, 0);
1708
1709 switch (packet_id)
1710 {
1711 case CS_GEPARD_SYNC:
1712 {
1713 uint32 control_value;
1714
1715 if (RFIFOREST(fd) < 6)
1716 {
1717 return true;
1718 }
1719
1720 gepard_enc_dec(packet_data + 2, packet_data + 2, 4, &session[fd]->sync_crypt);
1721
1722 control_value = RFIFOL(fd, 2);
1723
1724 if (control_value == 0xDDCCBBAA)
1725 {
1726 session[fd]->gepard_info.sync_tick = gettick();
1727 }
1728
1729 RFIFOSKIP(fd, 6);
1730
1731 return true;
1732 }
1733 break;
1734
1735 case CS_LOGIN_PACKET_1:
1736 case CS_LOGIN_PACKET_2:
1737 case CS_LOGIN_PACKET_3:
1738 case CS_LOGIN_PACKET_4:
1739 case CS_LOGIN_PACKET_5:
1740 case CS_LOGIN_PACKET_6:
1741 {
1742 set_eof(fd);
1743 return true;
1744 }
1745 break;
1746
1747 case CS_LOGIN_PACKET:
1748 {
1749 if (RFIFOREST(fd) < 55)
1750 {
1751 return false;
1752 }
1753
1754 if (session[fd]->gepard_info.is_init_ack_received == false)
1755 {
1756 RFIFOSKIP(fd, RFIFOREST(fd));
1757 gepard_init(fd, GEPARD_LOGIN);
1758 return true;
1759 }
1760
1761 gepard_enc_dec(packet_data + 2, packet_data + 2, RFIFOREST(fd) - 2, link);
1762 }
1763 break;
1764
1765 case CS_WHISPER_TO:
1766 {
1767 if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < (packet_size = RBUFW(packet_data, 2)) || packet_size < 4)
1768 {
1769 return true;
1770 }
1771
1772 gepard_enc_dec(packet_data + 4, packet_data + 4, packet_size - 4, link);
1773 }
1774 break;
1775
1776 case CS_WALK_TO_XY:
1777 case CS_USE_SKILL_TO_ID:
1778 case CS_USE_SKILL_TO_POS:
1779 {
1780 if (packet_size < 2 || RFIFOREST(fd) < packet_size)
1781 {
1782 return true;
1783 }
1784
1785 gepard_enc_dec(packet_data + 2, packet_data + 2, packet_size - 2, link);
1786 }
1787 break;
1788
1789 case SC_WHISPER_FROM:
1790 case SC_SET_UNIT_IDLE:
1791 case SC_SET_UNIT_WALKING:
1792 {
1793 if (&session[fd]->send_crypt != link)
1794 {
1795 return true;
1796 }
1797
1798 gepard_enc_dec(packet_data + 4, packet_data + 4, packet_size - 4, link);
1799 }
1800 break;
1801
1802 case CS_GEPARD_INIT_ACK:
1803 {
1804 uint32 unique_id, unique_id_, shield_ver;
1805
1806 if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < (packet_size = RFIFOW(fd, 2)))
1807 {
1808 return true;
1809 }
1810
1811 if (packet_size < 16)
1812 {
1813 ShowWarning("gepard_process_packet: invalid size of CS_GEPARD_INIT_ACK packet: %u\n", packet_size);
1814 set_eof(fd);
1815 return true;
1816 }
1817
1818 gepard_enc_dec(packet_data + 4, packet_data + 4, packet_size - 4, link);
1819
1820 unique_id = RFIFOL(fd, 4);
1821 shield_ver = RFIFOL(fd, 8);
1822 unique_id_ = RFIFOL(fd, 12) ^ UNIQUE_ID_XOR;
1823
1824 RFIFOSKIP(fd, packet_size);
1825
1826 if (!unique_id || !unique_id_ || unique_id != unique_id_)
1827 {
1828 WFIFOHEAD(fd, 6);
1829 WFIFOW(fd, 0) = SC_GEPARD_INFO;
1830 WFIFOL(fd, 2) = 3;
1831 WFIFOSET(fd, 6);
1832 set_eof(fd);
1833 }
1834
1835 session[fd]->gepard_info.is_init_ack_received = true;
1836 session[fd]->gepard_info.unique_id = unique_id;
1837 session[fd]->gepard_info.gepard_shield_version = shield_ver;
1838
1839 return true;
1840 }
1841 break;
1842 }
1843
1844 return false;
1845}
1846
1847inline void gepard_srand(unsigned int seed)
1848{
1849 gepard_rand_seed = seed;
1850}
1851
1852inline unsigned int gepard_rand()
1853{
1854 return (((gepard_rand_seed = gepard_rand_seed * 214013L + 2531011L) >> 16) & 0x7fff);
1855}
1856
1857void gepard_session_init(int fd, unsigned int recv_key, unsigned int send_key, unsigned int sync_key)
1858{
1859 uint32 i;
1860 uint8 random_1 = RAND_1_START;
1861 uint8 random_2 = RAND_2_START;
1862
1863 session[fd]->recv_crypt.pos_1 = session[fd]->send_crypt.pos_1 = session[fd]->sync_crypt.pos_1 = POS_1_START;
1864 session[fd]->recv_crypt.pos_2 = session[fd]->send_crypt.pos_2 = session[fd]->sync_crypt.pos_2 = POS_2_START;
1865 session[fd]->recv_crypt.pos_3 = session[fd]->send_crypt.pos_3 = session[fd]->sync_crypt.pos_3 = 0;
1866
1867 gepard_srand(recv_key ^ SRAND_CONST);
1868
1869 for (i = 0; i < (KEY_SIZE-1); ++i)
1870 {
1871 random_1 ^= shield_matrix[gepard_rand() % (MATRIX_SIZE-1)];
1872 random_1 -= (6 * random_2) + 3;
1873 random_2 ^= shield_matrix[gepard_rand() % (MATRIX_SIZE-1)];
1874 random_2 += (7 * random_1) + 2;
1875 random_1 += random_2 ^ shield_matrix[gepard_rand() % (MATRIX_SIZE-1)];
1876 session[fd]->recv_crypt.key[i] = random_1;
1877 }
1878
1879 random_1 = RAND_1_START;
1880 random_2 = RAND_2_START;
1881 gepard_srand(send_key | SRAND_CONST);
1882
1883 for (i = 0; i < (KEY_SIZE-1); ++i)
1884 {
1885 random_1 ^= shield_matrix[gepard_rand() % (MATRIX_SIZE-1)];
1886 random_1 -= (2 * random_2) - 9;
1887 random_2 ^= shield_matrix[gepard_rand() % (MATRIX_SIZE-1)];
1888 random_2 -= (5 * random_1) + 6;
1889 random_1 += random_2 ^ shield_matrix[gepard_rand() % (MATRIX_SIZE-1)];
1890 session[fd]->send_crypt.key[i] = random_1;
1891 }
1892
1893 random_1 = RAND_1_START;
1894 random_2 = RAND_2_START;
1895 gepard_srand(sync_key | SRAND_CONST);
1896
1897 for (i = 0; i < (KEY_SIZE-1); ++i)
1898 {
1899 random_1 ^= shield_matrix[gepard_rand() % (MATRIX_SIZE-1)];
1900 random_1 -= (3 * random_2) + 8;
1901 random_2 ^= shield_matrix[gepard_rand() % (MATRIX_SIZE-1)];
1902 random_2 += (2 * random_1) - 7;
1903 random_1 -= random_2 ^ shield_matrix[gepard_rand() % (MATRIX_SIZE-1)];
1904 session[fd]->sync_crypt.key[i] = random_1;
1905 }
1906}
1907
1908void gepard_init(int fd, uint16 server_type)
1909{
1910 const uint16 init_packet_size = 20;
1911 uint16 recv_key = (gepard_rand() % 0xFFFF);
1912 uint16 send_key = (gepard_rand() % 0xFFFF);
1913 uint16 sync_key = (gepard_rand() % 0xFFFF);
1914
1915 gepard_srand((unsigned)time(NULL) ^ clock());
1916
1917 WFIFOHEAD(fd, init_packet_size);
1918 WFIFOW(fd, 0) = SC_GEPARD_INIT;
1919 WFIFOW(fd, 2) = init_packet_size;
1920 WFIFOW(fd, 4) = recv_key;
1921 WFIFOW(fd, 6) = send_key;
1922 WFIFOW(fd, 8) = server_type;
1923 WFIFOL(fd, 10) = GEPARD_ID;
1924 WFIFOL(fd, 14) = min_allowed_gepard_version;
1925 WFIFOW(fd, 18) = sync_key;
1926 WFIFOSET(fd, init_packet_size);
1927
1928 gepard_session_init(fd, recv_key, send_key, sync_key);
1929}
1930
1931void gepard_enc_dec(uint8* in_data, uint8* out_data, uint32 data_size, struct gepard_crypt_link* link)
1932{
1933 uint32 i;
1934
1935 for(i = 0; i < data_size; ++i)
1936 {
1937 link->pos_1 += link->key[link->pos_3 % (KEY_SIZE-1)];
1938 link->pos_2 += (6- link->pos_1) * 7;
1939 link->key[link->pos_2 % (KEY_SIZE-1)] ^= link->pos_1;
1940 link->pos_1 += ((link->pos_2 - link->pos_3) * 3) - 5;
1941 link->key[link->pos_3 % (KEY_SIZE-1)] ^= link->pos_1;
1942 out_data[i] = in_data[i] ^ link->pos_1;
1943 link->pos_1 *= 8;
1944 link->pos_2 -= data_size % 0xFF;
1945 link->pos_3++;
1946 }
1947}
1948
1949void gepard_send_info(int fd, unsigned short info_type, char* message)
1950{
1951 int message_len = strlen(message) + 1;
1952 int packet_len = 2 + 2 + 2 + message_len;
1953
1954 WFIFOHEAD(fd, packet_len);
1955 WFIFOW(fd, 0) = SC_GEPARD_INFO;
1956 WFIFOW(fd, 2) = packet_len;
1957 WFIFOW(fd, 4) = info_type;
1958 safestrncpy((char*)WFIFOP(fd, 6), message, message_len);
1959 WFIFOSET(fd, packet_len);
1960}