Infer ipv6_server from bind_address; fix client connect to IN(6)ADDR_ANY

This commit is contained in:
Kahrl 2014-03-07 01:00:03 +01:00 committed by sapier
parent edcad09dee
commit 6090e95cdc
7 changed files with 88 additions and 47 deletions

View File

@ -438,6 +438,7 @@
#enable_ipv6 = true #enable_ipv6 = true
# Enable/disable running an IPv6 server. An IPv6 server may be restricted # Enable/disable running an IPv6 server. An IPv6 server may be restricted
# to IPv6 clients, depending on system configuration. # to IPv6 clients, depending on system configuration.
# Ignored if bind_address is set.
#ipv6_server = false #ipv6_server = false
#main_menu_script = #main_menu_script =

View File

@ -1147,27 +1147,34 @@ void the_game(bool &kill, bool random_input, InputHandler *input,
draw_load_screen(text, device, font,0,25); draw_load_screen(text, device, font,0,25);
delete[] text; delete[] text;
infostream<<"Creating server"<<std::endl; infostream<<"Creating server"<<std::endl;
server = new Server(map_dir, gamespec,
simple_singleplayer_mode);
std::string bind_str = g_settings->get("bind_address"); std::string bind_str = g_settings->get("bind_address");
Address bind_addr(0,0,0,0, port); Address bind_addr(0,0,0,0, port);
if (bind_str != "") 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);
}
}
} }
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(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); server->start(bind_addr);
} }
@ -1193,31 +1200,33 @@ void the_game(bool &kill, bool random_input, InputHandler *input,
delete[] text; delete[] text;
} }
Address connect_address(0,0,0,0, port); Address connect_address(0,0,0,0, port);
try{ try {
if(address == "") connect_address.Resolve(address.c_str());
{ if (connect_address.isZero()) { // i.e. INADDR_ANY, IN6ADDR_ANY
//connect_address.Resolve("localhost"); //connect_address.Resolve("localhost");
if(g_settings->getBool("enable_ipv6") && g_settings->getBool("ipv6_server")) if (connect_address.isIPv6()) {
{
IPv6AddressBytes addr_bytes; IPv6AddressBytes addr_bytes;
addr_bytes.bytes[15] = 1; addr_bytes.bytes[15] = 1;
connect_address.setAddress(&addr_bytes); connect_address.setAddress(&addr_bytes);
} } else {
else
{
connect_address.setAddress(127,0,0,1); 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()); error_message = L"Couldn't resolve address: " + narrow_to_wide(e.what());
errorstream<<wide_to_narrow(error_message)<<std::endl; errorstream<<wide_to_narrow(error_message)<<std::endl;
// Break out of client scope // Break out of client scope
break; 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 Create client

View File

@ -1023,21 +1023,6 @@ int main(int argc, char *argv[])
if(port == 0) if(port == 0)
port = 30000; 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 // World directory
std::string commanded_world = ""; std::string commanded_world = "";
if(cmd_args.exists("world")) if(cmd_args.exists("world"))
@ -1223,8 +1208,29 @@ int main(int argc, char *argv[])
} }
verbosestream<<_("Using gameid")<<" ["<<gamespec.id<<"]"<<std::endl; 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 // Create server
Server server(world_path, gamespec, false); Server server(world_path, gamespec, false, bind_addr.isIPv6());
// Database migration // Database migration
if (cmd_args.exists("migrate")) { if (cmd_args.exists("migrate")) {

View File

@ -166,7 +166,8 @@ v3f ServerSoundParams::getPos(ServerEnvironment *env, bool *pos_exists) const
Server::Server( Server::Server(
const std::string &path_world, const std::string &path_world,
const SubgameSpec &gamespec, const SubgameSpec &gamespec,
bool simple_singleplayer_mode bool simple_singleplayer_mode,
bool ipv6
): ):
m_path_world(path_world), m_path_world(path_world),
m_gamespec(gamespec), m_gamespec(gamespec),
@ -176,7 +177,7 @@ Server::Server(
m_con(PROTOCOL_ID, m_con(PROTOCOL_ID,
512, 512,
CONNECTION_TIMEOUT, CONNECTION_TIMEOUT,
g_settings->getBool("enable_ipv6") && g_settings->getBool("ipv6_server"), ipv6,
this), this),
m_banmanager(NULL), m_banmanager(NULL),
m_rollback(NULL), m_rollback(NULL),

View File

@ -174,7 +174,8 @@ public:
Server( Server(
const std::string &path_world, const std::string &path_world,
const SubgameSpec &gamespec, const SubgameSpec &gamespec,
bool simple_singleplayer_mode bool simple_singleplayer_mode,
bool ipv6
); );
~Server(); ~Server();
void start(Address bind_addr); void start(Address bind_addr);

View File

@ -143,6 +143,15 @@ bool Address::operator!=(Address &address)
void Address::Resolve(const char *name) 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; struct addrinfo *resolved, hints;
memset(&hints, 0, sizeof(hints)); memset(&hints, 0, sizeof(hints));
@ -251,6 +260,18 @@ bool Address::isIPv6() const
return m_addr_family == AF_INET6; 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) void Address::setAddress(u32 address)
{ {
m_addr_family = AF_INET; m_addr_family = AF_INET;

View File

@ -88,6 +88,7 @@ public:
Address(const IPv6AddressBytes * ipv6_bytes, u16 port); Address(const IPv6AddressBytes * ipv6_bytes, u16 port);
bool operator==(Address &address); bool operator==(Address &address);
bool operator!=(Address &address); bool operator!=(Address &address);
// Resolve() may throw ResolveError (address is unchanged in this case)
void Resolve(const char *name); void Resolve(const char *name);
struct sockaddr_in getAddress() const; struct sockaddr_in getAddress() const;
unsigned short getPort() const; unsigned short getPort() const;
@ -97,6 +98,7 @@ public:
struct sockaddr_in6 getAddress6() const; struct sockaddr_in6 getAddress6() const;
int getFamily() const; int getFamily() const;
bool isIPv6() const; bool isIPv6() const;
bool isZero() const;
void setPort(unsigned short port); void setPort(unsigned short port);
void print(std::ostream *s) const; void print(std::ostream *s) const;
std::string serializeString() const; std::string serializeString() const;