Windowsプログラミング
アルゴリズム Vitual C++ 2008/2013によるWin32/Win64 APIレベルのプログラム 基礎 Vitual C++ 2008/2013によるAPIレベルのプログラム(32/64bit) Wix3でインストーラーを作る Visual C++ 2008 Standard Editonによるフォームアプリケーションのプログラム(32/64bit) Vitual C++ 2008 Standard EditonによるAPIレベルのプログラム(32/64bit) Windows 7対応 Visual C++ 2008 ExpressによるAPIレベルのプログラム Visual C++ 2005 ExpressによるAPIレベルのプログラム Visual C++ Versiosn 5 BORLAND C++ Windowsプログラム全般 Excel VBA その他
概要
プログラムソース内で定義されているIPアドレス範囲(192.168.0.0~192.168.0.254)にpingを実行し、応答があればホスト名及びmacアドレスを取得します。
プログラムはコマンドラインで動作します。(IPv4専用)
表示内容は、応答があったIPアドレスとtimeはパケット送信から受信までの時間(ミリ秒)、TTLはIPパケットの生存時間、macアドレス、ホスト名、ベンダー名である。
ベンダー名の一覧は、IEEE-SAのホームページの下のほうのDownload a copyより本プログラムが自動的に取得し、macアドレスと一致するベンダーを表示します。
テスト環境
コンパイラ
Visual C++ 2008/2013 Express 32/64bit マルチバイト/UNICODE実行環境
Windows XP Professional Service Pack 3 32bit(Virtual Box上の仮想マシーン)Windows 7 Enterprise Service Pack 1 64bit
プログラムソースの概要
ping2.cpp
_tmain
カレントフォルダーにIEEE-SAサイトからダウンロードしたoui.txtファイルがあればこれを開きます。ファイルがなければインターネットからダウンロードします。
get_mac_vendor関数によりファイルを読み取り、macアドレスとベンダー名の一覧(vendor_vec)を作成します。
IcmpCreateFile APIによりハンドルを作成します。
IPアドレスは、for文の中の配列ipで定義しています。(ビックエンディアンで設定)
IcmpSendEcho APIでpingを実行します。引数で送信するデータサイズやタイムアウトなどを指定できます。ここではマクロBUF_SIZEで32byteのデータサイズ及び2000ミリ秒をタイムアウト値としています。
APIが正常値を返した場合、SendARP APIによりIPアドレスからmacアドレスを取得します。
macアドレスよりmac2vendor_name関数によりベンダー名を取得します。
gethostbyaddr APIによりIPアドレスからホスト名を取得します。このAPI実行にはWINSOCKの初期化が必要であるため、WSAStartup APIをあらかじめ実行しておきます。
なぜかこのAPIはUNICODE版がないので、MultiByteToWideChar APIによりUNICODEに変換します。
for文のループから抜けたら、IcmpCloseHandle APIによりハンドルの開放、WSACleanup APIによりWINSOCKの開放を行います。
get_mac_vendor
ファイルよりmacアドレスとベンダー名の対応を一覧を作成します。一覧はvendor_vecに保存されます。
mac2vendor_name
macアドレスよりベンダー名を取得します。該当するmacアドレスがない場合は文字列errorを返します。ソースコード
ping2.cpp
// 指定した範囲のIPアドレスにPINGを実行し、レスポンスがあればマックアドレスとベンダー名およびホスト名を表示
// 2014/07/20
#include <stdio.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <iphlpapi.h>
#include <icmpapi.h>
#include <wininet.h>
#include <locale.h>
#include <tchar.h>
#include <vector>
#pragma comment(lib,"iphlpapi.lib")
#pragma comment(lib,"Ws2_32.lib") // gethostbyaddr関数に必要
#pragma comment(lib,"wininet.lib")
#define BUF_SIZE 32
struct VENDOR_ID{
unsigned char mac[3]; // macアドレス 上位3byte
TCHAR* name; // ベンダー名
void put(FILE* fp){
_ftprintf(fp,_TEXT("%02x:%02x:%02x\t%s\n"),mac[0],mac[1],mac[2],name);
}
bool cmp(unsigned char* src_mac){
if(mac[0]==src_mac[0] && mac[1]==src_mac[1] && mac[2]==src_mac[2])
return true;
else
return false;
}
};
using namespace std;
vector<VENDOR_ID> vendor_vec; // macアドレスとベンダー名の一覧
// macアドレスよりベンダー名を取得する
TCHAR* mac2vendor_name(unsigned char* src_mac);
// macアドレスとベンダー名の対応を一覧する
void vendor_fput(FILE* fp);
// macアドレスとベンダー名の対応を一覧する
void vendor_fput(FILE* fp);
// ファイルよりmacアドレスとベンダー名の対応を一覧を作成する
void get_mac_vendor(FILE* fp);
void _tmain(void){
_tsetlocale(LC_ALL,_TEXT("")); // UNICODE文字を標準出力に正しく表示できるように設定
FILE* fp;
// ファイルが開けない場合、インターネットから取得しファイルに保存後、再度ファイルを開く
if(_tfopen_s(&fp,_TEXT("oui.txt"),_TEXT("r"))){
_tprintf(_TEXT("ファイルが開けないのでインターネットから取得します\nhttp://standards.ieee.org/develop/regauth/oui/oui.txt\n"));
if(_tfopen_s(&fp,_TEXT("oui.txt"),_TEXT("wb"))){
_tprintf(_TEXT("ファイルが開けません。\n"));
return;
}
HINTERNET hInet, hUrl;
//インターネット(WinInet)開始
hInet = InternetOpen(_TEXT("xyz-123"),
INTERNET_OPEN_TYPE_PRECONFIG,
NULL, NULL, 0);
if (hInet == NULL) {
_tprintf(_TEXT("インタネットから取得できませんでした。\n"));
return;
}
//HTTPセッションの開始, 指定のURLオープン
hUrl = InternetOpenUrl(hInet, _TEXT("http://standards.ieee.org/develop/regauth/oui/oui.txt"), NULL, 0, 0, 0);
if (hUrl == NULL) {
_tprintf(_TEXT("インタネットから取得できませんでした。\n"));
InternetCloseHandle(hInet);
return;
}
char szBuf[1024];
DWORD dwRead = 0;
//読み出す物がなくなるまで読み出す
while (1) {
InternetReadFile(hUrl, szBuf, (DWORD)sizeof(szBuf), &dwRead);
//読み出す物がなくなったのでループ脱出
if (dwRead == 0)
break;
fwrite(szBuf,1,dwRead,fp);
}
fclose(fp);
if(_tfopen_s(&fp,_TEXT("oui.txt"),_TEXT("r"))){
_tprintf(_TEXT("ファイルが開けません。\n"));
return;
}
//インターネットハンドルの解放
InternetCloseHandle(hUrl);
InternetCloseHandle(hInet);
}
get_mac_vendor(fp);
fclose(fp);
#ifdef _DEBUG
if(_tfopen_s(&fp,_TEXT("vendor.txt"),_TEXT("w"))){
_tprintf(_TEXT("ファイルが開けません。\n"));
return;
}
vendor_fput(fp);
fclose(fp);
#endif
HANDLE hIcmp;
IPAddr ipaddr;
hIcmp=IcmpCreateFile();
char cbRequest[BUF_SIZE]; // 送信するデータ
memset(cbRequest,'a',BUF_SIZE); // 送信するデータを設定
DWORD cbReply=sizeof(ICMP_ECHO_REPLY)+BUF_SIZE;
char* pReply=new char[cbReply]; // 受信するヘッダー + 受信するデータ
PICMP_ECHO_REPLY p=(PICMP_ECHO_REPLY)pReply;
WSADATA wsaData;
int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData); // WINSOCKを初期化
unsigned char* ip=(unsigned char*)&ipaddr;
_tprintf(_TEXT("IPアドレス time TTL マックアドレス ベンダー名\tホスト名\n"));
for(unsigned n=0;n<=244;n++){ // IPアドレスの検索範囲を設定している
ip[0]=192; // IPアドレス ビックエンディアンで設定
ip[1]=168;
ip[2]=0;
ip[3]=n;
_tprintf(_TEXT("%3i.%3i.%3i.%3i\r"),ip[0],ip[1],ip[2],ip[3]);
// pingを実行
// IPアドレス 送信データ データーサイズ タイムアウトms
DWORD ret=IcmpSendEcho( hIcmp ,ipaddr , cbRequest ,BUF_SIZE , NULL , pReply , cbReply , 2000);
if(ret){ // pingが成功した
unsigned char mac[6];
struct hostent* hostp;
ULONG len=sizeof(mac)/sizeof(unsigned char);
if(SendARP(ipaddr,NULL,mac,&len)==NO_ERROR){ // IPアドレスからmacアドレスを取得
hostp=gethostbyaddr((const char*)ip,4,AF_INET); // IPアドレスからホスト名を取得
TCHAR buf[64];
if(hostp)
#ifdef UNICODE
// UNICODEに変換
MultiByteToWideChar(932,0,hostp->h_name,-1,buf,sizeof(buf)/sizeof(TCHAR));
#else
_tcscpy_s(buf,sizeof(buf)/sizeof(TCHAR),hostp->h_name);
#endif
else
buf[0]=_T('\0');
_tprintf(_TEXT("%3i.%3i.%3i.%3i "),ip[0],ip[1],ip[2],ip[3]);
_tprintf(_TEXT("%4d %4d %02x:%02x:%02x:%02x:%02x:%02x %s\t%s\n"),p->RoundTripTime,p->Options.Ttl,mac[0],mac[1],mac[2],mac[3],mac[4],mac[5],mac2vendor_name(mac),buf);
}
}else{ // pingに失敗した場合
}
}
delete [] pReply;
IcmpCloseHandle(hIcmp);
WSACleanup();
}
// macアドレスよりベンダー名を取得する
TCHAR* mac2vendor_name(unsigned char* src_mac){
for(unsigned n=0;n<vendor_vec.size();n++){
if(vendor_vec[n].cmp(src_mac)==true)
return vendor_vec[n].name;
}
return _TEXT("error");
}
// macアドレスとベンダー名の対応を一覧する
void vendor_fput(FILE* fp){
for(unsigned n=0;n<vendor_vec.size();n++){
vendor_vec[n].put(fp);
}
}
// ファイルよりmacアドレスとベンダー名の対応を一覧を作成する
void get_mac_vendor(FILE* fp){
TCHAR buf[256];
int f=1;
int len;
TCHAR* top;
TCHAR* p;
VENDOR_ID id;
while(_fgetts(buf,sizeof(buf)/sizeof(TCHAR),fp)){
top=buf;
while(*top){
if(*top!=_T(' '))
break;
++top;
}
if(f==1){
len=(int)_tcslen(top);
if(10<=len){
if(_istxdigit(top[0]) && top[2]==_T('-')){
f=2;
}
}
}
switch(f){
case 2:{
TCHAR* name=top;
id.mac[0]=(unsigned char)_tcstol(top,NULL,16);
id.mac[1]=(unsigned char)_tcstol(top+3,NULL,16);
id.mac[2]=(unsigned char)_tcstol(top+6,NULL,16);
while(*name){
if(*name==_T(' '))
break;
++name;
}
while(*name){
if(*name!=_T(' '))
break;
++name;
}
while(*name){
if(*name==_T(')'))
break;
++name;
}
while(*name){
if(*name!=_T('\t'))
break;
++name;
}
name+=3;
p=name;
while(*p){
if(*p==_T('\n') || *p==_T('\r') || *p==_T('\t'))
*p=_T('\0');
++p;
}
id.name=_tcsdup(name);
vendor_vec.push_back(id);
f=1;
break;
}
}
}
}
Copyright (C) 2012 山本ワールド All Rights Reserved.