关于获得网卡mac地址问题

cnlm2 2013-09-12 04:14:22
我用 getsockname 获得 socket 的ip地址,然后再使用SendARP 来获得目的ip网卡的mac地址,如果是PPPOE拨号连接的话,就会变成获得PPPOE连接的MAC了

有什么办法知道这个PPPOE连接所使用的物理网卡吗?

...全文
307 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
halleyzhang3 2013-09-16
  • 打赏
  • 举报
回复
取MAC做机器码不太可靠,因为有USB无线网卡这种东西。还是CPUID好一些。
cnlm2 2013-09-13
  • 打赏
  • 举报
回复
引用 7 楼 spirit008 的回复:
这是某知名软件的方式,也挺省事的,用着也没什么问题
// 判断MAC地址是否有效
bool peerid::invalid_mac_address(const BYTE* mac_ptr, const std::vector<std::string>& invalid_mac_v)
{
	if (invalid_mac_v.empty())
	{
		return ((mac_ptr[0] == 0x44 && mac_ptr[1] == 0x45 && mac_ptr[2] == 0x53 && mac_ptr[3] == 0x54)
			|| (mac_ptr[0] == 0xff && mac_ptr[1] == 0xff && mac_ptr[2] == 0xff && mac_ptr[3] == 0xff && mac_ptr[4] == 0xff && mac_ptr[5] == 0xff )
			|| (mac_ptr[0] == 0x00 && mac_ptr[1] == 0x00 && mac_ptr[2] == 0x00 && mac_ptr[3] == 0x00 && mac_ptr[4] == 0x00 && mac_ptr[5] == 0x00 )
			|| (mac_ptr[0] == 0x00 && mac_ptr[1] == 0x50 && mac_ptr[2] == 0x56 && mac_ptr[3] == 0xc0)
			|| (mac_ptr[0] == 0x00 && mac_ptr[1] == 0xe0 && mac_ptr[2] == 0x06 && mac_ptr[3] == 0x09 && mac_ptr[4] == 0x55 && mac_ptr[5] == 0x66 )
			|| (mac_ptr[0] == 0x02 && mac_ptr[1] == 0x00 && mac_ptr[2] == 0x4c && mac_ptr[3] == 0x4f && mac_ptr[4] == 0x4f && mac_ptr[5] == 0x50 )
			/*
			02004C4F4F50 :Microsoft Loopback Adapter

			00e006095566
			This was one of those SiS-chipset motherboards with the integrated NIC 
			whose MAC addresses are all the same - 
			//someone:
			Miles said that if he installs the patch to enable the correct MAC address, 
			he wouldn't be charged. This is what he/she promised to do.					 
			*/
			//filter special mac:0250F23D0001	0600AF090C00
			|| (mac_ptr[0] == 0x02 && mac_ptr[1] == 0x50 && mac_ptr[2] == 0xF2 && mac_ptr[3] == 0x3D && mac_ptr[4] == 0x00 && mac_ptr[5] == 0x01 )
			|| (mac_ptr[0] == 0x06 && mac_ptr[1] == 0x00 && mac_ptr[2] == 0xAF && mac_ptr[3] == 0x09 && mac_ptr[4] == 0x0C && mac_ptr[5] == 0x00 ));
	}
	else
	{
		std::string mac_str;
		for (unsigned i = 0; i < 6; i ++)
		{
			mac_str.append( char_2_hex( mac_ptr[i]) );
		}
		const char * mac_buffer = mac_str.c_str();
		for (unsigned k = 0; k < invalid_mac_v.size(); k++)
		{
            unsigned j;
			for(j = 0; j < 12; j ++)
			{
				if (mac_buffer[j] != invalid_mac_v[k][j] && invalid_mac_v[k][j] != 'N')
				{
					break;
				}
			}
			if (j == 12)
			{
				return true;
			}
		}
		return false;
	}
}

