ip_spoofing/
socket.rs

1use super::{Result, ReusablePacketWriter};
2
3use nix::sys::socket::{
4    AddressFamily, MsgFlags, SockFlag, SockProtocol, SockType, SockaddrIn, sendto, socket,
5};
6use std::os::fd::{AsRawFd, OwnedFd, RawFd};
7
8/// Wrapper around low-level `socket(AF_INET, SOCK_RAW, IPPROTO_RAW)`
9#[derive(Debug)]
10pub struct RawSocket {
11    fd: OwnedFd,
12}
13
14impl RawSocket {
15    /// Trying to create raw socket
16    #[inline]
17    pub fn new() -> Result<Self> {
18        let fd = socket(
19            AddressFamily::Inet,
20            SockType::Raw,
21            SockFlag::empty(),
22            Some(SockProtocol::Raw),
23        )?;
24        Ok(Self { fd })
25    }
26
27    /// Wraps `sendto` call with `nix` crate and other extra security checks
28    #[inline]
29    pub fn sendto(&self, buf: &[u8], addr: [u8; 4]) -> Result<usize> {
30        let [a, b, c, d] = addr;
31        let addr = SockaddrIn::new(a, b, c, d, 0);
32        let len = sendto(self.as_raw_fd(), buf, &addr, MsgFlags::empty())?;
33        Ok(len)
34    }
35
36    /// Sends fake UDP packet with given parameters
37    #[inline]
38    pub fn send_fake_udp_packet(
39        &self,
40        writer: &mut ReusablePacketWriter,
41        source: [u8; 4],
42        source_port: u16,
43        destination: [u8; 4],
44        destination_port: u16,
45        payload: &[u8],
46        time_to_live: u8,
47    ) -> Result<usize> {
48        writer.write_udp_packet(
49            source,
50            source_port,
51            destination,
52            destination_port,
53            payload,
54            time_to_live,
55        )?;
56        self.sendto(writer.as_slice(), destination)
57    }
58
59    /// Sends fake TCP-SYN packet with given parameters
60    #[inline]
61    pub fn send_fake_tcp_syn_packet(
62        &self,
63        writer: &mut ReusablePacketWriter,
64        source: [u8; 4],
65        source_port: u16,
66        destination: [u8; 4],
67        destination_port: u16,
68        payload: &[u8],
69        time_to_live: u8,
70        sequence_number: u32,
71        window_size: u16,
72    ) -> Result<usize> {
73        writer.write_tcp_syn_packet(
74            source,
75            source_port,
76            destination,
77            destination_port,
78            payload,
79            time_to_live,
80            sequence_number,
81            window_size,
82        )?;
83        self.sendto(writer.as_slice(), destination)
84    }
85}
86
87/// Implementation that converts `RawSocket` into `fd` (file descriptor)
88impl AsRawFd for RawSocket {
89    fn as_raw_fd(&self) -> RawFd {
90        self.fd.as_raw_fd()
91    }
92}