メインコンテンツまでスキップ

Message Formats (メッセージ形式)

ICMPメッセージは、基本的なIPヘッダーを使用して送信されます。データグラムのデータ部分の最初のオクテットはICMPタイプフィールドです。このフィールドの値が残りのデータの形式を決定します。「unused (未使用)」とラベル付けされたフィールドは、将来の拡張のために予約されており、送信時にはゼロでなければなりません (MUST) が、受信者はこれらのフィールドを使用すべきではありません (SHOULD NOT) (チェックサムに含めることを除く)。特に明記されていない限り、インターネットヘッダーフィールドの値は次のとおりです。

ICMPのためのIPヘッダーフィールド

Version (バージョン)

4

IHL (Internet Header Length, インターネットヘッダー長)

32ビットワード単位のインターネットヘッダー長。

Type of Service (サービスタイプ)

0

Total Length (全長)

オクテット単位のインターネットヘッダーとデータの長さ。

Identification, Flags, Fragment Offset (識別子、フラグ、フラグメントオフセット)

フラグメンテーションに使用、[1] を参照。

Time to Live (生存時間)

秒単位の生存時間。このフィールドはデータグラムが処理されるすべてのマシンでデクリメントされるため、このフィールドの値はこのデータグラムが通過するゲートウェイの数以上であるべきです (SHOULD)。

Protocol (プロトコル)

ICMP = 1

Header Checksum (ヘッダーチェックサム)

ヘッダー内のすべての16ビットワードの1の補数和の16ビット1の補数。チェックサムを計算する場合、チェックサムフィールドはゼロであるべきです (SHOULD)。このチェックサムは将来置き換えられる可能性があります (MAY)。

Source Address (送信元アドレス)

ICMPメッセージを構成するゲートウェイまたはホストのアドレス。特に明記されていない限り、これはゲートウェイの任意のアドレスである可能性があります (CAN)。

Destination Address (宛先アドレス)

メッセージを送信すべきゲートウェイまたはホストのアドレス。

ICMPメッセージ形式

 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 |
| (形式はTypeによって異なる) |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Typeフィールド (8ビット)

ICMPメッセージタイプを識別します。一般的な値:

メッセージタイプ
0Echo Reply (エコー応答)
3Destination Unreachable (宛先到達不能)
4Source Quench (送信元抑制)
5Redirect (リダイレクト)
8Echo Request (エコー要求)
11Time Exceeded (時間超過)
12Parameter Problem (パラメータ問題)
13Timestamp Request (タイムスタンプ要求)
14Timestamp Reply (タイムスタンプ応答)
15Information Request (情報要求)
16Information Reply (情報応答)

Codeフィールド (8ビット)

メッセージタイプに対する追加のコンテキストを提供します。意味はTypeフィールドに依存します。

例 - Destination Unreachable (Type 3) のコード:

  • 0 = ネットワーク到達不能
  • 1 = ホスト到達不能
  • 2 = プロトコル到達不能
  • 3 = ポート到達不能
  • 4 = フラグメンテーションが必要だがDFが設定されている
  • 5 = 送信元ルート失敗

Checksumフィールド (16ビット)

チェックサムは、ICMPタイプフィールドから始まるICMPメッセージの1の補数和の16ビット1の補数です。チェックサムを計算する場合、チェックサムフィールドはゼロであるべきです (SHOULD)。

チェックサム計算アルゴリズム:

// ICMPチェックサム計算の疑似コード
uint16_t calculate_icmp_checksum(uint8_t *data, int length) {
uint32_t sum = 0;

// すべての16ビットワードを合計
for (int i = 0; i < length; i += 2) {
uint16_t word = (data[i] << 8) + data[i+1];
sum += word;
}

// 長さが奇数の場合、最後のバイトを追加
if (length % 2 == 1) {
sum += (data[length-1] << 8);
}

// 32ビット和を16ビットに畳み込む
while (sum >> 16) {
sum = (sum & 0xFFFF) + (sum >> 16);
}

// 1の補数を返す
return ~sum;
}

検証:

// 受信者はメッセージ全体 (チェックサムフィールドを含む) に対して
// チェックサムを計算することで検証します。結果は0xFFFFであるべきです。
bool verify_icmp_checksum(uint8_t *message, int length) {
uint16_t result = calculate_icmp_checksum(message, length);
return (result == 0xFFFF);
}

完全なICMPパケット構造

イーサネットフレーム
┌──────────────────────────────────────────┐
│ イーサネットヘッダー │
├──────────────────────────────────────────┤
│ IPヘッダー │
│ - Version: 4 │
│ - IHL: 5 (20バイト) │
│ - Protocol: 1 (ICMP) │
│ - Source IP: 192.168.1.1 │
│ - Dest IP: 10.0.0.1 │
├──────────────────────────────────────────┤
│ ICMPメッセージ │
│ ┌────────────────────────────────────┐ │
│ │ Type (8ビット) │ │
│ ├────────────────────────────────────┤ │
│ │ Code (8ビット) │ │
│ ├────────────────────────────────────┤ │
│ │ Checksum (16ビット) │ │
│ ├────────────────────────────────────┤ │
│ │ メッセージ固有のデータ │ │
│ │ (TypeとCodeによって異なる) │ │
│ └────────────────────────────────────┘ │
└──────────────────────────────────────────┘

