基本步骤
- 打开网络设备
- 设置过滤规则
- 捕获数据包
- 关闭网络设备
相关API
#include <pcap/pcap.h>
char errbuf[PCAP_ERRBUF_SIZE];
/*
功能:找到要捕获的默认设备
参数:errbuf传递的是数组首元素地址,用来返回错误信息;
返回值:成功返回网络设备的名称,失败返回NULL且设置errbuf指针指向空间(错误消息)
*/
char *pcap_lookupdev(char *errbuf);
#include <pcap/pcap.h>
char errbuf[PCAP_ERRBUF_SIZE];
/**
* [pcap_open_live 打开捕获数据的设备]
* @param device [需要打开设备的名称]
* @param snaplen [捕获数据包的长度]
* @param promisc [捕获数据的模式:1 代表混杂模式;其它非混杂模式,一般使用0]
* @param to_ms [捕获数据的超时时间,以ms为单位]
* @param errbuf [存储错误消息]
* @return [成功返回设备的句柄,失败返回NULL且通过errbuf返回错误消息]
*/
pcap_t *pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, char *errbuf);
#include <pcap/pcap.h>
char errbuf[PCAP_ERRBUF_SIZE];
/**
* [pcap_lookupnet 获取网络设备的设备号和掩码]
* @param device [需要获取网络设备的名称]
* @param netp [返回网络设备号]
* @param maskp [返回子网掩码]
* @param errbuf [存储错误消息]
* @return [成功返回0,失败返回-1]
*/
int pcap_lookupnet(const char *device, bpf_u_int32 *netp, bpf_u_int32 *maskp, char *errbuf);
#include <pcap/pcap.h>
/**
* [pcap_next 捕获一个数据包]
* @param p [已打开的网络设备句柄]
* @param h [捕获到的数据包的头部]
* @return [成功返回捕获的数据包,失败返回NULL]
*/
const u_char *pcap_next(pcap_t *p, struct pcap_pkthdr *h);
#include <pcap/pcap.h>
typedef void (*pcap_handler)(u_char *user, const struct pcap_pkthdr *h,const u_char *bytes);
/**
* [pcap_loop 循环捕获网络数据包,直到遇到错误或者满足退出条件;每次捕获一个数据包就会调用 callback 指示的回调函数,所以,可以在回调函数中进行数据包的处理操作]
* @param p [已打开的网络设备句柄]
* @param cnt [循环捕获数据包的条数]
* @param callback [捕获的数据的回调函数]
* @param user [需要给回调函数传递的参数]
* @return [成功返回0,失败返回负数]
*/
int pcap_loop(pcap_t *p, int cnt, pcap_handler callback, u_char *user);
#include <pcap/pcap.h>
/**
* [pcap_compile 过滤规则]
* @param p [打开网络设备的句柄]
* @param fp [过滤规则(由libpcap库所能识别的过滤规则)]
* @param str [过滤规则(由用户所能识别的过滤规则)]
* @param optimize [优化选项,一般使用0]
* @param netmask [子网掩码。255.255.255.0 (0xffffff00)]
* @return [成功返回0,识别返回-1]
*/
int pcap_compile(pcap_t *p, struct bpf_program *fp, const char *str, int optimize, bpf_u_int32 netmask);
#include <pcap/pcap.h>
/*将编译好的过滤规则fp设置给已打开网络句柄p的网络设备*/
int pcap_setfilter(pcap_t *p, struct bpf_program *fp);
过滤规则
- 协议过滤
tcp udp tftp http icmp 表示协议过滤
- mac地址过滤
ether src 11:22:33:44:55:66 捕获源mac地址为11:22:33:44:55:66的数据包
ether dest 11:22:33:44:55:66 捕获目的mac地址为11:22:33:44:55:66的数据包
ether host 11:22:33:44:55:66 捕获目的(或者源)mac地址为11:22:33:44:55:66的数据包
- IP地址过滤
src host 192.168.4.250 捕获源IP为192.168.4.250的数据包
dest host 192.168.4.250 捕获目的IP为192.168.4.250的数据包
host 192.168.4.250 捕获目的(或者源)IP为192.168.4.250的数据包
ip src host 192.168.4.250 捕获源IP为192.168.4.250的数据包
ip dest host 192.168.4.250 捕获目的IP为192.168.4.250的数据包
- 端口过滤
src port 8888 捕获源端口为8888的数据包
dest port 8888 捕获目的端口为8888的数据包
port 8888 捕获目的(或者源)端口为8888的数据包
tcp src port 8888 捕获源端口为8888的tcp数据包
tcp dest port 8888 捕获目的端口为8888的tcp数据包
udp src port 8888 捕获源端口为8888的udp数据包
udp dest port 8888 捕获目的端口为8888的udp数据包
- 多条件过滤
and 满足所有的条件
or 只有满足其中一个条件都会过滤
实例
#include <stdio.h>
#include <pcap/pcap.h>
char errbuf[PCAP_ERRBUF_SIZE];
void my_pcap_handler(u_char *user, const struct pcap_pkthdr *h,const u_char *bytes)
{
/* 捕获到的数据包内容:bytes */
unsigned char src_mac[28] = {0};
unsigned char dest_mac[28] = {0};
/* 对于接收到的数据,是以太网数据包:解析 */
sprintf(dest_mac, "%02x:%02x:%02x:%02x:%02x:%02x", bytes[0], bytes[1],bytes[2], bytes[3], bytes[4], bytes[5]);
sprintf(src_mac, "%02x:%02x:%02x:%02x:%02x:%02x", bytes[6], bytes[7], bytes[8], bytes[9], bytes[10], bytes[11]);
printf("%s -> %s\n", src_mac, dest_mac);
}
int main()
{
int ret;
char *dev_name;
pcap_t * my_pcap;
struct pcap_pkthdr h;
struct bpf_program fp;
/* 获取默认捕获数据设备 */
dev_name = pcap_lookupdev(errbuf);
if (dev_name == NULL) {
fprintf(stderr, "pcap_lookupdev errbuf: %s\n", errbuf);
return -1;
}
printf("dev_name:%s\n", dev_name);
/* 打开捕获数据设备 */
my_pcap = pcap_open_live(dev_name, 1024, 0, 0, errbuf);
if (my_pcap == NULL) {
fprintf(stderr, "pcap_open_live errbuf: %s\n", errbuf);
return -1;
}
printf("pcap_open_live success\n");
/* 编译过滤规则 */
ret = pcap_compile(my_pcap, &fp, "arp or ip", 0, 0xffffff00);
if (ret == -1) {
fprintf(stderr, "pcap_compile fail\n");
return -1;
}
/* 设置编译规则 */
ret = pcap_setfilter(my_pcap, &fp);
if (ret == -1) {
fprintf(stderr, "pcap_setfilter fail\n");
return -1;
}
/* 循环捕获10条数据包 */
ret = pcap_loop(my_pcap, 10, my_pcap_handler, NULL);
//while(1);
pcap_close(my_pcap);
return 0;
}
网友评论