// 获取MAC地址
bool peerid::get_mac_address(std::string& result)
{
	result = "";

	// 读取无效MAC地址列表
	std::vector<std::string> filter_peerids;
	unsigned filter_num = 0;

	// 获取本机MAC地址
	IP_ADAPTER_INFO Data[12];
	PIP_ADAPTER_INFO pDatas = Data;
	ULONG len = sizeof(IP_ADAPTER_INFO) * 12;
	if ((GetAdaptersInfo(pDatas, &len)) == ERROR_SUCCESS)
	{
		for (int i=1; i<12; i++)
		{
			string desc = pDatas->Description;
			if (desc.find("PPP", 0) != desc.npos
				|| desc.find("VMare", 0) != desc.npos
				|| desc.find("Virtual", 0) != desc.npos
				|| desc.find("SLIP", 0) != desc.npos
				|| desc.find("P.P.P", 0) != desc.npos
				|| invalid_mac_address(pDatas->Address, filter_peerids) )
			{
				pDatas = pDatas->Next;
				if (pDatas == NULL)
				{
					break;
				}
			}
			else
			{				
				for (int j=5; j>=0; j--)
				{
					result.append(1, pDatas->Address[j]);
				}
				return true;
			}
		}
	}

	return false;
}
哥们,谢谢你!借鉴你的代码,稍微修改了下,你的代码是找到一个就return true 我找到符合条件的,然后进行一次字符串排序,然后取最小的mac 现在放在服务器上测试,取mac基本上没什么问题了!
木头菇 2013-09-12
  • 打赏
  • 举报
回复
这是某知名软件的方式,也挺省事的,用着也没什么问题
// 判断MAC地址是否有效
bool peerid::invalid_mac_address(const BYTE* mac_ptr, const std::vector<std::string>& invalid_mac_v)
{
	if (invalid_mac_v.empty())
	{
		return ((mac_ptr[0] == 0x44 && mac_ptr[1] == 0x45 && mac_ptr[2] == 0x53 && mac_ptr[3] == 0x54)
			|| (mac_ptr[0] == 0xff && mac_ptr[1] == 0xff && mac_ptr[2] == 0xff && mac_ptr[3] == 0xff && mac_ptr[4] == 0xff && mac_ptr[5] == 0xff )
			|| (mac_ptr[0] == 0x00 && mac_ptr[1] == 0x00 && mac_ptr[2] == 0x00 && mac_ptr[3] == 0x00 && mac_ptr[4] == 0x00 && mac_ptr[5] == 0x00 )
			|| (mac_ptr[0] == 0x00 && mac_ptr[1] == 0x50 && mac_ptr[2] == 0x56 && mac_ptr[3] == 0xc0)
			|| (mac_ptr[0] == 0x00 && mac_ptr[1] == 0xe0 && mac_ptr[2] == 0x06 && mac_ptr[3] == 0x09 && mac_ptr[4] == 0x55 && mac_ptr[5] == 0x66 )
			|| (mac_ptr[0] == 0x02 && mac_ptr[1] == 0x00 && mac_ptr[2] == 0x4c && mac_ptr[3] == 0x4f && mac_ptr[4] == 0x4f && mac_ptr[5] == 0x50 )
			/*
			02004C4F4F50 :Microsoft Loopback Adapter

			00e006095566
			This was one of those SiS-chipset motherboards with the integrated NIC 
			whose MAC addresses are all the same - 
			//someone:
			Miles said that if he installs the patch to enable the correct MAC address, 
			he wouldn't be charged. This is what he/she promised to do.					 
			*/
			//filter special mac:0250F23D0001	0600AF090C00
			|| (mac_ptr[0] == 0x02 && mac_ptr[1] == 0x50 && mac_ptr[2] == 0xF2 && mac_ptr[3] == 0x3D && mac_ptr[4] == 0x00 && mac_ptr[5] == 0x01 )
			|| (mac_ptr[0] == 0x06 && mac_ptr[1] == 0x00 && mac_ptr[2] == 0xAF && mac_ptr[3] == 0x09 && mac_ptr[4] == 0x0C && mac_ptr[5] == 0x00 ));
	}
	else
	{
		std::string mac_str;
		for (unsigned i = 0; i < 6; i ++)
		{
			mac_str.append( char_2_hex( mac_ptr[i]) );
		}
		const char * mac_buffer = mac_str.c_str();
		for (unsigned k = 0; k < invalid_mac_v.size(); k++)
		{
            unsigned j;
			for(j = 0; j < 12; j ++)
			{
				if (mac_buffer[j] != invalid_mac_v[k][j] && invalid_mac_v[k][j] != 'N')
				{
					break;
				}
			}
			if (j == 12)
			{
				return true;
			}
		}
		return false;
	}
}

