feat(fls): DNS records from /dns/hosts, as Java's server answers them
Java's DNS server reads its records from the text file /dns/hosts on every query. dnsHosts.ts ports that reading (DNSServer.leseRecordListe, ResourceRecord, Dateisystem.holeDatei) and keeps in the model the records Java answers: type exactly A, MX or NS, and a name Java accepted. The file stays in the file system as it is. Both oracles read 76 hand-picked hosts files (dns-hosts.cases.txt): the Java oracle through DNSServer.holeResourceRecords (DnsHostsCases), the Swift oracle through TopologyDNSHostsFileCodec (--dns-hosts). The Java view matches Java on every case; the model matches Swift except for 33 named cases in twelve reasons: Java splits at single spaces and LF only, has no comments or "IN", turns a TTL that is no int into 3600, keeps duplicates, and empties names with a leading digit. The Swift dump now carries each server's records; the corpus comparison covers them on 16 files. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+4
-2
@@ -12,7 +12,7 @@ Swift-Pfade relativ zu `filius-ipad/ios/FiliusPad/TopologyEditor/` (Stand
|
||||
| `src/model/node.ts` | `Model/TopologyNode.swift` | übertragen; Standard-Ports und -Namen wie Java; ein gegebener Name bleibt, auch leer (Java lässt Router unbenannt) |
|
||||
| `src/model/link.ts`, `src/model/graph.ts` | `Model/TopologyLink.swift`, `Model/TopologyGraph.swift` | übertragen, bisher nur die Daten (Abfragen folgen mit dem Editor) |
|
||||
| `src/model/documentation.ts` | `Model/TopologyDocumentation.swift` | übertragen; FNV-Kennung mit BigInt, gegen die IDs aus dem Swift-Import geprüft |
|
||||
| `src/runtime/config.ts` | `State/TopologyEditorState.swift` (Laufzeit-Konfigurationen, WLAN eines Rechners, DHCP, Portweiterleitung, Remote Link ohne LAN-Transport, Programme und ihre Konfiguration, Firewall); dazu Echo-Server- und Client-Konfiguration, die Swift nicht speichert | übertragen; Java-Beschriftungen der Oberfläche weggelassen |
|
||||
| `src/runtime/config.ts` | `State/TopologyEditorState.swift` (Laufzeit-Konfigurationen, WLAN eines Rechners, DHCP, Portweiterleitung, Remote Link ohne LAN-Transport, Programme und ihre Konfiguration, Firewall, DNS-Einträge aus `State/TopologyDNSResolver.swift`); dazu Echo-Server- und Client-Konfiguration, die Swift nicht speichert | übertragen; Java-Beschriftungen der Oberfläche weggelassen |
|
||||
| `src/runtime/engine.ts` | `State/TopologyNetworkRuntimeEngine.swift` Z. ~313–3585, ~4753–4850 | übertragen: Warteschlange, Uhr, Ethernet, Switch, ARP, IPv4, ICMP, Routing, Firewall. Klasse statt Werttyp. Noch nicht übertragen (wirft `NotPortedError`): Gateway-NAT, UDP, TCP, DHCP, DNS, RIP, Remote Link, WLAN |
|
||||
| `src/runtime/ipv4.ts` | Engine `parseIPv4`/`sameSubnet` | übertragen |
|
||||
| `src/runtime/packets.ts` | Engine, Paketmodelle | übertragen; `Data` → `Uint8Array` |
|
||||
@@ -37,14 +37,16 @@ Swift-Pfade relativ zu `filius-ipad/ios/FiliusPad/TopologyEditor/` (Stand
|
||||
| `src/zip.ts` | `Persistence/TopologyFLSArchive.swift` (Fehler, Grenzen, Pfadregeln, ZIP-Leser/-Schreiber, CRC-32) | übertragen; DEFLATE über `fflate`, mit Apples Abschneide-Verhalten nachgebildet; Pfadfaltung (NFC, Breite, volles Case-Folding) an 41 Paaren gegen das Swift-Orakel gemessen |
|
||||
| `src/archive.ts` | ebenda, Archiv-Teil von Import und Export | übertragen, ohne die XML-Ebene |
|
||||
| `src/javabeans.ts`, `src/javaDefaults.json` | — | neu: XMLEncoder-Leser nach den Regeln von `java.beans.XMLDecoder` (Swift liest elementweise und verliert geteilte Werte); Getter-Standardwerte und statische Konstanten mit `tools/java-oracle` gemessen |
|
||||
| `src/importProject.ts` | `Persistence/TopologyProjectStore.swift` (Knoten, Ports, Kabel, IP-Konfiguration, Switch/WLAN, Routen, RIP, Firewall, DHCP, Portweiterleitung, Modem, Dateisysteme, Programme, Doku-Elemente des Imports) | übertragen, Eingabe ist Javas Sicht: Name und Port-Anzahl wie Java, abgelehnte Adresse → Swift-Standard, Router-Standardgateway wie Java (Swift verliert es), jede Router-Firewall eingetragen, Konfigurationstexte wie in Swift getrimmt (`swiftTrim`), Rechner ohne Dateisystem leer wie in Java (Swift: Demo-Dateien), alle Programme bleiben (Swift verwirft sechs), Webserver-Dateien bleiben in `/webserver` (Swift: `/www`), keine versteckten Zustandsdateien im Dateisystem; gegen Swifts importiertes Modell auf 13 Dateien geprüft |
|
||||
| `src/importProject.ts` | `Persistence/TopologyProjectStore.swift` (Knoten, Ports, Kabel, IP-Konfiguration, Switch/WLAN, Routen, RIP, Firewall, DHCP, Portweiterleitung, Modem, Dateisysteme, Programme, Doku-Elemente des Imports) | übertragen, Eingabe ist Javas Sicht: Name und Port-Anzahl wie Java, abgelehnte Adresse → Swift-Standard, Router-Standardgateway wie Java (Swift verliert es), jede Router-Firewall eingetragen, Konfigurationstexte wie in Swift getrimmt (`swiftTrim`), Rechner ohne Dateisystem leer wie in Java (Swift: Demo-Dateien), alle Programme bleiben (Swift verwirft sechs), Webserver-Dateien bleiben in `/webserver` (Swift: `/www`), keine versteckten Zustandsdateien im Dateisystem, DNS-Einträge so, wie Javas Server sie aus `/dns/hosts` beantwortet; gegen Swifts importiertes Modell auf 13 Dateien geprüft |
|
||||
| `test/importProject.test.ts` | — | neu: Swifts importiertes Modell (13 Dateien, zwei begründete Abweichungen), Vollständigkeit aller 23, Pings im Kern (über einen Router; über drei Router mit manuellen Routen und Router-Gateways) |
|
||||
| `src/systemSoftware.ts` | Java `SwitchFirmware`, `Betriebssystem`, `VermittlungsrechnerBetriebssystem`, `GatewayFirmware`, `Weiterleitungstabelle`, `Firewall`, `FirewallRule`, `DHCPServer`, `ModemFirmware`, `Dateisystem`, `Datei` | neu nach Java: SSID, Lernzeit, RIP, manuelle Routen, Router-Firewall (an allen Stellen, an denen die Datei sie erreicht), DHCP, statische NAT, Modem, Dateisystem und installierte Programme von Rechner und Notebook; `Character.isWhitespace` am JDK gemessen; gegen Java geprüft |
|
||||
| `src/javaIp.ts` | Java `IP.inetAton`/`ipCheck` | neu nach Java; an 46 Fällen mit Java gemessen |
|
||||
| `src/dnsHosts.ts` | Java `DNSServer.leseRecordListe`, `ResourceRecord`, `Dateisystem.holeDatei`; Swift `State/TopologyDNSResolver.swift` (`TopologyDNSHostsFileCodec`) als Vergleich | neu nach Java: Felder nur an einzelnen Leerzeichen, keine Kommentare, ungültige TTL → 3600, Doppelte bleiben; ins Modell kommt nur, was Java beantwortet (Typ genau A/MX/NS, Name nicht leer); an 76 Fällen mit Java und Swift gemessen |
|
||||
| `src/topology.ts` | Java `SzenarioVerwaltung.netzwerkLaden`, Konstruktoren und Setter der Geräte; Swift `Persistence/TopologyProjectStore.swift` (Parser) als Vergleich | neu nach Java statt Übertragung: Geräteart aus der Klasse statt aus der Beschriftung, Geräte ohne Koordinaten bei 0,0 statt verworfen, Werte durch Javas Setter |
|
||||
| `test/javabeans.test.ts` | — | neu: je XMLDecoder-Regel ein Test; alle 23 Korpus-Dateien, Klasse und Position jedes Geräts wie Java |
|
||||
| `test/topology.test.ts` | — | neu: alle 23 Korpus-Dateien Feld für Feld wie Java (Geräte, Schnittstellen, Kabel, Doku-Elemente), dazu die Regeln, die der Korpus nicht berührt |
|
||||
| `test/javaIp.test.ts`, `test/ip-check.*` | — | neu: `IP.ipCheck`-Fälle, Ergebnis aus Java |
|
||||
| `test/dnsHosts.test.ts`, `test/dns-hosts.*` | — | neu: `/dns/hosts`-Fälle, Javas Sicht wie Java, das Modell wie Swift bis auf 33 benannte Fälle in zwölf Gründen |
|
||||
| `test/zip.test.ts` | `TopologyProjectPersistenceTests.swift` (Archiv-Ablehnungstests, `makeMinimalZIP`, `makePayloadZIP`) | übertragen, ergänzt um DEFLATE-Grenzfälle |
|
||||
| `test/corpus.test.ts` | — | neu: 23 Korpus-Dateien, gegengeprüft mit `fflate.unzipSync` |
|
||||
| `test/pathFolding.test.ts`, `test/path-folding.*.json` | — | neu: welche Pfade dieselbe Datei meinen, Ergebnis aus dem Swift-Kern |
|
||||
|
||||
@@ -266,6 +266,26 @@
|
||||
"system" : {
|
||||
"dnsServer" : {
|
||||
"forwardingServerIPAddress" : null,
|
||||
"records" : [
|
||||
[
|
||||
"filius.de",
|
||||
"MX",
|
||||
3600,
|
||||
"smtp.filius.de."
|
||||
],
|
||||
[
|
||||
"dns-root",
|
||||
"A",
|
||||
3600,
|
||||
"141.99.5.13"
|
||||
],
|
||||
[
|
||||
".",
|
||||
"NS",
|
||||
3600,
|
||||
"dns-root."
|
||||
]
|
||||
],
|
||||
"recursiveResolutionEnabled" : true
|
||||
},
|
||||
"installedPrograms" : [
|
||||
@@ -464,6 +484,20 @@
|
||||
"system" : {
|
||||
"dnsServer" : {
|
||||
"forwardingServerIPAddress" : null,
|
||||
"records" : [
|
||||
[
|
||||
"dns.de",
|
||||
"A",
|
||||
3600,
|
||||
"141.99.5.14"
|
||||
],
|
||||
[
|
||||
"de",
|
||||
"NS",
|
||||
3600,
|
||||
"dns.de."
|
||||
]
|
||||
],
|
||||
"recursiveResolutionEnabled" : false
|
||||
},
|
||||
"installedPrograms" : [
|
||||
@@ -678,6 +712,20 @@
|
||||
"system" : {
|
||||
"dnsServer" : {
|
||||
"forwardingServerIPAddress" : null,
|
||||
"records" : [
|
||||
[
|
||||
"dns.filius.de",
|
||||
"A",
|
||||
3600,
|
||||
"141.99.5.15"
|
||||
],
|
||||
[
|
||||
"filius.de",
|
||||
"NS",
|
||||
3600,
|
||||
"dns.filius.de."
|
||||
]
|
||||
],
|
||||
"recursiveResolutionEnabled" : false
|
||||
},
|
||||
"installedPrograms" : [
|
||||
@@ -727,6 +775,14 @@
|
||||
"system" : {
|
||||
"dnsServer" : {
|
||||
"forwardingServerIPAddress" : null,
|
||||
"records" : [
|
||||
[
|
||||
"www.filius.de",
|
||||
"A",
|
||||
3600,
|
||||
"141.99.5.10"
|
||||
]
|
||||
],
|
||||
"recursiveResolutionEnabled" : false
|
||||
},
|
||||
"installedPrograms" : [
|
||||
@@ -1219,6 +1275,14 @@
|
||||
"system" : {
|
||||
"dnsServer" : {
|
||||
"forwardingServerIPAddress" : null,
|
||||
"records" : [
|
||||
[
|
||||
"mywebserver.de",
|
||||
"A",
|
||||
3600,
|
||||
"160.10.20.10"
|
||||
]
|
||||
],
|
||||
"recursiveResolutionEnabled" : false
|
||||
},
|
||||
"installedPrograms" : [
|
||||
@@ -1886,6 +1950,14 @@
|
||||
"system" : {
|
||||
"dnsServer" : {
|
||||
"forwardingServerIPAddress" : null,
|
||||
"records" : [
|
||||
[
|
||||
"www.filius.de",
|
||||
"A",
|
||||
3600,
|
||||
"141.99.2.10"
|
||||
]
|
||||
],
|
||||
"recursiveResolutionEnabled" : false
|
||||
},
|
||||
"installedPrograms" : [
|
||||
@@ -3480,6 +3552,26 @@
|
||||
"system" : {
|
||||
"dnsServer" : {
|
||||
"forwardingServerIPAddress" : null,
|
||||
"records" : [
|
||||
[
|
||||
"filius.de",
|
||||
"MX",
|
||||
3600,
|
||||
"smtp.filius.de."
|
||||
],
|
||||
[
|
||||
"dns-root",
|
||||
"A",
|
||||
3600,
|
||||
"141.99.5.13"
|
||||
],
|
||||
[
|
||||
".",
|
||||
"NS",
|
||||
3600,
|
||||
"dns-root."
|
||||
]
|
||||
],
|
||||
"recursiveResolutionEnabled" : true
|
||||
},
|
||||
"installedPrograms" : [
|
||||
@@ -3678,6 +3770,20 @@
|
||||
"system" : {
|
||||
"dnsServer" : {
|
||||
"forwardingServerIPAddress" : null,
|
||||
"records" : [
|
||||
[
|
||||
"dns.de",
|
||||
"A",
|
||||
3600,
|
||||
"141.99.5.14"
|
||||
],
|
||||
[
|
||||
"de",
|
||||
"NS",
|
||||
3600,
|
||||
"dns.de."
|
||||
]
|
||||
],
|
||||
"recursiveResolutionEnabled" : false
|
||||
},
|
||||
"installedPrograms" : [
|
||||
@@ -3892,6 +3998,20 @@
|
||||
"system" : {
|
||||
"dnsServer" : {
|
||||
"forwardingServerIPAddress" : null,
|
||||
"records" : [
|
||||
[
|
||||
"dns.filius.de",
|
||||
"A",
|
||||
3600,
|
||||
"141.99.5.15"
|
||||
],
|
||||
[
|
||||
"filius.de",
|
||||
"NS",
|
||||
3600,
|
||||
"dns.filius.de."
|
||||
]
|
||||
],
|
||||
"recursiveResolutionEnabled" : false
|
||||
},
|
||||
"installedPrograms" : [
|
||||
@@ -3941,6 +4061,14 @@
|
||||
"system" : {
|
||||
"dnsServer" : {
|
||||
"forwardingServerIPAddress" : null,
|
||||
"records" : [
|
||||
[
|
||||
"www.filius.de",
|
||||
"A",
|
||||
3600,
|
||||
"141.99.5.10"
|
||||
]
|
||||
],
|
||||
"recursiveResolutionEnabled" : false
|
||||
},
|
||||
"installedPrograms" : [
|
||||
@@ -4475,6 +4603,20 @@
|
||||
},
|
||||
"dnsServer" : {
|
||||
"forwardingServerIPAddress" : null,
|
||||
"records" : [
|
||||
[
|
||||
"www.mein-server.de",
|
||||
"A",
|
||||
3600,
|
||||
"192.168.0.100"
|
||||
],
|
||||
[
|
||||
"xy",
|
||||
"A",
|
||||
3600,
|
||||
"192.168.0.100"
|
||||
]
|
||||
],
|
||||
"recursiveResolutionEnabled" : false
|
||||
},
|
||||
"installedPrograms" : [
|
||||
@@ -5868,6 +6010,38 @@
|
||||
"system" : {
|
||||
"dnsServer" : {
|
||||
"forwardingServerIPAddress" : null,
|
||||
"records" : [
|
||||
[
|
||||
"www.filius.de",
|
||||
"A",
|
||||
3600,
|
||||
"141.99.50.231"
|
||||
],
|
||||
[
|
||||
"mail-filius.de",
|
||||
"A",
|
||||
3600,
|
||||
"141.99.50.232"
|
||||
],
|
||||
[
|
||||
"mail-senior.de",
|
||||
"A",
|
||||
3600,
|
||||
"141.99.50.233"
|
||||
],
|
||||
[
|
||||
"filius.de",
|
||||
"MX",
|
||||
3600,
|
||||
"mail-filius.de."
|
||||
],
|
||||
[
|
||||
"senior.de",
|
||||
"MX",
|
||||
3600,
|
||||
"mail-senior.de."
|
||||
]
|
||||
],
|
||||
"recursiveResolutionEnabled" : false
|
||||
},
|
||||
"installedPrograms" : [
|
||||
@@ -6958,6 +7132,44 @@
|
||||
"system" : {
|
||||
"dnsServer" : {
|
||||
"forwardingServerIPAddress" : null,
|
||||
"records" : [
|
||||
[
|
||||
"webserver.com",
|
||||
"A",
|
||||
3600,
|
||||
"120.130.140.80"
|
||||
],
|
||||
[
|
||||
"gmx.com",
|
||||
"MX",
|
||||
3600,
|
||||
"mail.gmx.com."
|
||||
],
|
||||
[
|
||||
"mail.gmx.com",
|
||||
"A",
|
||||
3600,
|
||||
"130.100.200.25"
|
||||
],
|
||||
[
|
||||
"mail.webmail.com",
|
||||
"A",
|
||||
3600,
|
||||
"140.100.200.25"
|
||||
],
|
||||
[
|
||||
"webmail.com",
|
||||
"MX",
|
||||
3600,
|
||||
"mail.webmail.com."
|
||||
],
|
||||
[
|
||||
"myschool.org",
|
||||
"A",
|
||||
3600,
|
||||
"42.0.0.10"
|
||||
]
|
||||
],
|
||||
"recursiveResolutionEnabled" : false
|
||||
},
|
||||
"installedPrograms" : [
|
||||
@@ -7198,6 +7410,14 @@
|
||||
},
|
||||
"dnsServer" : {
|
||||
"forwardingServerIPAddress" : null,
|
||||
"records" : [
|
||||
[
|
||||
"meine-schule.de",
|
||||
"A",
|
||||
3600,
|
||||
"10.0.0.1"
|
||||
]
|
||||
],
|
||||
"recursiveResolutionEnabled" : false
|
||||
},
|
||||
"installedPrograms" : [
|
||||
@@ -8687,6 +8907,44 @@
|
||||
"system" : {
|
||||
"dnsServer" : {
|
||||
"forwardingServerIPAddress" : null,
|
||||
"records" : [
|
||||
[
|
||||
"webserver.de",
|
||||
"A",
|
||||
3600,
|
||||
"120.130.140.80"
|
||||
],
|
||||
[
|
||||
"gmx.de",
|
||||
"MX",
|
||||
3600,
|
||||
"mail.gmx.de."
|
||||
],
|
||||
[
|
||||
"mail.gmx.de",
|
||||
"A",
|
||||
3600,
|
||||
"130.100.200.25"
|
||||
],
|
||||
[
|
||||
"mail.webmail.de",
|
||||
"A",
|
||||
3600,
|
||||
"140.100.200.25"
|
||||
],
|
||||
[
|
||||
"webmail.de",
|
||||
"MX",
|
||||
3600,
|
||||
"mail.webmail.de."
|
||||
],
|
||||
[
|
||||
"meine-schule.de",
|
||||
"A",
|
||||
3600,
|
||||
"42.0.0.10"
|
||||
]
|
||||
],
|
||||
"recursiveResolutionEnabled" : false
|
||||
},
|
||||
"installedPrograms" : [
|
||||
@@ -8927,6 +9185,14 @@
|
||||
},
|
||||
"dnsServer" : {
|
||||
"forwardingServerIPAddress" : null,
|
||||
"records" : [
|
||||
[
|
||||
"meine-schule.de",
|
||||
"A",
|
||||
3600,
|
||||
"10.0.0.1"
|
||||
]
|
||||
],
|
||||
"recursiveResolutionEnabled" : false
|
||||
},
|
||||
"installedPrograms" : [
|
||||
@@ -10361,6 +10627,14 @@
|
||||
"system" : {
|
||||
"dnsServer" : {
|
||||
"forwardingServerIPAddress" : null,
|
||||
"records" : [
|
||||
[
|
||||
"www.filius.de",
|
||||
"A",
|
||||
3600,
|
||||
"141.99.5.10"
|
||||
]
|
||||
],
|
||||
"recursiveResolutionEnabled" : false
|
||||
},
|
||||
"installedPrograms" : [
|
||||
@@ -11142,6 +11416,32 @@
|
||||
"system" : {
|
||||
"dnsServer" : {
|
||||
"forwardingServerIPAddress" : null,
|
||||
"records" : [
|
||||
[
|
||||
"mail-senior.de",
|
||||
"A",
|
||||
3600,
|
||||
"141.99.50.233"
|
||||
],
|
||||
[
|
||||
"mail-filius.de",
|
||||
"A",
|
||||
3600,
|
||||
"141.99.50.232"
|
||||
],
|
||||
[
|
||||
"filius.de",
|
||||
"MX",
|
||||
3600,
|
||||
"mail-filius.de."
|
||||
],
|
||||
[
|
||||
"senior.de",
|
||||
"MX",
|
||||
3600,
|
||||
"mail-senior.de."
|
||||
]
|
||||
],
|
||||
"recursiveResolutionEnabled" : false
|
||||
},
|
||||
"installedPrograms" : [
|
||||
@@ -11409,6 +11709,38 @@
|
||||
"system" : {
|
||||
"dnsServer" : {
|
||||
"forwardingServerIPAddress" : null,
|
||||
"records" : [
|
||||
[
|
||||
"www.filius.de",
|
||||
"A",
|
||||
3600,
|
||||
"141.99.50.231"
|
||||
],
|
||||
[
|
||||
"filius.de",
|
||||
"MX",
|
||||
3600,
|
||||
"mail-filius.de."
|
||||
],
|
||||
[
|
||||
"senior.de",
|
||||
"MX",
|
||||
3600,
|
||||
"mail-senior.de."
|
||||
],
|
||||
[
|
||||
"mail-filius.de",
|
||||
"A",
|
||||
3600,
|
||||
"141.99.50.184"
|
||||
],
|
||||
[
|
||||
"mail-senior.de",
|
||||
"A",
|
||||
3600,
|
||||
"141.99.50.184"
|
||||
]
|
||||
],
|
||||
"recursiveResolutionEnabled" : false
|
||||
},
|
||||
"installedPrograms" : [
|
||||
@@ -12923,6 +13255,20 @@
|
||||
"system" : {
|
||||
"dnsServer" : {
|
||||
"forwardingServerIPAddress" : null,
|
||||
"records" : [
|
||||
[
|
||||
"www.filius.de",
|
||||
"A",
|
||||
3600,
|
||||
"141.99.5.10"
|
||||
],
|
||||
[
|
||||
"www.jupiter.de",
|
||||
"A",
|
||||
3600,
|
||||
"141.99.4.10"
|
||||
]
|
||||
],
|
||||
"recursiveResolutionEnabled" : false
|
||||
},
|
||||
"installedPrograms" : [
|
||||
@@ -14481,6 +14827,14 @@
|
||||
},
|
||||
"dnsServer" : {
|
||||
"forwardingServerIPAddress" : null,
|
||||
"records" : [
|
||||
[
|
||||
"www.filius.de",
|
||||
"A",
|
||||
3600,
|
||||
"141.99.2.10"
|
||||
]
|
||||
],
|
||||
"recursiveResolutionEnabled" : false
|
||||
},
|
||||
"installedPrograms" : [
|
||||
@@ -15260,6 +15614,14 @@
|
||||
},
|
||||
"dnsServer" : {
|
||||
"forwardingServerIPAddress" : null,
|
||||
"records" : [
|
||||
[
|
||||
"www.filius.de",
|
||||
"A",
|
||||
3600,
|
||||
"42.0.0.2"
|
||||
]
|
||||
],
|
||||
"recursiveResolutionEnabled" : false
|
||||
},
|
||||
"installedPrograms" : [
|
||||
@@ -15417,6 +15779,14 @@
|
||||
"system" : {
|
||||
"dnsServer" : {
|
||||
"forwardingServerIPAddress" : null,
|
||||
"records" : [
|
||||
[
|
||||
"webserver.de",
|
||||
"A",
|
||||
3600,
|
||||
"120.130.140.10"
|
||||
]
|
||||
],
|
||||
"recursiveResolutionEnabled" : false
|
||||
},
|
||||
"installedPrograms" : [
|
||||
@@ -15956,6 +16326,14 @@
|
||||
"system" : {
|
||||
"dnsServer" : {
|
||||
"forwardingServerIPAddress" : null,
|
||||
"records" : [
|
||||
[
|
||||
"mywebserver.de",
|
||||
"A",
|
||||
3600,
|
||||
"160.10.20.10"
|
||||
]
|
||||
],
|
||||
"recursiveResolutionEnabled" : false
|
||||
},
|
||||
"installedPrograms" : [
|
||||
@@ -16939,6 +17317,14 @@
|
||||
"system" : {
|
||||
"dnsServer" : {
|
||||
"forwardingServerIPAddress" : null,
|
||||
"records" : [
|
||||
[
|
||||
"www.filius.de",
|
||||
"A",
|
||||
3600,
|
||||
"141.99.2.10"
|
||||
]
|
||||
],
|
||||
"recursiveResolutionEnabled" : false
|
||||
},
|
||||
"installedPrograms" : [
|
||||
@@ -17670,6 +18056,20 @@
|
||||
},
|
||||
"dnsServer" : {
|
||||
"forwardingServerIPAddress" : null,
|
||||
"records" : [
|
||||
[
|
||||
"www.mein-server.de",
|
||||
"A",
|
||||
3600,
|
||||
"192.168.0.100"
|
||||
],
|
||||
[
|
||||
"xy",
|
||||
"A",
|
||||
3600,
|
||||
"192.168.0.100"
|
||||
]
|
||||
],
|
||||
"recursiveResolutionEnabled" : false
|
||||
},
|
||||
"installedPrograms" : [
|
||||
|
||||
@@ -180,10 +180,25 @@ export interface GnutellaConfiguration {
|
||||
readonly maximumKnownPeers: number;
|
||||
}
|
||||
|
||||
/** The DNS records follow with the hosts file (Java's /dns/hosts). */
|
||||
export type DnsRecordType = 'A' | 'MX' | 'NS';
|
||||
|
||||
/**
|
||||
* One record a DNS server answers with (Swift's TopologyDNSResourceRecord):
|
||||
* `name` in lower case without the final dot (the root is "."), `target` an
|
||||
* IPv4 address for A, an absolute name ("mail.filius.de.") for MX and NS.
|
||||
*/
|
||||
export interface DnsResourceRecord {
|
||||
readonly name: string;
|
||||
readonly type: DnsRecordType;
|
||||
readonly ttlSeconds: number;
|
||||
readonly target: string;
|
||||
}
|
||||
|
||||
export interface DnsServerConfiguration {
|
||||
readonly recursiveResolutionEnabled: boolean;
|
||||
readonly forwardingServerIPAddress?: string;
|
||||
/** In the order of Java's /dns/hosts, which stays in the file system as it is. */
|
||||
readonly records: readonly DnsResourceRecord[];
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,153 @@
|
||||
// Java's DNS server keeps its records in the text file /dns/hosts and reads
|
||||
// them on every query (DNSServer.leseRecordListe, ResourceRecord(String)).
|
||||
// Measured on test/dns-hosts.cases.txt against Java (dns-hosts.java.json)
|
||||
// and Swift (dns-hosts.swift.json); where the two differ, Java decides:
|
||||
// - fields are split at single spaces only: a tab or NBSP joins two fields;
|
||||
// - there are no comments, no "IN" and no zone-file order;
|
||||
// - a TTL that is not a Java int silently becomes 3600;
|
||||
// - a name Java does not accept becomes the empty name, and the record
|
||||
// still counts - it just never answers, like any record whose type is
|
||||
// not exactly A, MX or NS (lower-case "a" included);
|
||||
// - duplicates stay.
|
||||
|
||||
import type { DnsResourceRecord } from '@mdg-filius/core';
|
||||
import { javaIpCheck, javaParseInt } from './javaIp.js';
|
||||
import type { FlsFileTree } from './systemSoftware.js';
|
||||
|
||||
/** A record as Java's ResourceRecord holds it (the getters). */
|
||||
export interface JavaResourceRecord {
|
||||
readonly domainName: string;
|
||||
readonly type: string;
|
||||
readonly ttl: number;
|
||||
readonly rdata: string;
|
||||
}
|
||||
|
||||
export const DNS_HOSTS_PATH = '/dns/hosts';
|
||||
|
||||
// EingabenUeberpruefung.musterDomain, including its quirks: labels start with
|
||||
// a letter, labels after the first may hold a backslash, and the empty
|
||||
// string is a valid domain.
|
||||
const JAVA_DOMAIN = /^([a-zA-Z]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(\.[a-zA-Z]([a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9])?)*)?\.?$/;
|
||||
// EingabenUeberpruefung.musterIpAdresse.
|
||||
const JAVA_IP_ADDRESS =
|
||||
/^(0*([1-9]?[0-9]?|1[0-9]{1,2}|2[0-4]?[0-9]|25[0-5]))\.((0*(1?[0-9]{1,2}|2[0-4]?[0-9]|25[0-5]))\.){2}(0*(1?[0-9]{1,2}|2[0-4]?[0-9]|25[0-5]))$/;
|
||||
|
||||
/** `String.trim()`: every UTF-16 unit up to U+0020 off both ends. */
|
||||
function javaTrim(text: string): string {
|
||||
return text.replace(/^[\u0000-\u0020]+|[\u0000-\u0020]+$/g, '');
|
||||
}
|
||||
|
||||
/**
|
||||
* The content of /dns/hosts as `Dateisystem.holeDatei` finds it: the first
|
||||
* node in preorder whose path equals it ignoring case, and only if that node
|
||||
* is a file. Undefined when there is none; a file without content reads as
|
||||
* empty (Java would fail on it).
|
||||
*/
|
||||
export function javaHostsFileContent(root: FlsFileTree | undefined): string | undefined {
|
||||
if (root === undefined) return undefined;
|
||||
const found = firstInPreorder(root, '', (path) => javaEqualsIgnoreCase(path, DNS_HOSTS_PATH));
|
||||
return found?.kind === 'file' ? (found.content ?? '') : undefined;
|
||||
}
|
||||
|
||||
/** Preorder below the root; a node's path is "/" plus each name after the root's. */
|
||||
function firstInPreorder(node: FlsFileTree, path: string, matches: (path: string) => boolean): FlsFileTree | undefined {
|
||||
for (const child of node.children) {
|
||||
const childPath = `${path}/${child.kind === 'other' ? child.className : String(child.name)}`;
|
||||
if (matches(childPath)) return child;
|
||||
const found = firstInPreorder(child, childPath, matches);
|
||||
if (found !== undefined) return found;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* `String.equalsIgnoreCase` against an ASCII path, unit by unit: equal after
|
||||
* Character.toUpperCase, so the long s (U+017F) is an "s". Java also
|
||||
* compares the lower case of both; for the letters of /dns/hosts that adds
|
||||
* no unit (measured over the BMP).
|
||||
*/
|
||||
function javaEqualsIgnoreCase(text: string, asciiPath: string): boolean {
|
||||
if (text.length !== asciiPath.length) return false;
|
||||
for (let index = 0; index < text.length; index++) {
|
||||
if (text[index]!.toUpperCase() !== asciiPath[index]!.toUpperCase()) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/** `DNSServer.leseRecordListe` on the content of /dns/hosts. */
|
||||
export function readJavaDnsHosts(content: string): JavaResourceRecord[] {
|
||||
const records: JavaResourceRecord[] = [];
|
||||
for (const token of content.split('\n')) {
|
||||
const line = javaTrim(token);
|
||||
// line.split(" ", 5).length < 4: fewer than three single spaces.
|
||||
if (line === '' || line.split(' ').length < 4) continue;
|
||||
const record = javaResourceRecord(line);
|
||||
if (isValidJavaRecord(record)) records.push(record);
|
||||
}
|
||||
return records;
|
||||
}
|
||||
|
||||
/** `new ResourceRecord(line)`: up to four space-separated fields. */
|
||||
function javaResourceRecord(line: string): JavaResourceRecord {
|
||||
const fields = line.split(' ').filter((field) => field !== '').map(javaTrim);
|
||||
let domainName = '';
|
||||
let type = 'A';
|
||||
let ttl = 3600;
|
||||
let rdata = '';
|
||||
if (fields[0] !== undefined && JAVA_DOMAIN.test(fields[0])) {
|
||||
domainName = fields[0].endsWith('.') ? fields[0] : `${fields[0]}.`;
|
||||
}
|
||||
if (fields[1] !== undefined) type = fields[1];
|
||||
if (fields[2] !== undefined) ttl = javaParseInt(fields[2]) ?? ttl;
|
||||
if (fields[3] !== undefined) {
|
||||
// Java tests ".*\." (no line terminator before the dot); a target with
|
||||
// one fails the domain check anyway, so endsWith says the same.
|
||||
const needsDot = (type === 'NS' || type === 'MX') && !fields[3].endsWith('.');
|
||||
rdata = needsDot ? `${fields[3]}.` : fields[3];
|
||||
}
|
||||
return { domainName, type, ttl, rdata };
|
||||
}
|
||||
|
||||
function isValidJavaRecord(record: JavaResourceRecord): boolean {
|
||||
switch (record.type) {
|
||||
case 'A':
|
||||
return JAVA_DOMAIN.test(record.domainName) && JAVA_IP_ADDRESS.test(record.rdata);
|
||||
case 'MX':
|
||||
case 'NS':
|
||||
return JAVA_DOMAIN.test(record.domainName) && JAVA_DOMAIN.test(record.rdata);
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The records Java answers with, in the model's form: Java looks them up by
|
||||
* type (exactly "A", "MX", "NS") and by name ignoring case, so a record with
|
||||
* the empty name or another type never answers and is left out. The file
|
||||
* itself stays as it is.
|
||||
*/
|
||||
export function dnsRecordsOf(records: readonly JavaResourceRecord[], warn: (message: string) => void): DnsResourceRecord[] {
|
||||
const answered: DnsResourceRecord[] = [];
|
||||
for (const record of records) {
|
||||
if (record.domainName === '') continue;
|
||||
const name = record.domainName === '.' ? '.' : record.domainName.slice(0, -1).toLowerCase();
|
||||
switch (record.type) {
|
||||
case 'A': {
|
||||
const address = javaIpCheck(record.rdata);
|
||||
if (address === null) {
|
||||
warn(`DNS record '${name} A ${record.rdata}' has no usable IPv4 address, left out (it stays in ${DNS_HOSTS_PATH})`);
|
||||
continue;
|
||||
}
|
||||
answered.push({ name, type: 'A', ttlSeconds: record.ttl, target: address });
|
||||
break;
|
||||
}
|
||||
case 'MX':
|
||||
case 'NS':
|
||||
answered.push({ name, type: record.type, ttlSeconds: record.ttl, target: record.rdata.toLowerCase() });
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return answered;
|
||||
}
|
||||
@@ -33,7 +33,10 @@
|
||||
// - a web server's files stay in /webserver (its document root), where Swift
|
||||
// moves them to /www; and no program state is written into a host's files
|
||||
// (Swift keeps Gnutella and e-mail state there as hidden JSON files).
|
||||
// Not here yet: DNS records (from /dns/hosts) and e-mail accounts.
|
||||
// - a DNS server's records are what Java's server answers from /dns/hosts
|
||||
// (see dnsHosts.ts); Swift reads the file its own way — tabs, comments,
|
||||
// "IN", names with a leading digit — and drops Java's duplicates.
|
||||
// Not here yet: e-mail accounts.
|
||||
|
||||
import {
|
||||
canonicalMacAddress,
|
||||
@@ -88,6 +91,7 @@ import {
|
||||
type TopologyNode,
|
||||
type VirtualFileContent,
|
||||
} from '@mdg-filius/core';
|
||||
import { dnsRecordsOf, javaHostsFileContent, readJavaDnsHosts } from './dnsHosts.js';
|
||||
import type { FlsApplicationClass, FlsFileTree, FlsFirewall } from './systemSoftware.js';
|
||||
import type { FlsDocumentationItem, FlsInterface, FlsNode, FlsNodeClass, FlsTopology } from './topology.js';
|
||||
|
||||
@@ -415,11 +419,15 @@ function registerPrograms(source: FlsNode, node: TopologyNode, system: SystemCon
|
||||
const forwarder = trimmedOrEmpty(source.interfaces[0]?.dns);
|
||||
const primary = trimmedOrEmpty(source.interfaces[0]?.ip);
|
||||
const forwarding = recursive && forwarder !== '' && forwarder !== primary;
|
||||
const hosts = javaHostsFileContent(source.system.fileSystem);
|
||||
const records = dnsRecordsOf(readJavaDnsHosts(hosts ?? ''), (message) =>
|
||||
warnings.push(`node '${node.displayName}': ${message}`),
|
||||
);
|
||||
system.dnsServerConfigurations.set(
|
||||
node.id,
|
||||
forwarding
|
||||
? { recursiveResolutionEnabled: recursive, forwardingServerIPAddress: forwarder }
|
||||
: { recursiveResolutionEnabled: recursive },
|
||||
? { recursiveResolutionEnabled: recursive, forwardingServerIPAddress: forwarder, records }
|
||||
: { recursiveResolutionEnabled: recursive, records },
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// Public surface of the .fls codec.
|
||||
export * from './archive.js';
|
||||
export * from './dnsHosts.js';
|
||||
export * from './importProject.js';
|
||||
export * from './javaIp.js';
|
||||
export * from './javabeans.js';
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
www.filius.de. A 3600 1.2.3.4\u000A
|
||||
www.filius.de A 3600 1.2.3.4\u000A
|
||||
www.filius.de A 3600 1.2.3.4
|
||||
WWW.Filius.DE A 3600 1.2.3.4\u000A
|
||||
www.filius.de a 3600 1.2.3.4\u000A
|
||||
filius.de mx 3600 mail.filius.de\u000A
|
||||
www.filius.de A 3600 1.2.3.4\u000A
|
||||
www.filius.de\u0009A\u00093600\u00091.2.3.4\u000A
|
||||
www.filius.de A 3600 1.2.3.4 \u000A
|
||||
www.filius.de A 3600 1.2.3.4 # comment\u000A
|
||||
# www.filius.de A 3600 1.2.3.4\u000A
|
||||
www.filius.de A 3600 1.2.3.4#x\u000A
|
||||
www.filius.de A IN 3600 1.2.3.4\u000A
|
||||
www.filius.de 3600 IN A 1.2.3.4\u000A
|
||||
www.filius.de A x 1.2.3.4\u000A
|
||||
www.filius.de A -5 1.2.3.4\u000A
|
||||
www.filius.de A 0 1.2.3.4\u000A
|
||||
www.filius.de A +5 1.2.3.4\u000A
|
||||
www.filius.de A 4294967295 1.2.3.4\u000A
|
||||
www.filius.de A 99999999999 1.2.3.4\u000A
|
||||
www.filius.de A 3600 010.0.0.1\u000A
|
||||
www.filius.de A 3600 1.2.3\u000A
|
||||
www.filius.de A 3600 256.0.0.1\u000A
|
||||
www.filius.de A 3600 1.2.3.4.\u000A
|
||||
www.filius.de A 3600 1.2.3.4 extra\u000A
|
||||
www.filius.de A 3600\u000A
|
||||
1und1.de A 3600 1.2.3.4\u000A
|
||||
a_b.de A 3600 1.2.3.4\u000A
|
||||
-a.de A 3600 1.2.3.4\u000A
|
||||
a-.de A 3600 1.2.3.4\u000A
|
||||
www..de A 3600 1.2.3.4\u000A
|
||||
www.filius.de.. A 3600 1.2.3.4\u000A
|
||||
www.1und1.de A 3600 1.2.3.4\u000A
|
||||
www.a\u005Cb.de A 3600 1.2.3.4\u000A
|
||||
m\u00FCller.de A 3600 1.2.3.4\u000A
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.de A 3600 1.2.3.4\u000A
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.de A 3600 1.2.3.4\u000A
|
||||
localhost A 3600 127.0.0.1\u000A
|
||||
. NS 3600 dns-root.\u000A
|
||||
de NS 3600 dns.de\u000A
|
||||
de. NS 3600 .\u000A
|
||||
filius.de MX 3600 mail.filius.de\u000A
|
||||
filius.de MX 3600 10 mail.filius.de\u000A
|
||||
filius.de MX 3600 1.2.3.4\u000A
|
||||
filius.de CNAME 3600 www.filius.de\u000A
|
||||
filius.de TXT 3600 hello\u000A
|
||||
www.filius.de A 3600 1.2.3.4\u000Awww.filius.de A 3600 1.2.3.4\u000A
|
||||
www.filius.de A 3600 1.2.3.4\u000Awww.filius.de A 7200 1.2.3.4\u000A
|
||||
www.filius.de A 3600 1.2.3.4\u000AWWW.filius.de. A 3600 1.2.3.4\u000A
|
||||
www.filius.de A 3600 1.2.3.4\u000Awww.filius.de A 3600 1.2.3.5\u000A
|
||||
www.filius.de A 3600 1.2.3.4\u000D\u000Amail.filius.de A 3600 1.2.3.5\u000D\u000A
|
||||
www.filius.de A 3600 1.2.3.4\u000Dmail.filius.de A 3600 1.2.3.5\u000D
|
||||
www.filius.de A 3600 1.2.3.4\u2028mail.filius.de A 3600 1.2.3.5\u000A
|
||||
www.filius.de\u00A0A 3600 1.2.3.4\u000A
|
||||
www.filius.de A 3600 1.2.3.4\u0085\u000A
|
||||
|
||||
\u000A\u000Awww.filius.de A 3600 1.2.3.4\u000A\u000A
|
||||
filius.de. MX 3600 smtp.filius.de.\u000Adns-root. A 3600 141.99.5.13\u000A. NS 3600 dns-root.\u000A
|
||||
www.filius.de A \u0661\u0660 1.2.3.4\u000A
|
||||
www.filius.de A 2147483647 1.2.3.4\u000A
|
||||
www.filius.de A -2147483648 1.2.3.4\u000A
|
||||
www.filius.de A 2147483648 1.2.3.4\u000A
|
||||
www.filius.de \u0009 A 3600 1.2.3.4\u000A
|
||||
www.filius.de A \u0009 3600 1.2.3.4\u000A
|
||||
www.filius.de A 3600 1.2.3.4 \u0009\u000A
|
||||
www.filius.de A 3600 1.2.3.4\u000A
|
||||
www.filius.de A 3600 1.2.3.4\u000A
|
||||
www.filius.de A 3600 0.0.0.0\u000A
|
||||
www.filius.de A 3600 00000000000000000001.2.3.4\u000A
|
||||
filius.de NS 3600 dns..de\u000A
|
||||
filius.de NS 3600 dns.filius.de..\u000A
|
||||
filius.de. MX 3600 Mail.Filius.DE.\u000A
|
||||
www.filius.de A 3600 .1.2.3\u000A
|
||||
www.filius.de A 3600 1.2.3.4\u0001\u000A
|
||||
www.filius.de A 3600 1.2.3.4\u00A0\u000A
|
||||
\u001Fwww.filius.de A 3600 1.2.3.4\u000A
|
||||
@@ -0,0 +1,754 @@
|
||||
[
|
||||
[
|
||||
"www.filius.de. A 3600 1.2.3.4\\u000A",
|
||||
[
|
||||
[
|
||||
"www.filius.de.",
|
||||
"A",
|
||||
3600,
|
||||
"1.2.3.4"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de A 3600 1.2.3.4\\u000A",
|
||||
[
|
||||
[
|
||||
"www.filius.de.",
|
||||
"A",
|
||||
3600,
|
||||
"1.2.3.4"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de A 3600 1.2.3.4",
|
||||
[
|
||||
[
|
||||
"www.filius.de.",
|
||||
"A",
|
||||
3600,
|
||||
"1.2.3.4"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"WWW.Filius.DE A 3600 1.2.3.4\\u000A",
|
||||
[
|
||||
[
|
||||
"WWW.Filius.DE.",
|
||||
"A",
|
||||
3600,
|
||||
"1.2.3.4"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de a 3600 1.2.3.4\\u000A",
|
||||
[
|
||||
[
|
||||
"www.filius.de.",
|
||||
"a",
|
||||
3600,
|
||||
"1.2.3.4"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"filius.de mx 3600 mail.filius.de\\u000A",
|
||||
[
|
||||
[
|
||||
"filius.de.",
|
||||
"mx",
|
||||
3600,
|
||||
"mail.filius.de"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de A 3600 1.2.3.4\\u000A",
|
||||
[
|
||||
[
|
||||
"www.filius.de.",
|
||||
"A",
|
||||
3600,
|
||||
"1.2.3.4"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de\\u0009A\\u00093600\\u00091.2.3.4\\u000A",
|
||||
[]
|
||||
],
|
||||
[
|
||||
" www.filius.de A 3600 1.2.3.4 \\u000A",
|
||||
[
|
||||
[
|
||||
"www.filius.de.",
|
||||
"A",
|
||||
3600,
|
||||
"1.2.3.4"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de A 3600 1.2.3.4 # comment\\u000A",
|
||||
[
|
||||
[
|
||||
"www.filius.de.",
|
||||
"A",
|
||||
3600,
|
||||
"1.2.3.4"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"# www.filius.de A 3600 1.2.3.4\\u000A",
|
||||
[
|
||||
[
|
||||
"",
|
||||
"www.filius.de",
|
||||
3600,
|
||||
"3600"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de A 3600 1.2.3.4#x\\u000A",
|
||||
[]
|
||||
],
|
||||
[
|
||||
"www.filius.de A IN 3600 1.2.3.4\\u000A",
|
||||
[]
|
||||
],
|
||||
[
|
||||
"www.filius.de 3600 IN A 1.2.3.4\\u000A",
|
||||
[
|
||||
[
|
||||
"www.filius.de.",
|
||||
"3600",
|
||||
3600,
|
||||
"A"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de A x 1.2.3.4\\u000A",
|
||||
[
|
||||
[
|
||||
"www.filius.de.",
|
||||
"A",
|
||||
3600,
|
||||
"1.2.3.4"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de A -5 1.2.3.4\\u000A",
|
||||
[
|
||||
[
|
||||
"www.filius.de.",
|
||||
"A",
|
||||
-5,
|
||||
"1.2.3.4"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de A 0 1.2.3.4\\u000A",
|
||||
[
|
||||
[
|
||||
"www.filius.de.",
|
||||
"A",
|
||||
0,
|
||||
"1.2.3.4"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de A +5 1.2.3.4\\u000A",
|
||||
[
|
||||
[
|
||||
"www.filius.de.",
|
||||
"A",
|
||||
5,
|
||||
"1.2.3.4"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de A 4294967295 1.2.3.4\\u000A",
|
||||
[
|
||||
[
|
||||
"www.filius.de.",
|
||||
"A",
|
||||
3600,
|
||||
"1.2.3.4"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de A 99999999999 1.2.3.4\\u000A",
|
||||
[
|
||||
[
|
||||
"www.filius.de.",
|
||||
"A",
|
||||
3600,
|
||||
"1.2.3.4"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de A 3600 010.0.0.1\\u000A",
|
||||
[
|
||||
[
|
||||
"www.filius.de.",
|
||||
"A",
|
||||
3600,
|
||||
"010.0.0.1"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de A 3600 1.2.3\\u000A",
|
||||
[]
|
||||
],
|
||||
[
|
||||
"www.filius.de A 3600 256.0.0.1\\u000A",
|
||||
[]
|
||||
],
|
||||
[
|
||||
"www.filius.de A 3600 1.2.3.4.\\u000A",
|
||||
[]
|
||||
],
|
||||
[
|
||||
"www.filius.de A 3600 1.2.3.4 extra\\u000A",
|
||||
[
|
||||
[
|
||||
"www.filius.de.",
|
||||
"A",
|
||||
3600,
|
||||
"1.2.3.4"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de A 3600\\u000A",
|
||||
[]
|
||||
],
|
||||
[
|
||||
"1und1.de A 3600 1.2.3.4\\u000A",
|
||||
[
|
||||
[
|
||||
"",
|
||||
"A",
|
||||
3600,
|
||||
"1.2.3.4"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"a_b.de A 3600 1.2.3.4\\u000A",
|
||||
[
|
||||
[
|
||||
"",
|
||||
"A",
|
||||
3600,
|
||||
"1.2.3.4"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"-a.de A 3600 1.2.3.4\\u000A",
|
||||
[
|
||||
[
|
||||
"",
|
||||
"A",
|
||||
3600,
|
||||
"1.2.3.4"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"a-.de A 3600 1.2.3.4\\u000A",
|
||||
[
|
||||
[
|
||||
"",
|
||||
"A",
|
||||
3600,
|
||||
"1.2.3.4"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"www..de A 3600 1.2.3.4\\u000A",
|
||||
[
|
||||
[
|
||||
"",
|
||||
"A",
|
||||
3600,
|
||||
"1.2.3.4"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de.. A 3600 1.2.3.4\\u000A",
|
||||
[
|
||||
[
|
||||
"",
|
||||
"A",
|
||||
3600,
|
||||
"1.2.3.4"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.1und1.de A 3600 1.2.3.4\\u000A",
|
||||
[
|
||||
[
|
||||
"",
|
||||
"A",
|
||||
3600,
|
||||
"1.2.3.4"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.a\\u005Cb.de A 3600 1.2.3.4\\u000A",
|
||||
[
|
||||
[
|
||||
"www.a\\b.de.",
|
||||
"A",
|
||||
3600,
|
||||
"1.2.3.4"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"m\\u00FCller.de A 3600 1.2.3.4\\u000A",
|
||||
[
|
||||
[
|
||||
"",
|
||||
"A",
|
||||
3600,
|
||||
"1.2.3.4"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.de A 3600 1.2.3.4\\u000A",
|
||||
[
|
||||
[
|
||||
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.de.",
|
||||
"A",
|
||||
3600,
|
||||
"1.2.3.4"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.de A 3600 1.2.3.4\\u000A",
|
||||
[
|
||||
[
|
||||
"",
|
||||
"A",
|
||||
3600,
|
||||
"1.2.3.4"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"localhost A 3600 127.0.0.1\\u000A",
|
||||
[
|
||||
[
|
||||
"localhost.",
|
||||
"A",
|
||||
3600,
|
||||
"127.0.0.1"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
". NS 3600 dns-root.\\u000A",
|
||||
[
|
||||
[
|
||||
".",
|
||||
"NS",
|
||||
3600,
|
||||
"dns-root."
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"de NS 3600 dns.de\\u000A",
|
||||
[
|
||||
[
|
||||
"de.",
|
||||
"NS",
|
||||
3600,
|
||||
"dns.de."
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"de. NS 3600 .\\u000A",
|
||||
[
|
||||
[
|
||||
"de.",
|
||||
"NS",
|
||||
3600,
|
||||
"."
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"filius.de MX 3600 mail.filius.de\\u000A",
|
||||
[
|
||||
[
|
||||
"filius.de.",
|
||||
"MX",
|
||||
3600,
|
||||
"mail.filius.de."
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"filius.de MX 3600 10 mail.filius.de\\u000A",
|
||||
[]
|
||||
],
|
||||
[
|
||||
"filius.de MX 3600 1.2.3.4\\u000A",
|
||||
[]
|
||||
],
|
||||
[
|
||||
"filius.de CNAME 3600 www.filius.de\\u000A",
|
||||
[
|
||||
[
|
||||
"filius.de.",
|
||||
"CNAME",
|
||||
3600,
|
||||
"www.filius.de"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"filius.de TXT 3600 hello\\u000A",
|
||||
[
|
||||
[
|
||||
"filius.de.",
|
||||
"TXT",
|
||||
3600,
|
||||
"hello"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de A 3600 1.2.3.4\\u000Awww.filius.de A 3600 1.2.3.4\\u000A",
|
||||
[
|
||||
[
|
||||
"www.filius.de.",
|
||||
"A",
|
||||
3600,
|
||||
"1.2.3.4"
|
||||
],
|
||||
[
|
||||
"www.filius.de.",
|
||||
"A",
|
||||
3600,
|
||||
"1.2.3.4"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de A 3600 1.2.3.4\\u000Awww.filius.de A 7200 1.2.3.4\\u000A",
|
||||
[
|
||||
[
|
||||
"www.filius.de.",
|
||||
"A",
|
||||
3600,
|
||||
"1.2.3.4"
|
||||
],
|
||||
[
|
||||
"www.filius.de.",
|
||||
"A",
|
||||
7200,
|
||||
"1.2.3.4"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de A 3600 1.2.3.4\\u000AWWW.filius.de. A 3600 1.2.3.4\\u000A",
|
||||
[
|
||||
[
|
||||
"www.filius.de.",
|
||||
"A",
|
||||
3600,
|
||||
"1.2.3.4"
|
||||
],
|
||||
[
|
||||
"WWW.filius.de.",
|
||||
"A",
|
||||
3600,
|
||||
"1.2.3.4"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de A 3600 1.2.3.4\\u000Awww.filius.de A 3600 1.2.3.5\\u000A",
|
||||
[
|
||||
[
|
||||
"www.filius.de.",
|
||||
"A",
|
||||
3600,
|
||||
"1.2.3.4"
|
||||
],
|
||||
[
|
||||
"www.filius.de.",
|
||||
"A",
|
||||
3600,
|
||||
"1.2.3.5"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de A 3600 1.2.3.4\\u000D\\u000Amail.filius.de A 3600 1.2.3.5\\u000D\\u000A",
|
||||
[
|
||||
[
|
||||
"www.filius.de.",
|
||||
"A",
|
||||
3600,
|
||||
"1.2.3.4"
|
||||
],
|
||||
[
|
||||
"mail.filius.de.",
|
||||
"A",
|
||||
3600,
|
||||
"1.2.3.5"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de A 3600 1.2.3.4\\u000Dmail.filius.de A 3600 1.2.3.5\\u000D",
|
||||
[]
|
||||
],
|
||||
[
|
||||
"www.filius.de A 3600 1.2.3.4\\u2028mail.filius.de A 3600 1.2.3.5\\u000A",
|
||||
[]
|
||||
],
|
||||
[
|
||||
"www.filius.de\\u00A0A 3600 1.2.3.4\\u000A",
|
||||
[]
|
||||
],
|
||||
[
|
||||
"www.filius.de A 3600 1.2.3.4\\u0085\\u000A",
|
||||
[]
|
||||
],
|
||||
[
|
||||
"",
|
||||
[]
|
||||
],
|
||||
[
|
||||
"\\u000A\\u000Awww.filius.de A 3600 1.2.3.4\\u000A\\u000A",
|
||||
[
|
||||
[
|
||||
"www.filius.de.",
|
||||
"A",
|
||||
3600,
|
||||
"1.2.3.4"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"filius.de. MX 3600 smtp.filius.de.\\u000Adns-root. A 3600 141.99.5.13\\u000A. NS 3600 dns-root.\\u000A",
|
||||
[
|
||||
[
|
||||
"filius.de.",
|
||||
"MX",
|
||||
3600,
|
||||
"smtp.filius.de."
|
||||
],
|
||||
[
|
||||
"dns-root.",
|
||||
"A",
|
||||
3600,
|
||||
"141.99.5.13"
|
||||
],
|
||||
[
|
||||
".",
|
||||
"NS",
|
||||
3600,
|
||||
"dns-root."
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de A \\u0661\\u0660 1.2.3.4\\u000A",
|
||||
[
|
||||
[
|
||||
"www.filius.de.",
|
||||
"A",
|
||||
10,
|
||||
"1.2.3.4"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de A 2147483647 1.2.3.4\\u000A",
|
||||
[
|
||||
[
|
||||
"www.filius.de.",
|
||||
"A",
|
||||
2147483647,
|
||||
"1.2.3.4"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de A -2147483648 1.2.3.4\\u000A",
|
||||
[
|
||||
[
|
||||
"www.filius.de.",
|
||||
"A",
|
||||
-2147483648,
|
||||
"1.2.3.4"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de A 2147483648 1.2.3.4\\u000A",
|
||||
[
|
||||
[
|
||||
"www.filius.de.",
|
||||
"A",
|
||||
3600,
|
||||
"1.2.3.4"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de \\u0009 A 3600 1.2.3.4\\u000A",
|
||||
[
|
||||
[
|
||||
"www.filius.de.",
|
||||
"",
|
||||
3600,
|
||||
"3600"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de A \\u0009 3600 1.2.3.4\\u000A",
|
||||
[]
|
||||
],
|
||||
[
|
||||
"www.filius.de A 3600 1.2.3.4 \\u0009\\u000A",
|
||||
[
|
||||
[
|
||||
"www.filius.de.",
|
||||
"A",
|
||||
3600,
|
||||
"1.2.3.4"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de A 3600 1.2.3.4\\u000A",
|
||||
[
|
||||
[
|
||||
"www.filius.de.",
|
||||
"A",
|
||||
3600,
|
||||
"1.2.3.4"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de A 3600 1.2.3.4\\u000A",
|
||||
[
|
||||
[
|
||||
"www.filius.de.",
|
||||
"A",
|
||||
3600,
|
||||
"1.2.3.4"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de A 3600 0.0.0.0\\u000A",
|
||||
[
|
||||
[
|
||||
"www.filius.de.",
|
||||
"A",
|
||||
3600,
|
||||
"0.0.0.0"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de A 3600 00000000000000000001.2.3.4\\u000A",
|
||||
[
|
||||
[
|
||||
"www.filius.de.",
|
||||
"A",
|
||||
3600,
|
||||
"00000000000000000001.2.3.4"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"filius.de NS 3600 dns..de\\u000A",
|
||||
[]
|
||||
],
|
||||
[
|
||||
"filius.de NS 3600 dns.filius.de..\\u000A",
|
||||
[]
|
||||
],
|
||||
[
|
||||
"filius.de. MX 3600 Mail.Filius.DE.\\u000A",
|
||||
[
|
||||
[
|
||||
"filius.de.",
|
||||
"MX",
|
||||
3600,
|
||||
"Mail.Filius.DE."
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de A 3600 .1.2.3\\u000A",
|
||||
[
|
||||
[
|
||||
"www.filius.de.",
|
||||
"A",
|
||||
3600,
|
||||
".1.2.3"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de A 3600 1.2.3.4\\u0001\\u000A",
|
||||
[
|
||||
[
|
||||
"www.filius.de.",
|
||||
"A",
|
||||
3600,
|
||||
"1.2.3.4"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de A 3600 1.2.3.4\\u00A0\\u000A",
|
||||
[]
|
||||
],
|
||||
[
|
||||
"\\u001Fwww.filius.de A 3600 1.2.3.4\\u000A",
|
||||
[
|
||||
[
|
||||
"www.filius.de.",
|
||||
"A",
|
||||
3600,
|
||||
"1.2.3.4"
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
@@ -0,0 +1,749 @@
|
||||
[
|
||||
[
|
||||
"www.filius.de. A 3600 1.2.3.4\\u000A",
|
||||
[
|
||||
[
|
||||
"www.filius.de",
|
||||
"A",
|
||||
3600,
|
||||
"1.2.3.4"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de A 3600 1.2.3.4\\u000A",
|
||||
[
|
||||
[
|
||||
"www.filius.de",
|
||||
"A",
|
||||
3600,
|
||||
"1.2.3.4"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de A 3600 1.2.3.4",
|
||||
[
|
||||
[
|
||||
"www.filius.de",
|
||||
"A",
|
||||
3600,
|
||||
"1.2.3.4"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"WWW.Filius.DE A 3600 1.2.3.4\\u000A",
|
||||
[
|
||||
[
|
||||
"www.filius.de",
|
||||
"A",
|
||||
3600,
|
||||
"1.2.3.4"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de a 3600 1.2.3.4\\u000A",
|
||||
[
|
||||
[
|
||||
"www.filius.de",
|
||||
"A",
|
||||
3600,
|
||||
"1.2.3.4"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"filius.de mx 3600 mail.filius.de\\u000A",
|
||||
[
|
||||
[
|
||||
"filius.de",
|
||||
"MX",
|
||||
3600,
|
||||
"mail.filius.de."
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de A 3600 1.2.3.4\\u000A",
|
||||
[
|
||||
[
|
||||
"www.filius.de",
|
||||
"A",
|
||||
3600,
|
||||
"1.2.3.4"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de\\u0009A\\u00093600\\u00091.2.3.4\\u000A",
|
||||
[
|
||||
[
|
||||
"www.filius.de",
|
||||
"A",
|
||||
3600,
|
||||
"1.2.3.4"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
" www.filius.de A 3600 1.2.3.4 \\u000A",
|
||||
[
|
||||
[
|
||||
"www.filius.de",
|
||||
"A",
|
||||
3600,
|
||||
"1.2.3.4"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de A 3600 1.2.3.4 # comment\\u000A",
|
||||
[
|
||||
[
|
||||
"www.filius.de",
|
||||
"A",
|
||||
3600,
|
||||
"1.2.3.4"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"# www.filius.de A 3600 1.2.3.4\\u000A",
|
||||
[
|
||||
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de A 3600 1.2.3.4#x\\u000A",
|
||||
[
|
||||
[
|
||||
"www.filius.de",
|
||||
"A",
|
||||
3600,
|
||||
"1.2.3.4"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de A IN 3600 1.2.3.4\\u000A",
|
||||
[
|
||||
[
|
||||
"www.filius.de",
|
||||
"A",
|
||||
3600,
|
||||
"1.2.3.4"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de 3600 IN A 1.2.3.4\\u000A",
|
||||
[
|
||||
[
|
||||
"www.filius.de",
|
||||
"A",
|
||||
3600,
|
||||
"1.2.3.4"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de A x 1.2.3.4\\u000A",
|
||||
[
|
||||
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de A -5 1.2.3.4\\u000A",
|
||||
[
|
||||
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de A 0 1.2.3.4\\u000A",
|
||||
[
|
||||
[
|
||||
"www.filius.de",
|
||||
"A",
|
||||
0,
|
||||
"1.2.3.4"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de A +5 1.2.3.4\\u000A",
|
||||
[
|
||||
[
|
||||
"www.filius.de",
|
||||
"A",
|
||||
5,
|
||||
"1.2.3.4"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de A 4294967295 1.2.3.4\\u000A",
|
||||
[
|
||||
[
|
||||
"www.filius.de",
|
||||
"A",
|
||||
4294967295,
|
||||
"1.2.3.4"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de A 99999999999 1.2.3.4\\u000A",
|
||||
[
|
||||
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de A 3600 010.0.0.1\\u000A",
|
||||
[
|
||||
[
|
||||
"www.filius.de",
|
||||
"A",
|
||||
3600,
|
||||
"10.0.0.1"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de A 3600 1.2.3\\u000A",
|
||||
[
|
||||
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de A 3600 256.0.0.1\\u000A",
|
||||
[
|
||||
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de A 3600 1.2.3.4.\\u000A",
|
||||
[
|
||||
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de A 3600 1.2.3.4 extra\\u000A",
|
||||
[
|
||||
[
|
||||
"www.filius.de",
|
||||
"A",
|
||||
3600,
|
||||
"1.2.3.4"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de A 3600\\u000A",
|
||||
[
|
||||
|
||||
]
|
||||
],
|
||||
[
|
||||
"1und1.de A 3600 1.2.3.4\\u000A",
|
||||
[
|
||||
[
|
||||
"1und1.de",
|
||||
"A",
|
||||
3600,
|
||||
"1.2.3.4"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"a_b.de A 3600 1.2.3.4\\u000A",
|
||||
[
|
||||
|
||||
]
|
||||
],
|
||||
[
|
||||
"-a.de A 3600 1.2.3.4\\u000A",
|
||||
[
|
||||
|
||||
]
|
||||
],
|
||||
[
|
||||
"a-.de A 3600 1.2.3.4\\u000A",
|
||||
[
|
||||
|
||||
]
|
||||
],
|
||||
[
|
||||
"www..de A 3600 1.2.3.4\\u000A",
|
||||
[
|
||||
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de.. A 3600 1.2.3.4\\u000A",
|
||||
[
|
||||
[
|
||||
"www.filius.de",
|
||||
"A",
|
||||
3600,
|
||||
"1.2.3.4"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.1und1.de A 3600 1.2.3.4\\u000A",
|
||||
[
|
||||
[
|
||||
"www.1und1.de",
|
||||
"A",
|
||||
3600,
|
||||
"1.2.3.4"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.a\\u005Cb.de A 3600 1.2.3.4\\u000A",
|
||||
[
|
||||
|
||||
]
|
||||
],
|
||||
[
|
||||
"m\\u00FCller.de A 3600 1.2.3.4\\u000A",
|
||||
[
|
||||
|
||||
]
|
||||
],
|
||||
[
|
||||
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.de A 3600 1.2.3.4\\u000A",
|
||||
[
|
||||
[
|
||||
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.de",
|
||||
"A",
|
||||
3600,
|
||||
"1.2.3.4"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.de A 3600 1.2.3.4\\u000A",
|
||||
[
|
||||
|
||||
]
|
||||
],
|
||||
[
|
||||
"localhost A 3600 127.0.0.1\\u000A",
|
||||
[
|
||||
[
|
||||
"localhost",
|
||||
"A",
|
||||
3600,
|
||||
"127.0.0.1"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
". NS 3600 dns-root.\\u000A",
|
||||
[
|
||||
[
|
||||
".",
|
||||
"NS",
|
||||
3600,
|
||||
"dns-root."
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"de NS 3600 dns.de\\u000A",
|
||||
[
|
||||
[
|
||||
"de",
|
||||
"NS",
|
||||
3600,
|
||||
"dns.de."
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"de. NS 3600 .\\u000A",
|
||||
[
|
||||
|
||||
]
|
||||
],
|
||||
[
|
||||
"filius.de MX 3600 mail.filius.de\\u000A",
|
||||
[
|
||||
[
|
||||
"filius.de",
|
||||
"MX",
|
||||
3600,
|
||||
"mail.filius.de."
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"filius.de MX 3600 10 mail.filius.de\\u000A",
|
||||
[
|
||||
[
|
||||
"filius.de",
|
||||
"MX",
|
||||
3600,
|
||||
"10."
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"filius.de MX 3600 1.2.3.4\\u000A",
|
||||
[
|
||||
[
|
||||
"filius.de",
|
||||
"MX",
|
||||
3600,
|
||||
"1.2.3.4."
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"filius.de CNAME 3600 www.filius.de\\u000A",
|
||||
[
|
||||
|
||||
]
|
||||
],
|
||||
[
|
||||
"filius.de TXT 3600 hello\\u000A",
|
||||
[
|
||||
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de A 3600 1.2.3.4\\u000Awww.filius.de A 3600 1.2.3.4\\u000A",
|
||||
[
|
||||
[
|
||||
"www.filius.de",
|
||||
"A",
|
||||
3600,
|
||||
"1.2.3.4"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de A 3600 1.2.3.4\\u000Awww.filius.de A 7200 1.2.3.4\\u000A",
|
||||
[
|
||||
[
|
||||
"www.filius.de",
|
||||
"A",
|
||||
3600,
|
||||
"1.2.3.4"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de A 3600 1.2.3.4\\u000AWWW.filius.de. A 3600 1.2.3.4\\u000A",
|
||||
[
|
||||
[
|
||||
"www.filius.de",
|
||||
"A",
|
||||
3600,
|
||||
"1.2.3.4"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de A 3600 1.2.3.4\\u000Awww.filius.de A 3600 1.2.3.5\\u000A",
|
||||
[
|
||||
[
|
||||
"www.filius.de",
|
||||
"A",
|
||||
3600,
|
||||
"1.2.3.4"
|
||||
],
|
||||
[
|
||||
"www.filius.de",
|
||||
"A",
|
||||
3600,
|
||||
"1.2.3.5"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de A 3600 1.2.3.4\\u000D\\u000Amail.filius.de A 3600 1.2.3.5\\u000D\\u000A",
|
||||
[
|
||||
[
|
||||
"www.filius.de",
|
||||
"A",
|
||||
3600,
|
||||
"1.2.3.4"
|
||||
],
|
||||
[
|
||||
"mail.filius.de",
|
||||
"A",
|
||||
3600,
|
||||
"1.2.3.5"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de A 3600 1.2.3.4\\u000Dmail.filius.de A 3600 1.2.3.5\\u000D",
|
||||
[
|
||||
[
|
||||
"www.filius.de",
|
||||
"A",
|
||||
3600,
|
||||
"1.2.3.4"
|
||||
],
|
||||
[
|
||||
"mail.filius.de",
|
||||
"A",
|
||||
3600,
|
||||
"1.2.3.5"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de A 3600 1.2.3.4\\u2028mail.filius.de A 3600 1.2.3.5\\u000A",
|
||||
[
|
||||
[
|
||||
"www.filius.de",
|
||||
"A",
|
||||
3600,
|
||||
"1.2.3.4"
|
||||
],
|
||||
[
|
||||
"mail.filius.de",
|
||||
"A",
|
||||
3600,
|
||||
"1.2.3.5"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de\\u00A0A 3600 1.2.3.4\\u000A",
|
||||
[
|
||||
[
|
||||
"www.filius.de",
|
||||
"A",
|
||||
3600,
|
||||
"1.2.3.4"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de A 3600 1.2.3.4\\u0085\\u000A",
|
||||
[
|
||||
[
|
||||
"www.filius.de",
|
||||
"A",
|
||||
3600,
|
||||
"1.2.3.4"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"",
|
||||
[
|
||||
|
||||
]
|
||||
],
|
||||
[
|
||||
"\\u000A\\u000Awww.filius.de A 3600 1.2.3.4\\u000A\\u000A",
|
||||
[
|
||||
[
|
||||
"www.filius.de",
|
||||
"A",
|
||||
3600,
|
||||
"1.2.3.4"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"filius.de. MX 3600 smtp.filius.de.\\u000Adns-root. A 3600 141.99.5.13\\u000A. NS 3600 dns-root.\\u000A",
|
||||
[
|
||||
[
|
||||
"filius.de",
|
||||
"MX",
|
||||
3600,
|
||||
"smtp.filius.de."
|
||||
],
|
||||
[
|
||||
"dns-root",
|
||||
"A",
|
||||
3600,
|
||||
"141.99.5.13"
|
||||
],
|
||||
[
|
||||
".",
|
||||
"NS",
|
||||
3600,
|
||||
"dns-root."
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de A \\u0661\\u0660 1.2.3.4\\u000A",
|
||||
[
|
||||
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de A 2147483647 1.2.3.4\\u000A",
|
||||
[
|
||||
[
|
||||
"www.filius.de",
|
||||
"A",
|
||||
2147483647,
|
||||
"1.2.3.4"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de A -2147483648 1.2.3.4\\u000A",
|
||||
[
|
||||
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de A 2147483648 1.2.3.4\\u000A",
|
||||
[
|
||||
[
|
||||
"www.filius.de",
|
||||
"A",
|
||||
2147483648,
|
||||
"1.2.3.4"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de \\u0009 A 3600 1.2.3.4\\u000A",
|
||||
[
|
||||
[
|
||||
"www.filius.de",
|
||||
"A",
|
||||
3600,
|
||||
"1.2.3.4"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de A \\u0009 3600 1.2.3.4\\u000A",
|
||||
[
|
||||
[
|
||||
"www.filius.de",
|
||||
"A",
|
||||
3600,
|
||||
"1.2.3.4"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de A 3600 1.2.3.4 \\u0009\\u000A",
|
||||
[
|
||||
[
|
||||
"www.filius.de",
|
||||
"A",
|
||||
3600,
|
||||
"1.2.3.4"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de A 3600 1.2.3.4\\u000A",
|
||||
[
|
||||
[
|
||||
"www.filius.de",
|
||||
"A",
|
||||
3600,
|
||||
"1.2.3.4"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de A 3600 1.2.3.4\\u000A",
|
||||
[
|
||||
[
|
||||
"www.filius.de",
|
||||
"A",
|
||||
3600,
|
||||
"1.2.3.4"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de A 3600 0.0.0.0\\u000A",
|
||||
[
|
||||
[
|
||||
"www.filius.de",
|
||||
"A",
|
||||
3600,
|
||||
"0.0.0.0"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de A 3600 00000000000000000001.2.3.4\\u000A",
|
||||
[
|
||||
[
|
||||
"www.filius.de",
|
||||
"A",
|
||||
3600,
|
||||
"1.2.3.4"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"filius.de NS 3600 dns..de\\u000A",
|
||||
[
|
||||
|
||||
]
|
||||
],
|
||||
[
|
||||
"filius.de NS 3600 dns.filius.de..\\u000A",
|
||||
[
|
||||
[
|
||||
"filius.de",
|
||||
"NS",
|
||||
3600,
|
||||
"dns.filius.de."
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"filius.de. MX 3600 Mail.Filius.DE.\\u000A",
|
||||
[
|
||||
[
|
||||
"filius.de",
|
||||
"MX",
|
||||
3600,
|
||||
"mail.filius.de."
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de A 3600 .1.2.3\\u000A",
|
||||
[
|
||||
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de A 3600 1.2.3.4\\u0001\\u000A",
|
||||
[
|
||||
|
||||
]
|
||||
],
|
||||
[
|
||||
"www.filius.de A 3600 1.2.3.4\\u00A0\\u000A",
|
||||
[
|
||||
[
|
||||
"www.filius.de",
|
||||
"A",
|
||||
3600,
|
||||
"1.2.3.4"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"\\u001Fwww.filius.de A 3600 1.2.3.4\\u000A",
|
||||
[
|
||||
|
||||
]
|
||||
]
|
||||
]
|
||||
@@ -0,0 +1,209 @@
|
||||
// Java's reading of /dns/hosts (DNSServer.leseRecordListe): every case in
|
||||
// dns-hosts.cases.txt was run through Java (dns-hosts.java.json) and through
|
||||
// Swift's hosts-file codec (dns-hosts.swift.json, tools/swift-oracle). The
|
||||
// Java view must match Java exactly; the records the model keeps must match
|
||||
// Swift except where Java answers differently — each case named below.
|
||||
|
||||
import { readFileSync } from 'node:fs';
|
||||
import { dirname, join } from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import type { FlsFileTree } from '../src/index.js';
|
||||
import { dnsRecordsOf, javaHostsFileContent, readJavaDnsHosts } from '../src/dnsHosts.js';
|
||||
|
||||
const here = dirname(fileURLToPath(import.meta.url));
|
||||
type Row = [string, string, number, string];
|
||||
const javaMeasured = JSON.parse(readFileSync(join(here, 'dns-hosts.java.json'), 'utf8')) as [string, Row[]][];
|
||||
const swiftMeasured = JSON.parse(readFileSync(join(here, 'dns-hosts.swift.json'), 'utf8')) as [string, Row[]][];
|
||||
|
||||
/** The cases file's escapes: a backslash, `u` and four hex digits for one UTF-16 unit. */
|
||||
function unescape(line: string): string {
|
||||
return line.replace(/\\u([0-9a-fA-F]{4})/g, (_, hex: string) => String.fromCharCode(Number.parseInt(hex, 16)));
|
||||
}
|
||||
|
||||
function modelRows(line: string, warnings: string[] = []): Row[] {
|
||||
return dnsRecordsOf(readJavaDnsHosts(unescape(line)), (message) => warnings.push(message)).map((record) => [
|
||||
record.name,
|
||||
record.type,
|
||||
record.ttlSeconds,
|
||||
record.target,
|
||||
]);
|
||||
}
|
||||
|
||||
/** Lines Swift reads as records that Java never answers. */
|
||||
const SWIFT_READS_JAVA_NEVER_ANSWERS: { reason: string; lines: string[] }[] = [
|
||||
{
|
||||
reason: 'a type in lower case is another type in Java, which never answers',
|
||||
lines: [
|
||||
String.raw`www.filius.de a 3600 1.2.3.4\u000A`,
|
||||
String.raw`filius.de mx 3600 mail.filius.de\u000A`,
|
||||
],
|
||||
},
|
||||
{
|
||||
reason: 'Java splits fields at single spaces only: a tab or NBSP is part of a field',
|
||||
lines: [
|
||||
String.raw`www.filius.de\u0009A\u00093600\u00091.2.3.4\u000A`,
|
||||
String.raw`www.filius.de\u00A0A 3600 1.2.3.4\u000A`,
|
||||
String.raw`www.filius.de A 3600 1.2.3.4\u00A0\u000A`,
|
||||
String.raw`www.filius.de \u0009 A 3600 1.2.3.4\u000A`,
|
||||
String.raw`www.filius.de A \u0009 3600 1.2.3.4\u000A`,
|
||||
],
|
||||
},
|
||||
{
|
||||
reason: 'Java splits lines at LF only: CR, LS and NEL stay in the line',
|
||||
lines: [
|
||||
String.raw`www.filius.de A 3600 1.2.3.4\u000Dmail.filius.de A 3600 1.2.3.5\u000D`,
|
||||
String.raw`www.filius.de A 3600 1.2.3.4\u2028mail.filius.de A 3600 1.2.3.5\u000A`,
|
||||
String.raw`www.filius.de A 3600 1.2.3.4\u0085\u000A`,
|
||||
],
|
||||
},
|
||||
{
|
||||
reason: 'Java has no comments, no "IN" and no zone-file order',
|
||||
lines: [
|
||||
String.raw`www.filius.de A 3600 1.2.3.4#x\u000A`,
|
||||
String.raw`www.filius.de A IN 3600 1.2.3.4\u000A`,
|
||||
String.raw`www.filius.de 3600 IN A 1.2.3.4\u000A`,
|
||||
],
|
||||
},
|
||||
{
|
||||
reason: 'a label that starts with a digit, or two final dots, make the name empty in Java',
|
||||
lines: [
|
||||
String.raw`1und1.de A 3600 1.2.3.4\u000A`,
|
||||
String.raw`www.1und1.de A 3600 1.2.3.4\u000A`,
|
||||
String.raw`www.filius.de.. A 3600 1.2.3.4\u000A`,
|
||||
],
|
||||
},
|
||||
{
|
||||
reason: 'an MX or NS target must be a name Java accepts: no preference, no address, one final dot',
|
||||
lines: [
|
||||
String.raw`filius.de MX 3600 10 mail.filius.de\u000A`,
|
||||
String.raw`filius.de MX 3600 1.2.3.4\u000A`,
|
||||
String.raw`filius.de NS 3600 dns.filius.de..\u000A`,
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
/** Lines Java answers that Swift drops or reads otherwise. */
|
||||
const JAVA_ANSWERS_SWIFT_DROPS: { reason: string; lines: string[] }[] = [
|
||||
{
|
||||
reason: 'a TTL that is no Java int is 3600',
|
||||
lines: [
|
||||
String.raw`www.filius.de A x 1.2.3.4\u000A`,
|
||||
String.raw`www.filius.de A 4294967295 1.2.3.4\u000A`,
|
||||
String.raw`www.filius.de A 99999999999 1.2.3.4\u000A`,
|
||||
String.raw`www.filius.de A 2147483648 1.2.3.4\u000A`,
|
||||
],
|
||||
},
|
||||
{
|
||||
reason: 'a TTL is Java\'s Integer.parseInt: negative, and in any script\'s digits',
|
||||
lines: [
|
||||
String.raw`www.filius.de A -5 1.2.3.4\u000A`,
|
||||
String.raw`www.filius.de A -2147483648 1.2.3.4\u000A`,
|
||||
String.raw`www.filius.de A \u0661\u0660 1.2.3.4\u000A`,
|
||||
],
|
||||
},
|
||||
{
|
||||
reason: 'labels after the first may hold a backslash (Java\'s domain pattern)',
|
||||
lines: [
|
||||
String.raw`www.a\u005Cb.de A 3600 1.2.3.4\u000A`,
|
||||
],
|
||||
},
|
||||
{
|
||||
reason: 'Java trims control characters off a line (String.trim)',
|
||||
lines: [
|
||||
String.raw`www.filius.de A 3600 1.2.3.4\u0001\u000A`,
|
||||
String.raw`\u001Fwww.filius.de A 3600 1.2.3.4\u000A`,
|
||||
],
|
||||
},
|
||||
{
|
||||
reason: 'an NS record may name the root',
|
||||
lines: [
|
||||
String.raw`de. NS 3600 .\u000A`,
|
||||
],
|
||||
},
|
||||
{
|
||||
reason: 'duplicates stay, as in Java\'s list',
|
||||
lines: [
|
||||
String.raw`www.filius.de A 3600 1.2.3.4\u000Awww.filius.de A 3600 1.2.3.4\u000A`,
|
||||
String.raw`www.filius.de A 3600 1.2.3.4\u000Awww.filius.de A 7200 1.2.3.4\u000A`,
|
||||
String.raw`www.filius.de A 3600 1.2.3.4\u000AWWW.filius.de. A 3600 1.2.3.4\u000A`,
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
const departures = new Map(
|
||||
[...SWIFT_READS_JAVA_NEVER_ANSWERS, ...JAVA_ANSWERS_SWIFT_DROPS].flatMap(({ reason, lines }) =>
|
||||
lines.map((line) => [line, reason] as const),
|
||||
),
|
||||
);
|
||||
|
||||
describe('readJavaDnsHosts against Java', () => {
|
||||
it('covers every line of the cases file, in both oracles', () => {
|
||||
const lines = readFileSync(join(here, 'dns-hosts.cases.txt'), 'ascii').split('\n').slice(0, -1);
|
||||
expect(javaMeasured.map(([line]) => line)).toEqual(lines);
|
||||
expect(swiftMeasured.map(([line]) => line)).toEqual(lines);
|
||||
});
|
||||
|
||||
for (const [line, expected] of javaMeasured) {
|
||||
it(JSON.stringify(line), () => {
|
||||
const records = readJavaDnsHosts(unescape(line));
|
||||
expect(records.map((record) => [record.domainName, record.type, record.ttl, record.rdata])).toEqual(expected);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
describe('the records the model keeps, against Swift', () => {
|
||||
it('names only cases of the cases file as departures', () => {
|
||||
const lines = new Set(swiftMeasured.map(([line]) => line));
|
||||
expect([...departures.keys()].filter((line) => !lines.has(line))).toEqual([]);
|
||||
});
|
||||
|
||||
for (const [line, swift] of swiftMeasured) {
|
||||
const reason = departures.get(line);
|
||||
it(reason === undefined ? JSON.stringify(line) : `${JSON.stringify(line)} (departs: ${reason})`, () => {
|
||||
if (reason === undefined) expect(modelRows(line)).toEqual(swift);
|
||||
else expect(modelRows(line)).not.toEqual(swift);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
describe('the records Java answers', () => {
|
||||
it('leave out records Java never answers: an empty name, or a type other than A, MX, NS', () => {
|
||||
expect(modelRows(String.raw`1und1.de A 3600 1.2.3.4\u000Afilius.de CNAME 3600 www.filius.de\u000Afilius.de a 3600 1.2.3.4`)).toEqual([]);
|
||||
});
|
||||
|
||||
it('take names in lower case without the final dot, A targets as FILIUS normalises addresses', () => {
|
||||
expect(modelRows(String.raw`WWW.Filius.DE. A 60 010.000.0.1\u000Afilius.de MX 3600 Mail.Filius.DE\u000A. NS 3600 dns-root`)).toEqual([
|
||||
['www.filius.de', 'A', 60, '10.0.0.1'],
|
||||
['filius.de', 'MX', 3600, 'mail.filius.de.'],
|
||||
['.', 'NS', 3600, 'dns-root.'],
|
||||
]);
|
||||
});
|
||||
|
||||
it('warn about an A record Java answers with an address FILIUS cannot use', () => {
|
||||
const warnings: string[] = [];
|
||||
expect(modelRows(String.raw`www.filius.de A 3600 .1.2.3`, warnings)).toEqual([]);
|
||||
expect(warnings).toEqual(["DNS record 'www.filius.de A .1.2.3' has no usable IPv4 address, left out (it stays in /dns/hosts)"]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('javaHostsFileContent', () => {
|
||||
const file = (name: string, content: string | null): FlsFileTree => ({ kind: 'file', name, type: 'text', content, children: [] });
|
||||
const directory = (name: string, ...children: FlsFileTree[]): FlsFileTree => ({ kind: 'directory', name, children });
|
||||
|
||||
it('finds /dns/hosts ignoring case, as Java does', () => {
|
||||
expect(javaHostsFileContent(directory('root', directory('DNS', file('Hosts', 'x'))))).toBe('x');
|
||||
expect(javaHostsFileContent(directory('root', directory('dns', file('ho\u017Fts', 'long s'))))).toBe('long s');
|
||||
});
|
||||
|
||||
it('takes the first match in preorder, and nothing when that is a directory', () => {
|
||||
expect(javaHostsFileContent(directory('root', directory('dns', file('hosts', 'first')), directory('DNS', file('hosts', 'second'))))).toBe('first');
|
||||
expect(javaHostsFileContent(directory('root', directory('dns', directory('hosts'), file('HOSTS', 'later'))))).toBeUndefined();
|
||||
});
|
||||
|
||||
it('is undefined without the file, and empty for a file without content', () => {
|
||||
expect(javaHostsFileContent(undefined)).toBeUndefined();
|
||||
expect(javaHostsFileContent(directory('root', file('hosts', 'x')))).toBeUndefined();
|
||||
expect(javaHostsFileContent(directory('root', directory('dns', file('hosts', null))))).toBe('');
|
||||
});
|
||||
});
|
||||
@@ -145,6 +145,7 @@ function systemOf(project: ImportedProject, nodeId: Id) {
|
||||
result.dnsServer = {
|
||||
recursiveResolutionEnabled: dns.recursiveResolutionEnabled,
|
||||
forwardingServerIPAddress: dns.forwardingServerIPAddress ?? null,
|
||||
records: dns.records.map((record) => [record.name, record.type, record.ttlSeconds, record.target]),
|
||||
};
|
||||
}
|
||||
const remoteLink = project.remoteLinkConfigurations.get(nodeId);
|
||||
@@ -787,12 +788,39 @@ describe('importProject rules', () => {
|
||||
expect(project.simpleClientConfigurations.get(notebook!)).toEqual({ targetAddress: '10.0.0.9', targetPort: 7 });
|
||||
expect(project.firewallConfigurationsByNodeId.get(notebook!)).toMatchObject({ isActive: true, defaultPolicy: 'accept' });
|
||||
expect([forwarding, self, iterative].map((id) => project.dnsServerConfigurations.get(id!))).toEqual([
|
||||
{ recursiveResolutionEnabled: true, forwardingServerIPAddress: '8.8.8.8' },
|
||||
{ recursiveResolutionEnabled: true },
|
||||
{ recursiveResolutionEnabled: false },
|
||||
{ recursiveResolutionEnabled: true, forwardingServerIPAddress: '8.8.8.8', records: [] },
|
||||
{ recursiveResolutionEnabled: true, records: [] },
|
||||
{ recursiveResolutionEnabled: false, records: [] },
|
||||
]);
|
||||
});
|
||||
|
||||
it("takes a DNS server's records from its /dns/hosts, and names the node in a warning", () => {
|
||||
const hosts = 'www.filius.de A 3600 141.99.2.10\nfilius.de MX 3600 mail.filius.de\nbroken.de A 3600 .1.2.3\n';
|
||||
const server = flsNode('Rechner', {
|
||||
name: 'DNS',
|
||||
interfaces: [nic('10.0.0.1')],
|
||||
system: {
|
||||
applications: [{ key: 'dns', javaClass: 'filius.software.dns.DNSServer', source: flsNode('Rechner').source, isActive: true }],
|
||||
fileSystem: {
|
||||
kind: 'directory',
|
||||
name: 'root',
|
||||
children: [
|
||||
{ kind: 'directory', name: 'dns', children: [{ kind: 'file', name: 'hosts', type: 'text', content: hosts, children: [] }] },
|
||||
],
|
||||
},
|
||||
},
|
||||
});
|
||||
const project = importProject(topology({ nodes: [server] }), counter());
|
||||
const [id] = project.graph.nodes.map((node) => node.id);
|
||||
|
||||
expect(project.dnsServerConfigurations.get(id!)?.records).toEqual([
|
||||
{ name: 'www.filius.de', type: 'A', ttlSeconds: 3600, target: '141.99.2.10' },
|
||||
{ name: 'filius.de', type: 'MX', ttlSeconds: 3600, target: 'mail.filius.de.' },
|
||||
]);
|
||||
expect(project.virtualFileSystems.get(id!)?.textFile('/dns/hosts')).toBe(hosts);
|
||||
expect(project.warnings).toEqual(["node 'DNS': DNS record 'broken.de A .1.2.3' has no usable IPv4 address, left out (it stays in /dns/hosts)"]);
|
||||
});
|
||||
|
||||
it('leaves out a cable to itself and one to a port that already has a cable', () => {
|
||||
const project = importProject(
|
||||
topology({
|
||||
|
||||
@@ -64,3 +64,16 @@ Java-Filius schickt jede IP-Adresse und Maske beim Laden durch
|
||||
zählen nicht (`10..0.0.1`), Vorzeichen und führende Nullen gehen, ebenso
|
||||
Ziffern jeder Schrift in der BMP (Thai, Devanagari, Vollbreite) — aber kein
|
||||
Leerzeichen und kein 𝟏 (Ersatzpaar).
|
||||
|
||||
## `/dns/hosts`
|
||||
|
||||
Javas DNS-Server liest seine Einträge bei jeder Anfrage aus der Textdatei
|
||||
`/dns/hosts`. `DnsHostsCases` legt für jede Zeile von
|
||||
`packages/fls/test/dns-hosts.cases.txt` (eine ganze Datei je Zeile, ASCII,
|
||||
Zeilenumbruch als `\u000A`) einen Rechner mit dieser Datei an und schreibt,
|
||||
was `DNSServer.holeResourceRecords()` liefert, nach `dns-hosts.java.json`.
|
||||
Gemessen: Felder trennt nur ein einzelnes Leerzeichen (Tab und NBSP nicht),
|
||||
Zeilen nur LF; ein Name, den Javas Muster ablehnt (`1und1.de`, `müller.de`),
|
||||
wird leer, der Eintrag bleibt trotzdem; Typen außer A/MX/NS (auch `a`,
|
||||
`CNAME`, eine Kommentarzeile) gelten als gültig; eine TTL, die kein `int`
|
||||
ist, wird still 3600.
|
||||
|
||||
@@ -21,7 +21,7 @@ if [ ! -f "$upstream/target/filius.jar" ]; then
|
||||
fi
|
||||
classpath="$upstream/target/filius.jar:$upstream/target/lib/*"
|
||||
mkdir -p "$here/.build"
|
||||
javac -encoding UTF-8 -d "$here/.build" -cp "$classpath" "$here/src/FlsOracle.java" "$here/src/GetterDefaults.java" "$here/src/IpCheckCases.java"
|
||||
javac -encoding UTF-8 -d "$here/.build" -cp "$classpath" "$here/src/FlsOracle.java" "$here/src/GetterDefaults.java" "$here/src/IpCheckCases.java" "$here/src/DnsHostsCases.java"
|
||||
# FILIUS writes its settings below $HOME; keep them out of the real one.
|
||||
mkdir -p "$here/.build/home"
|
||||
# Removed first: a crashed run must not leave the previous result standing.
|
||||
@@ -66,3 +66,10 @@ ipcheck="$root/packages/fls/test/ip-check.java.json"
|
||||
rm -f "$ipcheck"
|
||||
HOME="$here/.build/home" java -cp "$classpath:$here/.build" IpCheckCases "$cases" "$ipcheck" 2>&1 | grep -v 'logback\|^$' || true
|
||||
test -s "$ipcheck"
|
||||
|
||||
# DNSServer's own reading of /dns/hosts on hand-picked files (packages/fls/src/dnsHosts.ts).
|
||||
cases="$root/packages/fls/test/dns-hosts.cases.txt"
|
||||
dnshosts="$root/packages/fls/test/dns-hosts.java.json"
|
||||
rm -f "$dnshosts"
|
||||
HOME="$here/.build/home" xvfb-run -a java -cp "$classpath:$here/.build" DnsHostsCases "$cases" "$dnshosts" 2>&1 | grep -v 'logback\|^$' || true
|
||||
test -s "$dnshosts"
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
// Runs FILIUS's own reading of /dns/hosts (DNSServer.holeResourceRecords)
|
||||
// on every case of a list and writes the records Java keeps — the reference
|
||||
// for packages/fls/src/dnsHosts.ts. One case per line: a whole hosts file,
|
||||
// ASCII with Java-style unicode escapes (backslash, u, four hex digits), so
|
||||
// line breaks and odd spaces survive editors and hooks.
|
||||
//
|
||||
// Usage: java -cp filius.jar:lib/*:classes DnsHostsCases <cases txt> <output json>
|
||||
|
||||
import filius.hardware.knoten.Rechner;
|
||||
import filius.software.dns.DNSServer;
|
||||
import filius.software.dns.ResourceRecord;
|
||||
import filius.software.system.Datei;
|
||||
import filius.software.system.Dateisystem;
|
||||
import filius.software.system.InternetKnotenBetriebssystem;
|
||||
|
||||
import java.io.FileOutputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class DnsHostsCases {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
List<Object> result = new ArrayList<>();
|
||||
for (String line : Files.readAllLines(Path.of(args[0]), StandardCharsets.US_ASCII)) {
|
||||
InternetKnotenBetriebssystem system = (InternetKnotenBetriebssystem) new Rechner().getSystemSoftware();
|
||||
Dateisystem fileSystem = system.getDateisystem();
|
||||
fileSystem.erstelleVerzeichnis(fileSystem.getRoot(), "dns");
|
||||
Datei hosts = new Datei();
|
||||
hosts.setName("hosts");
|
||||
hosts.setDateiInhalt(IpCheckCases.unescape(line));
|
||||
fileSystem.speicherDatei(fileSystem.holeRootPfad() + Dateisystem.FILE_SEPARATOR + "dns", hosts);
|
||||
DNSServer server = new DNSServer();
|
||||
server.setSystemSoftware(system);
|
||||
List<Object> records = new ArrayList<>();
|
||||
for (ResourceRecord record : server.holeResourceRecords()) {
|
||||
records.add(Arrays.asList(record.getDomainname(), record.getType(), record.getTtl(), record.getRdata()));
|
||||
}
|
||||
result.add(Arrays.asList(line, records));
|
||||
}
|
||||
try (FileOutputStream out = new FileOutputStream(args[1])) {
|
||||
out.write((FlsOracle.Json.write(result, "") + "\n").getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
System.out.println("dns hosts cases: " + result.size());
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
||||
@@ -38,6 +38,11 @@ Sortierung, Base64 — und die ganzen Mengen `whitespacesAndNewlines` und
|
||||
unter Linux; ihre Steuerzeichen-Tabelle hat in Ebene 14 einen Fehler, den
|
||||
der Port nicht übernimmt.
|
||||
|
||||
`--dns-hosts` liest dieselben `/dns/hosts`-Fälle wie das Java-Orakel
|
||||
(`packages/fls/test/dns-hosts.cases.txt`) mit Swifts
|
||||
`TopologyDNSHostsFileCodec`; unter `state` stehen die DNS-Einträge jedes
|
||||
Servers (`dnsServer.records`).
|
||||
|
||||
## Wie es gebaut wird
|
||||
|
||||
`fetch-upstream.sh` holt `filius-ipad` am festen Stand `3b5ded0` und kopiert
|
||||
|
||||
@@ -401,6 +401,7 @@ func describeSystem(_ state: TopologyEditorState, _ node: TopologyNode) -> JSON
|
||||
json["dnsServer"] = [
|
||||
"recursiveResolutionEnabled": dns.recursiveResolutionEnabled,
|
||||
"forwardingServerIPAddress": dns.forwardingServerIPAddress ?? NSNull(),
|
||||
"records": dns.typedRecords.map { dnsRecordJSON($0) },
|
||||
] as JSON
|
||||
}
|
||||
if let link = state.remoteLinkConfigurationsByNodeID[node.id] {
|
||||
@@ -614,6 +615,32 @@ func foldPaths(_ cases: [PathCase]) -> [JSON] {
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - /dns/hosts cases (packages/fls/test/dns-hosts.cases.txt)
|
||||
|
||||
func dnsRecordJSON(_ record: TopologyDNSResourceRecord) -> [Any] {
|
||||
[record.name.rawValue, record.type.rawValue, Int(record.ttlSeconds), record.target]
|
||||
}
|
||||
|
||||
/// One case per line: a whole hosts file, ASCII with Java-style unicode
|
||||
/// escapes (backslash, u, four hex digits) — the file the Java oracle reads.
|
||||
func readDNSHostsCases(_ url: URL) throws -> [(line: String, text: String)] {
|
||||
let lines = try String(contentsOf: url, encoding: .ascii).components(separatedBy: "\n")
|
||||
return lines.dropLast().map { line in
|
||||
var units: [UInt16] = []
|
||||
var rest = Substring(line)
|
||||
while let first = rest.first {
|
||||
if rest.hasPrefix("\\u"), rest.count >= 6, let unit = UInt16(rest.dropFirst(2).prefix(4), radix: 16) {
|
||||
units.append(unit)
|
||||
rest = rest.dropFirst(6)
|
||||
} else {
|
||||
units.append(contentsOf: String(first).utf16)
|
||||
rest = rest.dropFirst()
|
||||
}
|
||||
}
|
||||
return (line, String(decoding: units, as: UTF16.self))
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Main
|
||||
|
||||
if CommandLine.arguments.count == 4, CommandLine.arguments[1] == "--path-folding" {
|
||||
@@ -641,6 +668,15 @@ if CommandLine.arguments.count == 4, CommandLine.arguments[1] == "--strings" {
|
||||
exit(0)
|
||||
}
|
||||
|
||||
if CommandLine.arguments.count == 4, CommandLine.arguments[1] == "--dns-hosts" {
|
||||
let cases = try readDNSHostsCases(URL(fileURLWithPath: CommandLine.arguments[2]))
|
||||
let output: [[Any]] = cases.map { [$0.line, TopologyDNSHostsFileCodec.records(from: $0.text).map { dnsRecordJSON($0) }] }
|
||||
let data = try JSONSerialization.data(withJSONObject: output, options: [.prettyPrinted, .sortedKeys])
|
||||
try (data + Data("\n".utf8)).write(to: URL(fileURLWithPath: CommandLine.arguments[3]))
|
||||
print("dns hosts: \(cases.count) cases")
|
||||
exit(0)
|
||||
}
|
||||
|
||||
if CommandLine.arguments.count == 4, CommandLine.arguments[1] == "--corpus" {
|
||||
let summary = try readCorpus(root: URL(fileURLWithPath: CommandLine.arguments[2]))
|
||||
let data = try JSONSerialization.data(withJSONObject: summary, options: [.prettyPrinted, .sortedKeys])
|
||||
|
||||
@@ -14,4 +14,5 @@ docker run --rm -v "$root:/work" -w /work/tools/swift-oracle swift:6.1-jammy sh
|
||||
.build/debug/Oracle --corpus /work/corpus /work/corpus/corpus.swift.json
|
||||
.build/debug/Oracle --vfs /work/packages/core/test/vfs.cases.json /work/packages/core/test/vfs.swift.json
|
||||
.build/debug/Oracle --strings /work/packages/core/test/strings.cases.json /work/packages/core/test/strings.swift.json
|
||||
.build/debug/Oracle --path-folding /work/packages/fls/test/path-folding.cases.json /work/packages/fls/test/path-folding.swift.json'
|
||||
.build/debug/Oracle --path-folding /work/packages/fls/test/path-folding.cases.json /work/packages/fls/test/path-folding.swift.json
|
||||
.build/debug/Oracle --dns-hosts /work/packages/fls/test/dns-hosts.cases.txt /work/packages/fls/test/dns-hosts.swift.json'
|
||||
|
||||
Reference in New Issue
Block a user