diff options
-rw-r--r-- | minetest.conf.example | 1 | ||||
-rw-r--r-- | src/game.cpp | 63 | ||||
-rw-r--r-- | src/main.cpp | 38 | ||||
-rw-r--r-- | src/server.cpp | 5 | ||||
-rw-r--r-- | src/server.h | 3 | ||||
-rw-r--r-- | src/socket.cpp | 21 | ||||
-rw-r--r-- | src/socket.h | 2 |
7 files changed, 87 insertions, 46 deletions
diff --git a/minetest.conf.example b/minetest.conf.example index f728d6c88..4e4495338 100644 --- a/minetest.conf.example +++ b/minetest.conf.example @@ -438,6 +438,7 @@ #enable_ipv6 = true # Enable/disable running an IPv6 server. An IPv6 server may be restricted # to IPv6 clients, depending on system configuration. +# Ignored if bind_address is set. #ipv6_server = false #main_menu_script = diff --git a/src/game.cpp b/src/game.cpp index 7d881fa88..f435a4d71 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -1147,28 +1147,35 @@ void the_game(bool &kill, bool random_input, InputHandler *input, draw_load_screen(text, device, font,0,25); delete[] text; infostream<<"Creating server"<<std::endl; - server = new Server(map_dir, gamespec, - simple_singleplayer_mode); std::string bind_str = g_settings->get("bind_address"); Address bind_addr(0,0,0,0, port); - if (bind_str != "") - { - try { - bind_addr.Resolve(bind_str.c_str()); - address = bind_str; - } catch (ResolveError &e) { - infostream << "Resolving bind address \"" << bind_str - << "\" failed: " << e.what() - << " -- Listening on all addresses." << std::endl; + if (g_settings->getBool("ipv6_server")) { + bind_addr.setAddress((IPv6AddressBytes*) NULL); + } + try { + bind_addr.Resolve(bind_str.c_str()); + address = bind_str; + } catch (ResolveError &e) { + infostream << "Resolving bind address \"" << bind_str + << "\" failed: " << e.what() + << " -- Listening on all addresses." << std::endl; + } - if (g_settings->getBool("ipv6_server")) { - bind_addr.setAddress((IPv6AddressBytes*) NULL); - } - } + if(bind_addr.isIPv6() && !g_settings->getBool("enable_ipv6")) { + error_message = L"Unable to listen on " + + narrow_to_wide(bind_addr.serializeString()) + + L" because IPv6 is disabled"; + errorstream<<wide_to_narrow(error_message)<<std::endl; + // Break out of client scope + return; } + server = new Server(map_dir, gamespec, + simple_singleplayer_mode, + bind_addr.isIPv6()); + server->start(bind_addr); } @@ -1193,31 +1200,33 @@ void the_game(bool &kill, bool random_input, InputHandler *input, delete[] text; } Address connect_address(0,0,0,0, port); - try{ - if(address == "") - { + try { + connect_address.Resolve(address.c_str()); + if (connect_address.isZero()) { // i.e. INADDR_ANY, IN6ADDR_ANY //connect_address.Resolve("localhost"); - if(g_settings->getBool("enable_ipv6") && g_settings->getBool("ipv6_server")) - { + if (connect_address.isIPv6()) { IPv6AddressBytes addr_bytes; addr_bytes.bytes[15] = 1; connect_address.setAddress(&addr_bytes); - } - else - { + } else { connect_address.setAddress(127,0,0,1); } } - else - connect_address.Resolve(address.c_str()); } - catch(ResolveError &e) - { + catch(ResolveError &e) { error_message = L"Couldn't resolve address: " + narrow_to_wide(e.what()); errorstream<<wide_to_narrow(error_message)<<std::endl; // Break out of client scope break; } + if(connect_address.isIPv6() && !g_settings->getBool("enable_ipv6")) { + error_message = L"Unable to connect to " + + narrow_to_wide(connect_address.serializeString()) + + L" because IPv6 is disabled"; + errorstream<<wide_to_narrow(error_message)<<std::endl; + // Break out of client scope + break; + } /* Create client diff --git a/src/main.cpp b/src/main.cpp index e52002772..baaf8ebde 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1023,21 +1023,6 @@ int main(int argc, char *argv[]) if(port == 0) port = 30000; - // Bind address - std::string bind_str = g_settings->get("bind_address"); - Address bind_addr(0,0,0,0, port); - try { - bind_addr.Resolve(bind_str.c_str()); - } catch (ResolveError &e) { - infostream << "Resolving bind address \"" << bind_str - << "\" failed: " << e.what() - << " -- Listening on all addresses." << std::endl; - - if (g_settings->getBool("ipv6_server")) { - bind_addr.setAddress((IPv6AddressBytes*) NULL); - } - } - // World directory std::string commanded_world = ""; if(cmd_args.exists("world")) @@ -1223,8 +1208,29 @@ int main(int argc, char *argv[]) } verbosestream<<_("Using gameid")<<" ["<<gamespec.id<<"]"<<std::endl; + // Bind address + std::string bind_str = g_settings->get("bind_address"); + Address bind_addr(0,0,0,0, port); + + if (g_settings->getBool("ipv6_server")) { + bind_addr.setAddress((IPv6AddressBytes*) NULL); + } + try { + bind_addr.Resolve(bind_str.c_str()); + } catch (ResolveError &e) { + infostream << "Resolving bind address \"" << bind_str + << "\" failed: " << e.what() + << " -- Listening on all addresses." << std::endl; + } + if(bind_addr.isIPv6() && !g_settings->getBool("enable_ipv6")) { + errorstream << "Unable to listen on " + << bind_addr.serializeString() + << L" because IPv6 is disabled" << std::endl; + return 1; + } + // Create server - Server server(world_path, gamespec, false); + Server server(world_path, gamespec, false, bind_addr.isIPv6()); // Database migration if (cmd_args.exists("migrate")) { diff --git a/src/server.cpp b/src/server.cpp index 0cd8630c3..5c93988b8 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -166,7 +166,8 @@ v3f ServerSoundParams::getPos(ServerEnvironment *env, bool *pos_exists) const Server::Server( const std::string &path_world, const SubgameSpec &gamespec, - bool simple_singleplayer_mode + bool simple_singleplayer_mode, + bool ipv6 ): m_path_world(path_world), m_gamespec(gamespec), @@ -176,7 +177,7 @@ Server::Server( m_con(PROTOCOL_ID, 512, CONNECTION_TIMEOUT, - g_settings->getBool("enable_ipv6") && g_settings->getBool("ipv6_server"), + ipv6, this), m_banmanager(NULL), m_rollback(NULL), diff --git a/src/server.h b/src/server.h index c0928e574..ab89fbc6e 100644 --- a/src/server.h +++ b/src/server.h @@ -174,7 +174,8 @@ public: Server( const std::string &path_world, const SubgameSpec &gamespec, - bool simple_singleplayer_mode + bool simple_singleplayer_mode, + bool ipv6 ); ~Server(); void start(Address bind_addr); diff --git a/src/socket.cpp b/src/socket.cpp index 00856fb00..bca9c5390 100644 --- a/src/socket.cpp +++ b/src/socket.cpp @@ -143,6 +143,15 @@ bool Address::operator!=(Address &address) void Address::Resolve(const char *name) { + if (!name || name[0] == 0) { + if (m_addr_family == AF_INET) { + setAddress((u32) 0); + } else if (m_addr_family == AF_INET6) { + setAddress((IPv6AddressBytes*) 0); + } + return; + } + struct addrinfo *resolved, hints; memset(&hints, 0, sizeof(hints)); @@ -251,6 +260,18 @@ bool Address::isIPv6() const return m_addr_family == AF_INET6; } +bool Address::isZero() const +{ + if (m_addr_family == AF_INET) { + return m_address.ipv4.sin_addr.s_addr == 0; + } else if (m_addr_family == AF_INET6) { + static const char zero[16] = {0}; + return memcmp(m_address.ipv6.sin6_addr.s6_addr, + zero, 16) == 0; + } + return false; +} + void Address::setAddress(u32 address) { m_addr_family = AF_INET; diff --git a/src/socket.h b/src/socket.h index 7d35a32da..92e0cbb13 100644 --- a/src/socket.h +++ b/src/socket.h @@ -88,6 +88,7 @@ public: Address(const IPv6AddressBytes * ipv6_bytes, u16 port); bool operator==(Address &address); bool operator!=(Address &address); + // Resolve() may throw ResolveError (address is unchanged in this case) void Resolve(const char *name); struct sockaddr_in getAddress() const; unsigned short getPort() const; @@ -97,6 +98,7 @@ public: struct sockaddr_in6 getAddress6() const; int getFamily() const; bool isIPv6() const; + bool isZero() const; void setPort(unsigned short port); void print(std::ostream *s) const; std::string serializeString() const; |