#include "cwinpcaparp.h"
CWinPcapArp::CWinPcapArp(QObject *parent) : QObject(parent)
{
this->countDev = 0;
/* 申请内存存放IP地址 */
ip_addr = (char*)malloc(sizeof(char)*16);
if(ip_addr == NULL)
{
printf("apply for memary faild:ip addr\n");
return;
}
else
{
printf("apply for memary successful:ip addr\n");
}
/* 申请内存存放NETMASK地址 */
ip_netmask = (char*)malloc(sizeof(char)*16);
if(ip_netmask == NULL)
{
printf("apply for memary faild:net mask\n");
return;
}
else
{
printf("apply for memary successful:net mask\n");
}
/* 申请内存存放MAC地址 */
ip_mac = (unsigned char*)malloc(sizeof(unsigned char)*6);
if(ip_mac == NULL)
{
printf("apply for memary faild:MAC\n");
}
else
{
printf("apply for memary successful:MAC\n");
}
}
CWinPcapArp::~CWinPcapArp()
{
}
void CWinPcapArp::GetAllDevs()
{
/* 获取本地适配器列表 */
if(pcap_findalldevs(&alldevs,errbuf) == -1)
{
/* 结果为-1代表出现获取适配器列表失败 */
fprintf(stderr,"Error in pcap_findalldevs_ex:\n",errbuf);
/* exit(0)代表正常退出,exit(other)为非正常退出,这个值会传给操作系统 */
return;
}
for(dev = alldevs;dev !=NULL;dev = dev->next)
{
printf("--number:%d\n--name:%s\n",++countDev,dev->name);
if(dev->description)
{
//打印适配器的描述信息
printf("description:%s\n",dev->description);
}else{
//适配器不存在描述信息
printf("description:%s","no description\n");
}
//打印本地环回地址
printf("\tLoopback: %s\n",(dev->flags & PCAP_IF_LOOPBACK)?"yes":"no");
/**
pcap_addr * next 指向下一个地址的指针
sockaddr * addr IP地址
sockaddr * netmask 子网掩码
sockaddr * broadaddr 广播地址
sockaddr * dstaddr 目的地址
*/
pcap_addr_t *a; /* 网络适配器的地址用来存储变量 */
for(a = dev->addresses;a;a = a->next){
/* sa_family代表了地址的类型,是IPV4地址类型还是IPV6地址类型 */
switch (a->addr->sa_family)
{
case AF_INET: /* 代表IPV4类型地址 */
printf("Address Family Name:AF_INET\n");
if(a->addr){
/* ->的优先级等同于括号,高于强制类型转换,因为addr为sockaddr类型,对其进行操作须转换为sockaddr_in类型 */
printf("Address:%s\n",iptos(((struct sockaddr_in *)a->addr)->sin_addr.s_addr));
}
if (a->netmask){
printf("Netmask: %s\n",iptos(((struct sockaddr_in *)a->netmask)->sin_addr.s_addr));
}
if (a->broadaddr){
printf("Broadcast Address: %s\n",iptos(((struct sockaddr_in *)a->broadaddr)->sin_addr.s_addr));
}
if (a->dstaddr){
printf("Destination Address: %s\n",iptos(((struct sockaddr_in *)a->dstaddr)->sin_addr.s_addr));
}
break;
case AF_INET6: /* 代表IPV6类型地址 */
printf("Address Family Name:AF_INET6\n");
printf("this is an IPV6 address\n");
break;
default:
break;
}
}
}
/* i为0代表上述循环未进入,即没有找到适配器,可能的原因为Winpcap没有安装导致未扫描到 */
if(countDev == 0){
printf("interface not found,please check winpcap installation");
}
/* 选中的适配器 */
for(dev=alldevs, countDev=0; countDev< 0/* 默认适配器序号 */; dev=dev->next, countDev++);
/* 打开适配器 */
if((adhandle = pcap_open_live(dev->name, /* 设备名称 */
65535, /* 存放数据包的内容长度 */
1, /* 混杂模式 */
1000, /* 超时时间 */
errbuf /* 错误缓冲 */
)) == NULL)
{
/* 打开适配器失败,打印错误并释放适配器列表 */
fprintf(stderr,"\nUnable to open the adapter. %s is not supported by WinPcap\n", dev->name);
/* 释放设备列表 */
pcap_freealldevs(alldevs);
}
ifget(dev,ip_addr, ip_netmask); /* 获取本地IP,子网掩码*/
GetSelfMac(adhandle,ip_addr,ip_mac);/* 获得本机MAC地址 */
/* 赋值 */
sp.adhandle = adhandle;
sp.ip = ip_addr;
sp.mac = this->ip_mac;
sp.netmask = ip_netmask;
gp.adhandle = adhandle;
/* 创建线程发送和接收线程 */
sendthread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)SendArpPacket,&sp,0,NULL);
recvthread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)GetLivePC, &gp,0,NULL);
printf("\nlistening on net card %d ...\n", countDev);
}
/**
* @brief CWinPcapArp::iptos u_long即为 unsigned long
* @param in
* @return
*/
char *CWinPcapArp::iptos(u_long in)
{
static char output[IPTOSBUFFERS][3*4+3+1];
static short which;
u_char *p;
p = (u_char *)∈
which = (which + 1 == IPTOSBUFFERS ? 0 : which + 1);
sprintf_s(output[which], "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
return output[which];
}
/**
* @brief CWinPcapArp::ifget 获取IP和子网掩码赋值为ip_addr和ip_netmask
* @param d
* @param ip_addr
* @param ip_netmask
*/
void CWinPcapArp::ifget(pcap_if_t *d, char *ip_addr, char *ip_netmask)
{
pcap_addr_t *a;
/* 遍历所有的地址,a代表一个pcap_addr */
for (a = d->addresses; a; a = a->next) {
switch (a->addr->sa_family) {
case AF_INET: /* sa_family :是2字节的地址家族,一般都是“AF_xxx”的形式。通常用的都是AF_INET。代表IPV4 */
if (a->addr) {
char *ipstr;
/* 将地址转化为字符串 */
ipstr = iptos(((struct sockaddr_in *) a->addr)->sin_addr.s_addr);
printf("ip str:%s\n",ipstr);
memcpy(ip_addr, ipstr, 16);
}
if (a->netmask) {
char *netmaskstr;
netmaskstr = iptos(((struct sockaddr_in *) a->netmask)->sin_addr.s_addr);
printf("netmask:%s\n",netmaskstr);
memcpy(ip_netmask, netmaskstr, 16);
}
case AF_INET6:
break;
}
}
}
/**
* @brief CWinPcapArp::GetSelfMac 获取自己主机的MAC地址
* @param adhandle
* @param ip_addr
* @param ip_mac
* @return
*/
int CWinPcapArp::GetSelfMac(pcap_t *adhandle, const char *ip_addr, unsigned char *ip_mac)
{
unsigned char sendbuf[42]; /* arp包结构大小 */
int i = -1;
int res;
EthernetHeader eh; /* 以太网帧头 */
Arpheader ah; /* ARP帧头 */
struct pcap_pkthdr * pkt_header;
const u_char * pkt_data;
/* 将已开辟内存空间 eh.dest_mac_add 的首 6个字节的值设为值 0xff */
memset(eh.DestMAC, 0xff, 6); /* 目的地址为全为广播地址 */
memset(eh.SourMAC, 0x0f, 6);
memset(ah.DestMacAdd, 0x0f, 6);
memset(ah.SourceMacAdd, 0x00, 6);
/* htons将一个无符号短整型的主机数值转换为网络字节顺序 */
eh.EthType = htons(ETH_ARP);
ah.HardwareType= htons(ARP_HARDWARE);
ah.ProtocolType = htons(ETH_IP);
ah.HardwareAddLen = 6;
ah.ProtocolAddLen = 4;
ah.SourceIpAdd