Zum Hauptinhalt springen

Message Formats (Nachrichtenformate)

ICMP-Nachrichten werden unter Verwendung des grundlegenden IP-Headers gesendet. Das erste Oktett des Datenteils des Datagramms ist ein ICMP-Typfeld; der Wert dieses Feldes bestimmt das Format der verbleibenden Daten. Jedes Feld, das als „unused (nicht verwendet)" gekennzeichnet ist, ist für zukünftige Erweiterungen reserviert und muss beim Senden Null sein, aber Empfänger sollten diese Felder nicht verwenden (außer um sie in die Prüfsumme einzubeziehen). Sofern nicht anders angegeben, sind die Werte der Internet-Header-Felder wie folgt:

IP-Header-Felder für ICMP

Version

4

IHL (Internet Header Length, Internet-Header-Länge)

Internet-Header-Länge in 32-Bit-Wörtern.

Type of Service (Diensttyp)

0

Total Length (Gesamtlänge)

Länge des Internet-Headers und der Daten in Oktetten.

Identification, Flags, Fragment Offset (Identifikation, Flags, Fragment-Offset)

Verwendet bei der Fragmentierung, siehe [1].

Time to Live (Lebensdauer)

Lebensdauer in Sekunden; da dieses Feld bei jeder Maschine, in der das Datagramm verarbeitet wird, dekrementiert wird, sollte der Wert in diesem Feld mindestens so groß sein wie die Anzahl der Gateways, die dieses Datagramm durchqueren wird.

Protocol (Protokoll)

ICMP = 1

Header Checksum (Header-Prüfsumme)

Das 16-Bit-Einerkomplement der Einerkomplement-Summe aller 16-Bit-Wörter im Header. Zur Berechnung der Prüfsumme sollte das Prüfsummenfeld Null sein. Diese Prüfsumme kann in Zukunft ersetzt werden.

Source Address (Quelladresse)

Die Adresse des Gateways oder Hosts, der die ICMP-Nachricht erstellt. Sofern nicht anders angegeben, kann dies jede der Adressen eines Gateways sein.

Destination Address (Zieladresse)

Die Adresse des Gateways oder Hosts, an den die Nachricht gesendet werden soll.

ICMP-Nachrichtenformat

 0                   1                   2                   3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Type | Code | Checksum |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
| Message Body |
| (Format variiert nach Type) |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Type-Feld (8 Bits)

Identifiziert den ICMP-Nachrichtentyp. Häufige Werte:

WertNachrichtentyp
0Echo Reply (Echo-Antwort)
3Destination Unreachable (Ziel nicht erreichbar)
4Source Quench (Quelldrosselung)
5Redirect (Umleitung)
8Echo Request (Echo-Anfrage)
11Time Exceeded (Zeit überschritten)
12Parameter Problem (Parameterproblem)
13Timestamp Request (Zeitstempelanfrage)
14Timestamp Reply (Zeitstempelantwort)
15Information Request (Informationsanfrage)
16Information Reply (Informationsantwort)

Code-Feld (8 Bits)

Bietet zusätzlichen Kontext für den Nachrichtentyp. Die Bedeutung hängt vom Type-Feld ab.

Beispiel - Destination Unreachable (Type 3) Codes:

  • 0 = Netzwerk nicht erreichbar
  • 1 = Host nicht erreichbar
  • 2 = Protokoll nicht erreichbar
  • 3 = Port nicht erreichbar
  • 4 = Fragmentierung erforderlich, aber DF gesetzt
  • 5 = Quellenroute fehlgeschlagen

Checksum-Feld (16 Bits)

Die Prüfsumme ist das 16-Bit-Einerkomplement der Einerkomplement-Summe der ICMP-Nachricht, beginnend mit dem ICMP-Type-Feld. Zur Berechnung der Prüfsumme sollte das Prüfsummenfeld Null sein.

Prüfsummen-Berechnungsalgorithmus:

