From 49223a7853a0fd56816de6ef906c3e9cb4b2fdaa Mon Sep 17 00:00:00 2001 From: Jason Rhinelander Date: Mon, 12 Sep 2022 13:05:49 -0300 Subject: [PATCH] bind/close to find free UDP port The current code isn't working and gives a 0 (which then fails unbound initialization). This replaces it by doing a socket+bind to find a free port then immediately closes (but passes the port we got into unbound). --- llarp/dns/server.cpp | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/llarp/dns/server.cpp b/llarp/dns/server.cpp index 41632e6e4..33e254d58 100644 --- a/llarp/dns/server.cpp +++ b/llarp/dns/server.cpp @@ -2,6 +2,7 @@ #include "dns.hpp" #include #include +#include #include #include #include @@ -247,19 +248,26 @@ namespace llarp::dns // on our system and use it so we KNOW what it is before giving it to unbound to // explicitly bind to JUST that port. - addrinfo hints{}; - addrinfo* result{nullptr}; - hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST; - hints.ai_socktype = SOCK_DGRAM; - hints.ai_family = AF_INET; - if (auto err = getaddrinfo(host.c_str(), nullptr, &hints, &result)) - throw std::invalid_argument{strerror(err)}; - addr.setPort(net::port_t{reinterpret_cast(result->ai_addr)->sin_port}); - freeaddrinfo(result); + int fd = socket(AF_INET, SOCK_DGRAM, 0); + if (fd == -1) + throw std::invalid_argument{fmt::format("Failed to create UDP socket for unbound: {}", strerror(errno))}; + if (0 != bind(fd, static_cast(addr), addr.sockaddr_len())) { + close(fd); + throw std::invalid_argument{fmt::format("Failed to bind UDP socket for unbound: {}", strerror(errno))}; + } + struct sockaddr_storage sas; + auto* sa = reinterpret_cast(&sas); + socklen_t sa_len; + if (0 != getsockname(fd, sa, &sa_len)) { + close(fd); + throw std::invalid_argument{fmt::format("Failed to query UDP port for unbound: {}", strerror(errno))}; + } + addr = SockAddr{*sa}; + close(fd); } m_LocalAddr = addr; - LogInfo(fmt::format("sening dns queries from {}:{}", host, addr.getPort())); + LogInfo(fmt::format("sending dns queries from {}:{}", host, addr.getPort())); // set up query bind port if needed SetOpt("outgoing-interface:", host); SetOpt("outgoing-range:", "1");