?
知道如何獲取適配器的信息了,那我們就開始一項更具意義的工作,打開適配器并捕獲數(shù)據(jù)包。編寫一個程序,將每一個 通過適配器的數(shù)據(jù)包 打印出來。
?
打開設(shè)備的函數(shù)是? pcap_open() 。
(Open a generic source in order to capture / send (WinPcap only) traffic.)
pcap_t* pcap_open (
const
char
*
source,
int
snaplen,
int
flags,
int
read_timeout,
struct
pcap_rmtauth *
auth,
char
*
errbuf
)
?
· snaplen 制定要捕獲數(shù)據(jù)包中的哪些部分。 在一些操作系統(tǒng)中 (比如 xBSD 和 Win32), 驅(qū)動可以被配置成 只捕獲數(shù)據(jù)包的初始化部分 : 這樣可以減少應用程序間復制數(shù)據(jù)的量,從而提高捕獲效率。本例中,我們將值定為65535,它比我們能遇到的最大的MTU還要大。因此,我們確信我們總能收到完整的數(shù)據(jù)包。
· flags : 最最重要的flag是用來指示適配器是否要被設(shè)置成 混雜模式 。 一般情況下,適配器只接收發(fā)給它自己的數(shù)據(jù)包, 而那些在其他機器之間通訊的數(shù)據(jù)包,將會被丟棄 。 相反,如果適配器是混雜模式,那么不管這個數(shù)據(jù)包是不是發(fā)給我的,我都會去捕獲。也就是說,我會去捕獲所有的數(shù)據(jù)包。 這意味著在一個共享媒介(比如總線型以太網(wǎng)),WinPcap能捕獲其他主機的所有的數(shù)據(jù)包。 大多數(shù)用于數(shù)據(jù)捕獲的應用程序都會將適配器設(shè)置成混雜模式 ,所以,我們也會在下面的范例中,使用混雜模式。?
· read_timeout(to_ms): 指定 讀取數(shù)據(jù)的超時時間 ,以毫秒計(1s=1000ms)。在適配器上進行讀取操作(比如用 pcap_dispatch() 或 pcap_next_ex() ) 都會在 to_ms 毫秒時間內(nèi)響應,即使在網(wǎng)絡(luò)上沒有可用的數(shù)據(jù)包。 在統(tǒng)計模式下 , to_ms 還可以用來定義 統(tǒng)計的時間間隔 。 將 to_ms 設(shè)置為0意味著沒有超時,那么如果沒有數(shù)據(jù)包到達的話,讀操作將永遠不會返回。 如果設(shè)置成-1,則情況恰好相反,無論有沒有數(shù)據(jù)包到達,讀操作都會立即返回。
- Returns:
- A pointer to a 'pcap_t' which can be used as a parameter to the following calls ( pcap_compile() and so on) and that specifies an opened WinPcap session. In case of problems, it returns NULL and the 'errbuf' variable keeps the error message.
- Warning:
-
The source cannot be larger than PCAP_BUF_SIZE.
The following formats are not allowed as 'source' strings:
- rpcap:// [to open the first local adapter]
- rpcap://hostname/ [to open the first remote adapter]?
?
?
int
pcap_dispatch ( pcap_t *
p,
int
cnt,
pcap_handler callback,
u_char
*
user
)
?
Collect a group of packets.?
?
int
pcap_loop ( pcap_t *
p,
int
cnt,
pcap_handler callback,
u_char
*
user
)
?
Collect a group of packets.
?
pcap_dispatch()與pcap_loop()的區(qū)別:
當適配器被打開,捕獲工作就可以用 pcap_dispatch() 或 pcap_loop() 進行。 這兩個函數(shù)非常的相似, 區(qū)別就是 pcap_ dispatch() 當超時時間到了(timeout expires)就返回 (盡管不能保證) ,而 pcap_loop() 不會因此而返回 ,只有當 cnt 數(shù)據(jù)包被捕獲,所以,pcap_loop()會在一小段時間內(nèi),阻塞網(wǎng)絡(luò)的利用。 pcap_loop() 對于我們這個簡單的范例來說,可以滿足需求,不過, pcap_dispatch() 函數(shù)一般用于比較復雜的程序中。
這兩個函數(shù)都有一個 回調(diào) 參數(shù), packet_handler 指向一個可以接收數(shù)據(jù)包的函數(shù) 。 這個函數(shù)會在收到每個新的數(shù)據(jù)包并收到一個通用狀態(tài)時被libpcap所調(diào)用 ( 與函數(shù) pcap_loop() 和 pcap_dispatch() 中的 user 參數(shù)相似),數(shù)據(jù)包的首部一般有一些諸如時間戳,數(shù)據(jù)包長度的信息,還有包含了協(xié)議首部的實際數(shù)據(jù)。 注意:冗余校驗碼CRC不再支持,因為幀到達適配器,并經(jīng)過校驗確認以后,適配器就會將CRC刪除,與此同時,大部分適配器會直接丟棄CRC錯誤的數(shù)據(jù)包,所以,WinPcap沒法捕獲到它們。
上面的程序?qū)⒚恳粋€數(shù)據(jù)包的時間戳和長度從 pcap_pkthdr 的首部解析出來,并打印在屏幕上。
請注意,使用 pcap_loop() 函數(shù)可能會遇到障礙,主要因為它直接由數(shù)據(jù)包捕獲驅(qū)動所調(diào)用。因此,用戶程序是不能直接控制它的。另一個實現(xiàn)方法(也是提高可讀性的方法),是使用 pcap_next_ex() 函數(shù)。有關(guān)這個函數(shù)的使用,請看 ( 不用回調(diào)方法捕獲數(shù)據(jù)包 ).
?
struct
pcap_pkthdr{
timeval ts
//
time stamp
bpf_u_int32 caplen
//
length of portion present
bpf_u_int32 len
//
length this packet (off wire)
};
Detailed Description
Header of a packet in the dump file.
Each packet in the dump file is prepended with this generic header. This gets around the problem of different headers for different packet interfaces.?
?
1
#include
"
pcap.h
"
2
#pragma
comment(lib, "wpcap.lib")
3
#pragma
comment(lib, "Packet.lib")
4
#pragma
comment(lib, "wsock32.lib")
5
6
7
#include
"
pcap.h
"
8
9
/*
packet handler 函數(shù)原型
*/
10
void
packet_handler(u_char *param,
const
struct
pcap_pkthdr *header,
const
u_char *
pkt_data);
11
12
main()
13
{
14
pcap_if_t *
alldevs;
15
pcap_if_t *
d;
16
int
inum;
17
int
i=
0
;
18
pcap_t *
adhandle;
19
char
errbuf[PCAP_ERRBUF_SIZE];
20
21
/*
獲取本機設(shè)備列表
*/
22
if
(pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) == -
1
)
23
{
24
fprintf(stderr,
"
Error in pcap_findalldevs: %s\n
"
, errbuf);
25
exit(
1
);
26
}
27
28
/*
打印列表
*/
29
for
(d=alldevs; d; d=d->
next)
30
{
31
printf(
"
%d. %s
"
, ++i, d->
name);
32
if
(d->
description)
33
printf(
"
(%s)\n
"
, d->
description);
34
else
35
printf(
"
(No description available)\n
"
);
36
}
37
38
if
(i==
0
)
39
{
40
printf(
"
\nNo interfaces found! Make sure WinPcap is installed.\n
"
);
41
return
-
1
;
42
}
43
44
printf(
"
Enter the interface number (1-%d):
"
,i);
45
scanf(
"
%d
"
, &
inum);
46
47
if
(inum <
1
|| inum >
i)
48
{
49
printf(
"
\nInterface number out of range.\n
"
);
50
/*
釋放設(shè)備列表
*/
51
pcap_freealldevs(alldevs);
52
return
-
1
;
53
}
54
55
/*
跳轉(zhuǎn)到選中的適配器
*/
56
for
(d=alldevs, i=
0
; i< inum-
1
;d=d->next, i++
);
57
58
/*
打開設(shè)備
*/
59
if
( (adhandle= pcap_open(d->name,
//
設(shè)備名
60
65536
,
//
65535保證能捕獲到不同數(shù)據(jù)鏈路層上的每個數(shù)據(jù)包的全部內(nèi)容
61
PCAP_OPENFLAG_PROMISCUOUS,
//
混雜模式
62
1000
,
//
讀取超時時間
63
NULL,
//
遠程機器驗證
64
errbuf
//
錯誤緩沖池
65
) ) ==
NULL)
66
{
67
fprintf(stderr,
"
\nUnable to open the adapter. %s is not supported by WinPcap\n
"
, d->
name);
68
/*
釋放設(shè)備列表
*/
69
pcap_freealldevs(alldevs);
70
return
-
1
;
71
}
72
73
printf(
"
\nlistening on %s...\n
"
, d->
description);
74
75
/*
釋放設(shè)備列表
*/
76
pcap_freealldevs(alldevs);
77
78
/*
開始捕獲
*/
79
pcap_loop(adhandle,
0
, packet_handler, NULL);
80
81
return
0
;
82
}
83
84
85
/*
每次捕獲到數(shù)據(jù)包時,libpcap都會自動調(diào)用這個回調(diào)函數(shù)
*/
86
void
packet_handler(u_char *param,
const
struct
pcap_pkthdr *header,
const
u_char *
pkt_data)
87
{
88
struct
tm *
ltime;
89
char
timestr[
16
];
90
time_t local_tv_sec;
91
92
/*
將時間戳轉(zhuǎn)換成可識別的格式
*/
93
local_tv_sec = header->
ts.tv_sec;
94
ltime=localtime(&
local_tv_sec);
95
strftime( timestr,
sizeof
timestr,
"
%H:%M:%S
"
, ltime);
96
97
printf(
"
%s,%.6d len:%d\n
"
, timestr, header->ts.tv_usec, header->
len);
98
}
*結(jié)果:
時間戳(精確到微妙),包長度;
?
timeval
The? timeval ?structure is used to specify time values. It is associated with the Berkeley Software Distribution (BSD) file Time.h.
struct
timeval {
long
tv_sec;
//
seconds
long
tv_usec;
//
and microseconds
};
Members
- tv_sec
- Time value, in seconds.
- tv_usec
- Time value, in microseconds.?
?
localtime
Converts a time value and corrects for the local time zone.
struct
tm *localtime(
const
time_t *timer );
?
?
struct
tm {
int
tm_sec;
/*
seconds after the minute - [0,59]
*/
int
tm_min;
/*
minutes after the hour - [0,59]
*/
int
tm_hour;
/*
hours since midnight - [0,23]
*/
int
tm_mday;
/*
day of the month - [1,31]
*/
int
tm_mon;
/*
months since January - [0,11]
*/
int
tm_year;
/*
years since 1900
*/
int
tm_wday;
/*
days since Sunday - [0,6]
*/
int
tm_yday;
/*
days since January 1 - [0,365]
*/
int
tm_isdst;
/*
daylight savings time flag
*/
};
?
?
?
asctime, _wasctime
Converts a? tm? time structure to a character string.
char
*asctime(
const
struct
tm *
timeptr );
wchar_t
*_wasctime(
const
struct
tm *timeptr );
?
Return Value
asctime ?returns a pointer to the character string result;? _wasctime ?returns a pointer to the wide-character string result. There is no error return value.
?
?
time
Gets the system time.
time_t time( time_t *timer );
?
?
?
strftime, wcsftime
Format a time string.
size_t strftime(
char
*strDest, size_t maxsize,
const
char
*format,
const
struct
tm *
timeptr );
size_t wcsftime( wchar_t
*strDest, size_t maxsize,
const
wchar_t *format,
const
struct
tm *timeptr );
?
Return Value
strftime ?returns the number of characters placed in? strDest ?if the total number of resulting characters, including the terminating null, is not more than? maxsize .
wcsftime ?returns the corresponding number of wide characters. Otherwise, the functions return 0, and the contents of? strDest ?is indeterminate.
?
?
void
pcap_freealldevs ( pcap_if_t * alldevsp )
Free an interface list returned by? pcap_findalldevs() . ?
?
更多文章、技術(shù)交流、商務合作、聯(lián)系博主
微信掃碼或搜索:z360901061
微信掃一掃加我為好友
QQ號聯(lián)系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元

