std.net.dns

DNS (Domain Name System) übersetzt Hostnamen in IP-Adressen und umgekehrt. Die Unit implementiert einen vollständigen DNS-Resolver über UDP mit Unterstützung für alle gängigen Record-Typen: A, AAAA, MX, NS, CNAME, TXT, PTR, SOA, SRV, CAA, DNSKEY und DS. Auflösungen können gegen den System-Resolver, Google Public DNS (8.8.8.8) oder Cloudflare DNS (1.1.1.1) gerichtet werden.

Einsatzbereiche sind Domainvalidierung, Mail-Routing (MX-Lookup), Infrastruktur-Abfragen, DNSSEC-Analysen und alle Anwendungen, die Hostnamen selbst auflösen müssen ohne auf libc-Resolver zu setzen.

import std.net.dns;
import std.alloc;

// Der Aufrufer stellt den Ergebnispuffer: 32 Byte Kopf, danach der Datenbereich.
var res: int64 := alloc(512);
if (DNSResolve("example.com"c as int64, 11, 0x08080808, res)) {
    DNSPrintIP(DNSResultGetIPv4(res));
}

DNSResolve nimmt vier Argumente: Hostname als Adresse, dessen Länge, den DNS-Server als gepackte IPv4-Adresse (0 = Voreinstellung) und den Ergebnispuffer. Es gibt keine Fassung mit nur einem Argument.


Imports

  • std.net.socket
  • std.net.types

Konstanten

Name Typ Wert Sichtbarkeit
DNS_QR_QUERY int64 0 pub
DNS_QR_RESPONSE int64 1 pub
DNS_OPCODE_QUERY int64 0 pub
DNS_RD int64 1 pub
DNS_RA int64 1 pub
DNS_TYPE_A int64 1 pub
DNS_TYPE_AAAA int64 28 pub
DNS_TYPE_CNAME int64 5 pub
DNS_TYPE_MX int64 15 pub
DNS_TYPE_TXT int64 16 pub
DNS_TYPE_NS int64 2 pub
DNS_TYPE_SOA int64 6 pub
DNS_TYPE_PTR int64 12 pub
DNS_TYPE_SRV int64 33 pub
DNS_TYPE_CAA int64 257 pub
DNS_TYPE_DS int64 43 pub
DNS_TYPE_DNSKEY int64 48 pub
DNS_TYPE_ANY int64 255 pub
DNS_CLASS_IN int64 1 pub
DNS_RCODE_OK int64 0 pub
DNS_RCODE_FORMERR int64 1 pub
DNS_RCODE_SERVFAIL int64 2 pub
DNS_RCODE_NXDOMAIN int64 3 pub
DNS_RCODE_NOTIMP int64 4 pub
DNS_RCODE_REFUSED int64 5 pub
DNS_PORT int64 53 pub
DNS_TIMEOUT_SEK int64 2 pub
DNS_VERSUCHE int64 3 pub

Typen

DNSResult (struct)

Feld Typ
success bool
recordType int64
ttl int64
rcode int64
dataLen int64

Funktionen