// 获取MAC地址
bool peerid::get_mac_address(std::string& result)
{
	result = "";

	// 读取无效MAC地址列表
	std::vector<std::string> filter_peerids;
	unsigned filter_num = 0;

	// 获取本机MAC地址
	IP_ADAPTER_INFO Data[12];
	PIP_ADAPTER_INFO pDatas = Data;
	ULONG len = sizeof(IP_ADAPTER_INFO) * 12;
	if ((GetAdaptersInfo(pDatas, &len)) == ERROR_SUCCESS)
	{
		for (int i=1; i<12; i++)
		{
			string desc = pDatas->Description;
			if (desc.find("PPP", 0) != desc.npos
				|| desc.find("VMare", 0) != desc.npos
				|| desc.find("Virtual", 0) != desc.npos
				|| desc.find("SLIP", 0) != desc.npos
				|| desc.find("P.P.P", 0) != desc.npos
				|| invalid_mac_address(pDatas->Address, filter_peerids) )
			{
				pDatas = pDatas->Next;
				if (pDatas == NULL)
				{
					break;
				}
			}
			else
			{				
				for (int j=5; j>=0; j--)
				{
					result.append(1, pDatas->Address[j]);
				}
				return true;
			}
		}
	}

	return false;
}
木头菇 2013-09-12
  • 打赏
  • 举报
回复
引用 5 楼 cnlm2 的回复:
[quote=引用 4 楼 spirit008 的回复:] [quote=引用 3 楼 cnlm2 的回复:] [quote=引用 2 楼 spirit008 的回复:]
    IP_ADAPTER_ADDRESSES info_temp;
    ULONG len = 0;

    // First get number of networks.
    ULONG result = GetAdaptersAddresses(AF_UNSPEC, 0, NULL, &info_temp, &len);
    if (result != ERROR_BUFFER_OVERFLOW) 
    {
        // There are 0 networks.
        return ;
    }

    scoped_array<char> buf(new char[len]);
    IP_ADAPTER_ADDRESSES *adapters =
        reinterpret_cast<IP_ADAPTER_ADDRESSES *>(buf.get());
    result = GetAdaptersAddresses(AF_UNSPEC, 0, NULL, adapters, &len);
    if (result != NO_ERROR) 
    {
        LOG(ERROR) << "GetAdaptersAddresses failed: " << result;
        return;
    }

    for (IP_ADAPTER_ADDRESSES *adapter = adapters; adapter != NULL;adapter = adapter->Next) 
    {
        if (adapter->IfType == IF_TYPE_PPP) //这里
        {
        }
    }
