IP-Literale für iOS prüfen: Adressfamilien und Normalisierung
Sie haben unter Windows die Verbindungskonfiguration angepasst und übergeben die Abnahme an einen Cloud-Mac. Dabei zeigt sich: Die IPv6-Adresse desselben Geräts wird als zwei unterschiedliche Ziele behandelt. An einer Stelle sind alle Nullgruppen ausgeschrieben, an einer anderen wird der Doppelpunkt-Operator :: verwendet. Wenn Verbindungsliste, Deduplizierung und Zugriffsregeln jeweils die ursprünglichen Zeichenfolgen vergleichen, fallen die Ergebnisse unterschiedlich aus. Mit Swift und den Parse-Funktionen des Systems lässt sich dafür eine Offline-Prüfung aufbauen – ohne echten Server und unabhängig davon, ob das Netzwerk erreichbar ist.
Zuerst den Eingabevertrag festlegen
Dieses Beispiel akzeptiert ausschließlich IP-Adressliterale, keine Domainnamen, Ports oder vollständigen URLs. IPv4-Adressen müssen aus vier dezimalen Gruppen bestehen; für IPv6 sind die vom System unterstützten Standardschreibweisen zulässig. Führende und nachgestellte Leerraumzeichen werden abgewiesen, nicht stillschweigend entfernt. So können der in der Oberfläche angezeigte Wert und der tatsächlich für die Verbindung verwendete Wert nicht auseinanderfallen.
Eckige Klammern um eine IPv6-Adresse gehören zur Hostdarstellung in einer URL, nicht zur Adresse selbst. Auch Zonenkennungen wie %en0 verarbeitet dieser Parser nicht. Für Verbindungen zu link-lokalen Adressen müssen Adresse und Schnittstelleninformationen auf einer anderen Ebene ausdrücklich entgegengenommen werden. Einfach den Teil ab dem Prozentzeichen abzuschneiden und anschließend eine Verbindung aufzubauen, ist keine geeignete Lösung.
Erfolgreiches Parsen bedeutet lediglich, dass der Text eine Adresse darstellt. Es bedeutet weder, dass der Zugriff auf diese Adresse erlaubt ist, noch dass das zugehörige Gerät online ist.
Die Dokumentationsadressen in den Beispielen dienen ausschließlich dem lokalen Parsen. Das Skript baut keine Verbindungen zu ihnen auf.
Das Ergebnis als Adressfamilie und Bytes speichern
Erstellen Sie im Projektverzeichnis auf dem Cloud-Mac die Datei ip-contract.swift. Prüfen Sie zunächst, ob xcrun swiftc --version die Compilerinformationen ausgibt, und fügen Sie dann den folgenden Code ein. Hier kommen keine Schnittstellen zum Einsatz, die Hostnamen auflösen könnten. Dadurch bleibt DNS-Verhalten aus der Prüfung von Adressliteralen heraus.
import Darwin
import Foundation
struct IPAddress: Equatable {
let family: Int32
let bytes: [UInt8]
}
func parseIP(_ text: String) -> IPAddress? {
guard !text.isEmpty,
text.utf8.count <= 45,
!text.utf8.contains(0) else {
return nil
}
var v4 = in_addr()
let result4 = text.withCString {
inet_pton(AF_INET, $0, &v4)
}
if result4 == 1 {
return IPAddress(
family: AF_INET,
bytes: withUnsafeBytes(of: &v4) { Array($0) }
)
}
var v6 = in6_addr()
let result6 = text.withCString {
inet_pton(AF_INET6, $0, &v6)
}
if result6 == 1 {
return IPAddress(
family: AF_INET6,
bytes: withUnsafeBytes(of: &v6) { Array($0) }
)
}
return nil
}
func require(_ condition: Bool, _ message: String) {
if !condition {
fatalError(message)
}
}
let good = [
"192.0.2.1",
"2001:db8::1",
"2001:0DB8:0000:0000:0000:0000:0000:0001",
"::",
"::1",
"::ffff:192.0.2.1"
]
for text in good {
require(parseIP(text) != nil, "Rejected valid literal")
}
let bad = [
"",
" 192.0.2.1",
"192.0.2.1\n",
"192.0.2.256",
"192.0.2",
"192.0.02.1",
"0xC0000201",
"[2001:db8::1]",
"fe80::1%en0",
"2001:::1",
"192.0.2.1\u{0}ignored"
]
for text in bad {
require(parseIP(text) == nil, "Accepted invalid literal")
}
let short = parseIP("2001:db8::1")!
let expanded = parseIP(
"2001:0DB8:0000:0000:0000:0000:0000:0001"
)!
require(short == expanded, "Equivalent IPv6 mismatch")
require(short.bytes.count == 16, "Invalid IPv6 length")
let v4 = parseIP("192.0.2.1")!
let mapped = parseIP("::ffff:192.0.2.1")!
require(v4.bytes.count == 4, "Invalid IPv4 length")
require(v4 != mapped, "Address families collapsed")
Die Längenobergrenze ist das Bytebudget dieses Parse-Vertrags, keine allgemeine Grenze für sämtliche Adressen mit Zonenkennung. Die Adressbytes werden direkt aus den Systemstrukturen übernommen und bleiben in Netzwerk-Byte-Reihenfolge. Interpretieren Sie den gesamten Byteblock für Vergleiche nicht nachträglich als Ganzzahl in der Byte-Reihenfolge des Hosts.
Kompilieren, ausführen und das Fehlerverhalten prüfen
Kompilieren Sie das Skript zu einem eigenständigen Programm. So lässt es sich in Build-Aufgaben einbinden, ohne dass unterschiedliche Startarten die interpretierte Ausführung beeinflussen:
set -eu
mkdir -p .ip-check
xcrun swiftc ip-contract.swift -o .ip-check/ip-contract
.ip-check/ip-contract
Bei erfolgreichem Durchlauf gibt es keine Ausgabe, und der Exitcode ist null. Sobald eine Vertragsbedingung verletzt wird, endet das Programm mit einem Status ungleich null. Hier werden explizite Prüfungen statt assert verwendet, weil Optimierungseinstellungen Assertions entfernen können.
Ändern Sie den Gleichheitsvergleich vorübergehend in einen Ungleichheitsvergleich, vergewissern Sie sich, dass die Aufgabe tatsächlich fehlschlägt, und machen Sie die Änderung anschließend rückgängig. Dieser Negativtest deckt Pipelines auf, die Exitcodes ignorieren und trotz gespeicherter Fehlerprotokolle einen Erfolg melden. Es reicht nicht, nur festzustellen, dass das Skript „einmal gelaufen ist“.
Normalisierung und Zugriffsregeln trennen
Äquivalenz nicht beliebig erweitern
Die komprimierte und die vollständig ausgeschriebene Form derselben IPv6-Adresse müssen als gleich gelten. IPv4 und IPv4-gemappte IPv6-Adressen gehören in diesem Modell jedoch weiterhin zu unterschiedlichen Adressfamilien. Soll die Anwendung beide als dasselbe logische Ziel behandeln, braucht es eine explizite Konvertierung samt Tests der Zugriffsregeln vor und nach dieser Umwandlung. Das bloße Entfernen eines Zeichenfolgenpräfixes genügt nicht.
Für die Anzeige kann inet_ntop eine einheitliche Textdarstellung erzeugen. Deduplizierung und Autorisierung sollten dagegen weiterhin auf dem geparsten Modell beruhen. Behandeln Sie die Textausgabe einer bestimmten Systemversion nicht als dauerhaft versionsübergreifend unveränderliches Speicherformat.
Domainnamen gesondert prüfen
Dass ein Domainname diese Funktion nicht passiert, macht ihn nicht ungültig. Er gehört lediglich nicht zum vorgesehenen Eingabetyp. Unterstützt das Produkt auch Domainnamen, sollte es dafür einen eigenen Eingabepfad geben. Nach der Namensauflösung muss dann die Menge der Adressen geprüft werden, zu denen tatsächlich eine Verbindung aufgebaut werden soll. Allein die vom Nutzer eingegebene Host-Zeichenfolge zu prüfen, reicht nicht aus, um Änderungen der Auflösungsergebnisse abzudecken.
Welche Loopback-, privaten oder link-lokalen Adressen zulässig sind, hängt vom Einsatzzweck des Produkts ab. Ein Werkzeug zur Gerätefehlersuche braucht andere Regeln als ein Dienst zum Abrufen öffentlich erreichbarer Ressourcen. Beide sollten deshalb keinen unscharf definierten booleschen Wert für „sichere Adresse“ gemeinsam verwenden.
Fehlerfälle als Regressionstests bewahren
Nachdem der Parser in den gemeinsam genutzten Quellcode übernommen wurde, führen Sie dieselben Testvektoren sowohl in der macOS-Kommandozeilenprüfung als auch im iOS-Test-Target aus. Die erste Variante eignet sich dazu, in einer Remote-Umgebung schnell Fehler zu finden; die zweite bestätigt das Verhalten auf dem Zielsystem. Ein erfolgreicher Test auf dem Host ersetzt keine Abnahme auf der Zielplattform.
Ergänzen Sie bei jeder Korrektur die ursprüngliche Eingabe, die erwartete Adressfamilie und das erwartete Ergebnis. Bei eingebetteten Nullbytes müssen insbesondere die ursprünglichen Bytes erhalten bleiben, da sie in der Protokollausgabe unsichtbar sein können. C-Zeichenfolgen enden am Nullbyte. Ohne Prüfung am Eingang wird daher unter Umständen nur ein gültiges Präfix validiert.
Prüfen Sie abschließend drei Punkte: Werden unterschiedliche Schreibweisen derselben Adresse zugeordnet? Bleiben die Grenzen zwischen unterschiedlichen Adressfamilien erhalten? Werden ungültige Eingaben vor dem Verbindungsaufbau abgewiesen? Solange diese Verträge stabil bleiben, steht für spätere Erweiterungen der Oberflächenvalidierung oder der Verbindungsregeln eine wiederholbar ausführbare Prüfgrundlage bereit.
Häufig gestellte Fragen
Sind unterschiedlich geschriebene IPv6-Adressen immer verschieden?
Nein. Nullkompression, führende Nullen und Großschreibung können variieren. Vergleiche nach dem Parsen die Adressfamilie und die Bytes in Netzwerkreihenfolge.
Darf eine erfolgreich geparste Adresse direkt verbunden werden?
Nein. Loopback-, private, linklokale und gemappte Adressen brauchen eigene Zugriffsregeln. Auch Ergebnisse einer DNS-Auflösung müssen geprüft werden.
Aufgaben auf einem exklusiven Mac in der Cloud erledigen
Mieten Sie einen exklusiven physischen Mac mini in der Cloud und wählen Sie Standort und Laufzeit passend zu Ihrem Arbeitsalltag. Nach der Bereitstellung finden Sie die Verbindungsdaten in der Konsole. Bei Fragen können Sie dort ein Supportticket erstellen.
Cloud-Mac-Tarife ansehen