使用Winpcap编写:
最近工作需要抓取傻瓜交换机的MAC,由于没有IP只能使用Winpcap抓包工具来实现。本人初学者,大佬请绕行。
a, 先获取电脑的网卡信息
在SwithCheckMacDlg.h文件中定义两个全局变量
pcap_if_t *alldevs; // pcap_if 结构体中包含了适配器的详细信息
pcap_if_t *d;
void CSwithCheckMacDlg::GetNetworkSource()
{
int i=0;
CString m_sTemp = "";
/* 获得设备列表 */
//int pcap_findalldevs(pcap_if_t **, char *);
if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING,NULL,
&alldevs, // 输出参数,详细信息
errbuf // 缓冲区 大小为PCAP_BUF_SIZE,函数失败是保存错误
) == -1)
{
fprintf(stderr,"Error in pcap_findalldevs: %s\n", errbuf);
exit(1);
}
/* 打印列表 */
CString NetCardInfo = "";
for(d=alldevs; d != NULL; d=d->next)
{
m_sTemp.Format("%d.%s\r\n",++i,d->name);
m_RunMsgEdit.ReplaceSel(m_sTemp);
if (d->description)
{
m_sTemp.Format("(%s)\r\n",d->description);
m_RunMsgEdit.ReplaceSel(m_sTemp);
NetCardInfo.Format("%d. %s",i,d->description);
m_NetworkCard.AddString(NetCardInfo);
}
else
{
m_sTemp.Format("(No description available) %s\r\n",d->description);
m_RunMsgEdit.ReplaceSel(m_sTemp);
}
}
if(i==0)
{
m_RunMsgEdit.ReplaceSel("No interfaces found! Make sure WinPcap is installed.\r\n");
}
//pcap_freealldevs(alldevs);
//GetSwithMac();
}
b, 获取交换机的MAC地址 和 所选择网卡的MAC地址
pcap_compile() 过滤条件的设置,以下我验证了协议类型和通过源IP和目标MAC过滤获取相应的信息
例如: char packet_filter[] = "src host 192.168.1.1";
参考链接:https://blog.csdn.net/a1009563517/article/details/47311813
char packet_filter[] = "src host 192.168.1.1";
//编译过滤器
if (pcap_compile(adhandle, &fcode, packet_filter, 1, netmask) <0 )
{
m_RunMsgEdit.ReplaceSel("Unable to compile the packet filter. Check the syntax.\r\n");
/* 释放设备列表 */
pcap_freealldevs(alldevs);
}
//设置过滤器
if (pcap_setfilter(adhandle, &fcode)<0)
{
m_RunMsgEdit.ReplaceSel("Error setting the filter.\r\n");
/* 释放设备列表 */
pcap_freealldevs(alldevs);
}
完整代码片:
// 获取MAC号
void CSwithCheckMacDlg::GetSwithMac()
{
int inum = 0;
int i=0;
u_int netmask;
CString m_sTemp = "";
//char packet_filter[] = "ether proto 0x8899";
//char packet_filter[] = "ether proto 0x0800";
//char packet_filter[] = "ether dst c8:a7:76:a7:ae:8a";
char packet_filter[] = "src host 192.168.1.1";
struct bpf_program fcode;
//Sleep(10000);
int index = m_NetworkCard.GetCurSel();
CString strl;
inum = index + 1;
/* 跳转到已选设备 */
for(d=alldevs, i=0; i< inum-1 ; d=d->next, i++);
// 获取打开的网卡的mac号
LPADAPTER lpAdapter = 0;
DWORD dwErrorCode;
PPACKET_OID_DATA OidData;
BOOLEAN Status;
char addr_mac[1024] = {0};
strl.Format("%s",d->name);
strl = strl.Mid(strl.Find('\\'));
memcpy(addr_mac,strl.GetBuffer(0),strl.GetLength());
m_AdapterName.Format("%s",addr_mac);
//AfxBeginThread(StartMainThread,this,0,0,THREAD_PRIORITY_NORMAL,NULL);
lpAdapter = PacketOpenAdapter((addr_mac));
if (!lpAdapter || (lpAdapter->hFile == INVALID_HANDLE_VALUE))
{
dwErrorCode = GetLastError();
m_sTemp.Format("Unable to open the adapter, Error Code : %lx\r\n",dwErrorCode);
m_RunMsgEdit.ReplaceSel(m_sTemp);
return;
}
OidData = (PPACKET_OID_DATA)malloc(6 + sizeof(PACKET_OID_DATA));
if (OidData == NULL)
{
m_sTemp.Format("error allocating memory!\r\n");
PacketCloseAdapter(lpAdapter);
m_RunMsgEdit.ReplaceSel(m_sTemp);
return ;
}
OidData->Oid = OID_802_3_CURRENT_ADDRESS;
OidData->Length = 6;
ZeroMemory(OidData->Data, 6);
Status = PacketRequest(lpAdapter, FALSE, OidData);
if(Status)
{
NetMac.Format("%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(OidData->Data)[0],(OidData->Data)[1],(OidData->Data)[2],(OidData->Data)[3],(OidData->Data)[4],(OidData->Data)[5]);
NetMac.MakeUpper();
m_sTemp.Format("The MAC address of the adapter is %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\r\n",
(OidData->Data)[0],
(OidData->Data)[1],
(OidData->Data)[2],
(OidData->Data)[3],
(OidData->Data)[4],
(OidData->Data)[5]);
m_RunMsgEdit.ReplaceSel(m_sTemp);
}
else
{
m_sTemp.Format("error retrieving the MAC address of the adapter!\n");
m_RunMsgEdit.ReplaceSel(m_sTemp);
}
free(OidData);
PacketCloseAdapter(lpAdapter);
// 开始ping线程
AfxBeginThread(ReadNetWorkRate,this,0,0,THREAD_PRIORITY_NORMAL,NULL);
/* 打开适配器 指定网络设备进行抓包/发包*/
if ( (adhandle= pcap_open(d->name, // 设备名
65536, // 要捕捉的数据包的部分
// 65535保证能捕获到不同数据链路层上的每个数据包的全部内容
PCAP_OPENFLAG_PROMISCUOUS, // 混杂模式
1000, // 读取超时时间
NULL,
errbuf // 错误缓冲池
) ) == NULL)
{
m_RunMsgEdit.ReplaceSel("Unable to open the adapter. is not supported by WinPcap\r\n");
/* 释放设备列表 */
pcap_freealldevs(alldevs);
}
/* 检查数据链路层,为了简单,我们只考虑以太网 */
if(pcap_datalink(adhandle) != DLT_EN10MB)
{
m_RunMsgEdit.ReplaceSel("This program works only on Ethernet networks.\r\n");
/* 释放设备列表 */
pcap_freealldevs(alldevs);
}
if (d->addresses->addr->sa_family == AF_INET6)
{
d->addresses = d->addresses->next;
}
if(d->addresses != NULL)
/* 获得接口第一个地址的掩码 */
netmask=((struct sockaddr_in *)(d->addresses->netmask))->sin_addr.S_un.S_addr;
else
/* 如果接口没有地址,那么我们假设一个C类的掩码 */
netmask=0xffffff;
//编译过滤器
if (pcap_compile(adhandle, &fcode, packet_filter, 1, netmask) <0 )
{
m_RunMsgEdit.ReplaceSel("Unable to compile the packet filter. Check the syntax.\r\n");
/* 释放设备列表 */
pcap_freealldevs(alldevs);
}
//设置过滤器
if (pcap_setfilter(adhandle, &fcode)<0)
{
m_RunMsgEdit.ReplaceSel("Error setting the filter.\r\n");
/* 释放设备列表 */
pcap_freealldevs(alldevs);
}
m_sTemp.Format("listening on %s....\r\n",d->description);
m_RunMsgEdit.ReplaceSel(m_sTemp);
/* 释放设备列表 */
pcap_freealldevs(alldevs);
/* 开始捕捉 */
//pcap_loop(adhandle, 0, packet_handler, NULL);
int res;
struct pcap_pkthdr *header;
const u_char *pkt_data;
time_t local_tv_sec;
struct tm ltime;
char timestr[16];
mac_header *mh;
u_short ethernet_type;
ip_header *ih;
tcp_header *th;
u_int ip_len;
u_short sport,dport;
int n_Count = 0;
pcap_stat ps;
int nRet = 0;
u_int nRecv1 = 0;
u_int nRecv2 = 0;
CString OldMac = "";
while((res = pcap_next_ex(adhandle,&header,&pkt_data)) >= 0)
{
if (m_DeviceConnetFlag == FALSE)
{
m_PingMacFalg = FALSE;
AigenTestUpdateUI();
continue;
}
Sleep(100);
nRet = pcap_stats(adhandle, &ps);
m_sTemp.Format("%d", nRet);
nRecv2 = ps.ps_recv;
if(nRecv2 > nRecv1)
{
nRecv1 = nRecv2;
n_Count = 0;
}
else
{
if (bDisConnectCount == n_Count)
{
//AigenTestUpdateUI();
//m_PingMacFalg = FALSE;
n_Count = 0;
}
n_Count++;
Sleep(bDisConnectTime);
continue;
}
if (res == 0 )
{
continue;
}
n_Count = 0;
if (m_PingMacFalg == TRUE) // 判断交换机是否连接了PC机
{
continue;
}
m_PingMacFalg = TRUE;
m_ScanMsgEdit.EnableWindow(TRUE);
m_TestMsgStatic.SetWindowTextA("正在Check MAC...");
/*将时间戳转换为可读格式*/
//local_tv_sec = header->ts.tv_sec;
//localtime_s(<ime,&local_tv_sec);
//strftime(timestr,sizeof(timestr),"%H:%H:%S",<ime);
///* 打印数据包的时间戳和长度 */
//m_sTemp.Format("%s,%.6d len: %d\r\n",timestr,header->ts.tv_usec,header->len);
//m_RunMsgEdit.ReplaceSel(m_sTemp);
//获得MAC帧头部位置
mh = (mac_header *)(pkt_data);
m_RunMsgEdit.ReplaceSel("正在Check MAC...\r\n");
m_RunMsgEdit.ReplaceSel("以太网类型为 : \t\r\n");
ethernet_type = ntohs(mh->type);
m_sTemp.Format("%04x\r\n",ethernet_type);
m_RunMsgEdit.ReplaceSel(m_sTemp);
/* 获得IP数据包头部的位置 */
ih = (ip_header *) (pkt_data +14); //以太网头部长度
switch(ethernet_type) /*判断以太网类型的值*/
{
case 0x0800 :
m_sTemp.Format("网络层是:\tIPv4协议\r\n");
/*if(ih->ip_protocol != 1)
{
m_PingMacFalg = FALSE;
continue;
}*/
break;
case 0x0806 :
m_sTemp.Format("网络层是:\tARP协议\r\n");break;
case 0x8035 :
m_sTemp.Format("网络层是:\tRARP 协议\r\n");break;
case 0x8899 :
m_sTemp.Format("网络层是:\tRARP 协议\r\n");break;
default:
m_PingMacFalg = FALSE;
continue;
}
m_RunMsgEdit.ReplaceSel(m_sTemp);
///获得TCP首部的位置
//ip_len = (ih->ihl) * 4;
//th = (tcp_header *) ((u_char*)ih + ip_len);
//
///* 将网络字节序列转换成主机字节序列 */
//sport = ntohs( th->sport );
//dport = ntohs( th->dport );
SourceMac = "";
AimsMac = "";
SourceMac.Empty();
AimsMac.Empty();
SourceMac.Format("%02x:%02x:%02x:%02x:%02x:%02x",mh->saddr.byte1,mh->saddr.byte2,mh->saddr.byte3,mh->saddr.byte4,mh->saddr.byte5,mh->saddr.byte6);
AimsMac.Format("%02x:%02x:%02x:%02x:%02x:%02x",mh->daddr.byte1,mh->daddr.byte2,mh->daddr.byte3,mh->daddr.byte4,mh->daddr.byte5,mh->daddr.byte6);
m_sTemp.Format("获取MAC源地址: \t\t%s\r\n",SourceMac);
m_RunMsgEdit.ReplaceSel(m_sTemp);
m_sTemp.Format("获取MAC目的地址: \t%s\r\n",AimsMac);
m_RunMsgEdit.ReplaceSel(m_sTemp);
Sleep(1000);
SourceMac.MakeUpper();
AimsMac.MakeUpper();
CString sMac = "";
if (SourceMac == NetMac || AimsMac == NetMac)
{
m_PingMacFalg = FALSE;
continue;
}
if (SourceMac == "FF:FF:FF:FF:FF:FF")
{
sMac = AimsMac;
}
else if (AimsMac == "FF:FF:FF:FF:FF:FF")
{
sMac = SourceMac;
}
else
{
m_PingMacFalg = FALSE;
continue;
}
m_sTemp.Format("获取MAC源地址: \t\t%s\r\n",SourceMac);
m_RunMsgEdit.ReplaceSel(m_sTemp);
m_sTemp.Format("获取MAC目的地址: \t%s\r\n",AimsMac);
m_RunMsgEdit.ReplaceSel(m_sTemp);
//m_PingMacFalg = FALSE;
CString strMac = "";
GetDlgItem(IDC_MINMAC_EDIT)->GetWindowTextA(strMac);
if (!CropMac(strMac,sMac))
{
AfxMessageBox("温馨提示:\r\n\t 获取MAC号非法");
m_sTemp.Format("获取MAC非法\r\n");
m_RunMsgEdit.ReplaceSel(m_sTemp);
m_TestResultFalg = FALSE;
continue;
}
strMac.Empty();
GetDlgItem(IDC_MAXMAC_EDIT)->GetWindowTextA(strMac);
if (!CropMac(sMac,strMac))
{
AfxMessageBox("温馨提示:\r\n\t 获取MAC号非法");
m_sTemp.Format("获取MAC非法\r\n");
m_RunMsgEdit.ReplaceSel(m_sTemp);
m_TestResultFalg = FALSE;
continue;
}
SourceMac = sMac;
startTestFlag = TRUE;
//if (ps.ps_recv > 100)
//{
// ps.ps_recv = 0;
// nRecv1 = 0;
// nRecv2 = 0;
//}
m_sTemp.Format("获取交换机得MAC: \t%s\r\n",sMac);
m_RunMsgEdit.ReplaceSel(m_sTemp);
m_ScanWin.DoModal();
barCode = m_ScanWin.ScanBarCode;
if (startTestFlag == TRUE && barCode != "")
{
assySnValue.Empty();
assySnValue = barCode;
startTestFlag = FALSE;
//GetDlgItem(IDC_SCAN_MSG_EDIT)->EnableWindow(FALSE);
//AfxBeginThread(StartMainThread,this,0,0,THREAD_PRIORITY_NORMAL,NULL);
CheckMesMac();
}
else
{
m_TestMsgStatic.SetWindowTextA("Check MAC失败");
assySnValue.Empty();
startTestFlag = FALSE;
UpdateWinResult(FALSE);
}
/*GetDlgItem(IDC_SCAN_MSG_EDIT)->SetFocus();
m_TestMsgStatic.SetWindowTextA("请扫描SN测试");*/
}
if (res == -1)
{
m_sTemp.Format("读取数据包时出错:%s \r\n",pcap_geterr(adhandle));
}
}
C, 怎么检查设备是否已经上线
刚开始我通过抓包数量是否增加来判断交换机是否如PC机已经连接。但是不是特别的好用,后来在高人的指点下,只用网卡的连接速率来判断交换机是否连接了PC机(没有连接是,网卡的速率是0.0Mbps)。
完整代码:
UINT __cdecl CSwithCheckMacDlg::ReadNetWorkRate(LPVOID pParam)
{
CSwithCheckMacDlg *ptr = (CSwithCheckMacDlg *) pParam;
DWORD dwOutBufLen = 0;
PIP_ADAPTER_INFO pAdapterInfo = NULL, pAdapter = NULL, pAdapterOld = NULL;
MIB_IFROW zSNMP;
char sTemp[20];
int iReturn;
iReturn = GetAdaptersInfo(pAdapterInfo, &dwOutBufLen);
if (iReturn != ERROR_BUFFER_OVERFLOW)
{
return 0;
}
pAdapterInfo = (PIP_ADAPTER_INFO)HeapAlloc(GetProcessHeap(), 0, dwOutBufLen);
iReturn = GetAdaptersInfo(pAdapterInfo, &dwOutBufLen);
if (iReturn != ERROR_SUCCESS)
{
HeapFree(GetProcessHeap(), 0, pAdapterInfo);
return 0;
}
pAdapter = pAdapterInfo;
//find if there is ppp adapter
double iIfSpeed;
while(TRUE)
{
if (TRUE == ptr->m_CloseDeviesThread)
{
return 0;
}
while (pAdapter != NULL)
{
if (TRUE == ptr->m_CloseDeviesThread)
{
return 0;
}
CString pName = pAdapter->AdapterName;
if (ptr->m_AdapterName.Find(pName) != -1)
{
zSNMP.dwIndex = pAdapter->Index;
iReturn = GetIfEntry(&zSNMP);
if (iReturn != NO_ERROR)
return 0;
iIfSpeed = 1.0*zSNMP.dwSpeed / (1000 * 1000); //----------你要的速率
if (0.0 != iIfSpeed)
{
ptr->m_DeviceConnetFlag = TRUE;
}
else
{
ptr->m_DeviceConnetFlag = FALSE;
}
}
pAdapter = pAdapter->Next;
if (pAdapter == nullptr)
{
pAdapter = pAdapterInfo;
}
}
}
return 0;
}
完整工程界面:
完整工程代码下载链接:https://download.csdn.net/download/yyhuyuming/11783683
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)