main函数的实现,调用libpcap提供的库函数,抓取数据包,然后交给回调函数进行对数据包的解析
/******************************************************************************
文 件 名 : packetAnalyze.c
版 本 号 : V1.1
负 责 人 : Sophisticated
生成日期 : 2018年9月27日
最近修改 :
文件描述 : 使用libpcap抓取数据包
函数列表 :
main
修改历史 :
1.日 期 : 2018年9月27日
作 者 : Sophisticated
修改内容 : 创建文件
******************************************************************************/
#include<stdio.h>
#include<sys/types.h>
#include<pcap.h>
#include"head.h"
#include"callback.h"
#define PROMISC 1
/*过滤条件*/
char filter_exp[128];
/*抓包设备名称*/
char *dev;
/*****************************************************************************
函 数 名 : main
功能描述 : 抓取数据包主函数
输入参数 : 无
输出参数 : 无
返 回 值 :
调用函数 :
被调函数 :
修改历史 :
1.日 期 : 2018年9月27日
作 者 : Sophisticated
审 核 人 : #
修改内容 : 新生成函数
*****************************************************************************/
int main(int argc, int *argv[])
{
pcap_t *pcap;
char errbuf[PCAP_ERRBUF_SIZE];
struct pcap_pkthdr hdr;
pcap_if_t *alldevs;
struct bpf_program bpf_p;
bpf_u_int32 net;
bpf_u_int32 mask;
/*find the device to capture packet*/
if (pcap_findalldevs(&alldevs, errbuf) == -1)
{
print("no device !\n");
}
/*默认取第一个网络设备*/
dev = alldevs->name;
//dev = "br0";
/*open the device*/
pcap = pcap_open_live(dev, SNAP_LEN, PROMISC, 0, errbuf);
if (pcap == NULL)
{
print("open error!\n");
return;
}
if (pcap_lookupnet(dev, &net, &mask, errbuf) == -1)
{
print("Could not get netmask for device!\n");
net = 0;
mask = 0;
}
if (argc > 1)
{
int i;
for (i = 1; i < argc; i++)
{
strncat(filter_exp, argv[i], 100);
strncat(filter_exp, " ", 100);
}
}
if (pcap_compile(pcap, &bpf_p, filter_exp, 0,net) == -1)
{
print("Could not parse filter\n");
return;
}
if(pcap_setfilter(pcap, &bpf_p) == -1)
{
print("Could not install filter\n");
return;
}
int id = 0;
/*capture the packet until occure error*/
pcap_loop(pcap, -1, ethernet_callback, (u_char *)&id);
pcap_close(pcap);
return 0;
}
将过滤条件通过main函数参数的方式传递进来,此时的过滤条件格式必须遵守libpcap的格式
可用的过滤格式例子:
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个字节)
这里的网络设备默认取第一个设备,也可以自己硬编码为指定的设备名称