ifconfigコマンドでインターフェースの状態などが確認できます。そこで今回、プログラムを通してインターフェースの状態を取得してみます。
ifconfigでは、flagの値と何がONになっているのかが分かるので、プログラムでも同じものを情報を表示させていきます。
まずはインターフェースの現在の状態を取得するために、ioctlのSIOCGIFFLAGSを使います。ioctlは、ネットワークインターフェースの制御をしたりするシステムコールです。また、ioctlを使うにはソケットを開くことと、取得した情報の格納先であるifreq構造体が必要です。取得したインターフェースの状態はioctlによって、ifreq構造体のifr_flagsメンバに格納されます。
このとき得られるにはフラグ値です。このフラグ値は各モードのON/OFFを示すビット単位の値です。例えば、flags = 14が得られたとします。ここで二進数表記にすると1110なので、左から1~3桁目に該当するモードがONになっていることを意味します。
フラグ値が得られたら、ビットが1になっているモードをprintfで表示させます。
もしインターフェースの任意のモードのON/OFFを切り替える場合は、ソース中の//----------で囲ってあるところで変更できます。インターフェースの状態を取得・表示させるだけなら、//---------の中身は必要ありません。
インタフェースの状態を変更する場合は、まずはifreqのメンバのifr_flagsの値を書き換えます。例えばこのとき、プロミスキャスモード のビットだけを1もしくは0にするようにします。値を書き換えたら、ioctlのSIOCSIFFLAGSを使って、ifreqのifr_flagsをインターフェースの状態に反映させます。これだけで変更は可能です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
#include<stdio.h> #include<string.h> #include<sys/ioctl.h> #include<sys/socket.h> #include<net/if.h> #include<net/ethernet.h> #include<netpacket/packet.h> #include<arpa/inet.h> #include<linux/if.h> int main(void) { struct ifreq ifreq; int s=socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); if(s<0){ perror("socket"); } memset(&ifreq, 0, sizeof(struct ifreq)); strncpy(ifreq.ifr_name, "enp0s3", sizeof(ifreq.ifr_name)-1); if(ioctl(s, SIOCGIFFLAGS, &ifreq)!=0){ perror("ioctl"); return -1; } //------------------------------------------------- ifreq.ifr_flags = ifreq.ifr_flags | IFF_PROMISC; //ON //ifreq.ifr_flags = ifreq.ifr_flags & ~IFF_PROMISC; //OFF if(ioctl(s, SIOCSIFFLAGS, &ifreq)!=0){ perror("ioctl"); return -1; } //------------------------------------------------- printf("flags = %d\n", ifreq.ifr_flags); if(ifreq.ifr_flags & IFF_UP) printf("up\n"); //0x1 if(ifreq.ifr_flags & IFF_BROADCAST) printf("broadcasr\n"); //0x2 if(ifreq.ifr_flags & IFF_DEBUG) printf("debug\n"); //0x4 if(ifreq.ifr_flags & IFF_LOOPBACK) printf("loopback\n"); //0x8 if(ifreq.ifr_flags & IFF_POINTOPOINT) printf("p2p\n"); //0x10 if(ifreq.ifr_flags & IFF_NOTRAILERS) printf("notrailers"); //0x20 if(ifreq.ifr_flags & IFF_RUNNING) printf("runnig\n"); //0x40 if(ifreq.ifr_flags & IFF_NOARP) printf("noarp\n"); //0x80 if(ifreq.ifr_flags & IFF_PROMISC) printf("promisc\n"); //0x100 if(ifreq.ifr_flags & IFF_ALLMULTI) printf("allmulti\n"); //0x200 if(ifreq.ifr_flags & IFF_MASTER) printf("master\n"); //0x400 if(ifreq.ifr_flags & IFF_SLAVE) printf("slave\n"); //0x800 if(ifreq.ifr_flags & IFF_MULTICAST) printf("multicast\n"); //0x1000 if(ifreq.ifr_flags & IFF_PORTSEL) printf("portsel\n"); //0x2000 if(ifreq.ifr_flags & IFF_AUTOMEDIA) printf("automedia\n"); //0x4000 if(ifreq.ifr_flags & IFF_DYNAMIC) printf("dynamic\n"); //0x8000 if(ifreq.ifr_flags & IFF_LOWER_UP) printf("lower_up\n"); //0x10000 if(ifreq.ifr_flags & IFF_DORMANT) printf("dormant\n"); //0x20000 return 0; } |
コメントアウトで十六進数表記してあるのは、各モードが対応するビット桁です。
実行結果とifconfigを見比べてみると、しっかりとインターフェースの状態を取得出来ているのが確認できます。
最後まで読んでいただきありがとうございました。