遍历网卡有个问题,就是无法区分虚拟机网卡和物理网卡,我用这个MAC是来做绑定机器码的,如果获得了虚拟机网卡的话,卸载了虚拟机后,那么机器码就会变![/quote] 我没有试过用虚拟机去做ppp拨号以后,网卡类型是不是IF_TYPE_PPP,我觉得你最好去试试。[/quote] 哥们,你会错意了,我原本的需求是获得网卡MAC做为机器码(可能是一部分), 如果使用遍历网卡的话,无法区分物理网卡和虚拟网卡(安装了虚拟机后,windows就会多出2张虚拟网卡),他们的类型都是MIB_IF_TYPE_ETHERNET 后来我就想到直接从socket取IP,然后用SendARP来获得socket对应网卡的MAC, 但是这个也出了个问题,直接插路由没有问题,拨号连接的话,socket对应的是PPPOE, 这样就会取到PPPOE连接的MAC,就不对了 现在我使用第一种遍历方法,if ((Type == MIB_IF_TYPE_ETHERNET \ && strstr(pAdapterInfo->Description, "Virtual") == NULL ) || Type == IF_TYPE_IEEE80211) { } 不知道这样是否可以忽略掉虚拟网卡! [/quote] 恩,就过滤字符串吧,反正我一直是这么过滤的,去注册表里去取得方法也不是万能的,这玩意好像只有驱动层能获取到较详细的信息。
cnlm2 2013-09-12
  • 打赏
  • 举报
回复
引用 4 楼 spirit008 的回复:
[quote=引用 3 楼 cnlm2 的回复:] [quote=引用 2 楼 spirit008 的回复:]
    IP_ADAPTER_ADDRESSES info_temp;
    ULONG len = 0;

    // First get number of networks.
    ULONG result = GetAdaptersAddresses(AF_UNSPEC, 0, NULL, &info_temp, &len);
    if (result != ERROR_BUFFER_OVERFLOW) 
    {
        // There are 0 networks.
        return ;
    }

    scoped_array<char> buf(new char[len]);
    IP_ADAPTER_ADDRESSES *adapters =
        reinterpret_cast<IP_ADAPTER_ADDRESSES *>(buf.get());
    result = GetAdaptersAddresses(AF_UNSPEC, 0, NULL, adapters, &len);
    if (result != NO_ERROR) 
    {
        LOG(ERROR) << "GetAdaptersAddresses failed: " << result;
        return;
    }

    for (IP_ADAPTER_ADDRESSES *adapter = adapters; adapter != NULL;adapter = adapter->Next) 
    {
        if (adapter->IfType == IF_TYPE_PPP) //这里
        {
        }
    }
遍历网卡有个问题,就是无法区分虚拟机网卡和物理网卡,我用这个MAC是来做绑定机器码的,如果获得了虚拟机网卡的话,卸载了虚拟机后,那么机器码就会变![/quote] 我没有试过用虚拟机去做ppp拨号以后,网卡类型是不是IF_TYPE_PPP,我觉得你最好去试试。[/quote] 哥们,你会错意了,我原本的需求是获得网卡MAC做为机器码(可能是一部分), 如果使用遍历网卡的话,无法区分物理网卡和虚拟网卡(安装了虚拟机后,windows就会多出2张虚拟网卡),他们的类型都是MIB_IF_TYPE_ETHERNET 后来我就想到直接从socket取IP,然后用SendARP来获得socket对应网卡的MAC, 但是这个也出了个问题,直接插路由没有问题,拨号连接的话,socket对应的是PPPOE, 这样就会取到PPPOE连接的MAC,就不对了 现在我使用第一种遍历方法,if ((Type == MIB_IF_TYPE_ETHERNET \ && strstr(pAdapterInfo->Description, "Virtual") == NULL ) || Type == IF_TYPE_IEEE80211) { } 不知道这样是否可以忽略掉虚拟网卡!
木头菇 2013-09-12
  • 打赏
  • 举报
