#define HAVE_REMOTE
#include
#include
//定义IP地址
typedef struct ip_address
{
u_char byte1;
u_char byte2;
u_char byte3;
u_char byte4;
}ip_address;
//定义mac
typedef struct ip_mac
{
u_char byte5;
u_char byte6;
u_char byte7;
u_char byte8;
u_char byte9;
u_char byte10;
u_char byte11;
u_char byte12;
}ip_mac;
//IP头结构
typedef struct ip_header
{
u_char ver_ihl; /* 识别IP协议版本(0100是IPv4,0110是Ipv6)+网络首部长度(4 bits)*/
u_char tos; /* 服务类型*/
u_short tlen; /* 总长*/
u_short identification; /*识别*/
u_short flags_fo; /*标记(3 bits)+片段偏移(13 bits)*/
u_char ttl; /*生存时间*/
u_char proto; /*标识上层使用的协议*/
u_short crc; /*头部检验*/
ip_address saddr;/*源IP地址*/
ip_address daddr;/*目的IP地址*/
ip_mac smac;
ip_mac dmac;
u_int op_pad; /*可选项*/
}ip_header;
//UDP头结构
typedef struct udp_header
{
u_char sport1;
u_char sport2; /*源端口*/
u_char dport1;
u_char dport2; /*目的端口*/
u_char len1;
u_char len2; /*数据包长度*/
u_char crc1;
u_char crc2; /*检查和*/
}udp_header;
//定义packet handler
void packet_handler(u_char param/数据包存储的文件指针*/, const struct pcap_pkthdr header, const u_char *pkt_data);
int main()
{
pcap_if *device;
pcap_if *d;
int inum;
int i = 0;
pcap_t *adhandle;
char errbuf[PCAP_ERRBUF_SIZE];
u_int netmask;
char packet_filter[] = "ip";
struct bpf_program fcode;
//↓↓↓从本地检索设备表↓↓↓
if (/获取设备列表函数*/pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL /*不需要授权*/,
&device/*搜索到的设备存在这里*/, errbuf/*如果有错误,存在这个错误缓冲区*/) == -1)
{
cout<<"Error in pcap_findalldevs_ex:"<
exit(1);
}
//↓↓展示列表↓↓
for (d=device; d!=NULL; d=d->next)
{
//↓↓↓其中这是展示设备名字↓↓↓
cout<<++i<<"--"<name<
//↓↓↓其中这是设备的描述↓↓↓
if (d->description)
{
cout<description<
}
else
{
cout
}
}
if (i == 0)
{
cout
return -1;
}
//选择一个适配器
cout
cin>>inum;
if (inumi)
{
cout<
//释放设备列表
pcap_freealldevs(device);
return -1;
}
//跳转到所选适配器
for (d=device,i=0;inext,++i);
//打开设备
if ((adhandle=pcap_open(d->name, /*要打开的源名*/
65536, /*65535保证能捕获到每个链路层上的数据*/
PCAP_OPENFLAG_PROMISCUOUS, /*混杂模式*/
1000, /*等待1秒,让更多的数据包到来后从OS内核一次读多个数据包*/
NULL, /*不是远程抓包*/
errbuf /*存放错误的缓冲区*/
)/*返回给device一个pcap_t指针,*/
) == NULL)
{
cout<name<<"不能被WinPcap支持"<
pcap_freealldevs(device);
return -1;
}
if (pcap_datalink(adhandle) != DLT_EN10MB/*以太网10m*/)
{
fprintf(stderr, "\nThis program works only on Ethernet networks.\n");
/*不是简单以太网,释放*/
pcap_freealldevs(device);
return -1;
}
if (d->addresses != NULL)
{
/*检索第一个地址接口的掩码*/
netmask=((struct sockaddr_in )(d->addresses->netmask))->sin_addr.S_un.S_addr;
}
else
{
/如果接口没有地址,我们假设是在一个c++网络*/
netmask = 0xffffffff;
}
if (pcap_compile(adhandle, &fcode, packet_filter,1, netmask) < 0)
{
fprintf(stderr, "\nUnable to compile the packet filter. Check the syntax.\n");
/*释放*/
pcap_freealldevs(device);
return -1;
}
if (pcap_setfilter(adhandle, &fcode) < 0)
{
fprintf(stderr, "\nError setting the filter.\n");
/*释放*/
pcap_freealldevs(device);
return -1;
}
cout<<endl<<"listening on "<<d->description<<endl;
//此刻我们不再需要这些设备了,释放掉
pcap_freealldevs(device);
//开始抓包
pcap_loop(adhandle/*句柄*/,50/*?*/,packet_handler,NULL);
return 1;
}
//回调函数,调用每个被Libpcap传入的数据包
void packet_handler(u_char param,const struct pcap_pkthdr *header/得到时间值,数据包长度*/,
const u_char pkt_data/获得IP首部的位置,UDP首部的位置*/)
{
struct tm ltime;
char timestr[16];
ip_header ih;
udp_header* uh;
u_int ip_len;
u_int ip_proto;//------------
int a=0;
//时间可视化
ltime=localtime(&header->ts.tv_sec);
strftime(timestr,sizeof(timestr),"%H:%M:%S",ltime);
cout<<"抓包时间: "<len<<"字节"<
ih=(ip_header*)(pkt_data);
cout
for(a;alen;++a)
{
ih=(ip_header*)(pkt_data+a-12);
}
cout<<endl<<"-----------------------------------------------"<<endl;
//检索ip首部
ih=(ip_header*)(pkt_data+14);
//14字节是以太网mac帧的帧头长度,14=6目的地址+6源地址+2类型说明。
ip_len=(ih->ver_ihl & 0xf)*4;//取首部长度
ip_proto=ih->proto;
uh=(udp_header*)((u_char*)ih+ip_len);
printf("该数据从 -%d.%d.%d.%d- 发送到 -%d.%d.%d.%d-\n",
ih->saddr.byte1,
ih->saddr.byte2,
ih->saddr.byte3,
ih->saddr.byte4,
/*sport,*/
ih->daddr.byte1,
ih->daddr.byte2,
ih->daddr.byte3,
ih->daddr.byte4);
/*dport*/
ih=(ip_header*)(pkt_data+14);
//14字节是以太网mac帧的帧头长度,14=6目的地址+6源地址+2类型说明。
ip_len=(ih->ver_ihl & 0xf)*6;//取首部长度
ip_proto=ih->proto;
uh=(udp_header*)((u_char*)ih+ip_len);
printf("该数据从 -%.2x.%.2x.%.2x.%.2x.%.2x.%.2x- 发送到 -%.2x.%.2x.%.2x.%.2x.%.2x.%.2x-\n",
ih->smac.byte5,
ih->smac.byte6,
ih->smac.byte7,
ih->smac.byte8,
ih->dmac.byte9,
ih->dmac.byte10,
ih->dmac.byte11,
ih->dmac.byte12,
/*sport,*/
ih->dmac.byte5,
ih->dmac.byte6,
ih->dmac.byte7,
ih->dmac.byte8,
ih->dmac.byte9,
ih->dmac.byte10,
ih->dmac.byte11,
ih->dmac.byte12);
/*dport*/
if (ih->proto==17)
{
cout<<"上层协议使用了-UDP-协议"<
printf("源端口号:%d,目的端口:%d,头部长度:%d,头部校验:0x%x\n\n",uh->sport1*256+uh->sport2,uh->dport1*256+uh->dport2,uh->len1*256+uh->len2,uh->crc1*256+uh->crc2);
}
if (ih->proto==6)
{cout<<"上层协议使用了-TCP-协议"<<endl<<endl;}
}