1use std::mem;
2
3use crate::{
4 capture::{Active, Capture, Inactive},
5 device::Device,
6 raw, Error,
7};
8
9#[cfg(libpcap_1_5_0)]
10use crate::capture::Precision;
11
12impl Capture<Inactive> {
13 pub fn from_device<D: Into<Device>>(device: D) -> Result<Capture<Inactive>, Error> {
34 let device: Device = device.into();
35 Capture::new_raw(Some(&device.name), |name, err| unsafe {
36 raw::pcap_create(name, err)
37 })
38 }
39
40 pub fn open(self) -> Result<Capture<Active>, Error> {
42 unsafe {
43 self.check_err(raw::pcap_activate(self.handle.as_ptr()) == 0)?;
44 Ok(mem::transmute::<Capture<Inactive>, Capture<Active>>(self))
45 }
46 }
47
48 pub fn timeout(self, ms: i32) -> Capture<Inactive> {
50 unsafe { raw::pcap_set_timeout(self.handle.as_ptr(), ms) };
51 self
52 }
53
54 #[cfg(libpcap_1_2_1)]
56 pub fn tstamp_type(self, tstamp_type: TimestampType) -> Capture<Inactive> {
57 unsafe { raw::pcap_set_tstamp_type(self.handle.as_ptr(), tstamp_type as _) };
58 self
59 }
60
61 pub fn promisc(self, to: bool) -> Capture<Inactive> {
63 unsafe { raw::pcap_set_promisc(self.handle.as_ptr(), to as _) };
64 self
65 }
66
67 #[cfg(any(libpcap_1_5_0, windows))]
74 pub fn immediate_mode(self, to: bool) -> Capture<Inactive> {
75 #[cfg(libpcap_1_5_0)]
81 unsafe {
82 raw::pcap_set_immediate_mode(self.handle.as_ptr(), to as _)
83 };
84
85 #[cfg(all(windows, not(libpcap_1_5_0)))]
87 unsafe {
88 raw::pcap_setmintocopy(
89 self.handle.as_ptr(),
90 if to {
91 0
92 } else {
93 raw::WINPCAP_MINTOCOPY_DEFAULT
94 },
95 )
96 };
97
98 self
99 }
100
101 #[cfg(all(libpcap_1_5_3, target_os = "macos"))]
103 pub fn want_pktap(self, to: bool) -> Capture<Inactive> {
104 unsafe { raw::pcap_set_want_pktap(self.handle.as_ptr(), to as _) };
105
106 self
107 }
108
109 #[cfg(not(windows))]
111 pub fn rfmon(self, to: bool) -> Capture<Inactive> {
112 unsafe { raw::pcap_set_rfmon(self.handle.as_ptr(), to as _) };
113 self
114 }
115
116 pub fn buffer_size(self, to: i32) -> Capture<Inactive> {
120 unsafe { raw::pcap_set_buffer_size(self.handle.as_ptr(), to) };
121 self
122 }
123
124 #[cfg(libpcap_1_5_0)]
126 pub fn precision(self, precision: Precision) -> Capture<Inactive> {
127 unsafe { raw::pcap_set_tstamp_precision(self.handle.as_ptr(), precision as _) };
128 self
129 }
130
131 pub fn snaplen(self, to: i32) -> Capture<Inactive> {
136 unsafe { raw::pcap_set_snaplen(self.handle.as_ptr(), to) };
137 self
138 }
139}
140
141#[repr(i32)]
142#[derive(Debug, PartialEq, Eq, Clone, Copy)]
143pub enum TimestampType {
157 Host = 0,
161 HostLowPrec = 1,
167 HostHighPrec = 2,
174 Adapter = 3,
178 AdapterUnsynced = 4,
182}
183
184#[cfg(test)]
185mod tests {
186 use crate::{
187 capture::testmod::test_capture,
188 raw::testmod::{as_pcap_t, geterr_expect, RAWMTX},
189 };
190
191 use super::*;
192
193 #[test]
194 fn test_from_device() {
195 let _m = RAWMTX.lock();
196
197 let mut dummy: isize = 777;
198 let pcap = as_pcap_t(&mut dummy);
199
200 let ctx = raw::pcap_create_context();
201 ctx.expect().return_once_st(move |_, _| pcap);
202
203 let ctx = raw::pcap_close_context();
204 ctx.expect()
205 .withf_st(move |ptr| *ptr == pcap)
206 .return_once(|_| {});
207
208 let result = Capture::from_device("some_device");
209 assert!(result.is_ok());
210 }
211
212 #[test]
213 fn test_from_device_error() {
214 let _m = RAWMTX.lock();
215
216 let ctx = raw::pcap_create_context();
217 ctx.expect().return_once_st(|_, _| std::ptr::null_mut());
218
219 let result = Capture::from_device("some_device");
220 assert!(result.is_err());
221 }
222
223 #[test]
224 fn test_open() {
225 let _m = RAWMTX.lock();
226
227 let mut dummy: isize = 777;
228 let pcap = as_pcap_t(&mut dummy);
229
230 let test_capture = test_capture::<Inactive>(pcap);
231 let capture = test_capture.capture;
232
233 let ctx = raw::pcap_activate_context();
234 ctx.expect()
235 .withf_st(move |arg1| *arg1 == pcap)
236 .return_once(|_| 0);
237
238 let result = capture.open();
239 assert!(result.is_ok());
240 }
241
242 #[test]
243 fn test_open_error() {
244 let _m = RAWMTX.lock();
245
246 let mut dummy: isize = 777;
247 let pcap = as_pcap_t(&mut dummy);
248
249 let test_capture = test_capture::<Inactive>(pcap);
250 let capture = test_capture.capture;
251
252 let ctx = raw::pcap_activate_context();
253 ctx.expect()
254 .withf_st(move |arg1| *arg1 == pcap)
255 .return_once(|_| -1);
256
257 let _err = geterr_expect(pcap);
258
259 let result = capture.open();
260 assert!(result.is_err());
261 }
262
263 #[test]
264 fn test_timeout() {
265 let _m = RAWMTX.lock();
266
267 let mut dummy: isize = 777;
268 let pcap = as_pcap_t(&mut dummy);
269
270 let test_capture = test_capture::<Inactive>(pcap);
271 let capture = test_capture.capture;
272
273 let ctx = raw::pcap_set_timeout_context();
274 ctx.expect()
275 .withf_st(move |arg1, _| *arg1 == pcap)
276 .return_once(|_, _| 0);
277
278 let _capture = capture.timeout(5);
279 }
280
281 #[test]
282 #[cfg(libpcap_1_2_1)]
283 fn test_timstamp_type() {
284 let _m = RAWMTX.lock();
285
286 let mut dummy: isize = 777;
287 let pcap = as_pcap_t(&mut dummy);
288
289 let test_capture = test_capture::<Inactive>(pcap);
290 let capture = test_capture.capture;
291
292 let ctx = raw::pcap_set_tstamp_type_context();
293 ctx.expect()
294 .withf_st(move |arg1, _| *arg1 == pcap)
295 .return_once(|_, _| 0);
296
297 let _capture = capture.tstamp_type(TimestampType::Host);
298
299 assert_ne!(TimestampType::Host, TimestampType::HostLowPrec);
301 assert_ne!(TimestampType::Host, TimestampType::HostHighPrec);
302 }
303
304 #[test]
305 fn test_promisc() {
306 let _m = RAWMTX.lock();
307
308 let mut dummy: isize = 777;
309 let pcap = as_pcap_t(&mut dummy);
310
311 let test_capture = test_capture::<Inactive>(pcap);
312 let capture = test_capture.capture;
313
314 let ctx = raw::pcap_set_promisc_context();
315 ctx.expect()
316 .withf_st(move |arg1, _| *arg1 == pcap)
317 .return_once(|_, _| 0);
318
319 let _capture = capture.promisc(true);
320 }
321
322 #[cfg(libpcap_1_5_0)]
323 struct ImmediateModeExpect(raw::__pcap_set_immediate_mode::Context);
324
325 #[cfg(all(windows, not(libpcap_1_5_0)))]
326 struct ImmediateModeExpect(raw::__pcap_setmintocopy::Context);
327
328 #[cfg(any(libpcap_1_5_0, windows))]
329 fn immediate_mode_expect(pcap: *mut raw::pcap_t) -> ImmediateModeExpect {
330 #[cfg(libpcap_1_5_0)]
331 {
332 let ctx = raw::pcap_set_immediate_mode_context();
333 ctx.checkpoint();
334 ctx.expect()
335 .withf_st(move |arg1, _| *arg1 == pcap)
336 .return_once(|_, _| 0);
337 ImmediateModeExpect(ctx)
338 }
339 #[cfg(all(windows, not(libpcap_1_5_0)))]
340 {
341 let ctx = raw::pcap_setmintocopy_context();
342 ctx.checkpoint();
343 ctx.expect()
344 .withf_st(move |arg1, _| *arg1 == pcap)
345 .return_once(|_, _| 0);
346 ImmediateModeExpect(ctx)
347 }
348 }
349
350 #[test]
351 #[cfg(any(libpcap_1_5_0, windows))]
352 fn test_immediate_mode() {
353 let _m = RAWMTX.lock();
354
355 let mut dummy: isize = 777;
356 let pcap = as_pcap_t(&mut dummy);
357
358 let test_capture = test_capture::<Inactive>(pcap);
359 let capture = test_capture.capture;
360
361 let _ctx = immediate_mode_expect(pcap);
362 let capture = capture.immediate_mode(true);
363
364 let _ctx = immediate_mode_expect(pcap);
365 let _capture = capture.immediate_mode(false);
366 }
367
368 #[test]
369 #[cfg(all(libpcap_1_5_3, target_os = "macos"))]
370 fn test_want_pktap() {
371 let _m = RAWMTX.lock();
372
373 let mut dummy: isize = 777;
374 let pcap = as_pcap_t(&mut dummy);
375
376 let test_capture = test_capture::<Inactive>(pcap);
377 let capture = test_capture.capture;
378
379 let ctx = raw::pcap_set_want_pktap_context();
380 ctx.expect()
381 .withf_st(move |arg1, _| *arg1 == pcap)
382 .return_once(|_, _| 0);
383 let _capture = capture.want_pktap(true);
384 }
385
386 #[test]
387 #[cfg(not(windows))]
388 fn test_rfmon() {
389 let _m = RAWMTX.lock();
390
391 let mut dummy: isize = 777;
392 let pcap = as_pcap_t(&mut dummy);
393
394 let test_capture = test_capture::<Inactive>(pcap);
395 let capture = test_capture.capture;
396
397 let ctx = raw::pcap_set_rfmon_context();
398 ctx.expect()
399 .withf_st(move |arg1, _| *arg1 == pcap)
400 .return_once(|_, _| 0);
401
402 let _capture = capture.rfmon(true);
403 }
404
405 #[test]
406 fn test_buffer_size() {
407 let _m = RAWMTX.lock();
408
409 let mut dummy: isize = 777;
410 let pcap = as_pcap_t(&mut dummy);
411
412 let test_capture = test_capture::<Inactive>(pcap);
413 let capture = test_capture.capture;
414
415 let ctx = raw::pcap_set_buffer_size_context();
416 ctx.expect()
417 .withf_st(move |arg1, _| *arg1 == pcap)
418 .return_once(|_, _| 0);
419
420 let _capture = capture.buffer_size(10);
421 }
422
423 #[test]
424 #[cfg(libpcap_1_5_0)]
425 fn test_precision() {
426 let _m = RAWMTX.lock();
427
428 let mut dummy: isize = 777;
429 let pcap = as_pcap_t(&mut dummy);
430
431 let test_capture = test_capture::<Inactive>(pcap);
432 let capture = test_capture.capture;
433
434 let ctx = raw::pcap_set_tstamp_precision_context();
435 ctx.expect()
436 .withf_st(move |arg1, _| *arg1 == pcap)
437 .return_once(|_, _| 0);
438
439 let _capture = capture.precision(Precision::Nano);
440 }
441
442 #[test]
443 fn test_snaplen() {
444 let _m = RAWMTX.lock();
445
446 let mut dummy: isize = 777;
447 let pcap = as_pcap_t(&mut dummy);
448
449 let test_capture = test_capture::<Inactive>(pcap);
450 let capture = test_capture.capture;
451
452 let ctx = raw::pcap_set_snaplen_context();
453 ctx.expect()
454 .withf_st(move |arg1, _| *arg1 == pcap)
455 .return_once(|_, _| 0);
456
457 let _capture = capture.snaplen(10);
458 }
459}