MasaのITC Life

夢は起業家!全てにおいて凡人だけど頑張ることだけはいっちょ前!

プログラミング

【DHCP】Cでdiscoverを送信してみた

投稿日:2019年8月7日 更新日:

今回はDHCPのdiscoverパケットを送信してみました。

実行環境にはVirtual Boxで構築したネットワークを使用しています

※DHCPパケット送信できるかという勉強目的なので、実際はDHCPクライアントに既にIPアドレスが割り振られていいます(192.168.198.3)




ということでコードの方を見ていきます。


最終的にはDHCPを実装するコードを完成させようかと思っています。まず手始めに今回は、クライアント側がDHCPのdiscoverをブロードキャストするだけのコードです。

まずはDHCPのフォーマットに従い、DHCPパケットの構造体を定義します。そしてマクロに 、DHCPパケットの各フィールドに対応したパラメータを定義します。ついでに、使用するポート番号なども書きます。



ソケットを作成しないとパケット送信などが出来ないので、まずはソケットを作成します。DHCPはUDP上で使うので、UDPソケットを作ります。このときにソケットのオプションをいじります。DHCPはUDPを使ったブロードキャストをするので、setsockopt関数でSO_BROADCASTを有効にします。あとは今後のこと(DHCPの本格的実装)を考えて、setsockopt関数でSO_REUSEADDRを指定し、ソケットの再利用を可能にしておきます。



これはクライアントのMACアドレスを取得するための関数です。DHCPのDiscoverパケットを送信するとき、chaddrフィールドにクライアントのMACアドレスを入れます。なので、ioctl(SIOCGIFHWADDR)で送信するインタフェースのMACアドレスを取得して、それを戻り値として返します。



DHCPのDiscoverを組み立てて、送信まで行う関数です。最初に定義したDHCPフォーマットの各フィールドに値を入れていきます。


op:クライアントからサーバに送るので、BOOTREQUESTを入れます。

htype:ハードウェアはethernetなので、値1を定義したHTYPE_ETHERを入れます。

hlen:ethernetアドレスは6バイトなので、値6を定義したHTYPE_ETHER_LENを入れます。

hops:リレーエージェントが何回経由したかを示すフィールドなので、クライアント側送信時点では0をセットします。

xid:トランザクションIDのことで、DiscoverからAckまで、DHCP一連の流れで一貫したランダム値が使われます。srandで現時刻を種として、ランダム値を生成し、それをxidにセットします。

secs:DHCPサーバによって払い出されたIPアドレスのリース残り期間を示しますが、Discoverの時点では0xFFをセットします。

flags:2Bytes(16Bits)の中の最初の1ビット目に1をセットし、残りのビットには0をセットします。

ciaddr, yiaddr, siaddr, giaddr:Discover送信時点では0が入ります。

chaddr:クライアントのMACアドレスが入ります。



Magic Cookieという0x63, 0x82, 0x53, 0x63の4バイト数字が必要です。実はDHCPプロトコルは、その前身であるBOOTP(Bootstrap Protocol)とフォーマットがほとんど同じです。なのでこのMagic Cookieで「このパケットは、BOOTPではなく、DHCPですよ」と識別しています。


あとはオプションを指定します。ここまででは「まだこのDHCPパケットはDiscoverですよ」という識別が出来ないので、オプションのMasic Cookieの次にMessage Typeとして、DHCP_DISCOVERを指定します。


main関数です。実行時に使用するインタフェース名を指定してます。
流れとしては、まずソケットを作成して、その次にそのソケットを使って、インタフェースのMACアドレスを取得します。そしてDHCPのDiscoverパケットを送信する関数に渡します。



実行結果は以下の感じになります。

ブロードキャストなので、DHCPサーバとDHCPクライアント(ゲストOS)以外のPC(ホストOS)でパケットキャプチャしました。



送信成功です!

最後まで読んでいただきありがとうございました。

-プログラミング

Copyright© MasaのITC Life , 2023 All Rights Reserved Powered by STINGER.