diff options
author | Andrei Karas <akaras@inbox.ru> | 2015-08-11 16:31:37 +0300 |
---|---|---|
committer | Andrei Karas <akaras@inbox.ru> | 2015-08-11 16:31:37 +0300 |
commit | 49211f9ea1ef985fd6c84cdf902b35dbb8d779a6 (patch) | |
tree | 34e7565fe11ead41519428143b3dc44b752b6e4b | |
parent | a8e54e5688bd3d7b8e9073274ff611040c3178ab (diff) | |
parent | e13f1f782a9d8d25cc622d050644c7f29c1bfd5e (diff) | |
download | hercules-49211f9ea1ef985fd6c84cdf902b35dbb8d779a6.tar.gz hercules-49211f9ea1ef985fd6c84cdf902b35dbb8d779a6.tar.bz2 hercules-49211f9ea1ef985fd6c84cdf902b35dbb8d779a6.tar.xz hercules-49211f9ea1ef985fd6c84cdf902b35dbb8d779a6.zip |
Merge pull request #633 from HerculesWS/subnet
subnet.conf overhaul
-rw-r--r-- | conf/network.conf | 37 | ||||
-rw-r--r-- | conf/subnet.conf | 7 | ||||
-rw-r--r-- | src/char/char.c | 113 | ||||
-rw-r--r-- | src/char/char.h | 5 | ||||
-rw-r--r-- | src/common/socket.c | 187 | ||||
-rw-r--r-- | src/common/socket.h | 21 | ||||
-rw-r--r-- | src/login/login.c | 103 | ||||
-rw-r--r-- | src/login/login.h | 13 |
8 files changed, 302 insertions, 184 deletions
diff --git a/conf/network.conf b/conf/network.conf new file mode 100644 index 000000000..b355acb25 --- /dev/null +++ b/conf/network.conf @@ -0,0 +1,37 @@ +// Network configuration file + +/* + * List here any LAN subnets this server is in. + * Example: + * - char- (or map-) server's IP in LAN is 192.168.0.10 + * - Public IP is 198.51.100.37 + * If the list contains "192.168.0.10:255.255.255.0", any clients connecting + * from the same 192.168.0.0/24 network will be presented with the LAN IP + * (192.168.0.10) in the server list, rather than the public IP (198.51.100.37). + */ +lan_subnets: ( + "127.0.0.1:255.0.0.0", + // "192.168.1.1:255.255.255.0", +) + +/* + * List here any IP ranges a char- or map-server can connect from. + * A wildcard of "0.0.0.0:0.0.0.0" means that server connections are allowed + * from ANY IP. (not recommended). + */ +allowed: ( + "0.0.0.0:0.0.0.0", + // "127.0.0.1:255.0.0.0", +) + +/* + * List here any IP ranges a char- or map-server can connect from. These ranges + * will also be excluded from the automatic ipban in casee of password failure. + * Any entry present in this list is also automatically included in the + * allowed IP list. + * Note: This may be a security threat. Only edit this list if you know what + * you are doing. + */ +trusted: ( + "127.0.0.1:255.0.0.0", +) diff --git a/conf/subnet.conf b/conf/subnet.conf deleted file mode 100644 index 5f2c75a99..000000000 --- a/conf/subnet.conf +++ /dev/null @@ -1,7 +0,0 @@ -// Subnet support file -// Format is: -// subnet: net-submask:char_ip:map_ip -// you can add more than one subnet - -subnet: 255.0.0.0:127.0.0.1:127.0.0.1 -subnet: 0.0.0.0:127.0.0.1:127.0.0.1 diff --git a/src/char/char.c b/src/char/char.c index b6ce70985..c731c89ee 100644 --- a/src/char/char.c +++ b/src/char/char.c @@ -121,14 +121,6 @@ int log_inter = 1; // logging inter or not [devil] int char_aegis_delete = 0; // Verify if char is in guild/party or char and reacts as Aegis does (doesn't allow deletion), see chr->delete2_req for more information -// Advanced subnet check [LuzZza] -struct s_subnet { - uint32 mask; - uint32 char_ip; - uint32 map_ip; -} subnet[16]; -int subnet_count = 0; - int max_connect_user = -1; int gm_allow_group = -1; int autosave_interval = DEFAULT_AUTOSAVE_INTERVAL; @@ -4171,20 +4163,22 @@ static int char_mapif_init(int fd) return inter->mapif_init(fd); } -//-------------------------------------------- -// Test to know if an IP come from LAN or WAN. -//-------------------------------------------- -int char_lan_subnetcheck(uint32 ip) +/** + * Checks whether the given IP comes from LAN or WAN. + * + * @param ip IP address to check. + * @retval 0 if it is a WAN IP. + * @return the appropriate LAN server address to send, if it is a LAN IP. + */ +uint32 char_lan_subnet_check(uint32 ip) { - int i; - ARR_FIND( 0, subnet_count, i, (subnet[i].char_ip & subnet[i].mask) == (ip & subnet[i].mask) ); - if( i < subnet_count ) { - ShowInfo("Subnet check [%u.%u.%u.%u]: Matches "CL_CYAN"%u.%u.%u.%u/%u.%u.%u.%u"CL_RESET"\n", CONVIP(ip), CONVIP(subnet[i].char_ip & subnet[i].mask), CONVIP(subnet[i].mask)); - return subnet[i].map_ip; - } else { - ShowInfo("Subnet check [%u.%u.%u.%u]: "CL_CYAN"WAN"CL_RESET"\n", CONVIP(ip)); - return 0; + struct s_subnet lan = {0}; + if (sockt->lan_subnet_check(ip, &lan)) { + ShowInfo("Subnet check [%u.%u.%u.%u]: Matches "CL_CYAN"%u.%u.%u.%u/%u.%u.%u.%u"CL_RESET"\n", CONVIP(ip), CONVIP(lan.ip & lan.mask), CONVIP(lan.mask)); + return lan.ip; } + ShowInfo("Subnet check [%u.%u.%u.%u]: "CL_CYAN"WAN"CL_RESET"\n", CONVIP(ip)); + return 0; } @@ -4662,7 +4656,7 @@ void char_parse_char_select(int fd, struct char_session_data* sd, uint32 ipl) return; } - subnet_map_ip = chr->lan_subnetcheck(ipl); // Advanced subnet check [LuzZza] + subnet_map_ip = chr->lan_subnet_check(ipl); //Send player to map chr->send_map_info(fd, i, subnet_map_ip, cd); @@ -4971,7 +4965,7 @@ void char_parse_char_login_map_server(int fd, uint32 ipl) i == ARRAYLENGTH(chr->server) || strcmp(l_user, chr->userid) != 0 || strcmp(l_pass, chr->passwd) != 0 || - !chr->lan_subnetcheck(ipl)) + !sockt->allowed_ip_check(ipl)) { chr->login_map_server_ack(fd, 3); // Failure } else { @@ -5449,60 +5443,6 @@ static int char_online_data_cleanup(int tid, int64 tick, int id, intptr_t data) return 0; } -//---------------------------------- -// Reading LAN Support configuration -// Rewrote: Advanced subnet check [LuzZza] -//---------------------------------- -int char_lan_config_read(const char *lancfgName) -{ - FILE *fp; - int line_num = 0; - char line[1024], w1[64], w2[64], w3[64], w4[64]; - - if((fp = fopen(lancfgName, "r")) == NULL) { - ShowWarning("LAN Support configuration file is not found: %s\n", lancfgName); - return 1; - } - - while(fgets(line, sizeof(line), fp)) { - line_num++; - if ((line[0] == '/' && line[1] == '/') || line[0] == '\n' || line[1] == '\n') - continue; - - if (sscanf(line,"%63[^:]: %63[^:]:%63[^:]:%63[^\r\n]", w1, w2, w3, w4) != 4) { - - ShowWarning("Error syntax of configuration file %s in line %d.\n", lancfgName, line_num); - continue; - } - - remove_control_chars(w1); - remove_control_chars(w2); - remove_control_chars(w3); - remove_control_chars(w4); - - if( strcmpi(w1, "subnet") == 0 ) - { - subnet[subnet_count].mask = str2ip(w2); - subnet[subnet_count].char_ip = str2ip(w3); - subnet[subnet_count].map_ip = str2ip(w4); - - if( (subnet[subnet_count].char_ip & subnet[subnet_count].mask) != (subnet[subnet_count].map_ip & subnet[subnet_count].mask) ) - { - ShowError("%s: Configuration Error: The char server (%s) and map server (%s) belong to different subnetworks!\n", lancfgName, w3, w4); - continue; - } - - subnet_count++; - } - } - - if( subnet_count > 1 ) /* only useful if there is more than 1 */ - ShowStatus("Read information about %d subnetworks.\n", subnet_count); - - fclose(fp); - return 0; -} - void char_sql_config_read(const char* cfgName) { char line[1024], w1[1024], w2[1024]; @@ -5826,7 +5766,7 @@ int do_final(void) { aFree(chr->server[i].map); aFree(chr->CHAR_CONF_NAME); - aFree(chr->LAN_CONF_NAME); + aFree(chr->NET_CONF_NAME); aFree(chr->SQL_CONF_NAME); aFree(chr->INTER_CONF_NAME); @@ -5911,15 +5851,15 @@ static CMDLINEARG(interconfig) return true; } /** - * --lan-config handler + * --net-config handler * - * Overrides the default subnet configuration file. + * Overrides the default network configuration file. * @see cmdline->exec */ -static CMDLINEARG(lanconfig) +static CMDLINEARG(netconfig) { - aFree(chr->LAN_CONF_NAME); - chr->LAN_CONF_NAME = aStrdup(params); + aFree(chr->NET_CONF_NAME); + chr->NET_CONF_NAME = aStrdup(params); return true; } /** @@ -5929,7 +5869,7 @@ void cmdline_args_init_local(void) { CMDLINEARG_DEF2(char-config, charconfig, "Alternative char-server configuration.", CMDLINE_OPT_PARAM); CMDLINEARG_DEF2(inter-config, interconfig, "Alternative inter-server configuration.", CMDLINE_OPT_PARAM); - CMDLINEARG_DEF2(lan-config, lanconfig, "Alternative subnet configuration.", CMDLINE_OPT_PARAM); + CMDLINEARG_DEF2(net-config, netconfig, "Alternative network configuration.", CMDLINE_OPT_PARAM); } int do_init(int argc, char **argv) { @@ -5939,7 +5879,7 @@ int do_init(int argc, char **argv) { char_load_defaults(); chr->CHAR_CONF_NAME = aStrdup("conf/char-server.conf"); - chr->LAN_CONF_NAME = aStrdup("conf/subnet.conf"); + chr->NET_CONF_NAME = aStrdup("conf/network.conf"); chr->SQL_CONF_NAME = aStrdup("conf/inter-server.conf"); chr->INTER_CONF_NAME = aStrdup("conf/inter-server.conf"); @@ -5958,7 +5898,7 @@ int do_init(int argc, char **argv) { cmdline->exec(argc, argv, CMDLINE_OPT_NORMAL); chr->config_read(chr->CHAR_CONF_NAME); - chr->lan_config_read(chr->LAN_CONF_NAME); + sockt->net_config_read(chr->NET_CONF_NAME); chr->sql_config_read(chr->SQL_CONF_NAME); if (strcmp(chr->userid, "s1")==0 && strcmp(chr->passwd, "p1")==0) { @@ -6194,7 +6134,7 @@ void char_defaults(void) chr->parse_frommap = char_parse_frommap; chr->search_mapserver = char_search_mapserver; chr->mapif_init = char_mapif_init; - chr->lan_subnetcheck = char_lan_subnetcheck; + chr->lan_subnet_check = char_lan_subnet_check; chr->delete2_ack = char_delete2_ack; chr->delete2_accept_actual_ack = char_delete2_accept_actual_ack; chr->delete2_accept_ack = char_delete2_accept_ack; @@ -6243,7 +6183,6 @@ void char_defaults(void) chr->check_connect_login_server = char_check_connect_login_server; chr->online_data_cleanup_sub = char_online_data_cleanup_sub; chr->online_data_cleanup = char_online_data_cleanup; - chr->lan_config_read = char_lan_config_read; chr->sql_config_read = char_sql_config_read; chr->config_dispatch = char_config_dispatch; chr->config_read = char_config_read; diff --git a/src/char/char.h b/src/char/char.h index b3aa7bc34..3b6e0fa8c 100644 --- a/src/char/char.h +++ b/src/char/char.h @@ -145,7 +145,7 @@ struct char_interface { int new_display; char *CHAR_CONF_NAME; - char *LAN_CONF_NAME; + char *NET_CONF_NAME; ///< Network config filename char *SQL_CONF_NAME; char *INTER_CONF_NAME; @@ -256,7 +256,7 @@ struct char_interface { int (*parse_frommap) (int fd); int (*search_mapserver) (unsigned short map, uint32 ip, uint16 port); int (*mapif_init) (int fd); - int (*lan_subnetcheck) (uint32 ip); + uint32 (*lan_subnet_check) (uint32 ip); void (*delete2_ack) (int fd, int char_id, uint32 result, time_t delete_date); void (*delete2_accept_actual_ack) (int fd, int char_id, uint32 result); void (*delete2_accept_ack) (int fd, int char_id, uint32 result); @@ -305,7 +305,6 @@ struct char_interface { int (*check_connect_login_server) (int tid, int64 tick, int id, intptr_t data); int (*online_data_cleanup_sub) (DBKey key, DBData *data, va_list ap); int (*online_data_cleanup) (int tid, int64 tick, int id, intptr_t data); - int (*lan_config_read) (const char *lancfgName); void (*sql_config_read) (const char* cfgName); void (*config_dispatch) (char *w1, char *w2); int (*config_read) (const char* cfgName); diff --git a/src/common/socket.c b/src/common/socket.c index 17c31db50..830877044 100644 --- a/src/common/socket.c +++ b/src/common/socket.c @@ -14,6 +14,7 @@ #include "common/db.h" #include "common/malloc.h" #include "common/mmo.h" +#include "common/nullpo.h" #include "common/showmsg.h" #include "common/strlib.h" #include "common/timer.h" @@ -1228,6 +1229,21 @@ void socket_final(void) aFree(session[0]); aFree(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; } /// Closes a socket. @@ -1589,6 +1605,164 @@ void send_shortlist_do_sends() } #endif +/** + * Checks whether the given IP comes from LAN or WAN. + * + * @param[in] ip IP address to check. + * @param[out] info Verbose output, if requested. Filled with the matching entry. Ignored if NULL. + * @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) +{ + 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) { + if (info) { + info->ip = sockt->lan_subnet[i].ip; + info->mask = sockt->lan_subnet[i].mask; + } + return sockt->lan_subnet[i].ip; + } + if (info) { + info->ip = info->mask = 0; + } + return 0; +} + +/** + * Checks whether the given IP is allowed to connect as a server. + * + * @param ip IP address to check. + * @retval true if we allow server connections from the given IP. + * @retval false otherwise. + */ +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) + return true; + return sockt->trusted_ip_check(ip); // If an address is trusted, it's automatically also allowed. +} + +/** + * Checks whether the given IP is trusted and can skip ipban checks. + * + * @param ip IP address to check. + * @retval true if we trust the given IP. + * @retval false otherwise. + */ +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) + return true; + return false; +} + +/** + * Helper function to read a list of network.conf values. + * + * 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] 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 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); + + for (i = 0; i < len; ++i) { + const char *subnet = libconfig->setting_get_string_elem(t, i); + struct s_subnet *l = NULL; + + if (sscanf(subnet, "%63[^:]:%63[^:]", ipbuf, maskbuf) != 2) { + ShowWarning("Invalid IP:Subnet entry in configuration file %s: '%s' (%s)\n", filename, subnet, groupname); + } + RECREATE(*list, struct s_subnet, *count + 1); + l = *list; + l[*count].ip = str2ip(ipbuf); + l[*count].mask = str2ip(maskbuf); + ++*count; + } + return *count; +} + +/** + * Reads the network configuration file. + * + * @param filename The filename to read from. + */ +void socket_net_config_read(const char *filename) +{ + config_t network_config; + int i; + nullpo_retv(filename); + + if (libconfig->read_file(&network_config, filename)) { + ShowError("LAN Support configuration file is not found: '%s'. This server won't be able to accept connections from any servers.\n", 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); + + 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; + } + } + + 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) { + 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; + } + } + libconfig->destroy(&network_config); + return; +} + void socket_defaults(void) { sockt = &sockt_s; @@ -1600,6 +1774,13 @@ 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; + sockt->init = socket_init; sockt->final = socket_final; /* */ @@ -1628,4 +1809,10 @@ void socket_defaults(void) { sockt->ntows = ntows; sockt->getips = socket_getips; sockt->set_eof = set_eof; + + sockt->lan_subnet_check = socket_lan_subnet_check; + sockt->allowed_ip_check = socket_allowed_ip_check; + 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; } diff --git a/src/common/socket.h b/src/common/socket.h index bd5d9baa2..26b674d43 100644 --- a/src/common/socket.h +++ b/src/common/socket.h @@ -6,6 +6,7 @@ #define COMMON_SOCKET_H #include "common/cbasetypes.h" +#include "common/conf.h" #ifdef WIN32 # include "common/winapi.h" @@ -105,6 +106,12 @@ struct hSockOpt { unsigned int setTimeo : 1; }; +/// Subnet/IP range in the IP/Mask format. +struct s_subnet { + uint32 ip; + uint32 mask; +}; + /// 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. @@ -132,6 +139,14 @@ struct socket_interface { /* */ uint32 addr_[16]; // ip addresses of local host (host byte order) int naddr_; // # of ip addresses + + 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 + /* */ void (*init) (void); void (*final) (void); @@ -165,6 +180,12 @@ struct socket_interface { int (*getips) (uint32* ips, int max); /* */ void (*set_eof) (int fd); + + 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); + void (*net_config_read) (const char *filename); }; struct socket_interface *sockt; diff --git a/src/login/login.c b/src/login/login.c index caace34da..141ab5e2b 100644 --- a/src/login/login.c +++ b/src/login/login.c @@ -12,6 +12,7 @@ #include "login/loginlog.h" #include "common/HPM.h" #include "common/cbasetypes.h" +#include "common/conf.h" #include "common/core.h" #include "common/db.h" #include "common/malloc.h" @@ -238,65 +239,17 @@ bool login_check_password(const char* md5key, int passwdenc, const char* passwd, } } -//-------------------------------------------- -// Test to know if an IP come from LAN or WAN. -//-------------------------------------------- -int login_lan_subnetcheck(uint32 ip) -{ - int i; - ARR_FIND( 0, login_config.subnet_count, i, (login_config.subnet[i].char_ip & login_config.subnet[i].mask) == (ip & login_config.subnet[i].mask) ); - return ( i < login_config.subnet_count ) ? login_config.subnet[i].char_ip : 0; -} -//---------------------------------- -// Reading LAN Support configuration -//---------------------------------- -int login_lan_config_read(const char *lancfgName) +/** + * Checks whether the given IP comes from LAN or WAN. + * + * @param ip IP address to check. + * @retval 0 if it is a WAN IP. + * @return the appropriate LAN server address to send, if it is a LAN IP. + */ +uint32 login_lan_subnet_check(uint32 ip) { - FILE *fp; - int line_num = 0; - char line[1024], w1[64], w2[64], w3[64], w4[64]; - - nullpo_ret(lancfgName); - if((fp = fopen(lancfgName, "r")) == NULL) { - ShowWarning("LAN Support configuration file is not found: %s\n", lancfgName); - return 1; - } - - while(fgets(line, sizeof(line), fp)) - { - line_num++; - if ((line[0] == '/' && line[1] == '/') || line[0] == '\n' || line[1] == '\n') - continue; - - if (sscanf(line, "%63[^:]: %63[^:]:%63[^:]:%63[^\r\n]", w1, w2, w3, w4) != 4) { - ShowWarning("Error syntax of configuration file %s in line %d.\n", lancfgName, line_num); - continue; - } - - if( strcmpi(w1, "subnet") == 0 ) - { - login_config.subnet[login_config.subnet_count].mask = str2ip(w2); - login_config.subnet[login_config.subnet_count].char_ip = str2ip(w3); - login_config.subnet[login_config.subnet_count].map_ip = str2ip(w4); - - if( (login_config.subnet[login_config.subnet_count].char_ip - & login_config.subnet[login_config.subnet_count].mask) != (login_config.subnet[login_config.subnet_count].map_ip - & login_config.subnet[login_config.subnet_count].mask) ) - { - ShowError("%s: Configuration Error: The char server (%s) and map server (%s) belong to different subnetworks!\n", lancfgName, w3, w4); - continue; - } - - login_config.subnet_count++; - } - } - - if( login_config.subnet_count > 1 ) /* only useful if there is more than 1 available */ - ShowStatus("Read information about %d subnetworks.\n", login_config.subnet_count); - - fclose(fp); - return 0; + return sockt->lan_subnet_check(ip, NULL); } void login_fromchar_auth_ack(int fd, int account_id, uint32 login_id1, uint32 login_id2, uint8 sex, int request_id, struct login_auth_node* node) @@ -1233,7 +1186,6 @@ void login_auth_ok(struct login_session_data* sd) int fd = 0; uint32 ip; uint8 server_num, n; - uint32 subnet_char_ip; struct login_auth_node* node; int i; @@ -1308,12 +1260,13 @@ void login_auth_ok(struct login_session_data* sd) memset(WFIFOP(fd,20), 0, 24); WFIFOW(fd,44) = 0; // unknown WFIFOB(fd,46) = sex_str2num(sd->sex); - for( i = 0, n = 0; i < ARRAYLENGTH(server); ++i ) - { + for (i = 0, n = 0; i < ARRAYLENGTH(server); ++i) { + uint32 subnet_char_ip; + if( !session_isValid(server[i].fd) ) continue; - subnet_char_ip = login->lan_subnetcheck(ip); // Advanced subnet check [LuzZza] + subnet_char_ip = login->lan_subnet_check(ip); WFIFOL(fd,47+n*32) = htonl((subnet_char_ip) ? subnet_char_ip : server[i].ip); WFIFOW(fd,47+n*32+4) = ntows(htons(server[i].port)); // [!] LE byte order here [!] memcpy(WFIFOP(fd,47+n*32+6), server[i].name, 20); @@ -1393,7 +1346,7 @@ void login_auth_failed(struct login_session_data* sd, int result) login_log(ip, sd->userid, result, error); // FIXME: result can be 100, conflicting with the value 100 we use for successful login... } - if( result == 1 && login_config.dynamic_pass_failure_ban ) + if (result == 1 && login_config.dynamic_pass_failure_ban && !sockt->trusted_ip_check(ip)) ipban_log(ip); // log failed password attempt #if PACKETVER >= 20120000 /* not sure when this started */ @@ -1590,7 +1543,7 @@ void login_parse_request_connection(int fd, struct login_session_data* sd, const sd->account_id >= 0 && sd->account_id < ARRAYLENGTH(server) && !session_isValid(server[sd->account_id].fd) && - login->lan_subnetcheck(ipl)) + sockt->allowed_ip_check(ipl)) { ShowStatus("Connection of the char-server '%s' accepted.\n", server_name); safestrncpy(server[sd->account_id].name, server_name, sizeof(server[sd->account_id].name)); @@ -1637,7 +1590,7 @@ int login_parse_login(int fd) if( sd == NULL ) { // Perform ip-ban check - if( login_config.ipban && ipban_check(ipl) ) + if (login_config.ipban && !sockt->trusted_ip_check(ipl) && ipban_check(ipl)) { ShowStatus("Connection refused: IP isn't authorized (deny/allow, ip: %s).\n", ip); login_log(ipl, "unknown", -3, "ip banned"); @@ -1759,7 +1712,6 @@ void login_set_defaults() login_config.client_hash_check = 0; login_config.client_hash_nodes = NULL; - login_config.subnet_count = 0; } //----------------------------------- @@ -1929,7 +1881,7 @@ int do_final(void) { HPM_login_do_final(); aFree(login->LOGIN_CONF_NAME); - aFree(login->LAN_CONF_NAME); + aFree(login->NET_CONF_NAME); HPM->event(HPET_POST_FINAL); @@ -1984,15 +1936,15 @@ static CMDLINEARG(loginconfig) return true; } /** - * --lan-config handler + * --net-config handler * * Overrides the default subnet configuration file. * @see cmdline->exec */ -static CMDLINEARG(lanconfig) +static CMDLINEARG(netconfig) { - aFree(login->LAN_CONF_NAME); - login->LAN_CONF_NAME = aStrdup(params); + aFree(login->NET_CONF_NAME); + login->NET_CONF_NAME = aStrdup(params); return true; } /** @@ -2001,7 +1953,7 @@ static CMDLINEARG(lanconfig) void cmdline_args_init_local(void) { CMDLINEARG_DEF2(login-config, loginconfig, "Alternative login-server configuration.", CMDLINE_OPT_PARAM); - CMDLINEARG_DEF2(lan-config, lanconfig, "Alternative subnet configuration.", CMDLINE_OPT_PARAM); + CMDLINEARG_DEF2(net-config, netconfig, "Alternative subnet configuration.", CMDLINE_OPT_PARAM); } //------------------------------ @@ -2025,7 +1977,7 @@ int do_init(int argc, char** argv) login_set_defaults(); login->LOGIN_CONF_NAME = aStrdup("conf/login-server.conf"); - login->LAN_CONF_NAME = aStrdup("conf/subnet.conf"); + login->NET_CONF_NAME = aStrdup("conf/network.conf"); HPM_login_do_init(); HPM->symbol_defaults_sub = login_hp_symbols; @@ -2035,7 +1987,7 @@ int do_init(int argc, char** argv) cmdline->exec(argc, argv, CMDLINE_OPT_NORMAL); login_config_read(login->LOGIN_CONF_NAME); - login->lan_config_read(login->LAN_CONF_NAME); + sockt->net_config_read(login->NET_CONF_NAME); for( i = 0; i < ARRAYLENGTH(server); ++i ) chrif_server_init(i); @@ -2112,8 +2064,7 @@ void login_defaults(void) { login->sync_ip_addresses = login_sync_ip_addresses; login->check_encrypted = login_check_encrypted; login->check_password = login_check_password; - login->lan_subnetcheck = login_lan_subnetcheck; - login->lan_config_read = login_lan_config_read; + login->lan_subnet_check = login_lan_subnet_check; login->fromchar_auth_ack = login_fromchar_auth_ack; login->fromchar_accinfo = login_fromchar_accinfo; @@ -2159,5 +2110,5 @@ void login_defaults(void) { login->send_coding_key = login_send_coding_key; login->LOGIN_CONF_NAME = NULL; - login->LAN_CONF_NAME = NULL; + login->NET_CONF_NAME = NULL; } diff --git a/src/login/login.h b/src/login/login.h index de504db07..6dc4c875b 100644 --- a/src/login/login.h +++ b/src/login/login.h @@ -101,14 +101,6 @@ struct Login_Config { int client_hash_check; ///< flags for checking client md5 struct client_hash_node *client_hash_nodes; ///< linked list containg md5 hash for each gm group - - /// Advanced subnet check [LuzZza] - struct s_subnet { - uint32 mask; - uint32 char_ip; - uint32 map_ip; - } subnet[16]; - int subnet_count; }; struct login_auth_node { @@ -163,8 +155,7 @@ struct login_interface { int (*sync_ip_addresses) (int tid, int64 tick, int id, intptr_t data); bool (*check_encrypted) (const char* str1, const char* str2, const char* passwd); bool (*check_password) (const char* md5key, int passwdenc, const char* passwd, const char* refpass); - int (*lan_subnetcheck) (uint32 ip); - int (*lan_config_read) (const char *lancfgName); + uint32 (*lan_subnet_check) (uint32 ip); void (*fromchar_accinfo) (int fd, int account_id, int u_fd, int u_aid, int u_group, int map_fd, struct mmo_account *acc); void (*fromchar_account) (int fd, int account_id, struct mmo_account *acc); void (*fromchar_account_update_other) (int account_id, unsigned int state); @@ -207,7 +198,7 @@ struct login_interface { void (*parse_request_connection) (int fd, struct login_session_data* sd, const char *ip, uint32 ipl); int (*parse_login) (int fd); char *LOGIN_CONF_NAME; - char *LAN_CONF_NAME; + char *NET_CONF_NAME; ///< Network configuration filename }; struct login_interface *login; |