diff options
Diffstat (limited to 'src/common/socket.c')
-rw-r--r-- | src/common/socket.c | 269 |
1 files changed, 174 insertions, 95 deletions
diff --git a/src/common/socket.c b/src/common/socket.c index d4b8bb43f..95d8bf578 100644 --- a/src/common/socket.c +++ b/src/common/socket.c @@ -2,7 +2,7 @@ * This file is part of Hercules. * http://herc.ws - http://github.com/HerculesWS/Hercules * - * Copyright (C) 2012-2016 Hercules Dev Team + * Copyright (C) 2012-2018 Hercules Dev Team * Copyright (C) Athena Dev Teams * * Hercules is free software: you can redistribute it and/or modify @@ -30,6 +30,7 @@ #include "common/memmgr.h" #include "common/mmo.h" #include "common/nullpo.h" +#include "common/packets.h" #include "common/showmsg.h" #include "common/strlib.h" #include "common/timer.h" @@ -75,19 +76,17 @@ /** * Socket Interface Source **/ -struct socket_interface sockt_s; +static struct socket_interface sockt_s; struct socket_interface *sockt; -struct socket_data **session; - -const char *SOCKET_CONF_FILENAME = "conf/common/socket.conf"; +static const char *SOCKET_CONF_FILENAME = "conf/common/socket.conf"; #ifdef SEND_SHORTLIST // Add a fd to the shortlist so that it'll be recognized as a fd that needs // sending done on it. -void send_shortlist_add_fd(int fd); +static void send_shortlist_add_fd(int fd); // Do pending network sends (and eof handling) from the shortlist. -void send_shortlist_do_sends(void); +static void send_shortlist_do_sends(void); #endif // SEND_SHORTLIST ///////////////////////////////////////////////////////////////////// @@ -123,7 +122,7 @@ static int sock_arr_len = 0; /// /// @param s Socket /// @return Fd or -1 -int sock2fd(SOCKET s) +static int sock2fd(SOCKET s) { int fd; @@ -144,7 +143,7 @@ int sock2fd(SOCKET s) /// /// @param s Socket /// @return New fd or -1 -int sock2newfd(SOCKET s) +static int sock2newfd(SOCKET s) { int fd; @@ -164,7 +163,7 @@ int sock2newfd(SOCKET s) return fd; } -int sAccept(int fd, struct sockaddr* addr, int* addrlen) +static int sAccept(int fd, struct sockaddr *addr, int *addrlen) { SOCKET s; @@ -175,14 +174,14 @@ int sAccept(int fd, struct sockaddr* addr, int* addrlen) return sock2newfd(s); } -int sClose(int fd) +static int sClose(int fd) { int ret = closesocket(fd2sock(fd)); fd2sock(fd) = INVALID_SOCKET; return ret; } -int sSocket(int af, int type, int protocol) +static int sSocket(int af, int type, int protocol) { SOCKET s; @@ -193,7 +192,7 @@ int sSocket(int af, int type, int protocol) return sock2newfd(s); } -char* sErr(int code) +static char *sErr(int code) { static char sbuf[512]; // strerror does not handle socket codes @@ -259,7 +258,7 @@ char* sErr(int code) #ifndef SOCKET_EPOLL // Select based Event Dispatcher: -fd_set readfds; +static fd_set readfds; #else // SOCKET_EPOLL // Epoll based Event Dispatcher: @@ -296,19 +295,17 @@ static time_t socket_data_last_tick = 0; #define WFIFO_MAX (1*1024*1024) #ifdef SEND_SHORTLIST -int send_shortlist_array[FD_SETSIZE];// we only support FD_SETSIZE sockets, limit the array to that -int send_shortlist_count = 0;// how many fd's are in the shortlist -uint32 send_shortlist_set[(FD_SETSIZE+31)/32];// to know if specific fd's are already in the shortlist +static int send_shortlist_array[FD_SETSIZE];// we only support FD_SETSIZE sockets, limit the array to that +static int send_shortlist_count = 0;// how many fd's are in the shortlist +static uint32 send_shortlist_set[(FD_SETSIZE+31)/32];// to know if specific fd's are already in the shortlist #endif // SEND_SHORTLIST static int create_session(int fd, RecvFunc func_recv, SendFunc func_send, ParseFunc func_parse); -#ifndef MINICORE - int ip_rules = 1; - static int connect_check(uint32 ip); -#endif // MINICORE +static int ip_rules = 1; +static int connect_check(uint32 ip); -const char* error_msg(void) +static const char *error_msg(void) { static char buf[512]; int code = sErrno; @@ -319,13 +316,24 @@ const char* error_msg(void) /*====================================== * CORE : Default processing functions *--------------------------------------*/ -int null_recv(int fd) { return 0; } -int null_send(int fd) { return 0; } -int null_parse(int fd) { return 0; } +static int null_recv(int fd) +{ + return 0; +} -ParseFunc default_func_parse = null_parse; +static int null_send(int fd) +{ + return 0; +} -void set_defaultparse(ParseFunc defaultparse) +static int null_parse(int fd) +{ + return 0; +} + +static ParseFunc default_func_parse = null_parse; + +static void set_defaultparse(ParseFunc defaultparse) { default_func_parse = defaultparse; } @@ -333,7 +341,7 @@ void set_defaultparse(ParseFunc defaultparse) /*====================================== * CORE : Socket options *--------------------------------------*/ -void set_nonblocking(int fd, unsigned long yes) +static void set_nonblocking(int fd, unsigned long yes) { // FIONBIO Use with a nonzero argp parameter to enable the nonblocking mode of socket s. // The argp parameter is zero if nonblocking is to be disabled. @@ -347,7 +355,7 @@ void set_nonblocking(int fd, unsigned long yes) * @param fd The socket descriptor * @param opt Optional, additional options to set (Can be NULL). */ -void setsocketopts(int fd, struct hSockOpt *opt) +static void setsocketopts(int fd, struct hSockOpt *opt) { #if defined(WIN32) BOOL yes = TRUE; @@ -409,7 +417,7 @@ void setsocketopts(int fd, struct hSockOpt *opt) /*====================================== * CORE : Socket Sub Function *--------------------------------------*/ -void set_eof(int fd) +static void set_eof(int fd) { if (sockt->session_is_active(fd)) { #ifdef SEND_SHORTLIST @@ -420,7 +428,7 @@ void set_eof(int fd) } } -int recv_to_fifo(int fd) +static int recv_to_fifo(int fd) { ssize_t len; @@ -457,7 +465,7 @@ int recv_to_fifo(int fd) return 0; } -int send_from_fifo(int fd) +static int send_from_fifo(int fd) { ssize_t len; @@ -504,13 +512,13 @@ int send_from_fifo(int fd) } /// Best effort - there's no warranty that the data will be sent. -void flush_fifo(int fd) +static void flush_fifo(int fd) { if(sockt->session[fd] != NULL) sockt->session[fd]->func_send(fd); } -void flush_fifos(void) +static void flush_fifos(void) { int i; for(i = 1; i < sockt->fd_max; i++) @@ -520,7 +528,7 @@ void flush_fifos(void) /*====================================== * CORE : Connection functions *--------------------------------------*/ -int connect_client(int listen_fd) +static int connect_client(int listen_fd) { int fd; struct sockaddr_in client_address; @@ -547,12 +555,10 @@ int connect_client(int listen_fd) setsocketopts(fd,NULL); sockt->set_nonblocking(fd, 1); -#ifndef MINICORE if( ip_rules && !connect_check(ntohl(client_address.sin_addr.s_addr)) ) { sockt->close(fd); return -1; } -#endif // MINICORE #ifndef SOCKET_EPOLL // Select Based Event Dispatcher @@ -575,11 +581,12 @@ int connect_client(int listen_fd) create_session(fd, recv_to_fifo, send_from_fifo, default_func_parse); sockt->session[fd]->client_addr = ntohl(client_address.sin_addr.s_addr); + sockt->session[fd]->flag.validate = sockt->validate; return fd; } -int make_listen_bind(uint32 ip, uint16 port) +static int make_listen_bind(uint32 ip, uint16 port) { struct sockaddr_in server_address = { 0 }; int fd; @@ -644,11 +651,10 @@ int make_listen_bind(uint32 ip, uint16 port) create_session(fd, connect_client, null_send, null_parse); sockt->session[fd]->client_addr = 0; // just listens sockt->session[fd]->rdata_tick = 0; // disable timeouts on this socket - return fd; } -int make_connection(uint32 ip, uint16 port, struct hSockOpt *opt) +static int make_connection(uint32 ip, uint16 port, struct hSockOpt *opt) { struct sockaddr_in remote_address = { 0 }; int fd; @@ -749,7 +755,7 @@ static void delete_session(int fd) } } -int realloc_fifo(int fd, unsigned int rfifo_size, unsigned int wfifo_size) +static int realloc_fifo(int fd, unsigned int rfifo_size, unsigned int wfifo_size) { if (!sockt->session_is_valid(fd)) return 0; @@ -766,7 +772,7 @@ int realloc_fifo(int fd, unsigned int rfifo_size, unsigned int wfifo_size) return 0; } -int realloc_writefifo(int fd, size_t addition) +static int realloc_writefifo(int fd, size_t addition) { size_t newsize; @@ -794,7 +800,7 @@ int realloc_writefifo(int fd, size_t addition) } /// advance the RFIFO cursor (marking 'len' bytes as processed) -int rfifoskip(int fd, size_t len) +static int rfifoskip(int fd, size_t len) { struct socket_data *s; @@ -805,7 +811,36 @@ int rfifoskip(int fd, size_t len) if (s->rdata_size < s->rdata_pos + len) { ShowError("RFIFOSKIP: skipped past end of read buffer! Adjusting from %"PRIuS" to %"PRIuS" (session #%d)\n", len, RFIFOREST(fd), fd); + Assert_report(0); len = RFIFOREST(fd); + } else { + const size_t lenRest = RFIFOREST(fd); + if (s->flag.validate == 1 && len == lenRest) { + if (lenRest >= 2) { + const uint32 cmd = (uint32)RFIFOW(fd, 0); + if (cmd < MIN_PACKET_DB || cmd > MAX_PACKET_DB) { + ShowError("Skip wrong packet id: 0x%04X\n", cmd); + Assert_report(0); + } else { + int packet_len = packets->db[cmd]; + if (packet_len == -1) { + if (lenRest < 4) { + ShowError("Skip packet with size smaller than 4\n"); + Assert_report(0); + } else { + packet_len = RFIFOW(fd, 2); + if (packet_len != lenRest) { + ShowError("Skip packet 0x%04X with dynamic size %"PRIuS", but must be size %d\n", cmd, lenRest, packet_len); + Assert_report(0); + } + } + } else if (packet_len != lenRest) { + ShowError("Skip packet 0x%04X with size %"PRIuS", but must be size %d\n", cmd, lenRest, packet_len); + Assert_report(0); + } + } + } + } } s->rdata_pos = s->rdata_pos + len; @@ -816,14 +851,12 @@ int rfifoskip(int fd, size_t len) } /// advance the WFIFO cursor (marking 'len' bytes for sending) -int wfifoset(int fd, size_t len) +static int wfifoset(int fd, size_t len, bool validate) { - size_t newreserve; - struct socket_data* s; - if (!sockt->session_is_valid(fd)) return 0; - s = sockt->session[fd]; + + struct socket_data* s = sockt->session[fd]; if (s == NULL || s->wdata == NULL) return 0; @@ -862,6 +895,10 @@ int wfifoset(int fd, size_t len) } } + + if (validate && s->flag.validate == 1) + sockt->validateWfifo(fd, len); + s->wdata_size += len; #ifdef SHOW_SERVER_STATS socket_data_qo += len; @@ -872,7 +909,7 @@ int wfifoset(int fd, size_t len) // always keep a WFIFO_SIZE reserve in the buffer // For inter-server connections, let the reserve be 1/4th of the link size. - newreserve = s->flag.server ? FIFOSIZE_SERVERLINK / 4 : WFIFO_SIZE; + size_t newreserve = s->flag.server ? FIFOSIZE_SERVERLINK / 4 : WFIFO_SIZE; // readjust the buffer to include the chosen reserve sockt->realloc_writefifo(fd, newreserve); @@ -884,7 +921,16 @@ int wfifoset(int fd, size_t len) return 0; } -int do_sockets(int next) +static void wfifohead(int fd, size_t len) +{ + Assert_retv(fd >= 0); + + sockt->session[fd]->last_head_size = (uint32)len; + if (sockt->session[fd]->wdata_size + len > sockt->session[fd]->max_wdata) + sockt->realloc_writefifo(fd, len); +} + +static int do_sockets(int next) { #ifndef SOCKET_EPOLL fd_set rfd; @@ -1056,9 +1102,6 @@ int do_sockets(int next) return 0; } -////////////////////////////// -#ifndef MINICORE -////////////////////////////// // IP rules and DDoS protection struct connect_history { @@ -1088,7 +1131,7 @@ static int access_debug = 0; static int ddos_count = 10; static int ddos_interval = 3*1000; static int ddos_autoreset = 10*60*1000; -struct DBMap *connect_history = NULL; +static struct DBMap *connect_history = NULL; static int connect_check_(uint32 ip); @@ -1232,7 +1275,7 @@ static int connect_check_clear(int tid, int64 tick, int id, intptr_t data) /// Parses the ip address and mask and puts it into acc. /// Returns 1 is successful, 0 otherwise. -int access_ipmask(const char *str, struct access_control *acc) +static int access_ipmask(const char *str, struct access_control *acc) { uint32 ip; uint32 mask; @@ -1288,7 +1331,7 @@ int access_ipmask(const char *str, struct access_control *acc) * * @retval false in case of failure */ -bool access_list_add(struct config_setting_t *setting, const char *list_name, struct access_control_list *access_list) +static bool access_list_add(struct config_setting_t *setting, const char *list_name, struct access_control_list *access_list) { const char *temp = NULL; int i, setting_length; @@ -1317,10 +1360,6 @@ bool access_list_add(struct config_setting_t *setting, const char *list_name, st return true; } -////////////////////////////// -#endif // MINICORE -////////////////////////////// - /** * Reads 'socket_configuration/ip_rules' and initializes required variables. * @@ -1330,9 +1369,8 @@ bool access_list_add(struct config_setting_t *setting, const char *list_name, st * * @retval false in case of error. */ -bool socket_config_read_iprules(const char *filename, struct config_t *config, bool imported) +static bool socket_config_read_iprules(const char *filename, struct config_t *config, bool imported) { -#ifndef MINICORE struct config_setting_t *setting = NULL; const char *temp = NULL; @@ -1375,7 +1413,6 @@ bool socket_config_read_iprules(const char *filename, struct config_t *config, b } else { access_list_add(setting, "deny_list", &access_deny); } -#endif // ! MINICORE return true; } @@ -1389,9 +1426,8 @@ bool socket_config_read_iprules(const char *filename, struct config_t *config, b * * @retval false in case of error. */ -bool socket_config_read_ddos(const char *filename, struct config_t *config, bool imported) +static bool socket_config_read_ddos(const char *filename, struct config_t *config, bool imported) { -#ifndef MINICORE struct config_setting_t *setting = NULL; nullpo_retr(false, filename); @@ -1408,7 +1444,6 @@ bool socket_config_read_ddos(const char *filename, struct config_t *config, bool libconfig->setting_lookup_int(setting, "count", &ddos_count); libconfig->setting_lookup_int(setting, "autoreset", &ddos_autoreset); -#endif // ! MINICORE return true; } @@ -1420,7 +1455,7 @@ bool socket_config_read_ddos(const char *filename, struct config_t *config, bool * * @retval false in case of error. */ -bool socket_config_read(const char *filename, bool imported) +static bool socket_config_read(const char *filename, bool imported) { struct config_t config; struct config_setting_t *setting = NULL; @@ -1455,7 +1490,6 @@ bool socket_config_read(const char *filename, bool imported) } #endif // SOCKET_EPOLL -#ifndef MINICORE { uint32 ui32 = 0; libconfig->setting_lookup_bool(setting, "debug", &access_debug); @@ -1468,7 +1502,6 @@ bool socket_config_read(const char *filename, bool imported) retval = false; if (!socket_config_read_ddos(filename, &config, imported)) retval = false; -#endif // MINICORE // import should overwrite any previous configuration, so it should be called last if (libconfig->lookup_string(&config, "import", &import) == CONFIG_TRUE) { @@ -1484,15 +1517,13 @@ bool socket_config_read(const char *filename, bool imported) return retval; } -void socket_final(void) +static void socket_final(void) { int i; -#ifndef MINICORE if( connect_history ) db_destroy(connect_history); VECTOR_CLEAR(access_allow); VECTOR_CLEAR(access_deny); -#endif // MINICORE for( i = 1; i < sockt->fd_max; i++ ) if(sockt->session[i]) @@ -1523,7 +1554,7 @@ void socket_final(void) } /// Closes a socket. -void socket_close(int fd) +static void socket_close(int fd) { if( fd <= 0 ||fd >= FD_SETSIZE ) return;// invalid @@ -1537,7 +1568,7 @@ void socket_close(int fd) // Epoll based Event Dispatcher epevent.data.fd = fd; epevent.events = EPOLLIN; - epoll_ctl(epfd, EPOLL_CTL_DEL, fd, &epevent); // removing the socket from epoll when it's being closed is not required but recommended + epoll_ctl(epfd, EPOLL_CTL_DEL, fd, &epevent); // removing the socket from epoll when it's being closed is not required but recommended #endif // SOCKET_EPOLL sShutdown(fd, SHUT_RDWR); // Disallow further reads/writes @@ -1547,7 +1578,7 @@ void socket_close(int fd) /// Retrieve local ips in host byte order. /// Uses loopback is no address is found. -int socket_getips(uint32* ips, int max) +static int socket_getips(uint32 *ips, int max) { int num = 0; @@ -1628,7 +1659,7 @@ int socket_getips(uint32* ips, int max) return num; } -void socket_init(void) +static void socket_init(void) { uint64 rlim_cur = FD_SETSIZE; @@ -1677,10 +1708,8 @@ void socket_init(void) } #endif // defined(HAVE_SETRLIMIT) && !defined(CYGWIN) -#ifndef MINICORE VECTOR_INIT(access_allow); VECTOR_INIT(access_deny); -#endif // ! MINICORE // Get initial local ips sockt->naddr_ = sockt->getips(sockt->addr_,16); @@ -1694,7 +1723,7 @@ void socket_init(void) #else // SOCKET_EPOLL // Epoll based Event Dispatcher: - epfd = epoll_create(FD_SETSIZE); // 2.6.8 or newer ignores the expected socket amount argument + epfd = epoll_create(FD_SETSIZE); // 2.6.8 or newer ignores the expected socket amount argument if(epfd == SOCKET_ERROR){ ShowError("Failed to Create Epoll Event Dispatcher: %s\n", error_msg()); exit(EXIT_FAILURE); @@ -1720,28 +1749,26 @@ void socket_init(void) // should hold enough buffer (it is a vacuum so to speak) as it is never flushed. [Skotlex] create_session(0, null_recv, null_send, null_parse); -#ifndef MINICORE // Delete old connection history every 5 minutes connect_history = uidb_alloc(DB_OPT_RELEASE_DATA); timer->add_func_list(connect_check_clear, "connect_check_clear"); timer->add_interval(timer->gettick()+1000, connect_check_clear, 0, 0, 5*60*1000); -#endif // MINICORE ShowInfo("Server supports up to '"CL_WHITE"%"PRIu64""CL_RESET"' concurrent connections.\n", rlim_cur); } -bool session_is_valid(int fd) +static bool session_is_valid(int fd) { return ( fd > 0 && fd < FD_SETSIZE && sockt->session[fd] != NULL ); } -bool session_is_active(int fd) +static bool session_is_active(int fd) { return ( sockt->session_is_valid(fd) && !sockt->session[fd]->flag.eof ); } // Resolves hostname into a numeric ip. -uint32 host2ip(const char *hostname) +static uint32 host2ip(const char *hostname) { struct hostent* h; nullpo_ret(hostname); @@ -1757,7 +1784,7 @@ uint32 host2ip(const char *hostname) * * @return A pointer to the output string. */ -const char *ip2str(uint32 ip, char *ip_str) +static const char *ip2str(uint32 ip, char *ip_str) { struct in_addr addr; addr.s_addr = htonl(ip); @@ -1765,20 +1792,20 @@ const char *ip2str(uint32 ip, char *ip_str) } // Converts a dot-formatted ip string into a numeric ip. -uint32 str2ip(const char* ip_str) +static uint32 str2ip(const char *ip_str) { return ntohl(inet_addr(ip_str)); } // Reorders bytes from network to little endian (Windows). // Necessary for sending port numbers to the RO client until Gravity notices that they forgot ntohs() calls. -uint16 ntows(uint16 netshort) +static uint16 ntows(uint16 netshort) { return ((netshort & 0xFF) << 8) | ((netshort & 0xFF00) >> 8); } /* [Ind/Hercules] - socket_datasync */ -void socket_datasync(int fd, bool send) +static void socket_datasync(int fd, bool send) { struct { unsigned int length;/* short is not enough for some */ @@ -1809,6 +1836,11 @@ void socket_datasync(int fd, bool send) { sizeof(struct guild_castle) }, { sizeof(struct fame_list) }, { PACKETVER }, + { PACKETVER_MAIN_NUM }, + { PACKETVER_RE_NUM }, + { PACKETVER_ZERO_NUM }, + { PACKETVER_AD_NUM }, + { PACKETVER_SAK_NUM }, }; unsigned short i; unsigned int alen = ARRAYLENGTH(data_list); @@ -1845,7 +1877,7 @@ void socket_datasync(int fd, bool send) #ifdef SEND_SHORTLIST // Add a fd to the shortlist so that it'll be recognized as a fd that needs // sending or eof handling. -void send_shortlist_add_fd(int fd) +static void send_shortlist_add_fd(int fd) { int i; int bit; @@ -1872,7 +1904,7 @@ void send_shortlist_add_fd(int fd) } // Do pending network sends and eof handling from the shortlist. -void send_shortlist_do_sends(void) +static void send_shortlist_do_sends(void) { int i; @@ -1928,7 +1960,7 @@ void send_shortlist_do_sends(void) * @retval 0 if it is a WAN IP. * @return the appropriate LAN server address to send, if it is a LAN IP. */ -uint32 socket_lan_subnet_check(uint32 ip, struct s_subnet *info) +static uint32 socket_lan_subnet_check(uint32 ip, struct s_subnet *info) { int i; ARR_FIND(0, VECTOR_LENGTH(sockt->lan_subnets), i, SUBNET_MATCH(ip, VECTOR_INDEX(sockt->lan_subnets, i).ip, VECTOR_INDEX(sockt->lan_subnets, i).mask)); @@ -1952,7 +1984,7 @@ uint32 socket_lan_subnet_check(uint32 ip, struct s_subnet *info) * @retval true if we allow server connections from the given IP. * @retval false otherwise. */ -bool socket_allowed_ip_check(uint32 ip) +static bool socket_allowed_ip_check(uint32 ip) { int i; ARR_FIND(0, VECTOR_LENGTH(sockt->allowed_ips), i, SUBNET_MATCH(ip, VECTOR_INDEX(sockt->allowed_ips, i).ip, VECTOR_INDEX(sockt->allowed_ips, i).mask)); @@ -1968,7 +2000,7 @@ bool socket_allowed_ip_check(uint32 ip) * @retval true if we trust the given IP. * @retval false otherwise. */ -bool socket_trusted_ip_check(uint32 ip) +static bool socket_trusted_ip_check(uint32 ip) { int i; ARR_FIND(0, VECTOR_LENGTH(sockt->trusted_ips), i, SUBNET_MATCH(ip, VECTOR_INDEX(sockt->trusted_ips, i).ip, VECTOR_INDEX(sockt->trusted_ips, i).mask)); @@ -1988,7 +2020,7 @@ bool socket_trusted_ip_check(uint32 ip) * @param[in] groupname Current group name, for output/logging reasons. * @return The amount of entries read, zero in case of errors. */ -int socket_net_config_read_sub(struct config_setting_t *t, struct s_subnet_vector *list, const char *filename, const char *groupname) +static int socket_net_config_read_sub(struct config_setting_t *t, struct s_subnet_vector *list, const char *filename, const char *groupname) { int i, len; char ipbuf[64], maskbuf[64]; @@ -2022,7 +2054,7 @@ int socket_net_config_read_sub(struct config_setting_t *t, struct s_subnet_vecto * * @param filename The filename to read from. */ -void socket_net_config_read(const char *filename) +static void socket_net_config_read(const char *filename) { struct config_t network_config; int i; @@ -2063,6 +2095,50 @@ void socket_net_config_read(const char *filename) return; } +static void socket_validateWfifo(int fd, size_t len) +{ + if (len < 2) { + ShowError("Sent packet with size smaller than 2\n"); + Assert_retv(0); + return; + } + const uint32 cmd = (uint32)WFIFOW(fd, 0); + const uint32 last_head_size = sockt->session[fd]->last_head_size; + sockt->session[fd]->last_head_size = 0; + + if (cmd < MIN_PACKET_DB || cmd > MAX_PACKET_DB) { + ShowError("Sent wrong packet id: 0x%04X\n", cmd); + Assert_retv(0); + return; + } + if (len > 65535) { + ShowError("Sent packet with size bigger than 65535\n"); + Assert_retv(0); + return; + } + int packet_len = packets->db[cmd]; + const int len2 = (int)len; + if (packet_len == -1) { + if (len2 < 4) { + ShowError("Sent packet with size smaller than 4\n"); + Assert_retv(0); + return; + } + packet_len = WFIFOW(fd, 2); + if (packet_len != len2) { + ShowError("Sent packet 0x%04X with dynamic size %d, but must be size %d\n", cmd, len2, packet_len); + Assert_retv(0); + } + } else if (packet_len != len2) { + ShowError("Sent packet 0x%04X with size %d, but must be size %d\n", cmd, len2, packet_len); + Assert_retv(0); + } + if (last_head_size < (uint32)packet_len) { + ShowError("Reserved too small packet buffer for packet 0x%04X with size %u, but must be size %d\n", cmd, last_head_size, packet_len); + Assert_retv(0); + } +} + void socket_defaults(void) { sockt = &sockt_s; @@ -2074,6 +2150,7 @@ void socket_defaults(void) /* */ memset(&sockt->addr_, 0, sizeof(sockt->addr_)); sockt->naddr_ = 0; + sockt->validate = false; /* */ VECTOR_INIT(sockt->lan_subnets); VECTOR_INIT(sockt->allowed_ips); @@ -2091,6 +2168,7 @@ void socket_defaults(void) sockt->realloc_fifo = realloc_fifo; sockt->realloc_writefifo = realloc_writefifo; sockt->wfifoset = wfifoset; + sockt->wfifohead = wfifohead; sockt->rfifoskip = rfifoskip; sockt->close = socket_close; /* */ @@ -2113,4 +2191,5 @@ void socket_defaults(void) sockt->trusted_ip_check = socket_trusted_ip_check; sockt->net_config_read_sub = socket_net_config_read_sub; sockt->net_config_read = socket_net_config_read; + sockt->validateWfifo = socket_validateWfifo; } |