libpcap是unix/linux平台下的网络数据包捕获函数包,大多数网络监控软件都以它为基础。
这个库的位置在/usr/local/lib下.在 /usr/local/include下是他的头文件pcap.h。要写一个使用libpcap库函数的程序只需要在代码中加上#include <pcap.h>,然后在编译时末尾加上-lpcap选项就可以了.
Libpcap应用程序从形式上看很简单,下面是一个简单的程序框架:
char * device; /* 用来捕获数据包的网络接口的名称 */------------what is it? -eth0
pcap_t * p; /* 捕获数据包句柄,最重要的数据结构 */-------------
struct bpf_program fcode; /* BPF 过滤代码结构 */-------------?how to write
/* 第一步:查找可以捕获数据包的设备 */
device = pcap_lookupdev(errbuf);---------------now i see
/* 第二步:创建捕获句柄,准备进行捕获 */
p = pcap_open_live(device, 8000, 1, 500, errbuf);
/* 第三步:如果用户设置了过滤条件,则编译和安装过滤代码 */------can i use nothing here?
pcap_compile(p, &fcode, filter_string, 0, netmask);
pcap_setfilter(p, &fcode);
pcap_loop (p, 7, printer, NULL); /* 这里的p就是我们刚刚生成的描述符;的第二个参数表示抓多少个包,设置为-1表示不定义数量,抓取所有的包;第三个参数是一个回调函数,每当抓到一个数据包之后程序将自动调用这个函数;第四个参数是一个指针,可以为空。 */
/*最后别忘了close*/
pcap_close (p);
libpcap是一个C语言库,其功能是通过网卡抓取网络以太网中的数据包,在windows系统下有相应的winpcap库。
要想使用这个库自然先要知道它在哪里,怎么安装就不废话了。在/usr/local/lib下有libpcap.a和libpcao.so,在 /usr/local/include下有pcap.h,打开手册的命令是man pcap,而不是man libpcap,如果觉得在字符模式下查看man太麻烦也可以baidu或者google一下"man pcap"会又可读性更高的手册。要写一个使用libpcap的程序只需要在代码中加上#i nclude <pcap.h>,然后在编译时使用-lpcap选项就可以了,例如:
$>gcc -o test1 test1.c -lpcap
二
如果能正确的编译通过使用libpcap的代码,那么便可以进入第二步了,写一个最简单的抓包程序。
先来介绍第一个类型:pcap_t。要抓包就要首先生成一个抓包的描述符(或称句柄),后来的很多操作都需要用这个描述符做参数。pcap_t就是由pcap.h定义的抓包描述符的类型,函数pcap_open_live返回指向该类型的指针:
pcap_t *pd = pcap_open_live ("eth0", 68, 0, 1000, ebuf);
其中第一个参数表示用来抓包的设备;第二个参数定义了抓包的最大字节数,如果这个值小于包的大小(如定义为68,包大于68),那么则只抓这个包的前68 个字节;第三个参数把网卡设置为混杂模式,以便抓取以太网中的数据包;第四个参数是一个以毫秒为单位的读取超时时间,如果设置为0则超时时间为无限大;第 五个参数为出错信息,需要这样声明(第一个简单的程序不需要出错处理,只知道这样声明就够了):
char ebuf[PCAP_ERRBUF_SIZE];
好了,现在生成了一个描述符了,现在我们可以用它来做一点什么事情了。开始一个抓包的循环,然后关闭抓包过程(释放描述符):
pcap_loop (pd, 7, printer, NULL);
pcap_close (pd);
这里的pd就是我们刚刚生成的描述符;pcap_loop的第二个参数表示抓多少个包,设置为-1表示不定义数量,抓取所有的包;第三个参数是一个回调函数,每当抓到一个数据包之后程序将自动调用这个函数;第四个参数是一个指针,可以为空,将在下面详细讲解。
下面我们来详细的实现这个回调函数,使其每抓到一个包则打印一次:
void printer()
{
printf("A packet is captured! ");
printf(" \n");
return;
}
当程序成功编译以后执行,则每抓到一个包后输出一行"A packet is captured! ",输出7行以后退出程序。
这样,一个最简单的抓包程序诞生了!参考源码:
/**
libpcap test program
compile command:"$>gcc -o exe_file_name this_file_name -lpcap"
written by Kxing <>
Last Modified 2006-03-02
*/
#include <stdio.h>
#include <pcap.h>
int main (int argc, char* argv[])
{
/*the printer running when packet have captured*/
void printer()
{
printf("A packet is captured!");
printf(" \n");
return;
}
/*the error code buf of libpcap*/
char ebuf[PCAP_ERRBUF_SIZE];
/*create capture handler of libpcap*/
pcap_t *pd = pcap_open_live ("eth0", 68, 0, 1000, ebuf);
/*start the loop of capture, loop 7 times, enter printer when capted*/
pcap_loop (pd, 7, printer, NULL);
pcap_close (pd);
return 0;
}
/*
*File:main.c
*Decripe:get the device use pcap
*parameter:
* input:
* output:
*return:
*Function: use pcap
*Author:maxingguo (msingle@163.com)
* Harbin Engineering University
* Information Security Research Center
*/
#include <stdio.h>
#include <pcap.h>
int main(int argc, char *argv[])
{
char *dev, errbuf[PCAP_ERRBUF_SIZE];
pcap_t *handle; //session handle
struct bpf_program fp; //the compiled filter expression
char filter_exp[] = "port 23"; //the filter expression
bpf_u_int32 mask; //the metmask of our sniffer device
bpf_u_int32 net; //the IP of our sniffing device
struct pcap_pkthdr header; //the header that pcap gives us
const u_char *packet; //the actual packet
/*Define the device*/
dev = pcap_lookupdev(errbuf); //get the device
if (dev == NULL) {
fprintf(stderr, "Couldn't find default device: %s\n", errbuf);
return(2);
}
printf("Device: %s\n", dev);
/*Find the properties for the device */
if( pcap_lookupnet(dev,&net,&mask,errbuf) == -1)
{
fprintf(stderr,"Couldn't get netmask for device %s: %s\n",dev,errbuf);
net = 0;
mask = 0;
}
/*Open the session in promiscuous mode*/
handle = pcap_open_live(dev,BUFSIZ,1,1000,errbuf);
if(handle == NULL)
{
fprintf(stderr,"Could't open device %s:%s\n",dev,errbuf);
return(2);
}
/*Compile and apply the filter*/
if( pcap_compile(handle,&fp,filter_exp,0,net) == -1 )
{
fprintf(stderr,"Could't parse filter %s:%s \n",filter_exp,pcap_geterr(handle));
return(2);
}
if( pcap_setfilter(handle,&fp) == -1)
{
fprintf(stderr,"Could't install filter %s: %s \n",filter_exp,pcap_geterr(handle));
return(2);
}
/*Grab a packet */
packet = pcap_next(handle,&header);
printf("Jack a packet:%s \n The length is: %d\n %s",packet,header.len);
/*Close the session*/
pcap_close(handle);
return(0);
}