在linux平台libpcap函数分析及流程(1)中讲述了一些常用函数的使用,在这篇文章中将介绍源码实现,本源码在ubuntu9.0下顺利运行。
#include
#include
#include
#define CAP_LEN 2048
int main(int argc, char *argv[])
{
bpf_u_int32 netaddr = 0, mask = 0;
int caplen=CAP_LEN;
char errbuf[PCAP_ERRBUF_SIZE];
char * device;
device=pcap_lookupdev(errbuf);
if (device == NULL)
exit(printf("%s n", errbuf));
#ifdef _DEBUG_
printf("device is %s /n",device);
#endif
pcap_t * phandle;
phandle = pcap_open_live(device, caplen, 1, 512, errbuf);
if(phandle == NULL)
exit(printf("%s/n",errbuf));
//返回pcap_open_live被调用后的snapshot参数值
int i=pcap_snapshot(phandle);
if(caplen < i)
{
printf("snaplen raised from %d to %d /n", caplen, i);
caplen=i;
}
if(pcap_lookupnet(device, &netaddr, &mask, errbuf) < 0)
{
netaddr=0;
mask=0;
printf("%s/n", errbuf);
}
struct bpf_program fcode;
if (pcap_compile(phandle, &fcode, "", 1, mask) < 0)
exit(printf("Error %s/n","pcap_compile"));
if (pcap_setfilter(phandle, &fcode) < 0)
exit(printf("Error %s/n","pcap_setfilter"));
system("ifconfig");
struct pcap_pkthdr pkthdr;
const unsigned char * packet = NULL;
while(1)
{
packet = pcap_next(phandle, &pkthdr);
printf("success\n");
//……
}
pcap_close(phandle);
return 0;
}
结构的内部定义:
struct pcap_pkthdr
{
struct timeval ts; ts是一个结构struct timeval,它有两个部分,第一部分是1900开始以来的秒数,第二部分是当前秒之后的毫秒数
bpf_u_int32 caplen; 表示抓到的数据长度
bpf_u_int32 len; 表示数据包的实际长度
}
几乎所有的操作系统(BSD, AIX, Mac OS, Linux等)都会在内核中提供过滤数据包的方法,主要都是基于BSD Packet Filter(BPF)结构的。libpcap利用BPF来过滤数据包。
BPF使用一种类似于汇编语言的语法书写过滤表达式,不过libpcap和tcpdump都把它封装成更高级且更容易的语法了,具体可以man tcpdump。
以下是一些例子:
src host 192.168.1.177 //只接收源ip地址是192.168.1.177的数据包
dst port 80 //只接收tcp/udp的目的端口是80的数据包
not tcp //只接收不使用tcp协议的数据包
tcp[13] == 0x02 and (dst port 22 or dst port 23)
//只接收SYN标志位置位且目标端口是22或23的数据包(tcp首部开始的第13个字节)
icmp[icmptype] == icmp-echoreply or icmp[icmptype] == icmp-echo
//只接收icmp的ping请求和ping响应的数据包
ehter dst 00:e0:09:c1:0e:82 //只接收以太网mac地址是00:e0:09:c1:0e:82的数据包
ip[8] == 5 //只接收ip的ttl=5的数据包(ip首部开始的第8个字节)
文章中具体介绍了捕获数据包的源码,最后还列举了一些过滤表达式的用法,希望看了文章以后能对抓包有一定的认识。最后,我还想多说几句,每个人抓到包的目的不一样,可以根据自己的需要将包进行解包,然后重新组包,这些都可以做到,不过我提醒一点,要对捕获的数据包的数据分析,要将TCP/IP协议深入的学习,理解,这不是一朝一夕的事,然后在编写代码时,不同的系统底层对TCP/IP协议的实现有一些小的差别,个人根据自己的系统加以修改,编写出适合自己需求的程序。