Signatur Sichtbarkeit Beschreibung
DNSResolve(hostname: int64, hostnameLen: int64, dnsServerIP: int64, resultPtr: int64): bool pub IPv4-Adresse eines Hostnamens auflösen
DNSResolveEx(hostname: int64, hostnameLen: int64, dnsServerIP: int64, queryType: int64, resultPtr: int64): bool pub DNS-Abfrage für beliebigen Record-Typ
DNSResolveAAAA(hostname: int64, hostnameLen: int64, dnsServerIP: int64, resultPtr: int64): bool pub IPv6-Adresse eines Hostnamens auflösen
DNSResolveAAAAGoogle(hostname: int64, hostnameLen: int64, resultPtr: int64): bool pub AAAA-Abfrage über Google DNS
DNSResolveAAAACoudflare(hostname: int64, hostnameLen: int64, resultPtr: int64): bool pub AAAA-Abfrage über Cloudflare DNS
DNSResolveCNAME(hostname: int64, hostnameLen: int64, dnsServerIP: int64, resultPtr: int64): bool pub CNAME-Record eines Hostnamens auflösen
DNSResolveCNAMEGoogle(hostname: int64, hostnameLen: int64, resultPtr: int64): bool pub CNAME-Abfrage über Google DNS
DNSResolveCNAMECloudflare(hostname: int64, hostnameLen: int64, resultPtr: int64): bool pub CNAME-Abfrage über Cloudflare DNS
DNSResolveMX(hostname: int64, hostnameLen: int64, dnsServerIP: int64, resultPtr: int64): bool pub MX-Record einer Domain auflösen
DNSResolveMXGoogle(hostname: int64, hostnameLen: int64, resultPtr: int64): bool pub MX-Abfrage über Google DNS
DNSResolveMXCloudflare(hostname: int64, hostnameLen: int64, resultPtr: int64): bool pub MX-Abfrage über Cloudflare DNS
DNSResolveNS(hostname: int64, hostnameLen: int64, dnsServerIP: int64, resultPtr: int64): bool pub NS-Record einer Domain auflösen
DNSResolveNSGoogle(hostname: int64, hostnameLen: int64, resultPtr: int64): bool pub NS-Abfrage über Google DNS
DNSResolveNSCloudflare(hostname: int64, hostnameLen: int64, resultPtr: int64): bool pub NS-Abfrage über Cloudflare DNS
DNSResolveTXT(hostname: int64, hostnameLen: int64, dnsServerIP: int64, resultPtr: int64): bool pub TXT-Record einer Domain auflösen
DNSResolveTXTGoogle(hostname: int64, hostnameLen: int64, resultPtr: int64): bool pub TXT-Abfrage über Google DNS
DNSResolveTXTCloudflare(hostname: int64, hostnameLen: int64, resultPtr: int64): bool pub TXT-Abfrage über Cloudflare DNS
DNSResolveSOA(hostname: int64, hostnameLen: int64, dnsServerIP: int64, resultPtr: int64): bool pub SOA-Record einer Domain auflösen
DNSResolveSOAGoogle(hostname: int64, hostnameLen: int64, resultPtr: int64): bool pub SOA-Abfrage über Google DNS
DNSResolveSOACloudflare(hostname: int64, hostnameLen: int64, resultPtr: int64): bool pub SOA-Abfrage über Cloudflare DNS
DNSResolvePTR(ip: int64, dnsServerIP: int64, resultPtr: int64): bool pub Reverse-DNS-Lookup für IP-Adresse
DNSResolvePTRGoogle(ip: int64, resultPtr: int64): bool pub PTR-Abfrage über Google DNS
DNSResolveSRV(service: int64, serviceLen: int64, dnsServerIP: int64, resultPtr: int64): bool pub SRV-Record eines Dienstes auflösen
DNSResolveSRVGoogle(service: int64, serviceLen: int64, resultPtr: int64): bool pub SRV-Abfrage über Google DNS
DNSResolveSRVCloudflare(service: int64, serviceLen: int64, resultPtr: int64): bool pub SRV-Abfrage über Cloudflare DNS
DNSResolveCAA(hostname: int64, hostnameLen: int64, dnsServerIP: int64, resultPtr: int64): bool pub CAA-Record einer Domain auflösen
DNSResolveCAAGoogle(hostname: int64, hostnameLen: int64, resultPtr: int64): bool pub CAA-Abfrage über Google DNS
DNSResolveDS(hostname: int64, hostnameLen: int64, dnsServerIP: int64, resultPtr: int64): bool pub DNSSEC DS-Record auflösen
DNSResolveDSGoogle(hostname: int64, hostnameLen: int64, resultPtr: int64): bool pub DS-Abfrage über Google DNS
DNSResolveDNSKEY(hostname: int64, hostnameLen: int64, dnsServerIP: int64, resultPtr: int64): bool pub DNSKEY-Record einer Domain auflösen
DNSResolveDNSKEYGoogle(hostname: int64, hostnameLen: int64, resultPtr: int64): bool pub DNSKEY-Abfrage über Google DNS
DNSResolveGoogle(hostname: int64, hostnameLen: int64, resultPtr: int64): bool pub A-Record über Google Public DNS auflösen
DNSResolveCloudflare(hostname: int64, hostnameLen: int64, resultPtr: int64): bool pub A-Record über Cloudflare DNS auflösen
GetHostByName(hostname: pchar): int64 pub IP-Adresse als int64 zurückgeben; Auflösungsreihenfolge siehe unten
ResolveHost(hostname: int64): IPAddr pub Hostname zu IPAddr-Struktur auflösen
DNSPrintIP(ip: int64) pub IPv4-Adresse als Text ausgeben
DNSPrintIPV6(data: int64) pub IPv6-Adresse als Text ausgeben
DNSResultGetIPv4(resultPtr: int64): int64 pub IPv4-Adresse aus DNS-Ergebnis lesen
DNSResultGetTTL(resultPtr: int64): int64 pub TTL-Wert aus DNS-Ergebnis lesen
DNSResultGetType(resultPtr: int64): int64 pub Record-Typ aus DNS-Ergebnis lesen
DNSResultIsSuccess(resultPtr: int64): bool pub Erfolg einer DNS-Abfrage prüfen

