1
use std::borrow::Borrow;
2

            
3
#[cfg(not(windows))]
4
use std::os::unix::io::{AsRawFd, RawFd};
5

            
6
use crate::{
7
    capture::{Active, Capture},
8
    raw, Error,
9
};
10

            
11
impl Capture<Active> {
12
    /// Sends a packet over this capture handle's interface.
13
4
    pub fn sendpacket<B: Borrow<[u8]>>(&mut self, buf: B) -> Result<(), Error> {
14
4
        let buf = buf.borrow();
15
4
        self.check_err(unsafe {
16
4
            raw::pcap_sendpacket(self.handle.as_ptr(), buf.as_ptr() as _, buf.len() as _) == 0
17
4
        })
18
4
    }
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
4
    pub fn setnonblock(mut self) -> Result<Capture<Active>, Error> {
23
6
        Error::with_errbuf(|err| unsafe {
24
4
            if raw::pcap_setnonblock(self.handle.as_ptr(), 1, err) != 0 {
25
2
                return Err(Error::new(err));
26
2
            }
27
2
            self.nonblock = true;
28
2
            Ok(self)
29
6
        })
30
4
    }
31
}
32

            
33
#[cfg(not(windows))]
34
impl AsRawFd for Capture<Active> {
35
    /// Returns the file descriptor for a live capture.
36
2
    fn as_raw_fd(&self) -> RawFd {
37
2
        let fd = unsafe { raw::pcap_fileno(self.handle.as_ptr()) };
38
2
        assert!(fd != -1, "Unable to get file descriptor for live capture");
39
2
        fd
40
2
    }
41
}
42

            
43
#[cfg(test)]
44
mod tests {
45
    use crate::{
46
        capture::testmod::test_capture,
47
        raw::{
48
            mock_ffi::*,
49
            testmod::{as_pcap_t, geterr_expect, RAWMTX},
50
        },
51
    };
52

            
53
    use super::*;
54

            
55
    #[test]
56
    fn test_sendpacket() {
57
        let _m = RAWMTX.lock();
58

            
59
        let mut dummy: isize = 777;
60
        let pcap = as_pcap_t(&mut dummy);
61

            
62
        let buffer: [u8; 10] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
63

            
64
        let test_capture = test_capture::<Active>(pcap);
65
        let mut capture = test_capture.capture;
66

            
67
        let ctx = pcap_sendpacket_context();
68
        ctx.expect()
69
            .withf_st(move |arg1, _, _| *arg1 == pcap)
70
            .return_once(|_, _, _| 0);
71

            
72
        let result = capture.sendpacket(buffer);
73
        assert!(result.is_ok());
74

            
75
        let ctx = pcap_sendpacket_context();
76
        ctx.checkpoint();
77
        ctx.expect()
78
            .withf_st(move |arg1, _, _| *arg1 == pcap)
79
            .return_once(|_, _, _| -1);
80

            
81
        let _err = geterr_expect(pcap);
82

            
83
        let result = capture.sendpacket(buffer);
84
        assert!(result.is_err());
85
    }
86

            
87
    #[test]
88
    fn test_setnonblock() {
89
        let _m = RAWMTX.lock();
90

            
91
        let mut dummy: isize = 777;
92
        let pcap = as_pcap_t(&mut dummy);
93

            
94
        let test_capture = test_capture::<Active>(pcap);
95
        let capture = test_capture.capture;
96
        assert!(!capture.is_nonblock());
97

            
98
        let ctx = pcap_setnonblock_context();
99
        ctx.expect()
100
            .withf_st(move |arg1, arg2, _| (*arg1 == pcap) && (*arg2 == 1))
101
            .return_once(|_, _, _| 0);
102

            
103
        let capture = capture.setnonblock().unwrap();
104
        assert!(capture.is_nonblock());
105
    }
106

            
107
    #[test]
108
    fn test_setnonblock_error() {
109
        let _m = RAWMTX.lock();
110

            
111
        let mut dummy: isize = 777;
112
        let pcap = as_pcap_t(&mut dummy);
113

            
114
        let test_capture = test_capture::<Active>(pcap);
115
        let capture = test_capture.capture;
116
        assert!(!capture.nonblock);
117

            
118
        let ctx = pcap_setnonblock_context();
119
        ctx.expect()
120
            .withf_st(move |arg1, arg2, _| (*arg1 == pcap) && (*arg2 == 1))
121
            .return_once(|_, _, _| -1);
122

            
123
        let result = capture.setnonblock();
124
        assert!(result.is_err());
125
    }
126

            
127
    #[test]
128
    #[cfg(not(windows))]
129
    fn test_as_raw_fd() {
130
        let _m = RAWMTX.lock();
131

            
132
        let mut dummy: isize = 777;
133
        let pcap = as_pcap_t(&mut dummy);
134

            
135
        let test_capture = test_capture::<Active>(pcap);
136
        let capture = test_capture.capture;
137

            
138
        let ctx = pcap_fileno_context();
139
        ctx.expect()
140
            .withf_st(move |arg1| *arg1 == pcap)
141
            .return_once(|_| 7);
142

            
143
        assert_eq!(capture.as_raw_fd(), 7);
144
    }
145
}