1use std::net::SocketAddrV4;
4use std::os::fd::AsRawFd;
5use std::time::Duration;
6
7use socket2::{Domain, Protocol, Socket, Type};
8use wireforge_core::ipv4::Ipv4Packet;
9use wireforge_core::types::IpProtocol;
10
11use crate::common;
12use crate::error::IoError;
13use crate::traits::{L3Reader, L3Writer};
14
15pub struct L3Receiver {
17 sock: Socket,
18 buf: Vec<u8>,
19}
20
21impl L3Receiver {
22 pub fn new(protocol: IpProtocol) -> Result<Self, IoError> {
24 let proto = Protocol::from(u8::from(protocol) as i32);
25 let sock = Socket::new(Domain::IPV4, Type::RAW, Some(proto))?;
26 Ok(Self {
27 sock,
28 buf: vec![0u8; 65536],
29 })
30 }
31
32 pub fn recv(&mut self) -> Result<Ipv4Packet<'_>, IoError> {
34 let n = unsafe {
35 libc::recv(
36 self.sock.as_raw_fd(),
37 self.buf.as_mut_ptr() as *mut libc::c_void,
38 self.buf.len(),
39 0,
40 )
41 };
42 if n < 0 {
43 return Err(IoError::Socket(std::io::Error::last_os_error()));
44 }
45 let n = n as usize;
46 Ipv4Packet::new(&self.buf[..n]).ok_or(IoError::Parse("invalid IPv4 packet"))
47 }
48
49 pub fn set_header_included(&mut self, on: bool) -> Result<(), IoError> {
51 let fd = self.sock.as_raw_fd();
52 let val: libc::c_int = if on { 1 } else { 0 };
53 unsafe {
54 if libc::setsockopt(
55 fd,
56 libc::IPPROTO_IP,
57 libc::IP_HDRINCL,
58 &val as *const _ as *const libc::c_void,
59 std::mem::size_of::<libc::c_int>() as libc::socklen_t,
60 ) < 0
61 {
62 return Err(IoError::Socket(std::io::Error::last_os_error()));
63 }
64 }
65 Ok(())
66 }
67
68 pub fn set_timeout(&mut self, dur: Option<Duration>) -> Result<(), IoError> {
70 common::set_socket_timeout(self.sock.as_raw_fd(), dur)
71 }
72}
73
74pub struct L3Sender {
76 sock: Socket,
77}
78
79impl L3Sender {
80 pub fn new() -> Result<Self, IoError> {
82 let sock = Socket::new(
83 Domain::IPV4,
84 Type::RAW,
85 Some(Protocol::from(libc::IPPROTO_RAW)),
86 )?;
87 Ok(Self { sock })
88 }
89
90 pub fn send_to(&self, packet: &[u8], dst: SocketAddrV4) -> Result<usize, IoError> {
92 let addr = socket2::SockAddr::from(std::net::SocketAddr::V4(dst));
93 let n = self.sock.send_to(packet, &addr)?;
94 Ok(n)
95 }
96}
97
98impl L3Reader for L3Receiver {
100 fn recv(&mut self) -> Result<Ipv4Packet<'_>, IoError> {
101 self.recv()
102 }
103
104 fn set_timeout(&mut self, dur: Option<Duration>) -> Result<(), IoError> {
105 self.set_timeout(dur)
106 }
107
108 fn set_header_included(&mut self, on: bool) -> Result<(), IoError> {
109 self.set_header_included(on)
110 }
111}
112
113impl L3Writer for L3Sender {
114 fn send_to(&self, packet: &[u8], dst: SocketAddrV4) -> Result<usize, IoError> {
115 self.send_to(packet, dst)
116 }
117}