回复
引用 3 楼 cnlm2 的回复:
[quote=引用 2 楼 spirit008 的回复:]
    IP_ADAPTER_ADDRESSES info_temp;
    ULONG len = 0;

    // First get number of networks.
    ULONG result = GetAdaptersAddresses(AF_UNSPEC, 0, NULL, &info_temp, &len);
    if (result != ERROR_BUFFER_OVERFLOW) 
    {
        // There are 0 networks.
        return ;
    }

    scoped_array<char> buf(new char[len]);
    IP_ADAPTER_ADDRESSES *adapters =
        reinterpret_cast<IP_ADAPTER_ADDRESSES *>(buf.get());
    result = GetAdaptersAddresses(AF_UNSPEC, 0, NULL, adapters, &len);
    if (result != NO_ERROR) 
    {
        LOG(ERROR) << "GetAdaptersAddresses failed: " << result;
        return;
    }

    for (IP_ADAPTER_ADDRESSES *adapter = adapters; adapter != NULL;adapter = adapter->Next) 
    {
        if (adapter->IfType == IF_TYPE_PPP) //这里
        {
        }
    }
遍历网卡有个问题,就是无法区分虚拟机网卡和物理网卡,我用这个MAC是来做绑定机器码的,如果获得了虚拟机网卡的话,卸载了虚拟机后,那么机器码就会变![/quote] 我没有试过用虚拟机去做ppp拨号以后,网卡类型是不是IF_TYPE_PPP,我觉得你最好去试试。
cnlm2 2013-09-12
  • 打赏
  • 举报
回复
引用 2 楼 spirit008 的回复:
    IP_ADAPTER_ADDRESSES info_temp;
    ULONG len = 0;

    // First get number of networks.
    ULONG result = GetAdaptersAddresses(AF_UNSPEC, 0, NULL, &info_temp, &len);
    if (result != ERROR_BUFFER_OVERFLOW) 
    {
        // There are 0 networks.
        return ;
    }

    scoped_array<char> buf(new char[len]);
    IP_ADAPTER_ADDRESSES *adapters =
        reinterpret_cast<IP_ADAPTER_ADDRESSES *>(buf.get());
    result = GetAdaptersAddresses(AF_UNSPEC, 0, NULL, adapters, &len);
    if (result != NO_ERROR) 
    {
        LOG(ERROR) << "GetAdaptersAddresses failed: " << result;
        return;
    }

    for (IP_ADAPTER_ADDRESSES *adapter = adapters; adapter != NULL;adapter = adapter->Next) 
    {
        if (adapter->IfType == IF_TYPE_PPP) //这里
        {
        }
    }
遍历网卡有个问题,就是无法区分虚拟机网卡和物理网卡,我用这个MAC是来做绑定机器码的,如果获得了虚拟机网卡的话,卸载了虚拟机后,那么机器码就会变!
木头菇 2013-09-12
  • 打赏
  • 举报
回复
    IP_ADAPTER_ADDRESSES info_temp;
    ULONG len = 0;

    // First get number of networks.
    ULONG result = GetAdaptersAddresses(AF_UNSPEC, 0, NULL, &info_temp, &len);
    if (result != ERROR_BUFFER_OVERFLOW) 
    {
        // There are 0 networks.
        return ;
    }

    scoped_array<char> buf(new char[len]);
    IP_ADAPTER_ADDRESSES *adapters =
        reinterpret_cast<IP_ADAPTER_ADDRESSES *>(buf.get());
    result = GetAdaptersAddresses(AF_UNSPEC, 0, NULL, adapters, &len);
    if (result != NO_ERROR) 
    {
        LOG(ERROR) << "GetAdaptersAddresses failed: " << result;
        return;
    }

    for (IP_ADAPTER_ADDRESSES *adapter = adapters; adapter != NULL;adapter = adapter->Next) 
    {
        if (adapter->IfType == IF_TYPE_PPP) //这里
        {
        }
    }
长尾巴的悟空 2013-09-12
  • 打赏
  • 举报
回复
好像获得系统的信息就可以取到mac的地址了。

18,356

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 网络编程
c++c语言开发语言 技术论坛(原bbs)
社区管理员
  • 网络编程
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