fix up local/external address handling
This commit is contained in:
+44
-25
@@ -10,6 +10,7 @@
|
||||
#include <phosg/JSON.hh>
|
||||
#include <phosg/Math.hh>
|
||||
#include <phosg/Network.hh>
|
||||
#include <phosg/Platform.hh>
|
||||
#include <phosg/Strings.hh>
|
||||
#include <phosg/Tools.hh>
|
||||
#include <set>
|
||||
@@ -53,6 +54,12 @@
|
||||
|
||||
using namespace std;
|
||||
|
||||
#ifdef PHOSG_WINDOWS
|
||||
static constexpr bool IS_WINDOWS = true;
|
||||
#else
|
||||
static constexpr bool IS_WINDOWS = false;
|
||||
#endif
|
||||
|
||||
bool use_terminal_colors = false;
|
||||
|
||||
void print_version_info();
|
||||
@@ -3167,9 +3174,21 @@ Action a_run_server_replay_log(
|
||||
state->ip_stack_simulator->listen(
|
||||
spec, netloc.first, netloc.second, IPStackSimulator::Protocol::HDLC_RAW);
|
||||
if (netloc.second) {
|
||||
if (state->local_address == state->external_address) {
|
||||
if (state->local_address == 0 && state->external_address == 0) {
|
||||
config_log.info(
|
||||
"Note: The Devolution phone number for %s is %" PRIu64,
|
||||
"Cannot generate Devolution phone numbers for %s because LocalAddress and ExternalAddress are not specified in the configuration",
|
||||
spec.c_str());
|
||||
} else if (state->local_address == 0) {
|
||||
config_log.info(
|
||||
"Note: The Devolution phone number for %s is %" PRIu64 " (external)",
|
||||
spec.c_str(), devolution_phone_number_for_netloc(state->external_address, netloc.second));
|
||||
} else if (state->external_address == 0) {
|
||||
config_log.info(
|
||||
"Note: The Devolution phone number for %s is %" PRIu64 " (local)",
|
||||
spec.c_str(), devolution_phone_number_for_netloc(state->local_address, netloc.second));
|
||||
} else if (state->local_address == state->external_address) {
|
||||
config_log.info(
|
||||
"Note: The Devolution phone number for %s is %" PRIu64 " (local+external)",
|
||||
spec.c_str(), devolution_phone_number_for_netloc(state->local_address, netloc.second));
|
||||
} else {
|
||||
config_log.info(
|
||||
@@ -3328,30 +3347,30 @@ int main(int argc, char** argv) {
|
||||
phosg::log_error("Unknown or invalid action; try --help");
|
||||
return 1;
|
||||
}
|
||||
#ifdef PHOSG_WINDOWS
|
||||
// Cygwin just gives a stackdump when an exception falls out of main(), so
|
||||
// unlike Linux and macOS, we have to manually catch exceptions here just to
|
||||
// see what the exception message was.
|
||||
try {
|
||||
if (IS_WINDOWS) {
|
||||
// Cygwin just gives a stackdump when an exception falls out of main(), so
|
||||
// unlike Linux and macOS, we have to manually catch exceptions here just to
|
||||
// see what the exception message was.
|
||||
try {
|
||||
a->run(args);
|
||||
} catch (const phosg::cannot_open_file& e) {
|
||||
phosg::log_error("Top-level exception (cannot_open_file): %s", e.what());
|
||||
throw;
|
||||
} catch (const invalid_argument& e) {
|
||||
phosg::log_error("Top-level exception (invalid_argument): %s", e.what());
|
||||
throw;
|
||||
} catch (const out_of_range& e) {
|
||||
phosg::log_error("Top-level exception (out_of_range): %s", e.what());
|
||||
throw;
|
||||
} catch (const runtime_error& e) {
|
||||
phosg::log_error("Top-level exception (runtime_error): %s", e.what());
|
||||
throw;
|
||||
} catch (const exception& e) {
|
||||
phosg::log_error("Top-level exception: %s", e.what());
|
||||
throw;
|
||||
}
|
||||
} else {
|
||||
a->run(args);
|
||||
} catch (const phosg::cannot_open_file& e) {
|
||||
phosg::log_error("Top-level exception (cannot_open_file): %s", e.what());
|
||||
throw;
|
||||
} catch (const invalid_argument& e) {
|
||||
phosg::log_error("Top-level exception (invalid_argument): %s", e.what());
|
||||
throw;
|
||||
} catch (const out_of_range& e) {
|
||||
phosg::log_error("Top-level exception (out_of_range): %s", e.what());
|
||||
throw;
|
||||
} catch (const runtime_error& e) {
|
||||
phosg::log_error("Top-level exception (runtime_error): %s", e.what());
|
||||
throw;
|
||||
} catch (const exception& e) {
|
||||
phosg::log_error("Top-level exception: %s", e.what());
|
||||
throw;
|
||||
}
|
||||
#else
|
||||
a->run(args);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -66,9 +66,16 @@ map<string, uint32_t> get_local_addresses() {
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool is_loopback_address(uint32_t addr) {
|
||||
return ((addr & 0xFF000000) == 0x7F000000); // 127.0.0.0/8
|
||||
}
|
||||
|
||||
bool is_local_address(uint32_t addr) {
|
||||
uint8_t net = (addr >> 24) & 0xFF;
|
||||
return ((net == 127) || (net == 172) || (net == 10) || (net == 192));
|
||||
return is_loopback_address(addr) || // 127.0.0.0/8
|
||||
((addr & 0xFF000000) == 0x0A000000) || // 10.0.0.0/8
|
||||
((addr & 0xFFF00000) == 0xAC100000) || // 172.16.0.0/12
|
||||
((addr & 0xFFFF0000) == 0xC0A80000) || // 192.168.0.0/16
|
||||
((addr & 0xFFFF0000) == 0xA9FE0000); // 169.254.0.0/16
|
||||
}
|
||||
|
||||
bool is_local_address(const sockaddr_storage& daddr) {
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
uint32_t resolve_address(const char* address);
|
||||
std::map<std::string, uint32_t> get_local_addresses();
|
||||
uint32_t get_connected_address(int fd);
|
||||
bool is_loopback_address(uint32_t addr);
|
||||
bool is_local_address(uint32_t daddr);
|
||||
bool is_local_address(const sockaddr_storage& daddr);
|
||||
|
||||
|
||||
+44
-6
@@ -5,6 +5,7 @@
|
||||
#include <memory>
|
||||
#include <phosg/Image.hh>
|
||||
#include <phosg/Network.hh>
|
||||
#include <phosg/Platform.hh>
|
||||
|
||||
#include "Compression.hh"
|
||||
#include "EventUtils.hh"
|
||||
@@ -19,6 +20,12 @@
|
||||
|
||||
using namespace std;
|
||||
|
||||
#ifdef PHOSG_WINDOWS
|
||||
static constexpr bool IS_WINDOWS = true;
|
||||
#else
|
||||
static constexpr bool IS_WINDOWS = false;
|
||||
#endif
|
||||
|
||||
CheatFlags::CheatFlags(const phosg::JSON& json) : CheatFlags() {
|
||||
unordered_set<std::string> enabled_keys;
|
||||
for (const auto& it : json.as_list()) {
|
||||
@@ -673,8 +680,10 @@ void ServerState::load_config_early() {
|
||||
for (const auto& item : this->config_json->at("IPStackListen").as_list()) {
|
||||
if (item->is_int()) {
|
||||
this->ip_stack_addresses.emplace_back(phosg::string_printf("0.0.0.0:%" PRId64, item->as_int()));
|
||||
} else {
|
||||
} else if (!IS_WINDOWS) {
|
||||
this->ip_stack_addresses.emplace_back(item->as_string());
|
||||
} else {
|
||||
config_log.warning("Unix sockets are not supported on Windows; skipping address %s", item->as_string().c_str());
|
||||
}
|
||||
}
|
||||
} catch (const out_of_range&) {
|
||||
@@ -683,8 +692,10 @@ void ServerState::load_config_early() {
|
||||
for (const auto& item : this->config_json->at("PPPStackListen").as_list()) {
|
||||
if (item->is_int()) {
|
||||
this->ppp_stack_addresses.emplace_back(phosg::string_printf("0.0.0.0:%" PRId64, item->as_int()));
|
||||
} else {
|
||||
} else if (!IS_WINDOWS) {
|
||||
this->ppp_stack_addresses.emplace_back(item->as_string());
|
||||
} else {
|
||||
config_log.warning("Unix sockets are not supported on Windows; skipping address %s", item->as_string().c_str());
|
||||
}
|
||||
}
|
||||
} catch (const out_of_range&) {
|
||||
@@ -693,8 +704,10 @@ void ServerState::load_config_early() {
|
||||
for (const auto& item : this->config_json->at("PPPRawListen").as_list()) {
|
||||
if (item->is_int()) {
|
||||
this->ppp_raw_addresses.emplace_back(phosg::string_printf("0.0.0.0:%" PRId64, item->as_int()));
|
||||
} else {
|
||||
} else if (!IS_WINDOWS) {
|
||||
this->ppp_raw_addresses.emplace_back(item->as_string());
|
||||
} else {
|
||||
config_log.warning("Unix sockets are not supported on Windows; skipping address %s", item->as_string().c_str());
|
||||
}
|
||||
}
|
||||
} catch (const out_of_range&) {
|
||||
@@ -703,8 +716,10 @@ void ServerState::load_config_early() {
|
||||
for (const auto& item : this->config_json->at("HTTPListen").as_list()) {
|
||||
if (item->is_int()) {
|
||||
this->http_addresses.emplace_back(phosg::string_printf("0.0.0.0:%" PRId64, item->as_int()));
|
||||
} else {
|
||||
} else if (!IS_WINDOWS) {
|
||||
this->http_addresses.emplace_back(item->as_string());
|
||||
} else {
|
||||
config_log.warning("Unix sockets are not supported on Windows; skipping address %s", item->as_string().c_str());
|
||||
}
|
||||
}
|
||||
} catch (const out_of_range&) {
|
||||
@@ -727,7 +742,18 @@ void ServerState::load_config_early() {
|
||||
this->all_addresses.erase("<local>");
|
||||
this->all_addresses.emplace("<local>", this->local_address);
|
||||
} catch (const out_of_range&) {
|
||||
config_log.warning("Local address not specified; interface defaults will be used");
|
||||
for (const auto& it : this->all_addresses) {
|
||||
// Choose any local interface except the loopback interface
|
||||
if (!is_loopback_address(it.second) && is_local_address(it.second)) {
|
||||
this->local_address = it.second;
|
||||
}
|
||||
}
|
||||
if (this->local_address) {
|
||||
string addr_str = string_for_address(this->local_address);
|
||||
config_log.warning("Local address not specified; using %s as default", addr_str.c_str());
|
||||
} else {
|
||||
config_log.warning("Local address not specified and no default is available");
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -744,7 +770,19 @@ void ServerState::load_config_early() {
|
||||
this->all_addresses.erase("<external>");
|
||||
this->all_addresses.emplace("<external>", this->external_address);
|
||||
} catch (const out_of_range&) {
|
||||
config_log.warning("External address not specified; only local clients will be able to connect");
|
||||
for (const auto& it : this->all_addresses) {
|
||||
// Choose any non-local address, if any exist
|
||||
if (!is_local_address(it.second)) {
|
||||
this->external_address = it.second;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (this->external_address) {
|
||||
string addr_str = string_for_address(this->external_address);
|
||||
config_log.warning("External address not specified; using %s as default", addr_str.c_str());
|
||||
} else {
|
||||
config_log.warning("External address not specified and no default is available; only local clients will be able to connect");
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user