DNS Resolver#

The Dns::Resolver class is a DNS resolver over UDP. It sends standard DNS queries to a specific server and returns parsed results. Each instance is connected to one server; static lookup* methods iterate over the system-configured servers from /etc/resolv.conf.


Construction#

// Connect to a specific server (IP or hostname), default port 53
Dns::Resolver resolver("8.8.8.8");

// Custom port and reactor
Dns::Resolver resolver("8.8.8.8", 5353, &myReactor);

// Default constructor — server must be set via connect() before use
Dns::Resolver resolver;

Dns::Resolver is neither copyable nor movable.


Host resolution (A / AAAA)#

Instance methods — query a specific server#

Dns::Resolver resolver("8.8.8.8");

// First IPv4 address
IpAddress ip = resolver.resolveAddress("example.com", AF_INET);

// First IPv6 address
IpAddress ip6 = resolver.resolveAddress("example.com", AF_INET6);

// First address, any family
IpAddress ip = resolver.resolveAddress("example.com");

// All addresses for a given family
IpAddressList v4 = resolver.resolveAllAddress("example.com", AF_INET);
IpAddressList v6 = resolver.resolveAllAddress("example.com", AF_INET6);

// All addresses, both families
IpAddressList all = resolver.resolveAllAddress("example.com");

// Custom timeout
IpAddress ip = resolver.resolveAddress("example.com", AF_INET,
                                        std::chrono::milliseconds(2000));

Static methods — use system name servers#

// First address
IpAddress ip = Dns::Resolver::lookupAddress("example.com", AF_INET);
IpAddress ip = Dns::Resolver::lookupAddress("example.com");

// All addresses
IpAddressList all = Dns::Resolver::lookupAllAddress("example.com", AF_INET);
IpAddressList all = Dns::Resolver::lookupAllAddress("example.com");

Static lookup* methods try each system name server in order and return on the first non-empty result.


Reverse DNS (PTR)#

Instance methods#

// First hostname for an IP
std::string name = resolver.resolveName("8.8.8.8");

// All hostnames
AliasList aliases = resolver.resolveAllName("8.8.8.8");

// Custom timeout
std::string name = resolver.resolveName("8.8.8.8", std::chrono::milliseconds(2000));

Static methods#

std::string name   = Dns::Resolver::lookupName("8.8.8.8");
AliasList aliases  = Dns::Resolver::lookupAllName("8.8.8.8");

Name servers (NS)#

Instance methods#

std::string        ns  = resolver.resolveNameServer("example.com");
ServerList         nsl = resolver.resolveAllNameServer("example.com");

Static methods#

std::string        ns  = Dns::Resolver::lookupNameServer("example.com");
ServerList         nsl = Dns::Resolver::lookupAllNameServer("example.com");

Start of Authority (SOA)#

Instance method#

std::string soa = resolver.resolveAuthority("example.com");

Static method#

std::string soa = Dns::Resolver::lookupAuthority("example.com");

Mail exchangers (MX)#

Instance methods#

std::string      mx  = resolver.resolveMailExchanger("example.com");
ExchangerList    mxl = resolver.resolveAllMailExchanger("example.com");

Static methods#

std::string      mx  = Dns::Resolver::lookupMailExchanger("example.com");
ExchangerList    mxl = Dns::Resolver::lookupAllMailExchanger("example.com");

System name servers#

IpAddressList servers = Dns::Resolver::nameServers();
for (const auto& s : servers)
{
    std::cout << s.toString() << "\n";
}

Reads /etc/resolv.conf via res_ninit.


Service name resolution#

uint16_t port = Dns::Resolver::resolveService("http");   // 80
uint16_t port = Dns::Resolver::resolveService("https");  // 443
uint16_t port = Dns::Resolver::resolveService("ssh");    // 22

Queries /etc/services via getservbyname_r. Returns 0 if not found.


Debug callbacks#

In DEBUG builds, onSuccess and onFailure are pre-wired to print dig-style output. In release builds they are nullptr. They can be overridden on any instance:

resolver.onSuccess = [](const DnsPacket& p) {
    for (const auto& a : p.answers)
        std::cout << a.host << " -> " << a.addr.toString() << "\n";
};

resolver.onFailure = [](const DnsPacket& p) {
    std::cerr << "Query failed: " << lastError.message() << "\n";
};

Error handling#

Instance methods return a wildcard IpAddress, empty string, or empty list on failure. Check lastError:

CodeCause
Errc::TimedOutNo response within timeout
Errc::InvalidParamEmpty host, bad server address, or serialization error
Errc::MessageTooLongResponse truncated (TC bit set)
Errc::OperationFailedDuplicate pending request id

DNS-level errors (NXDOMAIN, SERVFAIL, REFUSED…) are also mapped to lastError via DnsMessage::decodeError.


Protocol details#

  • Transport: UDP, default port 53, max message size 8192 bytes
  • One socket per instance, connected to the target server
  • Queries carry a random 16-bit transaction ID matched against responses
  • Recursion desired (RD) flag set on all queries

Summary#

Method familyInstanceStatic (lookup*)
resolveAddress / lookupAddress
resolveAllAddress / lookupAllAddress
resolveName / lookupName
resolveAllName / lookupAllName
resolveNameServer / lookupNameServer
resolveAllNameServer / lookupAllNameServer
resolveAuthority / lookupAuthority
resolveMailExchanger / lookupMailExchanger
resolveAllMailExchanger / lookupAllMailExchanger
nameServers✅ (static)
resolveService✅ (static)