UDPヘッダの編集をしたり、イーサネットを流れるフレームのMACアドレスからまるまる受信したりする、通常では許されていないソケットの使用方法。アプリケーションの実行にはスーパーユーザ特権が必要。一般ユーザ権限で実行するとソケットを生成できずにエラーとなる。
ケース1
アプリケーションがTCPやUDPのレイヤ4ヘッダを編集し、カーネルはIPヘッダより下のレイヤのヘッダーを生成。
protoent = getprotobyname("tcp");
s = socket(PF_INET, SOCK_RAW, protoent->p_proto);
読み出し書き込みには送信元を取得するためにrecvfromや送信先を指定するためにsendtoといったシステムコールを利用する。
ケース3
イーサネットのMACアドレス部分からアプリケーションで編集する。
s = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL) );
ソケットはパケット・ドメインでオープンされる(第一引数に注目)。
読み出し書き込みには、相手先IPアドレスを指定する必要がないのでシステムコール、readとwriteを利用する。
インタフェースを「プロミスキャス・モード」にすると、あて先MACアドレスによらず、インタフェースに接続されているネットワークセグメントを流れるすべてのフレームを取り込むことも可能になる。(通常では自分宛またはブロードキャストのみ)
ケース2
IPヘッダを送受信する。tracerootコマンドなどでの利用が考えられる。
利用方法はケース1の変形版で、TCPを指定した部分でIPを指定するだけです。
ただしIPヘッダまで含めて取得したい場合、IPヘッダも含めて編集したパケットを送出したい場合は、setsocketoptを使って、その旨をカーネルに指定しておく必要がある。
int onoff = 1;
s = socket(PF_INET, SOCK_RAW, IPPROTO_RAW);
setcoketopt(s, IPPROTO_IP, IP_HDRINCL, (void *)&onoff, sizeof(onoff) );
これらケース1から3の方法はLinuxカーネルが前提で、Windows APIではケース1は利用できるがケース3はサポートされていません。(これを実現するにはデバイス・ドライバを作成するか、他のDLL(Dynamic Link Library)を呼び出す必要がある。DLLはWinPcapが有名。)
ケース1のRAWモード・ソケットをWindowsで利用するためには、RAWモードで指定したソケットをWSARecvというAPIで読み出せば、IPヘッダの最初からパケットを取得できる。また、自分のIPアドレス宛以外のパケットも含むすべてのパケットを取得するにはWSAIoctlというAPIを使って、ソケットのSIO_RCVALLオプションを有効にする。
DWORD optval, d;
optval = 1;
s = WSASocket(AF_INET, SOCK_RAW, IPPROTO_IP, NULL, 0, WSA_FLAG_OVERLAPPED);
WSAIoctl(s, STO_RCVALL, &optval, sizeof(optval), NULL, 0, &d, NULL, NULL);
参考文献
1. 「いまどきのソケットプログラミング」 波多 浩昭 著 日経BP社 2004年


0 件のコメント:
コメントを投稿