diff options
-rw-r--r-- | src/common/socket.c | 121 | ||||
-rw-r--r-- | src/common/socket.h | 20 |
2 files changed, 58 insertions, 83 deletions
diff --git a/src/common/socket.c b/src/common/socket.c index a26873b67..f1318ab47 100644 --- a/src/common/socket.c +++ b/src/common/socket.c @@ -967,7 +967,7 @@ static int connect_check_(uint32 ip) // Search the allow list for( i=0; i < access_allownum; ++i ){ - if( (ip & access_allow[i].mask) == (access_allow[i].ip & access_allow[i].mask) ){ + if (SUBNET_MATCH(ip, access_allow[i].ip, access_allow[i].mask)) { if( access_debug ){ ShowInfo("connect_check: Found match from allow list:%d.%d.%d.%d IP:%d.%d.%d.%d Mask:%d.%d.%d.%d\n", CONVIP(ip), @@ -980,7 +980,7 @@ static int connect_check_(uint32 ip) } // Search the deny list for( i=0; i < access_denynum; ++i ){ - if( (ip & access_deny[i].mask) == (access_deny[i].ip & access_deny[i].mask) ){ + if (SUBNET_MATCH(ip, access_deny[i].ip, access_deny[i].mask)) { if( access_debug ){ ShowInfo("connect_check: Found match from deny list:%d.%d.%d.%d IP:%d.%d.%d.%d Mask:%d.%d.%d.%d\n", CONVIP(ip), @@ -1216,20 +1216,9 @@ void socket_final(void) aFree(sockt->session); - if (sockt->lan_subnet) - aFree(sockt->lan_subnet); - sockt->lan_subnet = NULL; - sockt->lan_subnet_count = 0; - - if (sockt->allowed_ip) - aFree(sockt->allowed_ip); - sockt->allowed_ip = NULL; - sockt->allowed_ip_count = 0; - - if (sockt->trusted_ip) - aFree(sockt->trusted_ip); - sockt->trusted_ip = NULL; - sockt->trusted_ip_count = 0; + VECTOR_CLEAR(sockt->lan_subnets); + VECTOR_CLEAR(sockt->allowed_ips); + VECTOR_CLEAR(sockt->trusted_ips); } /// Closes a socket. @@ -1605,13 +1594,13 @@ void send_shortlist_do_sends() uint32 socket_lan_subnet_check(uint32 ip, struct s_subnet *info) { int i; - ARR_FIND(0, sockt->lan_subnet_count, i, (sockt->lan_subnet[i].ip & sockt->lan_subnet[i].mask) == (ip & sockt->lan_subnet[i].mask)); - if (i < sockt->lan_subnet_count) { + 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)); + if (i != VECTOR_LENGTH(sockt->lan_subnets)) { if (info) { - info->ip = sockt->lan_subnet[i].ip; - info->mask = sockt->lan_subnet[i].mask; + info->ip = VECTOR_INDEX(sockt->lan_subnets, i).ip; + info->mask = VECTOR_INDEX(sockt->lan_subnets, i).mask; } - return sockt->lan_subnet[i].ip; + return VECTOR_INDEX(sockt->lan_subnets, i).ip; } if (info) { info->ip = info->mask = 0; @@ -1629,8 +1618,8 @@ uint32 socket_lan_subnet_check(uint32 ip, struct s_subnet *info) bool socket_allowed_ip_check(uint32 ip) { int i; - ARR_FIND(0, sockt->allowed_ip_count, i, (sockt->allowed_ip[i].ip & sockt->allowed_ip[i].mask) == (ip & sockt->allowed_ip[i].mask) ); - if (i < sockt->allowed_ip_count) + 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)); + if (i != VECTOR_LENGTH(sockt->allowed_ips)) return true; return sockt->trusted_ip_check(ip); // If an address is trusted, it's automatically also allowed. } @@ -1645,8 +1634,8 @@ bool socket_allowed_ip_check(uint32 ip) bool socket_trusted_ip_check(uint32 ip) { int i; - ARR_FIND(0, sockt->trusted_ip_count, i, (sockt->trusted_ip[i].ip & sockt->trusted_ip[i].mask) == (ip & sockt->trusted_ip[i].mask)); - if (i < sockt->trusted_ip_count) + 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)); + if (i != VECTOR_LENGTH(sockt->trusted_ips)) return true; return false; } @@ -1657,39 +1646,38 @@ bool socket_trusted_ip_check(uint32 ip) * Entries will be appended to the variable-size array pointed to by list/count. * * @param[in] t The list to parse. - * @param[in,out] list Pointer to the head of the output array to append to. Must not be NULL (but the array may be empty). - * @param[in,out] count Pointer to the counter of the output array to append to. Must not be NULL (but it may contain zero). + * @param[in,out] list Vector to append to. Must not be NULL (but the vector may be empty). * @param[in] filename Current filename, for output/logging reasons. * @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(config_setting_t *t, struct s_subnet **list, int *count, const char *filename, const char *groupname) +int socket_net_config_read_sub(config_setting_t *t, struct s_subnet_vector *list, const char *filename, const char *groupname) { int i, len; char ipbuf[64], maskbuf[64]; nullpo_retr(0, list); - nullpo_retr(0, count); if (t == NULL) return 0; len = libconfig->setting_length(t); + VECTOR_ENSURE(*list, len, 1); for (i = 0; i < len; ++i) { const char *subnet = libconfig->setting_get_string_elem(t, i); - struct s_subnet *l = NULL; + struct s_subnet *entry = NULL; if (sscanf(subnet, "%63[^:]:%63[^:]", ipbuf, maskbuf) != 2) { ShowWarning("Invalid IP:Subnet entry in configuration file %s: '%s' (%s)\n", filename, subnet, groupname); + continue; } - RECREATE(*list, struct s_subnet, *count + 1); - l = *list; - l[*count].ip = sockt->str2ip(ipbuf); - l[*count].mask = sockt->str2ip(maskbuf); - ++*count; + VECTOR_PUSHZEROED(*list); + entry = &VECTOR_LAST(*list); + entry->ip = sockt->str2ip(ipbuf); + entry->mask = sockt->str2ip(maskbuf); } - return *count; + return (int)VECTOR_LENGTH(*list); } /** @@ -1708,45 +1696,29 @@ void socket_net_config_read(const char *filename) return; } - if (sockt->lan_subnet) { - aFree(sockt->lan_subnet); - sockt->lan_subnet = NULL; - } - sockt->lan_subnet_count = 0; - if (sockt->net_config_read_sub(libconfig->lookup(&network_config, "lan_subnets"), &sockt->lan_subnet, &sockt->lan_subnet_count, filename, "lan_subnets") > 0) - ShowStatus("Read information about %d LAN subnets.\n", sockt->lan_subnet_count); + VECTOR_CLEAR(sockt->lan_subnets); + if (sockt->net_config_read_sub(libconfig->lookup(&network_config, "lan_subnets"), &sockt->lan_subnets, filename, "lan_subnets") > 0) + ShowStatus("Read information about %d LAN subnets.\n", (int)VECTOR_LENGTH(sockt->lan_subnets)); - if (sockt->trusted_ip) { - aFree(sockt->trusted_ip); - sockt->trusted_ip = NULL; - } - sockt->trusted_ip_count = 0; - if (sockt->net_config_read_sub(libconfig->lookup(&network_config, "trusted"), &sockt->trusted_ip, &sockt->trusted_ip_count, filename, "trusted") > 0) - ShowStatus("Read information about %d trusted IP ranges.\n", sockt->trusted_ip_count); - for (i = 0; i < sockt->allowed_ip_count; ++i) { - if ((sockt->allowed_ip[i].ip & sockt->allowed_ip[i].mask) == 0) { - ShowError("Using a wildcard IP range in the trusted server IPs is NOT RECOMMENDED.\n"); - ShowNotice("Please edit your '%s' trusted list to fit your network configuration.\n", filename); - break; - } + VECTOR_CLEAR(sockt->trusted_ips); + if (sockt->net_config_read_sub(libconfig->lookup(&network_config, "trusted"), &sockt->trusted_ips, filename, "trusted") > 0) + ShowStatus("Read information about %d trusted IP ranges.\n", (int)VECTOR_LENGTH(sockt->trusted_ips)); + ARR_FIND(0, VECTOR_LENGTH(sockt->trusted_ips), i, SUBNET_MATCH(0, VECTOR_INDEX(sockt->trusted_ips, i).ip, VECTOR_INDEX(sockt->trusted_ips, i).mask)); + if (i != VECTOR_LENGTH(sockt->trusted_ips)) { + ShowError("Using a wildcard IP range in the trusted server IPs is NOT RECOMMENDED.\n"); + ShowNotice("Please edit your '%s' trusted list to fit your network configuration.\n", filename); } - if (sockt->allowed_ip) { - aFree(sockt->allowed_ip); - sockt->allowed_ip = NULL; - } - sockt->allowed_ip_count = 0; - if (sockt->net_config_read_sub(libconfig->lookup(&network_config, "allowed"), &sockt->allowed_ip, &sockt->allowed_ip_count, filename, "allowed") > 0) - ShowStatus("Read information about %d allowed server IP ranges.\n", sockt->allowed_ip_count); - if (sockt->allowed_ip_count == 0) { + VECTOR_CLEAR(sockt->allowed_ips); + if (sockt->net_config_read_sub(libconfig->lookup(&network_config, "allowed"), &sockt->allowed_ips, filename, "allowed") > 0) + ShowStatus("Read information about %d allowed server IP ranges.\n", (int)VECTOR_LENGTH(sockt->allowed_ips)); + if (VECTOR_LENGTH(sockt->allowed_ips) + VECTOR_LENGTH(sockt->trusted_ips) == 0) { ShowError("No allowed server IP ranges configured. This server won't be able to accept connections from any char servers.\n"); } - for (i = 0; i < sockt->allowed_ip_count; ++i) { - if ((sockt->allowed_ip[i].ip & sockt->allowed_ip[i].mask) == 0) { - ShowWarning("Using a wildcard IP range in the allowed server IPs is NOT RECOMMENDED.\n"); - ShowNotice("Please edit your '%s' allowed list to fit your network configuration.\n", filename); - break; - } + ARR_FIND(0, VECTOR_LENGTH(sockt->allowed_ips), i, SUBNET_MATCH(0, VECTOR_INDEX(sockt->allowed_ips, i).ip, VECTOR_INDEX(sockt->allowed_ips, i).mask)); + if (i != VECTOR_LENGTH(sockt->allowed_ips)) { + ShowWarning("Using a wildcard IP range in the allowed server IPs is NOT RECOMMENDED.\n"); + ShowNotice("Please edit your '%s' allowed list to fit your network configuration.\n", filename); } libconfig->destroy(&network_config); return; @@ -1763,12 +1735,9 @@ void socket_defaults(void) { memset(&sockt->addr_, 0, sizeof(sockt->addr_)); sockt->naddr_ = 0; /* */ - sockt->lan_subnet_count = 0; - sockt->lan_subnet = NULL; - sockt->allowed_ip_count = 0; - sockt->allowed_ip = NULL; - sockt->trusted_ip_count = 0; - sockt->trusted_ip = NULL; + VECTOR_INIT(sockt->lan_subnets); + VECTOR_INIT(sockt->allowed_ips); + VECTOR_INIT(sockt->trusted_ips); sockt->init = socket_init; sockt->final = socket_final; diff --git a/src/common/socket.h b/src/common/socket.h index a2dea8b74..426f8e4bb 100644 --- a/src/common/socket.h +++ b/src/common/socket.h @@ -7,6 +7,7 @@ #include "common/hercules.h" #include "common/conf.h" +#include "common/db.h" #ifdef WIN32 # include "common/winapi.h" @@ -118,6 +119,9 @@ struct s_subnet { uint32 mask; }; +/// A vector of subnets/IP ranges. +VECTOR_STRUCT_DECL(s_subnet_vector, struct s_subnet); + /// Use a shortlist of sockets instead of iterating all sessions for sockets /// that have data to send or need eof handling. /// Adapted to use a static array instead of a linked list. @@ -129,6 +133,11 @@ struct s_subnet { #define CONVIP(ip) ((ip)>>24)&0xFF,((ip)>>16)&0xFF,((ip)>>8)&0xFF,((ip)>>0)&0xFF #define MAKEIP(a,b,c,d) ((uint32)( ( ( (a)&0xFF ) << 24 ) | ( ( (b)&0xFF ) << 16 ) | ( ( (c)&0xFF ) << 8 ) | ( ( (d)&0xFF ) << 0 ) )) +/// Applies a subnet mask to an IP +#define APPLY_MASK(ip, mask) ((ip)&(mask)) +/// Verifies the match between two IPs, with a subnet mask applied +#define SUBNET_MATCH(ip1, ip2, mask) (APPLY_MASK((ip1), (mask)) == APPLY_MASK((ip2), (mask))) + /** * Socket.c interface, mostly for reading however. **/ @@ -143,12 +152,9 @@ struct socket_interface { struct socket_data **session; - struct s_subnet *lan_subnet; ///< LAN subnets array - int lan_subnet_count; ///< LAN subnets count - struct s_subnet *trusted_ip; ///< Trusted IP ranges array - int trusted_ip_count; ///< Trusted IP ranges count - struct s_subnet *allowed_ip; ///< Allowed server IP ranges array - int allowed_ip_count; ///< Allowed server IP ranges count + struct s_subnet_vector lan_subnets; ///< LAN subnets. + struct s_subnet_vector trusted_ips; ///< Trusted IP ranges + struct s_subnet_vector allowed_ips; ///< Allowed server IP ranges /* */ void (*init) (void); @@ -187,7 +193,7 @@ struct socket_interface { uint32 (*lan_subnet_check) (uint32 ip, struct s_subnet *info); bool (*allowed_ip_check) (uint32 ip); bool (*trusted_ip_check) (uint32 ip); - int (*net_config_read_sub) (config_setting_t *t, struct s_subnet **list, int *count, const char *filename, const char *groupname); + int (*net_config_read_sub) (config_setting_t *t, struct s_subnet_vector *list, const char *filename, const char *groupname); void (*net_config_read) (const char *filename); }; |