用到了Libpcap 多线程,信号,临界资源,ioctl获取网卡信息。代码如下
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define IP_Swap_32(x) ( (
((x)>>24) |
(((x)>>8)&0xff00) ) |
( ((x)<<24) |
(((x)<<8)&0xff0000) )
)
#define Max_Cap_Loop 100
#define MAXINTERFACES 16
unsigned char Count=0; //累计抓包次数
unsigned long Packet=0; //每次抓包个数
unsigned long TotalCap=0; //总包数
unsigned long TotalDrop=0;//总丢弃数
pthread_t Time; //计时,每次抓30秒
pthread_t Loop_Packet; //循环抓包
pthread_mutex_t
mut; //临界区信号量,到指定时间后Count自增,并重新启动抓包线程
char Filter[8096];
unsigned long CapTime=0;
pcap_if_t *alldevs;
struct pcap_stat p_s; //状态
pcap_t *adhandle; //运行时句柄
char errbuf[PCAP_ERRBUF_SIZE];
struct bpf_program fp;
bpf_u_int32 maskp;
bpf_u_int32 netp;
struct InterfaceInfo{
char *in_name;
char *description;
unsigned char ip[4];
unsigned char mask[4];
};
struct Turple{
unsigned char proto;
unsigned char sip[4];
unsigned char dip[4];
unsigned short sport;
unsigned short dport; } turple;
InterfaceInfo net_interface[MAXINTERFACES];
int count_interface=0;
int timeup=0;
void sig_handle(int sig)
{
if (SIGINT == sig) {
timeup=-1;
printf("n- END -n");
}
}
void callback(u_char *param,const pcap_pkthdr *header,const
u_char *pkt_data)
{
char timestr[16];
//tm
*ltime=localtime(&header->ts.tv_sec);
time_t
dtime=header->ts.tv_sec;
u_int len=header->len;
u_int caplen=header->caplen;
printf("Time:%s Len:%4d,Captured:%4d
",ctime(&dtime),len,caplen);
//for(int
i=0;icaplen;i++)
//printf("%02x",pkt_data[i]);//return;
if(pkt_data[12]==0x08
&& pkt_data[13]==0x00)
{
turple.proto=pkt_data[23];
memcpy(turple.sip,(const
void*)&pkt_data[26],8);
memcpy(&turple.sport,(const
void *)&pkt_data[34],4);
turple.sport=turple.sport>>8|turple.sport<<8;
turple.dport=turple.dport>>8|turple.dport<<8;
printf("%d.%d.%d.%d:%d->%d.%d.%d.%d:%d|%dn",
turple.sip[0],turple.sip[1],turple.sip[2],turple.sip[3],turple.sport,
turple.dip[0],turple.dip[1],turple.dip[2],turple.dip[3],turple.dport,turple.proto);
}
//printf("n");
}
void CountTime(void)
{
for(;;)
{
sleep(CapTime);
Count++;
pthread_mutex_lock(&mut);
timeup=1;
pthread_mutex_unlock(&mut);
}
}
int InitCap(char *filterstring)
{
if(pcap_findalldevs(&alldevs,errbuf)==
-1)
{
pcap_freealldevs(alldevs);
fprintf(stderr,"Error in
pcap_findalldevs:%sn",errbuf);
return -1;
}
pcap_if_t *d;
int iCount=0;
for(d=alldevs;d;d=d->next)
{
net_interface[count_interface].in_name=(char
*)malloc(strlen(d->name)+1);
memcpy(net_interface[count_interface].in_name,d->name,strlen(d->name)+1);
if(d->description)
{
net_interface[count_interface].description=(char
*)malloc(strlen(d->description)+1);
memcpy(net_interface[count_interface].description,d->description,strlen(d->description)+1);
}
else
net_interface[count_interface].description="No
description"; memset(net_interface[count_interface].ip,0,4);
pcap_lookupnet(d->name,&netp,&maskp,errbuf);
net_interface[count_interface].mask[0]=maskp>>24;
net_interface[count_interface].mask[1]=maskp>>16;
net_interface[count_interface].mask[2]=maskp>>8;
net_interface[count_interface].mask[3]=maskp;
count_interface++;
iCount++;
}
if(iCount==0)
{
pcap_freealldevs(alldevs);
printf("nNo interface found!
Make sure Libpcap is working");
return -2;
}
pcap_freealldevs(alldevs);
return 0;
}
int InitCap_m(void)
{
register int fd, interface;
struct ifreq buf[MAXINTERFACES];
struct ifconf ifc;
if ((fd = socket(AF_INET, SOCK_DGRAM, 0))
>= 0)
{
ifc.ifc_len = sizeof buf;
ifc.ifc_buf = (caddr_t)
buf;
if (!ioctl(fd, SIOCGIFCONF,
(char *) &ifc))
{
interface =
ifc.ifc_len / sizeof(struct ifreq);
//printf("interface num is interface=%dnn",
interface);
while (interface-- > 0)
{
for(int
i=0;i
if((strcmp(buf[interface].ifr_name,net_interface[i].in_name))==0)
{
if
(!(ioctl(fd, SIOCGIFADDR, (char *)
&buf[interface])))
{
unsigned
long v;
v=*((unsigned
long*)&(((struct
sockaddr_in*)(&buf[interface].ifr_addr))->sin_addr));
memcpy(net_interface[i].ip,(unsigned
char *)(&v),4);
}
else
{
char
str[256] = "";
sprintf(str,
"cpm: ioctl device %s",
buf[interface].ifr_name);
perror(str);
close(fd);
return
-1;
}
}
}//end of
while
}
else
{ perror("cpm:
ioctl");
close(fd);
return
-1;
}
}
else
{ perror("cpm: socket");
return -1;
}
close(fd);
return 0;
}
int show_choose_dev(void)
{
int iChoose;
int iCount=count_interface;
for(int
i=0;i
{
printf("%d.%s(%s)
ip_addr:%d.%d.%d.%d,netmask:%d.%d.%d.%dn",
i+1,net_interface[i].in_name,net_interface[i].description,
net_interface[i].ip[0],net_interface[i].ip[1],net_interface[i].ip[2],net_interface[i].ip[3],
net_interface[i].mask[0],net_interface[i].mask[1],net_interface[i].mask[2],net_interface[i].mask[3]
);
}
printf("Choose an
interface(1-%d):",iCount);
scanf("%d",&iChoose);
printf("Your Choose:%dn",iChoose);
if(iChoose<1||iChoose>iCount)
{
printf("nInterface number out
of range.n");
return -1;
}
printf("nStart to sniffer on
%s..n",net_interface[iChoose-1].in_name);
return iChoose; }
int StartCap(int dev_num)
{
int iChoose=dev_num;
adhandle=pcap_open_live(net_interface[iChoose-1].in_name,65535,1,1000,errbuf);
if(adhandle==NULL)
{
fprintf(stderr,"nUnable to
open the adapter.n");
return
-1; }
maskp=(bpf_u_int32)(IP_Swap_32(*((unsigned
long*)(&(net_interface[iChoose-1].mask)))));
if(pcap_compile(adhandle,&fp,Filter,0,maskp)==-1)
{
fprintf(stderr,"Error calling
pcap_compilen");
pcap_close(adhandle);
return -1;
}
if(pcap_setfilter(adhandle,&fp)==-1)
{
pcap_close(adhandle);
fprintf(stderr,"Error setting
filtern");
return -1;
}
pcap_loop(adhandle,1000000,callback,NULL);
//printf("close========================================================================n");
//pcap_close(adhandle);//pcap_breakloop函数会关闭句柄故再次关闭会导致重复释放
return 0;
}
int main(int argc,char *argv[])
{
int create_thread_retval;
if(argc<=1
||argc>3)
{
printf("t Usage:%s
cap_time(seconds) "filter"n",argv[0]);
return -1;
}
memset(Filter,0,8096);
memcpy(Filter,argv[2],strlen(argv[2]));
CapTime=atol(argv[1]);
//printf("%d,%s,%dn",argc,Filter,CapTime);
signal(SIGINT, sig_handle);//register ctrl+c
to system
if(CapTime<=0||CapTime>0xffffff)
{
printf("Please input acceptable
timen");
return -1;
}
//printf("-n");
if(InitCap(Filter)!=0)
{
printf("Initiation capture
failed!n");
return -1;
}
if(InitCap_m()!=0)
{
printf("Get network interface
failed!n");
return -1;
}
int dev_num=show_choose_dev();
printf("main process starting:n");
if((create_thread_retval=pthread_create(&Time,NULL,(void*(*)(void*))CountTime,NULL))!=0)
{
printf("Create 'Count_Time'
thread failed!n");
return -1;
}
if((create_thread_retval=pthread_create(&Loop_Packet,NULL,(void*(*)(void*))StartCap,(void*)dev_num))!=0)
{
printf("Create 'Packet_Capture'
thread failed!n");
return -1;
}
while(timeup!=-1)
{
while(timeup==1)
{
pthread_mutex_lock(&mut);
printf("_%d#
capture finished==|++",Count);
timeup=0;
pcap_stats(adhandle,&p_s);
TotalCap+=p_s.ps_recv,
TotalDrop+=p_s.ps_drop;
printf("recv:%u,drop:%u,T_Cap=%u,T_Drop=%unn",p_s.ps_recv,p_s.ps_drop,TotalCap,TotalDrop);
pcap_breakloop(adhandle);
if((create_thread_retval=pthread_create(&Loop_Packet,NULL,(void*(*)(void*))StartCap,(void*)dev_num))!=0)
{
printf("Create
'Packet_Capture' thread failed!n");
return
-1;
}
pthread_mutex_unlock(&mut);
}
}
return 0;
}
文件存为file.cpp
编译+连接
gcc -lpcap -lpthread -lstdc++ -x c++ file.cpp
或者 g++ -lpcap -lpthread file.cpp
运行
[root@localhost experience]# ./a.out 5 "ip and host
218.199.87.171 and host ! 218.199.87.157 and udp port 9991"
1.eth0(No description)
ip_addr:192.168.0.10,netmask:128.255.255.255
2.eth1(No description)
ip_addr:218.199.87.171,netmask:128.255.255.255
3.any(Pseudo-device that captures on all interfaces)
ip_addr:0.0.0.0,netmask:0.0.0.0
4.lo(No description) ip_addr:127.0.0.1,netmask:0.0.0.255
Choose an interface(1-4):2
- END -
^[[A
Your Choose:0
Interface number out of range.
main process starting:
[root@localhost experience]# ./a.out 5 "ip and host 218.199.87.171
and host ! 218.199.87.157 and
tcp" 1.eth0(No description)
ip_addr:192.168.0.10,netmask:128.255.255.255
2.eth1(No description)
ip_addr:218.199.87.171,netmask:128.255.255.255
3.any(Pseudo-device that captures on all interfaces)
ip_addr:0.0.0.0,netmask:0.0.0.0
4.lo(No description) ip_addr:127.0.0.1,netmask:0.0.0.255
Choose an interface(1-4):2
Your Choose:2
Start to sniffer on eth1..
main process starting:
_1# capture finished==|++recv:0,drop:0,T_Cap=0,T_Drop=0
_2# capture finished==|++recv:1,drop:0,T_Cap=1,T_Drop=0
_3# capture finished==|++recv:0,drop:0,T_Cap=1,T_Drop=0
_4# capture finished==|++recv:1,drop:0,T_Cap=2,T_Drop=0
_5# capture finished==|++recv:1,drop:0,T_Cap=3,T_Drop=0
_6# capture finished==|++recv:1,drop:0,T_Cap=4,T_Drop=0
Time:Wed Dec 23 21:39:09 2009
Len: 74,Captured: 74
218.199.87.171:35757->152.46.7.222:80|6
Time:Wed Dec 23 21:39:09 2009
Len: 74,Captured: 74
218.199.87.171:35757->152.46.7.222:80|6
Time:Wed Dec 23 21:39:09 2009
Len: 74,Captured: 74
218.199.87.171:35757->152.46.7.222:80|6
Time:Wed Dec 23 21:39:09 2009
Len: 74,Captured: 74
218.199.87.171:35757->152.46.7.222:80|6
Time:Wed Dec 23 21:39:09 2009
Len: 74,Captured: 74
218.199.87.171:35757->152.46.7.222:80|6
Time:Wed Dec 23 21:39:09 2009
Len: 74,Captured: 74 Time:Wed Dec 23 21:39:09
2009
Len: 74,Captured: 74
218.199.87.171:35757->152.46.7.222:80|6
218.199.87.171:35757->152.46.7.222:80|6
Time:Wed Dec 23 21:39:09 2009
Len: 74,Captured: 74
152.46.7.222:80->218.199.87.171:35757|6
Time:Wed Dec 23 21:39:09 2009
Len: 66,Captured: 66
218.199.87.171:35757->152.46.7.222:80|6
Time:Wed Dec 23 21:39:09 2009
Len: 579,Captured: 579
218.199.87.171:35757->152.46.7.222:80|6
Time:Wed Dec 23 21:39:09 2009
Len: 66,Captured: 66
152.46.7.222:80->218.199.87.171:35757|6
Time:Wed Dec 23 21:39:09 2009
Len:1514,Captured:1514
152.46.7.222:80->218.199.87.171:35757|6
Time:Wed Dec 23 21:39:09 2009
Len: 66,Captured: 66
218.199.87.171:35757->152.46.7.222:80|6
Time:Wed Dec 23 21:39:09 2009
Len:1514,Captured:1514
152.46.7.222:80->218.199.87.171:35757|6
Time:Wed Dec 23 21:39:09 2009
Len: 66,Captured: 66
218.199.87.171:35757->152.46.7.222:80|6
Time:Wed Dec 23 21:39:09 2009
Len:1514,Captured:1514
152.46.7.222:80->218.199.87.171:35757|6
Time:Wed Dec 23 21:39:09 2009
Len: 66,Captured: 66
218.199.87.171:35757->152.46.7.222:80|6
Time:Wed Dec 23 21:39:09 2009
Len: 680,Captured: 680
152.46.7.222:80->218.199.87.171:35757|6
Time:Wed Dec 23 21:39:09 2009
Len: 66,Captured: 66
218.199.87.171:35757->152.46.7.222:80|6
_7# capture finished==|++recv:14,drop:0,T_Cap=18,T_Drop=0
_8# capture finished==|++recv:1,drop:0,T_Cap=19,T_Drop=0
_9# capture finished==|++recv:1,drop:0,T_Cap=20,T_Drop=0
Time:Wed Dec 23 21:39:24 2009
Len: 66,Captured: 66
152.46.7.222:80->218.199.87.171:35757|6
Time:Wed Dec 23 21:39:24 2009
Len: 66,Captured: 66 Time:Wed Dec 23 21:39:24
2009
Len: 66,Captured: 66
152.46.7.222:80->218.199.87.171:35757|6
Time:Wed Dec 23 21:39:24 2009
Len: 66,Captured: 66
152.46.7.222:80->218.199.87.171:35757|6
152.46.7.222:80->218.199.87.171:35757|6
Time:Wed Dec 23 21:39:24 2009
Len: 66,Captured: 66
218.199.87.171:35757->152.46.7.222:80|6
_10# capture finished==|++recv:3,drop:0,T_Cap=23,T_Drop=0
Time:Wed Dec 23 21:39:27 2009
Len: 74,Captured: 74
218.199.87.171:35478->121.195.178.52:80|6
Time:Wed Dec 23 21:39:27 2009
Len: 74,Captured: 74
218.199.87.171:35478->121.195.178.52:80|6
Time:Wed Dec 23 21:39:27 2009
Len: 74,Captured: 74
121.195.178.52:80->218.199.87.171:35478|6
Time:Wed Dec 23 21:39:27 2009
Len: 66,Captured: 66
218.199.87.171:35478->121.195.178.52:80|6
Time:Wed Dec 23 21:39:27 2009
Len: 849,Captured: 849
218.199.87.171:35478->121.195.178.52:80|6
Time:Wed Dec 23 21:39:27 2009
Len: 66,Captured: 66
121.195.178.52:80->218.199.87.171:35478|6
Time:Wed Dec 23 21:39:27 2009
Len: 307,Captured: 307
121.195.178.52:80->218.199.87.171:35478|6
Time:Wed Dec 23 21:39:27 2009
Len: 66,Captured: 66
218.199.87.171:35478->121.195.178.52:80|6
Time:Wed Dec 23 21:39:27 2009
Len: 818,Captured: 818
218.199.87.171:35478->121.195.178.52:80|6
Time:Wed Dec 23 21:39:27 2009
Len: 323,Captured: 323
121.195.178.52:80->218.199.87.171:35478|6
Time:Wed Dec 23 21:39:27 2009
Len: 66,Captured: 66
218.199.87.171:35478->121.195.178.52:80|6
_11# capture finished==|++recv:11,drop:0,T_Cap=34,T_Drop=0
_12# capture finished==|++recv:1,drop:0,T_Cap=35,T_Drop=0
Time:Wed Dec 23 21:39:38 2009
Len: 66,Captured: 66
218.199.87.171:35757->152.46.7.222:80|6
Time:Wed Dec 23 21:39:38 2009
Len: 66,Captured: 66
218.199.87.171:35757->152.46.7.222:80|6
Time:Wed Dec 23 21:39:38 2009
Len: 66,Captured: 66
218.199.87.171:35757->152.46.7.222:80|6
Time:Wed Dec 23 21:39:38 2009
Len: 74,Captured: 74
218.199.87.171:44727->123.125.51.20:80|6
Time:Wed Dec 23 21:39:38 2009
Len: 66,Captured: 66
152.46.7.222:80->218.199.87.171:35757|6
Time:Wed Dec 23 21:39:38 2009
Len: 74,Captured: 74
123.125.51.20:80->218.199.87.171:44727|6
Time:Wed Dec 23 21:39:38 2009
Len: 66,Captured: 66
218.199.87.171:44727->123.125.51.20:80|6
Time:Wed Dec 23 21:39:38 2009
Len: 743,Captured: 743
218.199.87.171:44727->123.125.51.20:80|6
Time:Wed Dec 23 21:39:38 2009
Len: 66,Captured: 66
123.125.51.20:80->218.199.87.171:44727|6
Time:Wed Dec 23 21:39:38 2009
Len: 233,Captured: 233
123.125.51.20:80->218.199.87.171:44727|6
Time:Wed Dec 23 21:39:38 2009
Len: 66,Captured: 66
218.199.87.171:44727->123.125.51.20:80|6
Time:Wed Dec 23 21:39:38 2009
Len: 66,Captured: 66
123.125.51.20:80->218.199.87.171:44727|6
Time:Wed Dec 23 21:39:38 2009
Len: 66,Captured: 66
218.199.87.171:44727->123.125.51.20:80|6
Time:Wed Dec 23 21:39:38 2009
Len: 66,Captured: 66
123.125.51.20:80->218.199.87.171:44727|6
_13# capture finished==|++recv:12,drop:0,T_Cap=47,T_Drop=0
- END -
(按 CTRL+C)
由于线程和主进程争用资源 导致显示不是严格按序号