Wie GetHostByName auflöst

Seit 1.0.20A wird nicht mehr jeder Name über das Netz abgefragt (#1330). Die Reihenfolge:

  1. literale IPv4„127.0.0.1“ wird als Adresse erkannt, nicht als Name abgefragt
  2. /etc/hosts — damit funktioniert „localhost“ und jeder dort eingetragene Name
  3. Nameserver aus /etc/resolv.conf
  4. Google DNS als Rückfall

import std.net.dns;
fn Zeige(name: pchar): void {
    var ip: int64 := GetHostByName(name);
    PrintLn("  ", name, " -> ", IntToStr((ip >> 24) & 255), ".", IntToStr((ip >> 16) & 255), ".",
            IntToStr((ip >> 8) & 255), ".", IntToStr(ip & 255));
}
fn main(): int64 {
    Zeige("127.0.0.1");
    Zeige("localhost");
    Zeige("example.com");
    return 0;
}

127.0.0.1 -> 127.0.0.1
  localhost -> 127.0.0.1
  example.com -> 172.66.147.243

Für alle Units mit einem host-Parameter heißt das: localhost und 127.0.0.1 funktionieren jetzt — betrifft unter anderem std.db.redis, std.net.imap, smtp, mongo, quic, telnet, ntp, https, rest und sip. Frühere Fassungen dieser Seiten schränkten auf „nur öffentlich auflösbare Namen„ ein; das gilt nicht mehr.

Zeitgrenze und Wiederholungen

Eine Anfrage wartet zwei Sekunden auf Antwort und wird bis zu dreimal gestellt; danach schlägt die Auflösung fehl. Die Werte stehen als DNS_TIMEOUT_SEK und DNS_VERSUCHE in der Unit.

Bis lyxc 1.1.3B las DNSResolve die Antwort ohne jede Zeitgrenze: blieb das Paket aus — verworfene Anfrage, Paketverlust, unerreichbarer Server —, kehrte GetHostByName nie zurück (#1641). Bei UDP ist genau das der Normalfall, weil es keine Verbindung gibt, die abbricht. Gesetzt wird die Grenze über UDPSocketSetRecvTimeout aus std.net.socket.

 
Zwei Units nehmen weiterhin nur literale IPv4: std.db.postgres und std.db.mysql zerlegen den Host selbst in vier Zahlen und kennen weder /etc/hosts noch DNS. Dort ist „localhost“ unbrauchbar.

Auflösung über den System-Resolver

Signatur Beschreibung
DNSResolveSystem(hostname: int64, hostnameLen: int64, resultPtr: int64): bool fragt den in /etc/resolv.conf eingetragenen Nameserver
DNSResolveSystemEx(hostname: int64, hostnameLen: int64, queryType: int64, resultPtr: int64): bool dasselbe mit wählbarem Record-Typ

Damit muss der Nameserver nicht im Programm stehen — es gilt, was das System vorgibt.

<WRAP alert> Ohne lesbare /etc/resolv.conf wird still 8.8.8.8 verwendet. Der Quelltext fällt auf Googles Nameserver zurück, wenn das Parsen kein Ergebnis liefert:

var ns: int64 := dns_parse_resolv_conf();
if (ns == 0) {
    ns := IPPack(8, 8, 8, 8);
}

Es gibt weder Meldung noch Rückgabewert, an dem sich das erkennen ließe. In abgeschotteten Umgebungen — Container ohne /etc/resolv.conf, chroot, seccomp-beschränkte Prozesse — gehen die Anfragen dann an einen fremden Anbieter, statt zu scheitern. Wer das ausschließen muss, verwendet DNSResolve mit ausdrücklich angegebenem Server. </WRAP>


Zwischenspeicher

Signatur Beschreibung
DNSResolveWithCache(hostname: int64, hostnameLen: int64, dnsServerIP: int64, queryType: int64, resultPtr: int64): bool wie DNSResolveEx, beantwortet Wiederholungen aber aus dem Zwischenspeicher
DNSCacheClear() Zwischenspeicher leeren
Kenngröße Wert
Plätze 16
Größe je Eintrag 224 Byte
Vorgabe-TTL 300 Sekunden

Die 16 Plätze sind fest vergeben. Wer mehr verschiedene Namen abfragt, verdrängt ältere Einträge — für eine Handvoll wiederkehrender Ziele ist der Zwischenspeicher gedacht, nicht als allgemeiner Resolver-Cache.


DNS over HTTPS

Signatur Beschreibung
DNSResolveDoH(hostname: int64, hostnameLen: int64, resultPtr: int64): bool Auflösung über HTTPS statt über UDP/53
DNSResolveDoHEx(hostname: int64, hostnameLen: int64, queryType: int64, resultPtr: int64): bool dasselbe mit wählbarem Record-Typ

DoH verpackt die Anfrage in HTTPS. Das verbirgt sie vor Beobachtern auf dem Weg und kommt durch Netze, die UDP/53 sperren — der Anbieter des DoH-Dienstes sieht die Anfragen dafür im Klartext.


IPv6

Signatur Beschreibung
GetHostByNameV6(hostname: int64, outHi: int64, outLo: int64): bool Namen zu einer AAAA-Adresse auflösen; schreibt zwei int64-Hälften
DNSResultGetIPv6Hi(resultPtr: int64): int64 obere 64 Bit der IPv6-Adresse aus dem Ergebnis
DNSResultGetIPv6Lo(resultPtr: int64): int64 untere 64 Bit
DNSResolvePtr6(ip6: int64, dnsServerIP: int64, resultPtr: int64): bool Rückwärtsauflösung einer IPv6-Adresse
DNSResolvePtr6Google(ip6: int64, resultPtr: int64): bool dasselbe über Googles Nameserver
DNSResolvePtr6Cloudflare(ip6: int64, resultPtr: int64): bool dasselbe über Cloudflare
TCPConnectHostIPv6(hostname: int64, port: int64): TCPConn AAAA-Auflösung und TCP-Verbindung in einem Schritt

outHi und outLo sind Zeiger auf int64 — die Funktion schreibt dorthin mit poke64. Die 16 Bytes im Ergebnis liegen ab Versatz 40 in Netzwerk-Byte-Order.

TCPConnectHostIPv6 ist der kürzeste Weg zu einer IPv6-Verbindung: es nimmt einen nullterminierten Namen und einen Port in Host-Byte-Order und liefert eine fertige TCPConn.

Letzte Aktualisierung: 2026-08-19 — Zeitgrenze und Wiederholungen der Auflösung ergänzt (#1641).

Vorherige Aktualisierung: 2026-08-18 — Kurzbeispiel auf die tatsächliche Signatur berichtigt; die Unit ist seit #1608 wieder übersetzbar (pchar/int64 waren nur halb umgestellt, 53 abhängige Dateien betroffen).