From ca4340b9e06067f36bbac9a7eee5f5319b62904e Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 30 Apr 2018 17:06:54 -0700 Subject: [PATCH] net: Support ipv6 lookups. We try to connect() to both, so should still be safe in environments where ipv6 is broken. --- UI/RemoteISOScreen.cpp | 16 +++++++++++++--- ext/native/net/http_client.cpp | 8 ++++---- ext/native/net/http_client.h | 3 ++- ext/native/net/http_server.h | 2 +- ext/native/net/resolve.cpp | 8 ++++++-- ext/native/net/resolve.h | 8 +++++++- 6 files changed, 33 insertions(+), 12 deletions(-) diff --git a/UI/RemoteISOScreen.cpp b/UI/RemoteISOScreen.cpp index 2767e72761..b5ad54498c 100644 --- a/UI/RemoteISOScreen.cpp +++ b/UI/RemoteISOScreen.cpp @@ -69,11 +69,13 @@ static ServerStatus RetrieveStatus() { // relay that address to a mobile device searching for the server. static void RegisterServer(int port) { http::Client http; - Buffer theVoid; - if (http.Resolve(REPORT_HOSTNAME, REPORT_PORT)) { + char resource[1024] = {}; + // We register both IPv4 and IPv6 in case the other client is using a different one. + // Our server is (currently?) ipv4 only, so we always register the ipv4 local for now. + if (http.Resolve(REPORT_HOSTNAME, REPORT_PORT, net::DNSType::IPV4)) { + Buffer theVoid; if (http.Connect(2, 20.0, &scanCancelled)) { - char resource[1024] = {}; std::string ip = fd_util::GetLocalIP(http.sock()); snprintf(resource, sizeof(resource) - 1, "/match/update?local=%s&port=%d", ip.c_str(), port); @@ -81,6 +83,14 @@ static void RegisterServer(int port) { http.Disconnect(); } } + + if (http.Resolve(REPORT_HOSTNAME, REPORT_PORT, net::DNSType::IPV6)) { + Buffer theVoid; + if (http.Connect()) { + http.GET(resource, &theVoid); + http.Disconnect(); + } + } } static void ExecuteServer() { diff --git a/ext/native/net/http_client.cpp b/ext/native/net/http_client.cpp index becb4e4473..3cb6967326 100644 --- a/ext/native/net/http_client.cpp +++ b/ext/native/net/http_client.cpp @@ -46,7 +46,7 @@ inline unsigned short myhtons(unsigned short x) { return (x >> 8) | (x << 8); } -bool Connection::Resolve(const char *host, int port) { +bool Connection::Resolve(const char *host, int port, DNSType type) { if ((intptr_t)sock_ != -1) { ELOG("Resolve: Already have a socket"); return false; @@ -63,7 +63,7 @@ bool Connection::Resolve(const char *host, int port) { snprintf(port_str, sizeof(port_str), "%d", port); std::string err; - if (!net::DNSResolve(host, port_str, &resolved_, err)) { + if (!net::DNSResolve(host, port_str, &resolved_, err, type)) { ELOG("Failed to resolve host %s: %s", host, err.c_str()); // So that future calls fail. port_ = 0; @@ -87,10 +87,10 @@ bool Connection::Connect(int maxTries, double timeout, bool *cancelConnect) { FD_ZERO(&fds); for (addrinfo *possible = resolved_; possible != nullptr; possible = possible->ai_next) { // TODO: Could support ipv6 without huge difficulty... - if (possible->ai_family != AF_INET) + if (possible->ai_family != AF_INET && possible->ai_family != AF_INET6) continue; - int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + int sock = socket(possible->ai_family, SOCK_STREAM, IPPROTO_TCP); if ((intptr_t)sock == -1) { ELOG("Bad socket"); continue; diff --git a/ext/native/net/http_client.h b/ext/native/net/http_client.h index 0f63c4bb9c..ac3d26ed97 100644 --- a/ext/native/net/http_client.h +++ b/ext/native/net/http_client.h @@ -6,6 +6,7 @@ #include "base/basictypes.h" #include "base/buffer.h" +#include "net/resolve.h" #ifdef _WIN32 #ifndef NOMINMAX @@ -28,7 +29,7 @@ public: virtual ~Connection(); // Inits the sockaddr_in. - bool Resolve(const char *host, int port); + bool Resolve(const char *host, int port, DNSType type = DNSType::ANY); bool Connect(int maxTries = 2, double timeout = 20.0f, bool *cancelConnect = nullptr); void Disconnect(); diff --git a/ext/native/net/http_server.h b/ext/native/net/http_server.h index 974b45ee6d..29ba802618 100644 --- a/ext/native/net/http_server.h +++ b/ext/native/net/http_server.h @@ -85,7 +85,7 @@ public: virtual void HandleRequest(const Request &request); int Port() { - return port_; + return port_; } private: diff --git a/ext/native/net/resolve.cpp b/ext/native/net/resolve.cpp index 1876427b14..ec7d17f1d1 100644 --- a/ext/native/net/resolve.cpp +++ b/ext/native/net/resolve.cpp @@ -77,7 +77,7 @@ char *DNSResolve(const char *host) return ip; } -bool DNSResolve(const std::string &host, const std::string &service, addrinfo **res, std::string &error) +bool DNSResolve(const std::string &host, const std::string &service, addrinfo **res, std::string &error, DNSType type) { addrinfo hints = {0}; // TODO: Might be uses to lookup other values. @@ -89,7 +89,11 @@ bool DNSResolve(const std::string &host, const std::string &service, addrinfo ** // http://stackoverflow.com/questions/1408030/what-is-the-purpose-of-the-ai-v4mapped-flag-in-getaddrinfo hints.ai_flags = /*AI_V4MAPPED |*/ AI_ADDRCONFIG; #endif - hints.ai_protocol = IPPROTO_TCP; + hints.ai_protocol = 0; + if (type == DNSType::IPV4) + hints.ai_family = AF_INET; + else if (type == DNSType::IPV6) + hints.ai_family = AF_INET6; const char *servicep = service.length() == 0 ? NULL : service.c_str(); diff --git a/ext/native/net/resolve.h b/ext/native/net/resolve.h index 46a8b3e598..58ce0984d9 100644 --- a/ext/native/net/resolve.h +++ b/ext/native/net/resolve.h @@ -14,7 +14,13 @@ void Shutdown(); char *DNSResolveTry(const char *host, const char **err); char *DNSResolve(const char *host); -bool DNSResolve(const std::string &host, const std::string &service, addrinfo **res, std::string &error); +enum class DNSType { + ANY = 0, + IPV4 = 1, + IPV6 = 2, +}; + +bool DNSResolve(const std::string &host, const std::string &service, addrinfo **res, std::string &error, DNSType type = DNSType::ANY); void DNSResolveFree(addrinfo *res); int inet_pton(int af, const char* src, void* dst);