1use nix::sys::socket;
21use std::io;
22use std::os::unix::io::AsRawFd;
23use std::os::unix::io::RawFd;
24use tokio::io::unix::AsyncFd;
25
26use crate::{addr::NetAddr, udp};
27use nix::libc;
28
29pub type Error = std::io::Error;
30pub type Result<T> = std::result::Result<T, Error>;
31pub type MsgFlags = socket::MsgFlags;
32pub use std::io::{IoSlice, IoSliceMut};
33
34pub type ControlMessage = udp::ControlMessage;
36
37#[derive(Copy, Clone)]
38pub struct IpProto(u8);
39impl IpProto {
40 pub const ICMP: IpProto = IpProto(1);
41 pub const TCP: IpProto = IpProto(6);
42 pub const UDP: IpProto = IpProto(17);
43 pub const ICMP6: IpProto = IpProto(58);
44}
45
46impl From<IpProto> for u8 {
47 fn from(ipp: IpProto) -> Self {
48 ipp.0
49 }
50}
51
52impl From<IpProto> for u16 {
53 fn from(ipp: IpProto) -> Self {
54 ipp.0 as u16
55 }
56}
57
58#[derive(Copy, Clone)]
59pub struct EthProto(u16);
60impl EthProto {
61 pub const IP4: EthProto = EthProto(0x0800);
62 pub const ALL: EthProto = EthProto(0x0003);
63 pub const LLDP: EthProto = EthProto(0x88cc);
64}
65
66#[derive(Debug)]
67pub struct RawSocket {
68 fd: AsyncFd<crate::socket::SocketFd>,
69}
70
71impl AsRawFd for RawSocket {
72 fn as_raw_fd(&self) -> RawFd {
73 self.fd.as_raw_fd()
74 }
75}
76
77impl RawSocket {
78 pub fn new(protocol: EthProto) -> Result<Self> {
79 Ok(Self {
80 fd: AsyncFd::new(crate::socket::new_socket(
81 libc::AF_PACKET,
82 libc::SOCK_RAW,
83 protocol.0.to_be() as libc::c_int,
84 )?)?,
85 })
86 }
87
88 #[allow(dead_code)]
89 pub fn send(&self, buf: &[u8], flags: MsgFlags) -> Result<usize> {
90 socket::send(self.as_raw_fd(), buf, flags).map_err(|e| e.into())
91 }
92
93 pub async fn recv_msg(
94 &self,
95 bufsize: usize,
96 flags: MsgFlags,
97 ) -> io::Result<crate::socket::RecvMsg> {
98 crate::socket::recv_msg(&self.fd, bufsize, flags).await
99 }
100
101 pub async fn send_msg(
102 &self,
103 buffer: &[u8],
104 cmsg: &ControlMessage,
105 flags: MsgFlags,
106 addr: Option<&NetAddr>,
107 ) -> io::Result<()> {
108 crate::socket::send_msg(&self.fd, buffer, cmsg, flags, addr).await
109 }
110
111 pub fn set_socket_option<O: nix::sys::socket::SetSockOpt>(
112 &self,
113 opt: O,
114 val: &O::Val,
115 ) -> Result<()> {
116 nix::sys::socket::setsockopt(self.as_raw_fd(), opt, val).map_err(|e| e.into())
117 }
118}
119
120#[derive(Debug)]
121pub struct CookedRawSocket {
122 fd: AsyncFd<crate::socket::SocketFd>,
123}
124
125impl AsRawFd for CookedRawSocket {
126 fn as_raw_fd(&self) -> RawFd {
127 self.fd.as_raw_fd()
128 }
129}
130
131impl CookedRawSocket {
132 pub fn new(protocol: EthProto) -> Result<Self> {
133 Ok(Self {
134 fd: AsyncFd::new(crate::socket::new_socket(
135 libc::AF_PACKET,
136 libc::SOCK_RAW,
137 protocol.0 as libc::c_int,
138 )?)?,
139 })
140 }
141
142 #[allow(dead_code)]
143 pub fn send(&self, buf: &[u8], flags: MsgFlags) -> Result<usize> {
144 socket::send(self.as_raw_fd(), buf, flags).map_err(|e| e.into())
145 }
146
147 pub async fn recv_msg(
148 &self,
149 bufsize: usize,
150 flags: MsgFlags,
151 ) -> io::Result<crate::socket::RecvMsg> {
152 crate::socket::recv_msg(&self.fd, bufsize, flags).await
153 }
154
155 pub async fn send_msg(
156 &self,
157 buffer: &[u8],
158 cmsg: &ControlMessage,
159 flags: MsgFlags,
160 addr: Option<&NetAddr>,
161 ) -> io::Result<()> {
162 crate::socket::send_msg(&self.fd, buffer, cmsg, flags, addr).await
163 }
164
165 pub fn set_socket_option<O: nix::sys::socket::SetSockOpt>(
166 &self,
167 opt: O,
168 val: &O::Val,
169 ) -> Result<()> {
170 nix::sys::socket::setsockopt(self.as_raw_fd(), opt, val).map_err(|e| e.into())
171 }
172}
173
174#[derive(Debug)]
175pub struct Raw6Socket {
176 fd: AsyncFd<crate::socket::SocketFd>,
177}
178
179impl AsRawFd for Raw6Socket {
180 fn as_raw_fd(&self) -> RawFd {
181 self.fd.as_raw_fd()
182 }
183}
184
185impl Raw6Socket {
186 pub fn new(protocol: IpProto) -> Result<Self> {
187 Ok(Self {
188 fd: AsyncFd::new(crate::socket::new_socket(
189 libc::AF_INET6,
190 libc::SOCK_RAW,
191 protocol.0 as libc::c_int,
192 )?)?,
193 })
194 }
195
196 #[allow(dead_code)]
197 pub fn send(&self, buf: &[u8], flags: MsgFlags) -> Result<usize> {
198 socket::send(self.as_raw_fd(), buf, flags).map_err(|e| e.into())
199 }
200
201 pub async fn recv_msg(
202 &self,
203 bufsize: usize,
204 flags: MsgFlags,
205 ) -> io::Result<crate::socket::RecvMsg> {
206 crate::socket::recv_msg(&self.fd, bufsize, flags).await
207 }
208
209 pub async fn send_msg(
210 &self,
211 buffer: &[u8],
212 cmsg: &ControlMessage,
213 flags: MsgFlags,
214 addr: Option<&NetAddr>,
215 ) -> io::Result<()> {
216 crate::socket::send_msg(&self.fd, buffer, cmsg, flags, addr).await
217 }
218
219 pub fn set_socket_option<O: nix::sys::socket::SetSockOpt>(
220 &self,
221 opt: O,
222 val: &O::Val,
223 ) -> Result<()> {
224 nix::sys::socket::setsockopt(self.as_raw_fd(), opt, val).map_err(|e| e.into())
225 }
226}
227
228#[derive(Debug)]
229pub struct Raw4Socket {
230 fd: AsyncFd<crate::socket::SocketFd>,
231}
232
233impl AsRawFd for Raw4Socket {
234 fn as_raw_fd(&self) -> RawFd {
235 self.fd.as_raw_fd()
236 }
237}
238
239impl Raw4Socket {
240 pub fn new(protocol: IpProto) -> Result<Self> {
241 Ok(Self {
242 fd: AsyncFd::new(crate::socket::new_socket(
243 libc::AF_INET,
244 libc::SOCK_RAW,
245 protocol.0 as libc::c_int,
246 )?)?,
247 })
248 }
249
250 #[allow(dead_code)]
251 pub fn send(&self, buf: &[u8], flags: MsgFlags) -> Result<usize> {
252 socket::send(self.as_raw_fd(), buf, flags).map_err(|e| e.into())
253 }
254
255 pub async fn recv_msg(
256 &self,
257 bufsize: usize,
258 flags: MsgFlags,
259 ) -> io::Result<crate::socket::RecvMsg> {
260 crate::socket::recv_msg(&self.fd, bufsize, flags).await
261 }
262
263 pub async fn send_msg(
264 &self,
265 buffer: &[u8],
266 cmsg: &ControlMessage,
267 flags: MsgFlags,
268 addr: Option<&NetAddr>,
269 ) -> io::Result<()> {
270 crate::socket::send_msg(&self.fd, buffer, cmsg, flags, addr).await
271 }
272
273 pub fn set_socket_option<O: nix::sys::socket::SetSockOpt>(
274 fd: RawFd,
275 opt: O,
276 val: &O::Val,
277 ) -> Result<()> {
278 nix::sys::socket::setsockopt(fd, opt, val).map_err(|e| e.into())
279 }
280}