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.socketstd.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:
- literale IPv4 —
„127.0.0.1“wird als Adresse erkannt, nicht als Name abgefragt /etc/hosts— damit funktioniert„localhost“und jeder dort eingetragene Name- Nameserver aus
/etc/resolv.conf - 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.postgresundstd.db.mysqlzerlegen den Host selbst in vier Zahlen und kennen weder/etc/hostsnoch 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).