// Pseudocode für ICMP-Prüfsummenberechnung
uint16_t calculate_icmp_checksum(uint8_t *data, int length) {
uint32_t sum = 0;

// Alle 16-Bit-Wörter summieren
for (int i = 0; i < length; i += 2) {
uint16_t word = (data[i] << 8) + data[i+1];
sum += word;
}

// Wenn die Länge ungerade ist, das letzte Byte hinzufügen
if (length % 2 == 1) {
sum += (data[length-1] << 8);
}

// 32-Bit-Summe auf 16 Bits falten
while (sum >> 16) {
sum = (sum & 0xFFFF) + (sum >> 16);
}

// Einerkomplement zurückgeben
return ~sum;
}

Überprüfung:

// Empfänger überprüft durch Berechnung der Prüfsumme über die gesamte Nachricht
// (einschließlich des Prüfsummenfelds). Das Ergebnis sollte 0xFFFF sein.
bool verify_icmp_checksum(uint8_t *message, int length) {
uint16_t result = calculate_icmp_checksum(message, length);
return (result == 0xFFFF);
}

Vollständige ICMP-Paketstruktur

Ethernet-Frame
┌──────────────────────────────────────────┐
│ Ethernet-Header │
├──────────────────────────────────────────┤
│ IP-Header │
│ - Version: 4 │
│ - IHL: 5 (20 Bytes) │
│ - Protocol: 1 (ICMP) │
│ - Source IP: 192.168.1.1 │
│ - Dest IP: 10.0.0.1 │
├──────────────────────────────────────────┤
│ ICMP-Nachricht │
│ ┌────────────────────────────────────┐ │
│ │ Type (8 Bits) │ │
│ ├────────────────────────────────────┤ │
│ │ Code (8 Bits) │ │
│ ├────────────────────────────────────┤ │
│ │ Checksum (16 Bits) │ │
│ ├────────────────────────────────────┤ │
│ │ Nachrichtenspezifische Daten │ │
│ │ (variiert nach Type und Code) │ │
│ └────────────────────────────────────┘ │
└──────────────────────────────────────────┘

Fehlernachrichtenformat

Für Fehlernachrichten (Types 3, 4, 5, 11, 12) enthält der Nachrichtentext:

 0                   1                   2                   3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Type | Code | Checksum |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Unused = 0 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Internet Header + 64 bits of Original Data Datagram |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Warum ursprüngliche Daten einschließen?

  • Ermöglicht dem Empfänger die Identifizierung, welche Übertragung den Fehler verursacht hat
  • Enthält Quell-/Zielports für Demultiplexing
  • Bietet Kontext für Fehlerbehandlung

Beispiel:

Ursprüngliches TCP-Segment:
┌─────────────────────────────────────┐
│ IP-Header (20 Bytes) │
│ - Src: 192.168.1.10 │
│ - Dst: 203.0.113.50 │
│ - Protocol: 6 (TCP) │
├─────────────────────────────────────┤
│ TCP-Header (20 Bytes) │
│ - Src Port: 54321 │
│ - Dst Port: 80 │
│ - Seq: 1000 │
├─────────────────────────────────────┤
│ TCP-Daten │
└─────────────────────────────────────┘

ICMP-Fehlernachricht enthält:
┌─────────────────────────────────────┐
│ ICMP-Header (8 Bytes) │
│ - Type: 3 │
│ - Code: 1 (Host Unreachable) │
├─────────────────────────────────────┤
│ Ursprünglicher IP-Header (20 Bytes) │ ← Vollständiger IP-Header
├─────────────────────────────────────┤
│ Erste 8 Bytes des TCP-Headers │ ← Enthält Ports
│ - Src Port: 54321 │
│ - Dst Port: 80 │
└─────────────────────────────────────┘

Die 8 Bytes des TCP-Headers reichen aus, um zu identifizieren:
- Quell- und Zielports
- Ermöglicht Demultiplexing des Fehlers zum richtigen Socket

