1
1
use crate :: { errors:: Error , pcap_util, stats:: Stats } ;
2
+ use crate :: bpf:: Bpf ;
2
3
use log:: * ;
3
- use std;
4
+ use std:: path:: Path ;
5
+ use std:: os:: raw:: c_int;
4
6
7
+ /// Wrapper around a pcap_t handle to indicate live or offline capture, and allow the handle to
8
+ /// be interrupted to stop capture.
5
9
#[ derive( Clone ) ]
6
10
pub struct Handle {
7
11
handle : * mut pcap_sys:: pcap_t ,
@@ -17,6 +21,7 @@ impl Handle {
17
21
self . live_capture
18
22
}
19
23
24
+ /// Create a live capture from a string representing an interface
20
25
pub fn live_capture ( iface : & str ) -> Result < std:: sync:: Arc < Handle > , Error > {
21
26
let device_str = std:: ffi:: CString :: new ( iface) . map_err ( Error :: Ffi ) ?;
22
27
@@ -43,7 +48,13 @@ impl Handle {
43
48
r
44
49
}
45
50
46
- pub fn file_capture ( path : & str ) -> Result < std:: sync:: Arc < Handle > , Error > {
51
+ /// Create an offline capture from a path to a file
52
+ pub fn file_capture < P : AsRef < Path > > ( path : P ) -> Result < std:: sync:: Arc < Handle > , Error > {
53
+ let path = if let Some ( s) = path. as_ref ( ) . to_str ( ) {
54
+ s
55
+ } else {
56
+ return Err ( Error :: Custom { msg : format ! ( "Invalid path: {:?}" , path. as_ref( ) ) } )
57
+ } ;
47
58
let device_str = std:: ffi:: CString :: new ( path) . map_err ( Error :: Ffi ) ?;
48
59
49
60
let errbuf = ( [ 0i8 ; 256 ] ) . as_mut_ptr ( ) ;
@@ -69,6 +80,23 @@ impl Handle {
69
80
r
70
81
}
71
82
83
+ /// Create a dead handle, typically used for compiling bpf's
84
+ pub fn dead ( linktype : i32 , snaplen : i32 ) -> Result < std:: sync:: Arc < Handle > , Error > {
85
+ let h = unsafe { pcap_sys:: pcap_open_dead ( linktype as c_int , snaplen as c_int ) } ;
86
+ if h. is_null ( ) {
87
+ error ! ( "Failed to create dead handle" ) ;
88
+ Err ( Error :: Custom { msg : "Could not create dead handle" . to_owned ( ) } )
89
+ } else {
90
+ info ! ( "Dead handle created" ) ;
91
+ let handle = std:: sync:: Arc :: new ( Handle {
92
+ handle : h,
93
+ live_capture : false ,
94
+ interrupted : std:: sync:: Arc :: new ( std:: sync:: Mutex :: new ( false ) )
95
+ } ) ;
96
+ Ok ( handle)
97
+ }
98
+ }
99
+
72
100
pub fn lookup ( ) -> Result < std:: sync:: Arc < Handle > , Error > {
73
101
let errbuf = ( [ 0i8 ; 256 ] ) . as_mut_ptr ( ) ;
74
102
let dev = unsafe { pcap_sys:: pcap_lookupdev ( errbuf) } ;
@@ -138,10 +166,10 @@ impl Handle {
138
166
}
139
167
}
140
168
141
- pub fn set_bpf (
169
+ pub fn compile_bpf (
142
170
& self ,
143
- bpf : & String ,
144
- ) -> Result < & Self , Error > {
171
+ bpf : & str ,
172
+ ) -> Result < Bpf , Error > {
145
173
let mut bpf_program = pcap_sys:: bpf_program {
146
174
bf_len : 0 ,
147
175
bf_insns : std:: ptr:: null_mut ( ) ,
@@ -161,10 +189,16 @@ impl Handle {
161
189
return Err ( pcap_util:: convert_libpcap_error ( self . handle ) ) ;
162
190
}
163
191
164
- let ret_code = unsafe { pcap_sys:: pcap_setfilter ( self . handle , & mut bpf_program) } ;
165
- unsafe {
166
- pcap_sys:: pcap_freecode ( & mut bpf_program) ;
167
- }
192
+ Ok ( Bpf :: new ( bpf_program) )
193
+ }
194
+
195
+ pub fn set_bpf (
196
+ & self ,
197
+ bpf : Bpf ,
198
+ ) -> Result < & Self , Error > {
199
+ let mut bpf = bpf;
200
+
201
+ let ret_code = unsafe { pcap_sys:: pcap_setfilter ( self . handle , bpf. inner_mut ( ) ) } ;
168
202
if ret_code != 0 {
169
203
return Err ( pcap_util:: convert_libpcap_error ( self . handle ) ) ;
170
204
}
@@ -259,4 +293,22 @@ mod tests {
259
293
260
294
assert ! ( handle. is_ok( ) ) ;
261
295
}
296
+ #[ test]
297
+ fn open_dead ( ) {
298
+ let _ = env_logger:: try_init ( ) ;
299
+
300
+ let handle = Handle :: dead ( 0 , 0 ) ;
301
+
302
+ assert ! ( handle. is_ok( ) ) ;
303
+ }
304
+ #[ test]
305
+ fn bpf_compile ( ) {
306
+ let _ = env_logger:: try_init ( ) ;
307
+
308
+ let handle = Handle :: dead ( 0 , 1555 ) . expect ( "Could not create dead handle" ) ;
309
+
310
+ let bpf = handle. compile_bpf ( "(not (net 192.168.0.0/16 and port 443)) and (not (host 192.1.2.3 and port 443))" ) ;
311
+
312
+ assert ! ( bpf. is_ok( ) , "{:?}" , bpf) ;
313
+ }
262
314
}
0 commit comments