C: pingコマンドの実装
5章で実装したソケットはUDPとTCPを対象としていました。ここではRAWソケット(SOCK_RAW)に対応させ、ICMP Echo要求/応答を直接やり取りするpingコマンドを作成してください。
pingは、宛先ホストにICMP Echo要求を送り、返ってくるEcho応答までの往復時間(RTT)を表示するツールです。TCP/UDPのようにトランスポート層を挟まず、IPの上で直接ICMPメッセージを組み立てるため、RAWソケットが必要になります。
目標
- RAWソケット(
SOCK_RAW)をソケット層に対応させる pingコマンドを作成し、ホスト(192.0.2.1)へICMP Echo要求を送って応答(RTT)を表示できることを確認する
ヒント
RAWソケットは「指定したプロトコル番号のIPデータグラムを、そのまま送受信できるソケット」です。ここまでに実装しているソケットに対してRAWソケット用の仕組みを実装します。
- RAWソケットの実装: IP層(
ip_input())で受信したデータグラムを、プロトコル番号が一致するRAWソケットへ渡す仕組みを用意し、sock.cにSOCK_RAWの振り分けを追加します。受信キューやブロックして待つ部分はudp.cの受信処理が参考になります。sock.h・user/socket.hへのSOCK_RAW/IPPROTO_ICMPの定義追加も必要です(socket()システムコールはprotocolを既にそのまま渡します)。 pingコマンド: RAWソケットでICMP Echo要求を組み立てて送受信します。ICMPチェックサムの計算や、RTT測定のための送信時刻の埋め込みが必要です。- 実装上の注意: RAWソケットの受信データにはIPヘッダが含まれる点と、応答が返らないときに受信でブロックし続けない工夫(
fork()で受信を別プロセスにするなど)に気をつけてください。
Note
送信先の
192.0.2.1は開発環境側のTapデバイス(ホスト)のアドレスです。ホストのカーネルがICMP Echo要求に応答するので、xv6側で応答(RTT)を確認できます。
完成イメージ
$ ping 192.0.2.1
PING 192.0.2.1: 56 data bytes
64 bytes from 192.0.2.1: icmp_seq=1 time=0.512 ms
64 bytes from 192.0.2.1: icmp_seq=2 time=0.487 ms
64 bytes from 192.0.2.1: icmp_seq=3 time=0.501 ms
64 bytes from 192.0.2.1: icmp_seq=4 time=0.498 ms
--- 192.0.2.1 ping statistics ---
4 packets transmitted, 4 packets received