參考
tcpdump & libpcap官網
使用PCAP獲取數據包納秒(ns)級精度的時間戳(timestamp)
tcpdump/libpcap中捕獲數據包的時間戳
基於libpcap多網卡抓包編程心得
在LINUX系統下使用libpcap,一些流程
Python-對Pcap文件進行處理,獲取指定TCP流
PCAP文件格式分析(做抓包軟件之必備)
pcap文件格式
Pcap文件頭24B各字段說明:
- Magic:4B:0x1A 2B 3C 4D:用來標示文件的開始
- Major:2B,0x02 00:當前文件主要的版本號
- Minor:2B,0x04 00當前文件次要的版本號
- ThisZone:4B當地的標準時間;全零
- SigFigs:4B時間戳的精度;全零
- SnapLen:4B最大的存儲長度
- LinkType:4B鏈路類型
常用類型:
- 0 BSD loopback devices, except for later OpenBSD
- 1 Ethernet, and Linux loopback devices
- 6 802.5 Token Ring
- 7 ARCnet
- 8 SLIP
- 9 PPP
- 10 FDDI
- 100 LLC/SNAP-encapsulated ATM
- 101 “raw IP”, with no link
- 102 BSD/OS SLIP
- 103 BSD/OS PPP
- 104 Cisco HDLC
- 105 802.11
- 108 later OpenBSD loopback devices (with the AF_value in network byte order)
- 113 special Linux “cooked” capture
- 114 LocalTalk
Packet 包頭和Packet數據組成
字段說明:
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);