Anfragenachrichtenformat

Für Anfrage-/Antwortnachrichten (Types 0, 8, 13, 14, 15, 16):

 0                   1                   2                   3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Type | Code | Checksum |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Identifier | Sequence Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Data |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Identifier und Sequence Number:

  • Verwendet, um Anfragen mit Antworten abzugleichen
  • Identifier: Normalerweise die Prozess-ID des Absenders
  • Sequence Number: Erhöht sich mit jeder Nachricht

Beispiel - Ping-Sitzung:

Anfrage 1:  ID=12345, Seq=1, Type=8
Antwort 1: ID=12345, Seq=1, Type=0

Anfrage 2: ID=12345, Seq=2, Type=8
Antwort 2: ID=12345, Seq=2, Type=0

Anfrage 3: ID=12345, Seq=3, Type=8
Antwort 3: ID=12345, Seq=3, Type=0

Abgleich: Antwort stimmt mit Anfrage überein, wenn (ID, Seq) identisch sind

Feldbeschreibungen

Nicht verwendete Felder

Jedes Feld, das als „unused (nicht verwendet)" oder „reserved (reserviert)" gekennzeichnet ist:

  • Sender: MUSS auf Null setzen
  • Empfänger:
    • MUSS in Prüfsummenberechnung einbeziehen
    • SOLLTE NICHT interpretieren oder für irgendeinen Zweck verwenden
    • Ermöglicht zukünftige Protokollerweiterungen

Nachrichtenspezifische Felder

Verschiedene ICMP-Nachrichtentypen verwenden zusätzliche Felder. Siehe individuelle Nachrichtentyp-Spezifikationen für Details.

Verarbeitungsrichtlinien

Verantwortlichkeiten des Senders

  1. Geeigneten IP-Header konstruieren:

    • Protocol = 1 (ICMP) setzen
    • Geeignete TTL setzen
    • IP-Header-Prüfsumme berechnen
  2. ICMP-Nachricht konstruieren:

    • Korrekten Type und Code setzen
    • Nachrichtenspezifische Felder ausfüllen
    • Nicht verwendete Felder auf Null setzen
    • ICMP-Prüfsumme berechnen
  3. Kontext für Fehler einschließen:

    • Ursprünglichen IP-Header einschließen
    • Erste 64 Bits der ursprünglichen Daten einschließen

Verantwortlichkeiten des Empfängers

  1. IP-Header validieren:

    • IP-Header-Prüfsumme prüfen
    • Zieladresse überprüfen
  2. ICMP-Nachricht validieren:

    • ICMP-Prüfsumme überprüfen
    • Type- und Code-Werte prüfen
  3. Nachricht verarbeiten:

    • Relevante Informationen extrahieren
    • Zu geeignetem Handler demultiplexen
    • Geeignete Aktion ergreifen
  4. Fehlerbehandlung:

    • Ungültige Nachrichten stillschweigend verwerfen
    • SENDE KEINE ICMP-Fehler über ICMP-Fehler

Byte-Reihenfolge

Alle Multi-Byte-Felder werden in Netzwerk-Byte-Reihenfolge (Big-Endian) übertragen:

  • Höchstwertiges Byte zuerst
  • Entspricht IP-Header-Konventionen

Beispiel:

// Prüfsummenwert: 0x1234
// Drahtformat: [0x12] [0x34]

uint16_t checksum = 0x1234;
uint8_t byte1 = (checksum >> 8) & 0xFF; // 0x12
uint8_t byte2 = checksum & 0xFF; // 0x34

// Auf dem Draht: byte1 wird zuerst übertragen, dann byte2

Implementierungshinweis: Alle ICMP-Nachrichtentypen teilen diese gemeinsame Header-Struktur. Die Interpretation der Felder nach der Prüfsumme variiert je nach Nachrichtentyp. Implementierungen müssen alle definierten Nachrichtentypen behandeln und nicht erkannte Typen stillschweigend verwerfen.