// Copyright (c) 2011. All rights reserved.
//
// Author: Abbott.Li <412472243@qq.com>
// Date: 2011/11/6
//
// Network utility function
#include "network_util.h"
#include <sstream>
#include <stdlib.h>
#if defined (OS_WIN)
#include <nb30.h>
#include <snmp.h>
#include <iphlpapi.h>
#else
#include <net/if_dl.h>
#if defined (OS_IOS) && !defined (IFT_ETHER)
#define IFT_ETHER 0x06 /* Ethernet CSMACD */
#else
#include <net/if_types.h>
#endif
#include <ifaddrs.h>
#endif
namespace nbase
{
bool GetIpAddressList(std::vector<uint32_t> &ip_addresses)
{
ip_addresses.clear();
char host_name[128];
if (::gethostname(host_name, sizeof(host_name)) == 0)
{
struct hostent *host;
host = ::gethostbyname(host_name);
for (int i = 0; host != NULL && host->h_addr_list[i] != NULL; ++i)
{
char *ip = ::inet_ntoa(*(struct in_addr*)host->h_addr_list[i]);
if (ip)
{
ip_addresses.push_back(InetStringToNumber(ip));
}
}
}
return ip_addresses.size() > 0;
}
bool GetIpAddressList(std::vector<std::string> &ip_addresses)
{
ip_addresses.clear();
char host_name[128];
std::string ip_address;
if (::gethostname(host_name, 128) == 0)
{
struct hostent *host;
host = ::gethostbyname(host_name);
for (int i = 0; host != NULL && host->h_addr_list[i] != NULL; ++i)
{
char *ip = ::inet_ntoa(*(struct in_addr*)host->h_addr_list[i]);
if (ip)
{
ip_address.assign(ip, strlen(ip));
ip_addresses.push_back(ip_address);
}
}
}
return ip_addresses.size() > 0;
}
#if defined(OS_WIN)
typedef struct _ASTAT
{
ADAPTER_STATUS adapt;
NAME_BUFFER NameBuffer[30];
}ASTAT, *PASTAT;
//通过NetBIOS获取MAC地址
bool GetMacAddressByNetBIOS(std::string &mac_address)
{
ASTAT Adapter;
NCB Ncb;
UCHAR uRetCode;
LANA_ENUM lenum;
int i;
memset(&Ncb, 0, sizeof(Ncb));
Ncb.ncb_command = NCBENUM;
Ncb.ncb_buffer = (UCHAR *)&lenum;
Ncb.ncb_length = sizeof(lenum);
uRetCode = Netbios(&Ncb);
for (i=0; i < lenum.length; ++i)
{
memset(&Ncb, 0, sizeof(Ncb));
Ncb.ncb_command = NCBRESET;
Ncb.ncb_lana_num = lenum.lana[i];
uRetCode = Netbios(&Ncb);
memset(&Ncb, 0, sizeof(Ncb));
Ncb.ncb_command = NCBASTAT;
Ncb.ncb_lana_num = lenum.lana[i];
strcpy((char *)Ncb.ncb_callname, "* ");
Ncb.ncb_buffer = (unsigned char *)&Adapter;
Ncb.ncb_length = sizeof(Adapter);
uRetCode = Netbios(&Ncb);
if (uRetCode == 0)
{
if (Adapter.adapt.adapter_address[0]+
Adapter.adapt.adapter_address[1]+
Adapter.adapt.adapter_address[2]+
Adapter.adapt.adapter_address[3]+
Adapter.adapt.adapter_address[4]+
Adapter.adapt.adapter_address[5]!=0)
{
StringPrintf(mac_address, "%02x-%02x-%02x-%02x-%02x-%02x",
Adapter.adapt.adapter_address[0],
Adapter.adapt.adapter_address[1],
Adapter.adapt.adapter_address[2],
Adapter.adapt.adapter_address[3],
Adapter.adapt.adapter_address[4],
Adapter.adapt.adapter_address[5]);
return true;
}
}
}
return false;
}
/*
bool ParseMac(const std::string &input, std::string &mac_address)
{
//using boost
const static boost::regex expression(
"([0-9a-fA-F]{2})-([0-9a-fA-F]{2})-([0-9a-fA-F]{2})-([0-9a-fA-F]{2})-([0-9a-fA-F]{2})-([0-9a-fA-F]{2})",
boost::regex::perl | boost::regex::icase);
boost::cmatch what;
if(boost::regex_search(input.c_str(), what, expression))
{
mac_address = what[1] + "-" + what[2] + "-" + what[3] + "-" + what[4] + "-" + what[5] + "-" + what[6];
return true;
}
return false;
}
//通过对控制台ipconfig /all命令重定向
bool GetMacAddressByCmd(std::string &mac_address)
{
bool ret = false;
//初始化返回MAC地址缓冲区
SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;
//创建管道
HANDLE read_pipe = NULL;
HANDLE write_pipe = NULL;
if(CreatePipe(&read_pipe, &write_pipe, &sa, 0) == TRUE)
{
//控制命令行窗口信息
STARTUPINFO si;
memset(&si, 0, sizeof(si));
//返回进程信息
PROCESS_INFORMATION pi;
si.cb = sizeof(STARTUPINFO);
GetStartupInfo(&si);
si.hStdError = write_pipe;
si.hStdOutput = write_pipe;
si.wShowWindow = SW_HIDE; //隐藏命令行窗口
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
//创建获取命令行进程
if (::CreateProcessW(NULL, L"ipconfig /all", NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi) == TRUE)
{
WaitForSingleObject(pi.hProcess, 3000); // 设置超时时间,防止Vista、Win7等操作系统卡死
unsigned long count;
CloseHandle(write_pipe);
std::string buffer(1024 * 10, '\0'); // 准备足够大的缓冲区
if(ReadFile(read_pipe, const_cast<char*>(buffer.data()), buffer.size() - 1, &count, 0) == TRUE)
{
buffer.resize(buffer.find_first_of('\0')); // 截掉缓冲区后面多余的'\0'
ret = ParseMac(buffer, mac_address);//提取MAC地址串
}
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
}
CloseHandle(write_pipe); // VS2010下调试,此处会有“An invalid handle was specified”的中断,直接运行正常,原因未知。VS2008上正常。
CloseHandle(read_pipe);
}
return ret;
}*/
//通过SNMP(简单网络访问协议)
bool GetMacAddressBySNMP(std::string &mac_address)
{
bool ret = false;
WSADATA winsock_data;
if (WSAStartup(MAKEWORD(2, 0), &winsock_data) != 0)
return false;
// Load the SNMP dll and get the addresses of the functions necessary
const HINSTANCE m_dll = LoadLibrary(L"inetmib1.dll");
if (m_dll < (HINSTANCE) HINSTANCE_ERROR)
return false;
const PFNSNMPEXTENSIONINIT f_SnmpExtensionInit = (PFNSNMPEXTENSIONINIT) GetProcAddress(m_dll, "SnmpExtensionInit");
// const PFNSNMPEXTENSIONINITEX f_SnmpExtensionInitEx = (PFNSNMPEXTENSIONINITEX) GetProcAddress(m_dll, "SnmpExtensionInitEx");
const PFNSNMPEXTENSIONQUERY f_SnmpExtensionQuery = (PFNSNMPEXTENSIONQUERY) GetProcAddress(m_dll, "SnmpExtensionQuery");
// const PFNSNMPEXTENSIONTRAP f_SnmpExtensionTrap = (PFNSNMPEXTENSIONTRAP) GetProcAddress(m_dll, "SnmpExtensionTrap");
HANDLE poll_for_trap_event;
AsnObjectIdentifier supported_view;
f_SnmpExtensionInit(GetTickCount(), &poll_for_trap_event, &supported_view);
// Initialize the variable list to be retrieved by f_SnmpExtensionQuery
const AsnObjectIdentifier MIB_NULL = { 0, 0 };
RFC1157VarBind var_bind[2];
var_bind[0].name = MIB_NULL;
var_bind[1].name = MIB_NULL;
RFC1157VarBindList var_bind_list;
var_bind_list.list = var_bind;
UINT OID_ifEntryType[] = { 1, 3, 6, 1, 2, 1, 2, 2, 1, 3 };
UINT OID_ifEntryNum[] = { 1, 3, 6, 1, 2, 1, 2, 1 };
UINT OID_ipMACEntAddr[] = { 1, 3, 6, 1, 2, 1, 2, 2, 1, 6 };
AsnObjectIdentifier MIB_ifMACEntAddr = { sizeof(OID_ipMACEntAddr) / sizeof(UINT), OID_ipMACEntAddr };
AsnObjectIdentifier MIB_ifEntryType = { sizeof(OID_ifEntryType) / sizeof(UINT), OID_ifEntryType };
AsnObjectIdentifier MIB_ifEntryNum = { sizeof(OID_ifEntryNum) / sizeof(UINT), OID_ifEntryNum };
// Copy in the OID to find the number of entries in the Inteface table
var_bind_list.len = 1; // Only retrieving one item
SnmpUtilOidCpy(&var_bind[0].name, &MIB_ifEntryNum);
AsnInteger errorStatus;
AsnInteger errorIndex;
f_SnmpExtensionQuery(ASN_RFC1157_GETNEXTREQUEST, &var_bind_list, &errorStatus, &errorIndex);
var_bind_list.len = 2;
// Copy in the OID of ifType, the type of interface
SnmpUtilOidCpy(&var_bind[0].name,