前にも述べたが ICMP のヘッダはメッセージのタイプ毎に少しずつ異なる。ほとんどの ICMP タイプはヘッダを基準にして幾つかのグループに分けることができる。そういうわけで、ここからは、まず初めに基本的なヘッダ形態について述べ、それから、特記すべきタイプグループ毎に特性を見ていくことにする。
いずれのタイプのパケットも、基本的な IPヘッダ の値はもれなく持っている。IPヘッダ については既に述べたので、ここでは簡単なリストにちょっとしたコメントを添えるだけに留める。
バージョン (Version) - 必ず 4 となる。
インターネットヘッダ長 (Internet Header Length) - 32 ビット単位で数えたヘッダの長さ。
サービスタイプ (Type of Service) - 前記参照。 RFC 792 - Internet Control Message Protocol によればここに指定できる有効な値は 0 しかないので、必ず 0。
全長 (Total Length) - ヘッダとデータ部を合わせたパケット全体の長さ。単位はオクテット。
識別子 (Identification), フラグ (Flags), フラグメントオフセット (Fragment offsets) - IP プロトコルからコピーする。
Time To Live - そのパケットが生きていられるホップ (hop) 数。
プロトコル (Protocol) - 使用されている ICMP のバージョン (常に 1)。
ヘッダチェックサム (Header Checksum) - IP での説明 を参照のこと。
送信元アドレス (Source Address) - パケットを送ってきた者のアドレス。この表現は正確とは限らない。というのは、パケットに刻まれているアドレスが今問題にしているマシン上のものとは限らず、どこか別の所であることもあり得るからだ。そうした性格を持つ ICMP タイプについては適宜述べる。
宛先アドレス (Destination Address) - そのパケットの宛先アドレス。
どのタイプの ICMP でも必ず備えるヘッダには、ここで初登場する 2〜3 のものもある。それが以下。ここからはもう少し詳しいコメントを添えよう。
タイプ (Type) - タイプ フィールドはそのパケットの ICMP タイプを収めている。これには ICMP のタイプ毎に違った値がある。例えば ICMP Destination Unreachable パケットならばここにタイプ 3 が入る。 ICMPタイプ の全リストは付録 ICMPタイプ で見られる。このフィールドは全部で 8 ビット。
コード (Code) - コード も ICMP のタイプ によって異なる。あるタイプ ではひとつのコード しか指定できないが、何種類かのコード を指定できるタイプ もある。例えば ICMP Destination Unreachable (タイプ3) が採れるコード には少なくとも 0, 1, 2, 3, 4, 5 のバリエーションがある。組み合わせによってコード の示す意味が変わる。コード の全リストは付録の ICMPタイプ にある。このフィールドの長さは全部で 8 ビット。各コード についてはこのセクションの後半でもう少し詳しく述べる。
チェックサム (Checksum) - チェックサム は 16 ビット長のフィールドで、 ICMPタイプ をはじめとした全てのヘッダから求めた相補 (one's complement = 1の補数) の和の相補である。チェックサムの計算は、チェックサムフィールド自体の値をゼロにした上で行うことになっている。
ここから先は、ヘッダはパケットの種類によって違ってくる。よく出くわす ICMP タイプをひとつずつ取り上げ、そのヘッダとコードの違いを簡単に述べていくことにしよう。
僕は、ここで ICMPエコー の応答パケット (reply) と要求パケット (request) をまとめて説明することにした。ふたつは極めて密接な関係にあるからだ。違いのひとつ目はまず、エコー要求 はタイプ 8 であり、エコー応答 はタイプが 0 だという点。或るホストがタイプ 8 を受け取れば、応答はタイプ 0 で行う。
応答パケットを送る際には、送信元アドレスと宛先アドレスも入れ替わる。そうした処理を全て行った後に、チェックサム を再計算してから返答が送信される。ただしそのどちらもコードはひとつに決まっており、常に 0 にセットされる。
識別子 (Identifier) - ここは要求パケットの時にセットされ、それに対する応答エコーの中で繰り返し使用される。複数の ping の中から要求と応答の対を見分けるためである。
シーケンスナンバー (Sequence number) - ホスト毎のシーケンスナンバー。通常 1 から始まり、パケットひとつ毎に 1 ずつ加算される。
パケットにはデータ部もひとつある。デフォルトではデータ部は通常は空だが、任意の量のランダムなデータを収容することもできる。
図に見られる最初の 3つのフィールドは前記と同じ。 Destination Unreachable のタイプでは、以下のリストのように、基本的に 16種類のコードを採る可能性がある。
コード 0 - Network unreachable (ネットワーク到達不能) - 指定されたネットワークへの到達が現在不能であることを知らせる。
コード 1 - Host unreachable (ホスト到達不能) - 指定されたホストへの到達が現在不能であることを知らせる。
コード 2 - Protocol unreachable (プロトコル到達不能) - このコードは指定されたプロトコル (tcp, udp など) への到達が現在できないということを知らせる。
コード 3 - Port unreachable (ポート到達不能) - このメッセージを受けるのは、ポート (ssh, http, ftp-data など) への到達ができない時。
コード 4 - Fragmentation needed and DF set (フラグメント必要だがDFフラグあり) - パケットをフラグメントする必要があるのだが "フラグメント不可" を表すビットがパケットにセットされている時に、ゲートウェイが返すメッセージ。
コード 5 - Source route failed (送信元指示によるルーティング失敗) - 送信元の指示によるルーティングが某かの理由で失敗に終わった時、このメッセージが返される。
コード 6 - Destination network unknown (宛先ネットワーク発見できず) - 指定されたネットワークまで達する経路がない時、このメッセージが返される。
コード 7 - Destination host unknown (宛先ホスト発見できず) - 指定されたホストまでの経路がない時、このメッセージが返される。
コード 8 - Source host isolated (発信元ホストへのルートなし)(廃) - ホストが孤立している場合にはこのメッセージを返すことになっている。当コードは旧式で今日では使われなくなった。
コード 9 - Destination network administratively prohibited - (宛先ネットワーク設定によりアクセス拒否) - 或るネットワークがゲートウェイでブロックされ、そのせいでパケットが対象のネットワークに到達できなかった場合、この ICMP コードが返ってくることになっている。
コード 10 - Destination host administratively prohibited (宛先ホスト設定によりアクセス拒否) - ホストが規制 (例えばルーティング規制) によってアクセス禁止となっているがために行き着けなかった時、返事としてこのメッセージが返ってくる。
コード 11 - Network unreachable for TOS (TOS種別によりネットワーク到達不能) - 送信したパケットの "不適切" な TOS のせいでネットワークまで届かなかった時、リターンパケットはこのコードで作られる。
コード 12 - Host unreachable for TOS (TOS種別によりホスト到達不能) - パケットの TOS のせいで送信パケットがホストまで届かなかった時、返事に受け取るのがこのメッセージ。
コード 13 - Communication administratively prohibited by filtering (フィルタリング設定により通信禁止) - 何らかのフィルタリング (例えばファイヤーウォール) によってパケットの着信が禁止されていた場合に、我々送信側はコード 13 を受け取る。
コード 14 - Host precedence violation (ホスト優先区分侵害) - このメッセージは第 1 ホップのルータが送ってくる。パケットの採用している優先区分 (precedence) が当該の宛先/送信元の組み合わせにおいては許容されないということを、接続してきたホストに伝える。
コード 15 - Precedence cutoff in effect (優先区分により遮断発動) - 渡されたデータグラムにセットされていた優先レベル (precedence level) が低すぎたた場合に、第 1 ホップのルータはホストへこのメッセージを送ってもよいことになっている (may)。
これに加えて、小さなデータ部を持つこともでき、その中身はインターネットヘッダ (IPヘッダ) のヘッダ全てと、元の IP データグラムのうちの 64 ビットを写したものとなる。次のレベルのプロトコルがポート定義などを持っているとすれば、この 64 ビットデータ部からそれが読み取れるはずである。
パケットまたはそのストリームの発信元に対して、送信を継続するのならパケットの送信間隔を緩めてくれと伝えるために、ソースクエンチパケットが送られることがある。ただし、パケットが渡り歩いていくそうしたゲートウェイやホストはソースクエンチパケットなど送らずに黙ってパケットを破棄しても構わないことになっている点に注意しなければならない。
このパケットには特別なヘッダはなく、データ部に特徴がある。そのデータ部は、元のデータのインターネットヘッダ と、データグラムのうちの 64 ビット分を格納している。それによって、そのソースクエンチメッセージが、問題のゲートウェイや宛先ホストを通じてデータを送ろうとしているどのプロセス に対するものなのかが、適切に割り出せる。
ソースクエンチパケットは ICMP タイプが必ず 4 である。コードは 0 しかあり得ない。
ゲートウェイや宛先のホストの過負荷を送信ホストや受信ホストへ知らせるには、今日では 2〜3 種類の手段がある。そのひとつとして ECN (Explicit Congestion Notification = 明示的輻輳通知) という仕組みがある。 |
ICMPリダイレクト パケットが使用されるケースはひとつしかない。こういう場合を考えてみよう。ここに、何台かのクライアントやサーバとふたつのゲートウェイを持つネットワーク (192.168.0.0/24) があるとする。ゲートウェイのひとつは 10.0.0.0/24 のネットワーク、もうひとつのゲートウェイはその他のインターネット全般へつながっている。さてここで、 192.168.0.0/24 内に、デフォルトゲートウェイは知っているが 10.0.0.0/24 へのルートを知らない 1 台のホストがあったとしよう。そのホストはパケットをデフォルトゲートウェイへ送る。デフォルトゲートウェイは当然 10.0.0.0/24 ネットワークの存在を知っている。デフォルトゲートウェイは、そのパケットはどうせ 10.0.0.0/24 のインターフェイスから出入りすることになるのだから、直接 10.0.0.0/24 用のゲートウェイへ送ったほうが早いと判断することができる。そこでデフォルトゲートウェイは、正しいゲートウェイを知らせる ICMPリダイレクト パケットをホストへと送り、先ほどのパケットは 10.0.0.0/24 のゲートウェイへ渡す。これによって問題のホストは 10.0.0.0/24 ゲートウェイという近道を知るので、うまくすれば次回からはそちらを使うようになるかもしれない、というわけだ。
リダイレクト タイプのパケットの主役となるヘッダはゲイトウェイインターネットアドレス (Gateway Internet Address) フィールドだ。このフィールドは、その時使用すべき適切なゲートウェイについての情報をホストに伝える。このパケットはそれ以外にも、元のパケットの IPヘッダ と、そのデータ部の初めの 64 ビット分も収めている。その情報は、当のリダイレクトパケットと、データを発したプロセスとを適切に結びつけるために利用される。
リダイレクト タイプは 4 種類のコードを採ることができる。それらを以下に挙げる。
コード 0 - Redirect for network - (上記の例のように) ネットワーク丸ごとのリダイレクトである時にだけ使用される。
コード 1 - Redirect for host - 特定のホストに関するリダイレクトの際にだけ使用される (例えばホストルーティング)。
コード 2 - Redirect for TOS and network - サービスタイプとネットワーク丸ごとのリダイレクトの際にのみ使用される。意味合いとしてはコード 0 と同じだが TOS にも関係している場合だ。
コード 3 - Redirect for TOS and host - サービスタイプとホストのリダイレクトである時に使用される。つまり、扱いとしてはコード 1 と同じだが TOS にも絡んでいる場合だ。
TTL equals 0 の ICMP タイプは別名 "時間超過メッセージ (Time Exceeded Message)" とも呼ばれる。セットされるタイプは 11 で、コードは 2 種類のうちから選べる。ゲートウェイでの伝送過程や宛先ホストでのフラグメント再構成中に TTL フィールドが 0 に達してしまった場合には、そのパケットは破棄されなければならない。パケットを送ってきたホストにそれを知らせるために使うのが TTL equals 0 の ICMP パケットだ。これにより送信者は、今度そこへパケットを送る必要が生じた時にはパケットの TTL を大きくしよう、と判断することができる。
このタイプのパケットは付加データ部だけを備える。このデータフィールドには、元のパケットのインターネットヘッダ と 64 ビット分のデータが入っており、相手方はその情報を頼りに送信元となったプロセスを正しく割り出すことができる。先にも述べたように、 TTL equals 0 タイプは 2 種類のコードを採ることができる。
コード 0 - TTL equals 0 during transit - いずれかのゲートウェイで転送を行おうとした時点で TTL が 0 になった場合に、このコードが送信元ホストへ送られる。
コード 1 - TTL equals 0 during reassembly - パケットがフラグメントされており、その再構成中に TTL が 0 に達してしまった場合に、このコードが送られる。このコードは最終目的地のホストからしか送られてこない。
パラメータ障害 (parameter problem) の ICMP はタイプ 12 を使用し、 2 種類のコード値も採り得る。パラメータ障害メッセージは、ゲートウェイか受信ホストがエラー等によって IPヘッダ の一部を理解できない場合や、必要とされるオプションが見あたらない場合に、送信元のホストにそれを知らせるために使用される。
パラメータ障害 タイプの ICMP メッセージは或る特殊なヘッダを備える。それは、元のパケットにおけるエラー原因フィールドへのポインタだ (コードが 0 の場合)。有効なコードを以下に述べる:
コード 0 - IP header bad (IPヘッダ異常)(全てのエラーを包括) - これは、上述したような全てのエラーを包括したエラーメッセージだ。このコードをポインタと組み合わせると、エラーが IPヘッダ のどの部位にあるかを伝えることができる。
コード 1 - Required options missing (必須オプション欠如) - 必要なオプションが欠けている時、このコードで知らせる。
タイムスタンプタイプは今日では廃れて使われなくなっているが、ここでは簡単に取り上げておく。応答も要求も同じコード (0) を持つ。要求の場合はタイプ 13、応答はタイプ 14 である。タイムスタンプパケットは UT (Universal Time) 午前 0 時からの時間をミリ秒で表した 32 ビットのタイムスタンプを 3つ格納している。
最初のタイムスタンプはオリジナルタイムスタンプ、つまり送信元が最後にパケットに触れた時を表す。レシーブタイムスタンプ はエコーを返そうとしたホストが初めてパケットに触れた時、トランスミットタイム は、パケットがエコー送信者の手を離れる瞬間のタイプスタンプである。
いずれのタイムスタンプメッセージも、述べたもの以外に、ICMPエコー パケット同様の識別子 とシーケンスナンバー を持つ。
インフォメーション要求とインフォメーション応答というタイプは、今日では、必要であれば IP プロトコルより上に同目的で利用できるプロトコル (DHCP など) があるため、既に廃止されている。インフォメーション要求は、それを受け取ったネットワーク上に存在する応答可能な全ホストから回答を発生させる。
情報を要求したホストは、送信元アドレスを自分の属するネットワーク (例えば 192.168.0.0)、宛先を 0 にしてパケットを送る。応答のパケットには様々な数値情報 (ネットマスクと IPアドレス) が書かれている。
インフォメーション要求は ICMP タイプが 15、かたや応答はタイプ 16 で送られる。