ネットワークインターフェース情報の取得
JavaのNetworkInterfaceでgetName()メソッドを呼び出してもXP環境では文字化けして正しく表示できないばかりでなく、getByName()メソッドでは、通常Windowsで利用される"ローカル エリア接続"等では探すことが出来ません。
それで、自前でアドレス情報を取得したりインターフェースを探せるクラスを作ってみようと思います。
まず、C++でインターフェース情報を取得するクラスの作成から。
IPアドレスを保存するクラスとして
addrinfo.h
#include <windows.h> #include <tchar.h> #include <comdef.h> #include <iphlpapi.h> #define LOOPBACK_INTERFACE IF_TYPE_SOFTWARE_LOOPBACK #define IPADDR_PRIMARY MIB_IPADDR_PRIMARY #define IPADDR_DYNAMIC MIB_IPADDR_DYNAMIC #define DIRECT_ROUTE MIB_IPROUTE_TYPE_DIRECT #define INDIRECT_ROUTE MIB_IPROUTE_TYPE_INDIRECT #include <vector> #include <string> using namespace std; typedef basic_string<_TCHAR> String; class AddrInfo; typedef vector<AddrInfo> address_list; extern const String HOST_MASK; extern const String GATEWAY_NET; extern const String GATEWAY_MASK; class AddrInfo { private: static String getBcastAddr(DWORD ip, DWORD mask, DWORD type); public: AddrInfo(const AddrInfo& info); AddrInfo(String address, String mask = HOST_MASK, String bcast = String(_T("")), int type = 0); AddrInfo(); ~AddrInfo(); String getIpAddress(); String getNetMask(); String getBroadcastAddress(); int getIpType(); bool isPrimaryAddress(); static address_list setAddressList(int ifIndex); private: String ipAddress; String netMask; String bcastAddr; int ipType; };
addrinfo.cpp
#include "addrinfo.h" const String HOST_MASK = String(_T("255.255.255.255")); const String GATEWAY_NET = String(_T("0.0.0.0")); const String GATEWAY_MASK = String(_T("0.0.0.0")); // Copy Constructor AddrInfo::AddrInfo(const AddrInfo& info) { ipAddress = info.ipAddress; netMask = info.netMask; bcastAddr = info.bcastAddr; ipType = info.ipType; } // Constructor AddrInfo::AddrInfo(String address, String mask, String bcast, int type) { ipAddress = address; netMask = mask; if (!bcast.empty()) { bcastAddr = bcast; } else { bcastAddr = address; } ipType = type; } // Constructor AddrInfo::AddrInfo() { ipType = 0; } // Destructor AddrInfo::~AddrInfo() { } /* * IPアドレスを取得する * param : 無し * * return : String */ String AddrInfo::getIpAddress() { return ipAddress; } /* * ネットワークマスクを取得する * param : 無し * * return : String */ String AddrInfo::getNetMask() { return netMask; } /* * Broadcastアドレスを取得する * param : 無し * * return : String */ String AddrInfo::getBroadcastAddress() { return bcastAddr; } /* * IPアドレスのタイプを取得する * param : 無し * * return : int */ int AddrInfo::getIpType() { return ipType; } /* * IPアドレスがプライマリアドレスか確認する * param : 無し * * return : bool * true = プライマリアドレスである * false = プライマリアドレスでない */ bool AddrInfo::isPrimaryAddress() { return ((ipType & IPADDR_PRIMARY) > 0) ? true : false; } /* * IPアドレスとネットマスクからブロードキャストアドレスを取得する * param : IPアドレス(DWORD) * ネットマスク(DWORD) * IPタイプ(DWORD) * * return : String */ String AddrInfo::getBcastAddr(DWORD ip, DWORD mask, DWORD type) { DWORD bcast = (type == 1) ? 0xffffffff : 0x00000000; bcast ^= mask; DWORD network = ~bcast; network &= ip; bcast |= network; return String((_TCHAR*)_bstr_t(inet_ntoa(*(struct in_addr *)&bcast))); } /* * 指定したインターフェースに設定されたアドレスを取得する * param : インターフェースの番号(int) * * return : address_list */ address_list AddrInfo::setAddressList(int ifIndex) { address_list result; String ipaddress; String netmask; String bcastaddress; long retCode = NO_ERROR; DWORD dwSize = 0; GetIpAddrTable(NULL, &dwSize, 0); PMIB_IPADDRTABLE pIPAddrTable = (MIB_IPADDRTABLE *)malloc(dwSize); memset(pIPAddrTable, 0, dwSize); if (GetIpAddrTable(pIPAddrTable, &dwSize, 0) == NO_ERROR) { for (unsigned int num = 0; num < pIPAddrTable->dwNumEntries; num++) { if (ifIndex == pIPAddrTable->table[num].dwIndex) { ipaddress = String((_TCHAR *)_bstr_t(inet_ntoa(*(struct in_addr *)&pIPAddrTable->table[num].dwAddr))); netmask = String((_TCHAR *)_bstr_t(inet_ntoa(*(struct in_addr *)&pIPAddrTable->table[num].dwMask))); bcastaddress = getBcastAddr(pIPAddrTable->table[num].dwAddr, pIPAddrTable->table[num].dwMask, pIPAddrTable->table[num].dwBCastAddr); AddrInfo info = AddrInfo(ipaddress, netmask, bcastaddress, pIPAddrTable->table[num].wType); result.push_back(info); } } } free(pIPAddrTable); return result; }
インターフェース情報を保存するクラスとして
ifinfo.h
#include <vector> #include <string> #include <sstream> using namespace std; #include "addrinfo.h" typedef basic_string<_TCHAR> String; class IfInfo; typedef vector<IfInfo> interface_list; typedef interface_list::iterator if_iter; class IfInfo { private: static interface_list getInterfaceList(); static void loadInterfaceInfo(IfInfo *if_table); static String getMacAddress(unsigned char *value, unsigned long len); public: IfInfo(const IfInfo& info); IfInfo(); ~IfInfo(); unsigned long getIndex(); String getName(); String getAdapterName(); String getDescription(); String getMacAddress(); int getType(); int getOpStatus(); address_list getIpAddressList(); bool isDhcpEnabled(); bool isRunning(); static interface_list getIfList(); static IfInfo findInterfaceByIndex(unsigned long index); static IfInfo findInterfaceByName(String ifname); private: unsigned long ifIndex; String ifName; String adapterName; String description; String ifAddress; int ifType; int opStatus; address_list ipAddressList; bool dhcpEnabled; };
ifinfo.cpp
#include "ifinfo.h" /* * システムで利用可能なインターフェースの一覧を取得する * param : 無し * * return : interface_list */ interface_list IfInfo::getInterfaceList() { interface_list if_list; long retCode = NO_ERROR; DWORD dwSize = 0; GetIfTable(NULL, &dwSize, true); PMIB_IFTABLE pIfTable = (MIB_IFTABLE *)malloc(dwSize); memset(pIfTable, 0, dwSize); retCode = GetIfTable(pIfTable, &dwSize, true); if (retCode == NO_ERROR) { for (u_int i = 0; i < pIfTable->dwNumEntries; i++) { IfInfo if_table = IfInfo(); MIB_IFROW pInterface = pIfTable->table[i]; if_table.ifIndex = pInterface.dwIndex; basic_stringstream<_TCHAR> buf; buf << _bstr_t((char *)pInterface.bDescr); if_table.ifName = if_table.description = buf.str(); if_table.ifType = pInterface.dwType; if_table.opStatus = pInterface.dwOperStatus; if_list.push_back(if_table); } } free(pIfTable); return if_list; } String IfInfo::getMacAddress(unsigned char *value, unsigned long len) { _bstr_t mac; for (u_int i = 0; i < len; i++) { if (i > 0) mac += _T(":"); char code[3]; sprintf(code, "%02x", value[i]); mac += code; } return String((_TCHAR *)mac); } // interface_info // Copy Constructor IfInfo::IfInfo(const IfInfo& info) { ifIndex = info.ifIndex; ifName = info.ifName; adapterName = info.adapterName; description = info.description; ifAddress = info.ifAddress; ifType = info.ifType; opStatus = info.opStatus; dhcpEnabled = info.dhcpEnabled; if (info.ipAddressList.size() > 0) { for (size_t i = 0; i < info.ipAddressList.size(); i++) { ipAddressList.push_back(info.ipAddressList[i]); } } } // Constructor IfInfo::IfInfo() { } // Destructor IfInfo::~IfInfo() { } /* * インターフェースの詳細情報を設定する * param : インターフェーステーブル(IfInfoポインター) * * return : 無し */ void IfInfo::loadInterfaceInfo(IfInfo *if_table) { DWORD dwSize = 0; long retCode = NO_ERROR; if (GetAdaptersInfo(NULL, &dwSize) == ERROR_BUFFER_OVERFLOW) { PIP_ADAPTER_INFO pAdapterInfo = (IP_ADAPTER_INFO *)malloc(dwSize); memset(pAdapterInfo, 0, dwSize); retCode = GetAdaptersInfo(pAdapterInfo, &dwSize); if (retCode == NO_ERROR) { PIP_ADAPTER_INFO pAdapter = pAdapterInfo; while (pAdapter) { if (pAdapter->Index == if_table->ifIndex) { if_table->adapterName = String((_TCHAR *)_bstr_t(pAdapter->AdapterName)); if_table->ifAddress = getMacAddress(pAdapter->Address, pAdapter->AddressLength); if_table->ipAddressList = AddrInfo::setAddressList(if_table->ifIndex); if_table->dhcpEnabled = pAdapter->DhcpEnabled ? true : false; HKEY hkey = NULL; _bstr_t adapter = _bstr_t(_T("SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\")); adapter += _bstr_t((char *)pAdapter->AdapterName); adapter += _bstr_t(_T("\\Connection")); int rc = RegOpenKeyEx(HKEY_LOCAL_MACHINE, (_TCHAR *)adapter, 0, KEY_READ, &hkey); if (rc == ERROR_SUCCESS) { DWORD valueType = 0; DWORD nameLen = 0; rc = RegQueryValueEx(hkey, _T("Name"), 0, &valueType, NULL, &nameLen); nameLen++; char *buff = (char *)calloc(nameLen, sizeof(char)); rc = RegQueryValueEx(hkey, _T("Name"), 0, &valueType, (LPBYTE)buff, &nameLen); RegCloseKey(hkey); basic_stringstream<_TCHAR> buf; buf << _bstr_t((_TCHAR *)buff); if_table->ifName = buf.str(); free(buff); } } pAdapter = pAdapter->Next; } free(pAdapterInfo); } } } /* * インターフェースの名前を取得する * param : 無し * * return : String */ String IfInfo::getName() { return ifName; } /* * インターフェースのアダプタ名を取得する * param : 無し * * return : String */ String IfInfo::getAdapterName() { return adapterName; } /* * インターフェースの説明を取得する * param : 無し * * return : String */ String IfInfo::getDescription() { return description; } /* * インターフェースのMACアドレスを取得する * param : 無し * * return : String */ String IfInfo::getMacAddress() { return ifAddress; } /* * インターフェースの番号を取得する * param : 無し * * return : u_long */ u_long IfInfo::getIndex() { return ifIndex; } /* * インターフェースのタイプを取得する * param : 無し * * return : int */ int IfInfo::getType() { return ifType; } /* * インターフェースのステータスを取得する * param : 無し * * return : int */ int IfInfo::getOpStatus() { return opStatus; } /* * インターフェースのアドレスリストを取得する * param : 無し * * return : address_list */ address_list IfInfo::getIpAddressList() { return ipAddressList; } /* * インターフェースがDHCPに設定されているか確認する * param : 無し * * return : bool * true = DHCPである * false = DHCPでない */ bool IfInfo::isDhcpEnabled() { return dhcpEnabled; } /* * インターフェースが動作中か確認する * param : 無し * * return : bool * true = 動作中である * false = 動作中でない */ bool IfInfo::isRunning() { return (opStatus == IF_OPER_STATUS_OPERATIONAL) ? true : false; } /* * システムで利用可能なインターフェースの一覧を取得する * param : 無し * * return : interface_list */ interface_list IfInfo::getIfList() { interface_list net_list = getInterfaceList(); for (if_iter if_ent = net_list.begin(); if_ent != net_list.end(); if_ent++) { IfInfo::loadInterfaceInfo(&(*if_ent)); } return net_list; } /* * インターフェースの一覧からインターフェース番号の情報を取得する * param : インターフェース番号(u_long) * * return : IfInfo */ IfInfo IfInfo::findInterfaceByIndex(unsigned long index) { IfInfo if_table; interface_list net_list = getInterfaceList(); for (if_iter if_ent = net_list.begin(); if_ent != net_list.end(); if_ent++) { if ((*if_ent).getIndex() == index) { IfInfo::loadInterfaceInfo(&(*if_ent)); return *if_ent; } } return if_table; } /* * インターフェースの一覧からインターフェース名の情報を取得する * param : インターフェース名(charポインター) * * return : IfInfo */ IfInfo IfInfo::findInterfaceByName(String ifname) { IfInfo if_table; interface_list net_list = getIfList(); for (if_iter if_ent = net_list.begin(); if_ent != net_list.end(); if_ent++) { if ((*if_ent).getName().compare(ifname) == 0) { IfInfo::loadInterfaceInfo(&(*if_ent)); return *if_ent; } } return if_table; }
テストの為に次のプログラムを実行して確認。
#include <windows.h> #include <string> #include <iostream> using namespace std; #include <addrinfo.h> #include <ifinfo.h> using namespace penguin; #ifdef _UNICODE #define COUT wcout #define CIN wcin #else #define COUT cout #define CIN cin #endif // _UNICODE void getAddress() { for (int i = 0; i < 256; i++) { address_list list = AddrInfo::setAddressList(i); for (size_t j = 0; j < list.size(); j++) { AddrInfo info = list.at(j); COUT << _T("Index : ") << i << _T("-") << info.getIpAddress() << endl; } } } void getInterface() { interface_list list = IfInfo::getIfList(); for (size_t j = 0; j < list.size(); j++) { IfInfo info = list.at(j); COUT << _T("Index : ") << info.getIndex() << _T("-") << info.getDescription() << _T("-") << info.getName() << endl; } IfInfo intInfo = IfInfo::findInterfaceByName(String(_T("ローカル エリア接続 3"))); COUT << _T("Index : ") << intInfo.getIndex() << _T("-") << intInfo.getDescription() << _T("-") << intInfo.getName() << endl; } int _tmain(int argc, _TCHAR* argv[]) { getAddress(); getInterface(); return 0; }
このプログラムをベースにJNIでJavaからのアクセスクラスを作成します。