pcap/capture/activated/
active.rs

1use std::borrow::Borrow;
2
3#[cfg(not(windows))]
4use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, RawFd};
5
6use crate::{
7    capture::{Active, Capture},
8    raw, Error,
9};
10
11impl Capture<Active> {
12    /// Sends a packet over this capture handle's interface.
13    pub fn sendpacket<B: Borrow<[u8]>>(&mut self, buf: B) -> Result<(), Error> {
14        let buf = buf.borrow();
15        self.check_err(unsafe {
16            raw::pcap_sendpacket(self.handle.as_ptr(), buf.as_ptr() as _, buf.len() as _) == 0
17        })
18    }
19
20    /// Set the capture to be non-blocking. When this is set, [`Self::next_packet()`] may return an
21    /// error indicating that there is no packet available to be read.
22    pub fn setnonblock(mut self) -> Result<Capture<Active>, Error> {
23        Error::with_errbuf(|err| unsafe {
24            if raw::pcap_setnonblock(self.handle.as_ptr(), 1, err) != 0 {
25                return Err(Error::new(err));
26            }
27            self.nonblock = true;
28            Ok(self)
29        })
30    }
31}
32
33#[cfg(not(windows))]
34impl AsRawFd for Capture<Active> {
35    /// Returns the file descriptor for a live capture.
36    fn as_raw_fd(&self) -> RawFd {
37        let fd = unsafe { raw::pcap_fileno(self.handle.as_ptr()) };
38        assert!(fd != -1, "Unable to get file descriptor for live capture");
39        fd
40    }
41}
42
43#[cfg(not(windows))]
44impl AsFd for Capture<Active> {
45    /// Returns the file descriptor for a live capture.
46    fn as_fd(&self) -> BorrowedFd<'_> {
47        // SAFETY: pcap_fileno always succeeds on a live capture,
48        // and we know this capture is live due to its State.
49        let fd = unsafe { raw::pcap_fileno(self.handle.as_ptr()) };
50        assert!(fd != -1, "Unable to get file descriptor for live capture");
51        // SAFETY: The lifetime is bound to self, which is correct.
52        // We have checked that fd != -1.
53        unsafe { BorrowedFd::borrow_raw(fd) }
54    }
55}
56
57#[cfg(test)]
58mod tests {
59    use crate::{
60        capture::testmod::test_capture,
61        raw::{
62            mock_ffi::*,
63            testmod::{as_pcap_t, geterr_expect, RAWMTX},
64        },
65    };
66
67    use super::*;
68
69    #[test]
70    fn test_sendpacket() {
71        let _m = RAWMTX.lock();
72
73        let mut dummy: isize = 777;
74        let pcap = as_pcap_t(&mut dummy);
75
76        let buffer: [u8; 10] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
77
78        let test_capture = test_capture::<Active>(pcap);
79        let mut capture = test_capture.capture;
80
81        let ctx = pcap_sendpacket_context();
82        ctx.expect()
83            .withf_st(move |arg1, _, _| *arg1 == pcap)
84            .return_once(|_, _, _| 0);
85
86        let result = capture.sendpacket(buffer);
87        assert!(result.is_ok());
88
89        let ctx = pcap_sendpacket_context();
90        ctx.checkpoint();
91        ctx.expect()
92            .withf_st(move |arg1, _, _| *arg1 == pcap)
93            .return_once(|_, _, _| -1);
94
95        let _err = geterr_expect(pcap);
96
97        let result = capture.sendpacket(buffer);
98        assert!(result.is_err());
99    }
100
101    #[test]
102    fn test_setnonblock() {
103        let _m = RAWMTX.lock();
104
105        let mut dummy: isize = 777;
106        let pcap = as_pcap_t(&mut dummy);
107
108        let test_capture = test_capture::<Active>(pcap);
109        let capture = test_capture.capture;
110        assert!(!capture.is_nonblock());
111
112        let ctx = pcap_setnonblock_context();
113        ctx.expect()
114            .withf_st(move |arg1, arg2, _| (*arg1 == pcap) && (*arg2 == 1))
115            .return_once(|_, _, _| 0);
116
117        let capture = capture.setnonblock().unwrap();
118        assert!(capture.is_nonblock());
119    }
120
121    #[test]
122    fn test_setnonblock_error() {
123        let _m = RAWMTX.lock();
124
125        let mut dummy: isize = 777;
126        let pcap = as_pcap_t(&mut dummy);
127
128        let test_capture = test_capture::<Active>(pcap);
129        let capture = test_capture.capture;
130        assert!(!capture.nonblock);
131
132        let ctx = pcap_setnonblock_context();
133        ctx.expect()
134            .withf_st(move |arg1, arg2, _| (*arg1 == pcap) && (*arg2 == 1))
135            .return_once(|_, _, _| -1);
136
137        let result = capture.setnonblock();
138        assert!(result.is_err());
139    }
140
141    #[test]
142    #[cfg(not(windows))]
143    fn test_as_raw_fd() {
144        let _m = RAWMTX.lock();
145
146        let mut dummy: isize = 777;
147        let pcap = as_pcap_t(&mut dummy);
148
149        let test_capture = test_capture::<Active>(pcap);
150        let capture = test_capture.capture;
151
152        let ctx = pcap_fileno_context();
153        ctx.expect()
154            .withf_st(move |arg1| *arg1 == pcap)
155            .return_once(|_| 7);
156
157        assert_eq!(capture.as_raw_fd(), 7);
158    }
159
160    #[test]
161    #[cfg(not(windows))]
162    fn test_as_fd() {
163        let _m = RAWMTX.lock();
164
165        let mut dummy: isize = 777;
166        let pcap = as_pcap_t(&mut dummy);
167
168        let test_capture = test_capture::<Active>(pcap);
169        let capture = test_capture.capture;
170
171        let ctx = pcap_fileno_context();
172        ctx.expect()
173            .withf_st(move |arg1| *arg1 == pcap)
174            .return_once(|_| 7);
175
176        assert_eq!(capture.as_fd().as_raw_fd(), 7);
177    }
178}