エラーメッセージ形式

エラーメッセージ (Types 3, 4, 5, 11, 12) の場合、メッセージ本体には次が含まれます:

 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 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

元のデータを含める理由:

  • 受信者がどの送信がエラーを引き起こしたかを特定できるようにする
  • 多重化のための送信元/宛先ポートを含む
  • エラー処理のコンテキストを提供

:

元のTCPセグメント:
┌─────────────────────────────────────┐
│ IPヘッダー (20バイト) │
│ - Src: 192.168.1.10 │
│ - Dst: 203.0.113.50 │
│ - Protocol: 6 (TCP) │
├─────────────────────────────────────┤
│ TCPヘッダー (20バイト) │
│ - Src Port: 54321 │
│ - Dst Port: 80 │
│ - Seq: 1000 │
├─────────────────────────────────────┤
│ TCPデータ │
└─────────────────────────────────────┘

ICMPエラーメッセージには以下が含まれる:
┌─────────────────────────────────────┐
│ ICMPヘッダー (8バイト) │
│ - Type: 3 │
│ - Code: 1 (Host Unreachable) │
├─────────────────────────────────────┤
│ 元のIPヘッダー (20バイト) │ ← 完全なIPヘッダー
├─────────────────────────────────────┤
│ TCPヘッダーの最初の8バイト │ ← ポートを含む
│ - Src Port: 54321 │
│ - Dst Port: 80 │
└─────────────────────────────────────┘

TCPヘッダーの8バイトは以下を識別するのに十分:
- 送信元と宛先のポート
- 正しいソケットへのエラーの多重化を可能にする

クエリメッセージ形式

クエリ/応答メッセージ (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とSequence Number:

  • 要求と応答を一致させるために使用
  • Identifier: 通常は送信者のプロセスID
  • Sequence Number: 各メッセージごとに増加

例 - Pingセッション:

要求1:  ID=12345, Seq=1, Type=8
応答1: ID=12345, Seq=1, Type=0

要求2: ID=12345, Seq=2, Type=8
応答2: ID=12345, Seq=2, Type=0

要求3: ID=12345, Seq=3, Type=8
応答3: ID=12345, Seq=3, Type=0

マッチング: (ID, Seq) が同一の場合、応答は要求と一致

フィールドの説明

未使用フィールド

「unused (未使用)」または「reserved (予約済み)」とラベル付けされたフィールド:

  • 送信者: ゼロに設定しなければなりません (MUST)
  • 受信者:
    • チェックサム計算に含めなければなりません (MUST)
    • いかなる目的にも解釈または使用すべきではありません (SHOULD NOT)
    • 将来のプロトコル拡張を可能にする

メッセージ固有のフィールド

異なるICMPメッセージタイプは追加のフィールドを使用します。詳細については、個々のメッセージタイプの仕様を参照してください。

処理ガイドライン

送信者の責任

  1. 適切なIPヘッダーを構築する:

    • Protocol = 1 (ICMP) を設定
    • 適切なTTLを設定
    • IPヘッダーチェックサムを計算
  2. ICMPメッセージを構築する:

    • 正しいTypeとCodeを設定
    • メッセージ固有のフィールドを埋める
    • 未使用フィールドをゼロにする
    • ICMPチェックサムを計算
  3. エラーのコンテキストを含める:

    • 元のIPヘッダーを含める
    • 元のデータの最初の64ビットを含める

受信者の責任

  1. IPヘッダーを検証する:

    • IPヘッダーチェックサムをチェック
    • 宛先アドレスを確認
  2. ICMPメッセージを検証する:

    • ICMPチェックサムを確認
    • TypeとCodeの値をチェック
  3. メッセージを処理する:

    • 関連情報を抽出
    • 適切なハンドラーに多重化
    • 適切なアクションを実行
  4. エラー処理:

    • 無効なメッセージを静かに破棄
    • ICMPエラーに関するICMPエラーを送信しない (DO NOT)

バイト順

すべてのマルチバイトフィールドはネットワークバイト順 (ビッグエンディアン) で送信されます:

  • 最上位バイトが最初
  • IPヘッダーの規則に一致

:

// チェックサム値: 0x1234
// ワイヤー形式: [0x12] [0x34]

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

// ワイヤー上: byte1が最初に送信され、次にbyte2

実装上の注意: すべてのICMPメッセージタイプは、この共通のヘッダー構造を共有します。チェックサムの後のフィールドの解釈は、メッセージタイプによって異なります。実装は、定義されたすべてのメッセージタイプを処理し、認識されないタイプを静かに破棄しなければなりません (MUST)。