tcpdump & libpcap官网
使用PCAP获取数据包纳秒(ns)级精度的时间戳(timestamp)
tcpdump/libpcap中捕获数据包的时间戳
基于libpcap多网卡抓包编程心得
在LINUX系统下使用libpcap,一些流程
Python-对Pcap文件进行处理,获取指定TCP流
PCAP文件格式分析(做抓包软件之必备)
tcpdump使用方法总结
常用类型:
字段说明:
Timestamp:时间戳高位,精确到seconds
Timestamp:时间戳低位,精确到microseconds
Caplen:当前数据区的长度,即抓取到的数据帧长度,由此可以得到下一个数据帧的位置。
Len:离线数据长度:网络中实际数据帧的长度,一般不大于caplen,多数情况下和Caplen数值相等。
Packet 数据:即 Packet(通常就是链路层的数据帧)具体内容,长度就是Caplen,这个长度的后面,就是当前PCAP文件中存放的下一个Packet数据包,PCAP文件里面并没有规定捕获的Packet数据包之间有什么间隔字符串,下一组数据在文件中的起始位置,我们需要靠第一个Packet包确定。
先编译libpcap,这里交叉编译,用于arm平台,
./configure --host=arm-xilinx-linux-gnueabi --prefix=$cur_path/zynq-$PETALINUX_VER
同样方法,交叉编译tcpdump,可以自动发现libpcap,采用静态编译的库,可直接拷贝到板卡运行,
...
checking for local pcap library... ../libpcap-1.9.0/libpcap.a
checking for pcap-config... ../libpcap-1.9.0/pcap-config
...
pcap文件的包格式,caplen
为捕获到长度,len
为数据包原始长度,也就是说caplen
可能比len
小,struct timeval
在这里长度为64字节。
/*
* Generic per-packet information, as supplied by libpcap.
*
* The time stamp can and should be a "struct timeval", regardless of
* whether your system supports 32-bit tv_sec in "struct timeval",
* 64-bit tv_sec in "struct timeval", or both if it supports both 32-bit
* and 64-bit applications. The on-disk format of savefiles uses 32-bit
* tv_sec (and tv_usec); this structure is irrelevant to that. 32-bit
* and 64-bit versions of libpcap, even if they're on the same platform,
* should supply the appropriate version of "struct timeval", even if
* that's not what the underlying packet capture mechanism supplies.
*/
struct pcap_pkthdr {
struct timeval ts; /* time stamp */
bpf_u_int32 caplen; /* length of portion present */
bpf_u_int32 len; /* length this packet (off wire) */
};
libpcap-1.9.0
和tcpdump-4.9.2
支持设置时间精度为毫秒或者纳秒,左边毫秒,右边纳秒,
代码,
// libpcap-1.9.0\pcap\pcap.h line404
/*
* Time stamp resolution types.
* Not all systems and interfaces will necessarily support all of these
* resolutions when doing live captures; all of them can be requested
* when reading a savefile.
*/
#define PCAP_TSTAMP_PRECISION_MICRO 0 /* use timestamps with microsecond precision, default */
#define PCAP_TSTAMP_PRECISION_NANO 1 /* use timestamps with nanosecond precision */
// tcpdump-4.9.2\tcpdump.c line945
static pcap_t *
open_interface(const char *device, netdissect_options *ndo, char *ebuf)
{
...
#ifdef HAVE_PCAP_SET_TSTAMP_PRECISION
status = pcap_set_tstamp_precision(pc, ndo->ndo_tstamp_precision);
if (status != 0)
error("%s: Can't set %ssecond time stamp precision: %s",
device,
tstamp_precision_to_string(ndo->ndo_tstamp_precision),
pcap_statustostr(status));
#endif
...
}
// tcpdump-4.9.2\tcpdump.c line1495 main
#ifdef HAVE_PCAP_SET_TSTAMP_PRECISION
case OPTION_TSTAMP_PRECISION:
ndo->ndo_tstamp_precision = tstamp_precision_from_string(optarg);
if (ndo->ndo_tstamp_precision < 0)
error("unsupported time stamp precision");
break;
#endif
代码,
char errbuf[PCAP_ERRBUF_SIZE];//存放错误信息的缓冲
pcap_if_t *it;
int r;
r=pcap_findalldevs(&it,errbuf);
if(r < 0) {
printf("err:%s\n",errbuf);
return r;
}
while(it) {
printf(":%s\n",it->name);
it=it->next;
}
pcap_freealldevs(it);
其中pcap_if_t
的name
成员用于pcap_open_live
函数,
/*
* Item in a list of interfaces.
*/
struct pcap_if {
struct pcap_if *next;
char *name; /* name to hand to "pcap_open_live()" */
char *description; /* textual description of interface, or NULL */
struct pcap_addr *addresses;
bpf_u_int32 flags; /* PCAP_IF_ interface flags */
};
只抓数据部分:src host 192.168.6.6 and src port 8080 and tcp[tcpflags] & (tcp-push) != 0
,
int pcap_compile(pcap_t *p, struct bpf_program *fp,char *str, int optimize, bpf_u_int32 netmask)
字符串str是过滤参数,program参数是一个指向bpf_program结构体的指针,optimize参数用于控制是否采用最优化的结果,netmask用于指定IPv4的网络子网掩码,这个参数仅仅在检查过滤程序中的IPv4广播地址时才会使用。
struct bpf_program filter;
pcap_compile(fip->nic, &filter, fip->filter, 1, 0);
pcap_setfilter(fip->nic, &filter);
只抓取网卡接收到的包,不抓取发出去的包,0xac是本机的mac地址,过滤源mac地址不等于0xac就达到效果了。
$ sudo tcpdump -i enp1s0 -v "ether[6] != 0xac" -w a.pcap
抓取报文后隔指定的时间保存一次,
%Y_%m%d_%H%M_%S.cap
$ sudo tcpdump -s 0 -G 60 -Z root -w %Y_%m%d_%H%M_%S.cap
抓取报文后达到指定的大小保存一次,
$ sudo tcpdump -s 0 -C 1 -Z root -W 1 -w test.cap