1#![allow(dead_code)]
3#![allow(non_camel_case_types)]
4
5use libc::{c_char, c_int, c_uchar, c_uint, c_ushort, sockaddr, timeval, FILE};
6
7#[cfg(test)]
8use mockall::automock;
9
10pub const PCAP_IF_LOOPBACK: u32 = 0x00000001;
11pub const PCAP_IF_UP: u32 = 0x00000002;
12pub const PCAP_IF_RUNNING: u32 = 0x00000004;
13pub const PCAP_IF_WIRELESS: u32 = 0x00000008;
14pub const PCAP_IF_CONNECTION_STATUS: u32 = 0x00000030;
15pub const PCAP_IF_CONNECTION_STATUS_UNKNOWN: u32 = 0x00000000;
16pub const PCAP_IF_CONNECTION_STATUS_CONNECTED: u32 = 0x00000010;
17pub const PCAP_IF_CONNECTION_STATUS_DISCONNECTED: u32 = 0x00000020;
18pub const PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE: u32 = 0x00000030;
19
20#[repr(C)]
21#[derive(Copy, Clone)]
22pub struct bpf_program {
23 pub bf_len: c_uint,
24 pub bf_insns: *mut bpf_insn,
25}
26
27#[repr(C)]
28#[derive(Copy, Clone)]
29pub struct bpf_insn {
30 pub code: c_ushort,
31 pub jt: c_uchar,
32 pub jf: c_uchar,
33 pub k: c_uint,
34}
35
36pub enum pcap_t {}
37
38pub enum pcap_dumper_t {}
39
40#[repr(C)]
41#[derive(Copy, Clone)]
42pub struct pcap_file_header {
43 pub magic: c_uint,
44 pub version_major: c_ushort,
45 pub version_minor: c_ushort,
46 pub thiszone: c_int,
47 pub sigfigs: c_uint,
48 pub snaplen: c_uint,
49 pub linktype: c_uint,
50}
51
52pub type pcap_direction_t = c_uint;
53
54pub const PCAP_D_INOUT: pcap_direction_t = 0;
55pub const PCAP_D_IN: pcap_direction_t = 1;
56pub const PCAP_D_OUT: pcap_direction_t = 2;
57
58#[repr(C)]
59#[derive(Copy, Clone)]
60pub struct pcap_pkthdr {
61 pub ts: timeval,
62 pub caplen: c_uint,
63 pub len: c_uint,
64}
65
66#[repr(C)]
67#[derive(Copy, Clone)]
68pub struct pcap_stat {
69 pub ps_recv: c_uint,
70 pub ps_drop: c_uint,
71 pub ps_ifdrop: c_uint,
72}
73
74#[repr(C)]
75#[derive(Copy, Clone)]
76pub struct pcap_if_t {
77 pub next: *mut pcap_if_t,
78 pub name: *mut c_char,
79 pub description: *mut c_char,
80 pub addresses: *mut pcap_addr_t,
81 pub flags: c_uint,
82}
83
84#[repr(C)]
85#[derive(Copy, Clone)]
86pub struct pcap_addr_t {
87 pub next: *mut pcap_addr_t,
88 pub addr: *mut sockaddr,
89 pub netmask: *mut sockaddr,
90 pub broadaddr: *mut sockaddr,
91 pub dstaddr: *mut sockaddr,
92}
93
94#[cfg(windows)]
95#[repr(C)]
96#[derive(Copy, Clone)]
97pub struct pcap_send_queue {
98 pub maxlen: c_uint,
99 pub len: c_uint,
100 pub buffer: *mut c_char,
101}
102
103pub type pcap_handler =
106 extern "C" fn(arg1: *mut c_uchar, arg2: *const pcap_pkthdr, arg3: *const c_uchar) -> ();
107
108#[cfg_attr(test, automock)]
109pub mod ffi {
110 use super::*;
111
112 extern "C" {
113 pub fn pcap_create(arg1: *const c_char, arg2: *mut c_char) -> *mut pcap_t;
117 pub fn pcap_set_snaplen(arg1: *mut pcap_t, arg2: c_int) -> c_int;
118 pub fn pcap_set_promisc(arg1: *mut pcap_t, arg2: c_int) -> c_int;
119 pub fn pcap_set_timeout(arg1: *mut pcap_t, arg2: c_int) -> c_int;
121 pub fn pcap_set_buffer_size(arg1: *mut pcap_t, arg2: c_int) -> c_int;
122 pub fn pcap_activate(arg1: *mut pcap_t) -> c_int;
123 pub fn pcap_open_dead(arg1: c_int, arg2: c_int) -> *mut pcap_t;
126 pub fn pcap_open_offline(arg1: *const c_char, arg2: *mut c_char) -> *mut pcap_t;
127 pub fn pcap_fopen_offline(arg1: *mut FILE, arg2: *mut c_char) -> *mut pcap_t;
128 pub fn pcap_close(arg1: *mut pcap_t);
129 pub fn pcap_loop(
130 arg1: *mut pcap_t,
131 arg2: c_int,
132 arg3: pcap_handler,
133 arg4: *mut c_uchar,
134 ) -> c_int;
135 pub fn pcap_next_ex(
139 arg1: *mut pcap_t,
140 arg2: *mut *mut pcap_pkthdr,
141 arg3: *mut *const c_uchar,
142 ) -> c_int;
143 pub fn pcap_breakloop(arg1: *mut pcap_t);
144 pub fn pcap_stats(arg1: *mut pcap_t, arg2: *mut pcap_stat) -> c_int;
145 pub fn pcap_setfilter(arg1: *mut pcap_t, arg2: *mut bpf_program) -> c_int;
146 pub fn pcap_setdirection(arg1: *mut pcap_t, arg2: pcap_direction_t) -> c_int;
147 pub fn pcap_setnonblock(arg1: *mut pcap_t, arg2: c_int, arg3: *mut c_char) -> c_int;
149 pub fn pcap_sendpacket(arg1: *mut pcap_t, arg2: *const c_uchar, arg3: c_int) -> c_int;
150 pub fn pcap_geterr(arg1: *mut pcap_t) -> *mut c_char;
153 pub fn pcap_compile(
155 arg1: *mut pcap_t,
156 arg2: *mut bpf_program,
157 arg3: *const c_char,
158 arg4: c_int,
159 arg5: c_uint,
160 ) -> c_int;
161 pub fn pcap_freecode(arg1: *mut bpf_program);
164 pub fn pcap_offline_filter(
165 arg1: *const bpf_program,
166 arg2: *const pcap_pkthdr,
167 arg3: *const c_uchar,
168 ) -> c_int;
169 pub fn pcap_datalink(arg1: *mut pcap_t) -> c_int;
170 pub fn pcap_list_datalinks(arg1: *mut pcap_t, arg2: *mut *mut c_int) -> c_int;
172 pub fn pcap_set_datalink(arg1: *mut pcap_t, arg2: c_int) -> c_int;
173 pub fn pcap_free_datalinks(arg1: *mut c_int);
174 pub fn pcap_datalink_name_to_val(arg1: *const c_char) -> c_int;
175 pub fn pcap_datalink_val_to_name(arg1: c_int) -> *const c_char;
176 pub fn pcap_datalink_val_to_description(arg1: c_int) -> *const c_char;
177 pub fn pcap_major_version(arg1: *mut pcap_t) -> c_int;
180 pub fn pcap_minor_version(arg1: *mut pcap_t) -> c_int;
181 pub fn pcap_fileno(arg1: *mut pcap_t) -> c_int;
183 pub fn pcap_dump_open(arg1: *mut pcap_t, arg2: *const c_char) -> *mut pcap_dumper_t;
184 pub fn pcap_dump_fopen(arg1: *mut pcap_t, fp: *mut FILE) -> *mut pcap_dumper_t;
185 pub fn pcap_dump_flush(arg1: *mut pcap_dumper_t) -> c_int;
188 pub fn pcap_dump_close(arg1: *mut pcap_dumper_t);
189 pub fn pcap_dump(arg1: *mut c_uchar, arg2: *const pcap_pkthdr, arg3: *const c_uchar);
190 pub fn pcap_findalldevs(arg1: *mut *mut pcap_if_t, arg2: *mut c_char) -> c_int;
191 pub fn pcap_freealldevs(arg1: *mut pcap_if_t);
192 pub fn pcap_get_selectable_fd(arg1: *mut pcap_t) -> c_int;
196 }
197
198 #[cfg(libpcap_1_2_1)]
199 extern "C" {
200 pub fn pcap_set_tstamp_type(arg1: *mut pcap_t, arg2: c_int) -> c_int;
206 }
207
208 #[cfg(libpcap_1_5_0)]
209 extern "C" {
210 pub fn pcap_fopen_offline_with_tstamp_precision(
211 arg1: *mut FILE,
212 arg2: c_uint,
213 arg3: *mut c_char,
214 ) -> *mut pcap_t;
215 pub fn pcap_open_dead_with_tstamp_precision(
217 arg1: c_int,
218 arg2: c_int,
219 arg3: c_uint,
220 ) -> *mut pcap_t;
221 pub fn pcap_open_offline_with_tstamp_precision(
222 arg1: *const c_char,
223 arg2: c_uint,
224 arg3: *mut c_char,
225 ) -> *mut pcap_t;
226 pub fn pcap_set_immediate_mode(arg1: *mut pcap_t, arg2: c_int) -> c_int;
227 pub fn pcap_set_tstamp_precision(arg1: *mut pcap_t, arg2: c_int) -> c_int;
228 }
229
230 #[cfg(libpcap_1_7_2)]
231 extern "C" {
232 pub fn pcap_dump_open_append(arg1: *mut pcap_t, arg2: *const c_char) -> *mut pcap_dumper_t;
233 }
234
235 #[cfg(libpcap_1_9_0)]
236 extern "C" {
237 }
251
252 #[cfg(libpcap_1_9_1)]
253 extern "C" {
254 }
256}
257
258#[cfg(not(windows))]
259#[cfg_attr(test, automock)]
260pub mod ffi_unix {
261 use super::*;
262
263 #[link(name = "pcap")]
264 extern "C" {
265 pub fn pcap_set_rfmon(arg1: *mut pcap_t, arg2: c_int) -> c_int;
267 }
268}
269
270#[cfg(target_os = "macos")]
271#[cfg_attr(test, automock)]
272pub mod ffi_macos {
273 use super::*;
274
275 #[cfg(libpcap_1_5_3)]
276 extern "C" {
277 pub fn pcap_set_want_pktap(arg1: *mut pcap_t, arg2: c_int) -> c_int;
278 }
279}
280
281#[cfg(windows)]
282#[cfg_attr(test, automock)]
283pub mod ffi_windows {
284 use windows_sys::Win32::Foundation::HANDLE;
285
286 use super::*;
287
288 pub const WINPCAP_MINTOCOPY_DEFAULT: c_int = 16000;
289
290 #[link(name = "wpcap")]
291 extern "C" {
292 pub fn pcap_setmintocopy(arg1: *mut pcap_t, arg2: c_int) -> c_int;
293 pub fn pcap_getevent(p: *mut pcap_t) -> HANDLE;
294 pub fn pcap_sendqueue_alloc(memsize: c_uint) -> *mut pcap_send_queue;
295 pub fn pcap_sendqueue_destroy(queue: *mut pcap_send_queue);
296 pub fn pcap_sendqueue_queue(
297 queue: *mut pcap_send_queue,
298 pkt_header: *const pcap_pkthdr,
299 pkt_data: *const c_uchar,
300 ) -> c_int;
301 pub fn pcap_sendqueue_transmit(
302 p: *mut pcap_t,
303 queue: *mut pcap_send_queue,
304 sync: c_int,
305 ) -> c_uint;
306 }
307}
308
309#[cfg(not(test))]
313pub use ffi::*;
314
315#[cfg(not(test))]
316#[cfg(not(windows))]
317pub use ffi_unix::*;
318
319#[cfg(not(test))]
320#[cfg(target_os = "macos")]
321pub use ffi_macos::*;
322
323#[cfg(not(test))]
324#[cfg(windows)]
325pub use ffi_windows::*;
326
327#[cfg(test)]
328pub use mock_ffi::*;
329
330#[cfg(test)]
331#[cfg(not(windows))]
332pub use mock_ffi_unix::*;
333
334#[cfg(test)]
335#[cfg(target_os = "macos")]
336pub use mock_ffi_macos::*;
337
338#[cfg(test)]
339#[cfg(windows)]
340pub use mock_ffi_windows::*;
341
342#[cfg(test)]
343pub mod testmod {
344 use std::{ffi::CString, sync::Mutex};
345
346 use once_cell::sync::Lazy;
347
348 use super::*;
349
350 pub struct GeterrContext(__pcap_geterr::Context);
351
352 pub static RAWMTX: Lazy<Mutex<()>> = Lazy::new(|| Mutex::new(()));
354
355 pub fn as_pcap_t<T: ?Sized>(value: &mut T) -> *mut pcap_t {
356 value as *mut T as *mut pcap_t
357 }
358
359 pub fn as_pcap_dumper_t<T: ?Sized>(value: &mut T) -> *mut pcap_dumper_t {
360 value as *mut T as *mut pcap_dumper_t
361 }
362
363 pub fn geterr_expect(pcap: *mut pcap_t) -> GeterrContext {
364 assert!(RAWMTX.try_lock().is_err());
366
367 let err = CString::new("oh oh").unwrap();
368 let ctx = pcap_geterr_context();
369 ctx.checkpoint();
370 ctx.expect()
371 .withf_st(move |arg1| *arg1 == pcap)
372 .return_once_st(|_| err.into_raw());
373
374 GeterrContext(ctx)
375 }
376}
377