From 266ee52704bcd986b77055a75ef519eb41a2f647 Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Mon, 30 Jan 2023 08:12:48 -0800 Subject: [PATCH] server: bind both wildcard for UDP When possible, bind both ipv4 and ipv6 wildcard addresses for UDP. Even when only binding ipv6 address for TCP (Linux) --- src/config.cpp | 27 +-------------------------- src/server.cpp | 43 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 43 insertions(+), 27 deletions(-) diff --git a/src/config.cpp b/src/config.cpp index 3199669..235f5e4 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -483,9 +483,6 @@ void Config::updateDefs(defs_t& defs) const void Config::expand() { - if(tcp_port==0) - tcp_port = 5075; - auto ifaces(parseAddresses(interfaces)); auto bdest(parseAddresses(beaconDestinations)); @@ -500,29 +497,7 @@ void Config::expand() for(size_t i=0; i [::]%s", "\n"); - - } else if(evsocket::ipstack!=evsocket::Linsock) { - /* Other IP stacks allow binding different sockets. - * OSX has the added oddity of ordering dependence. - * 0.0.0.0 and then :: is allowed, but not the reverse. - * - * So when possible, we always bind both in the allowed order. - */ - ep.addr = SockAddr::any(AF_INET, ep.addr.port()); - ifaces.emplace(ifaces.begin()+i+1u, - SockAddr::any(AF_INET6, ep.addr.port())); - i++; // continue after newly inserted EP - } - - } else if(!ep.addr.isMCast()) { + if(!ep.addr.isMCast()) { // no-op } else if(!ep.iface.empty()) { diff --git a/src/server.cpp b/src/server.cpp index 6002654..436863a 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -396,12 +396,19 @@ Server::Pvt::Pvt(const Config &conf) const auto cb(std::bind(&Pvt::onSearch, this, std::placeholders::_1)); + bool bindAny = false; std::vector tcpifaces; // may have port zero for(const auto& iface : effective.interfaces) { SockEndpoint addr(iface.c_str()); - if(!addr.addr.isMCast()) + + if(addr.addr.isAny()) { + bindAny = true; + + } else if(!addr.addr.isMCast()) { tcpifaces.push_back(addr.addr); + } + addr.addr.setPort(effective.udp_port); listeners.push_back(manager.onSearch(addr, cb)); @@ -409,12 +416,24 @@ Server::Pvt::Pvt(const Config &conf) // update to allow udp_port==0 effective.udp_port = addr.addr.port(); + + if(addr.addr.isAny()) { + continue; // special case handling below + } + if(addr.addr.family()==AF_INET && addr.addr.isAny()) { // if listening on 0.0.0.0, also listen on [::] auto any6(addr); any6.addr = SockAddr::any(AF_INET6); listeners.push_back(manager.onSearch(any6, cb)); + + } else if(addr.addr.family()==AF_INET6 && addr.addr.isAny()) { + // if listening on [::], also listen on 0.0.0.0 + auto any4(addr); + any4.addr = SockAddr::any(AF_INET); + + listeners.push_back(manager.onSearch(any4, cb)); } if(evsocket::ipstack!=evsocket::Winsock @@ -432,6 +451,28 @@ Server::Pvt::Pvt(const Config &conf) } } + if(bindAny) { + if(evsocket::canIPv6) { + if(evsocket::ipstack==evsocket::Linsock) { + /* Linux IP stack disallows binding both 0.0.0.0 and [::] for the same port. + * so we must always bind [::] + */ + tcpifaces.emplace_back(AF_INET6); + } else { + /* Other IP stacks allow binding different sockets. + * OSX has the added oddity of ordering dependence. + * 0.0.0.0 and then :: is allowed, but not the reverse. + * + * Always bind both in the OSX allowed order. + */ + tcpifaces.emplace_back(AF_INET); + tcpifaces.emplace_back(AF_INET6); + } + } else { + tcpifaces.emplace_back(AF_INET); + } + } + if(tcpifaces.empty()) { log_err_printf(serversetup, "Server Unreachable. Interface address list includes not TCP interfaces.%s", "\n"); }