1#![deny(warnings)]
20#![macro_use]
21
22extern crate libc;
23extern crate pnet_packet;
24extern crate pnet_sys;
25
26use self::TransportChannelType::{Layer3, Layer4};
27use self::TransportProtocol::{Ipv4, Ipv6};
28use pnet_packet::icmp::IcmpPacket;
29use pnet_packet::icmpv6::Icmpv6Packet;
30use pnet_packet::ip::IpNextHeaderProtocol;
31use pnet_packet::ipv4::Ipv4Packet;
32use pnet_packet::tcp::TcpPacket;
33use pnet_packet::udp::UdpPacket;
34use pnet_packet::Packet;
35
36use std::io;
37use std::io::Error;
38#[cfg(unix)]
39use std::io::ErrorKind;
40use std::mem;
41use std::net::{self, IpAddr};
42use std::sync::Arc;
43#[cfg(unix)]
44use std::time::Duration;
45
46#[derive(Clone, Copy)]
48pub enum TransportProtocol {
49 Ipv4(IpNextHeaderProtocol),
51 Ipv6(IpNextHeaderProtocol),
53}
54
55#[repr(u8)]
56#[derive(Clone,Copy,Debug,PartialEq)]
57pub enum Ecn {
58 NotEct = 0x0,
59 Ect1 = 0x1,
60 Ect0 = 0x2,
61 CE = 0x3
62}
63
64impl From<u8> for Ecn {
65 fn from(value: u8) -> Ecn {
66 let ecn_bits = value & 0x3;
67 if ecn_bits == Ecn::Ect0 as u8 {
68 return Ecn::Ect0
69 } else if ecn_bits == Ecn::Ect1 as u8 {
70 return Ecn::Ect1
71 } else if ecn_bits == Ecn::CE as u8 {
72 return Ecn::CE
73 }
74 Ecn::NotEct
75 }
76}
77
78#[derive(Clone, Copy)]
80pub enum TransportChannelType {
81 Layer4(TransportProtocol),
83 Layer3(IpNextHeaderProtocol),
85}
86
87pub struct TransportSender {
89 pub socket: Arc<pnet_sys::FileDesc>,
90 channel_type: TransportChannelType,
91}
92
93pub struct TransportReceiver {
95 pub socket: Arc<pnet_sys::FileDesc>,
96 pub buffer: Vec<u8>,
97 pub channel_type: TransportChannelType,
98}
99
100#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
103pub struct Config {
104 time_to_live: u8,
105}
106
107pub fn transport_channel(
118 buffer_size: usize,
119 channel_type: TransportChannelType,
120) -> io::Result<(TransportSender, TransportReceiver)> {
121 let _ = {
123 let ip = net::Ipv4Addr::new(255, 255, 255, 255);
124 let sockaddr = net::SocketAddr::V4(net::SocketAddrV4::new(ip, 0));
125
126 net::UdpSocket::bind(sockaddr)
127 };
128
129 let socket = unsafe {
130 match channel_type {
131 Layer4(Ipv4(IpNextHeaderProtocol(proto))) | Layer3(IpNextHeaderProtocol(proto)) => {
132 pnet_sys::socket(pnet_sys::AF_INET, pnet_sys::SOCK_RAW, proto as libc::c_int)
133 }
134 Layer4(Ipv6(IpNextHeaderProtocol(proto))) => {
135 pnet_sys::socket(pnet_sys::AF_INET6, pnet_sys::SOCK_RAW, proto as libc::c_int)
136 }
137 }
138 };
139 if socket == pnet_sys::INVALID_SOCKET {
140 return Err(Error::last_os_error());
141 }
142
143 if matches!(channel_type, Layer3(_) | Layer4(Ipv4(_))) {
144 let hincl: libc::c_int = match channel_type {
145 Layer4(..) => 0,
146 _ => 1,
147 };
148 let res = unsafe {
149 pnet_sys::setsockopt(
150 socket,
151 pnet_sys::IPPROTO_IP,
152 pnet_sys::IP_HDRINCL,
153 (&hincl as *const libc::c_int) as pnet_sys::Buf,
154 mem::size_of::<libc::c_int>() as pnet_sys::SockLen,
155 )
156 };
157 if res == -1 {
158 let err = Error::last_os_error();
159 unsafe {
160 pnet_sys::close(socket);
161 }
162 return Err(err);
163 }
164 }
165
166 let sock = Arc::new(pnet_sys::FileDesc { fd: socket });
167 let sender = TransportSender {
168 socket: sock.clone(),
169 channel_type,
170 };
171 let receiver = TransportReceiver {
172 socket: sock,
173 buffer: vec![0; buffer_size],
174 channel_type,
175 };
176
177 Ok((sender, receiver))
178}
179
180pub fn transport_channel_with(
185 buffer_size: usize,
186 channel_type: TransportChannelType,
187 configuration: Config,
188) -> io::Result<(TransportSender, TransportReceiver)> {
189 let (mut sender, receiver) = transport_channel(buffer_size, channel_type)?;
190
191 sender.set_ttl(configuration.time_to_live)?;
192 Ok((sender, receiver))
193}
194
195fn set_sockopt_u8(
197 socket: Arc<pnet_sys::FileDesc>,
198 level: libc::c_int,
199 name: libc::c_int,
200 value: u8,
201) -> io::Result<()> {
202 let value = value as i32;
203 let res = unsafe {
204 pnet_sys::setsockopt(
205 socket.fd,
206 level,
207 name,
208 (&value as *const libc::c_int) as pnet_sys::Buf,
209 mem::size_of::<libc::c_int>() as pnet_sys::SockLen,
210 )
211 };
212
213 match res {
214 -1 => {
215 let err = Error::last_os_error();
216 unsafe {
217 pnet_sys::close(socket.fd);
218 }
219 Err(err)
220 }
221 _ => Ok(()),
222 }
223}
224
225impl TransportSender {
226 fn send<T: Packet>(&mut self, packet: T, dst: IpAddr) -> io::Result<usize> {
227 let mut caddr = unsafe { mem::zeroed() };
228 let sockaddr = match dst {
229 IpAddr::V4(ip_addr) => net::SocketAddr::V4(net::SocketAddrV4::new(ip_addr, 0)),
230 IpAddr::V6(ip_addr) => net::SocketAddr::V6(net::SocketAddrV6::new(ip_addr, 0, 0, 0)),
231 };
232 let slen = pnet_sys::addr_to_sockaddr(sockaddr, &mut caddr);
233 let caddr_ptr = (&caddr as *const pnet_sys::SockAddrStorage) as *const pnet_sys::SockAddr;
234
235 pnet_sys::send_to(self.socket.fd, packet.packet(), caddr_ptr, slen)
236 }
237
238 #[inline]
240 pub fn send_to<T: Packet>(&mut self, packet: T, destination: IpAddr) -> io::Result<usize> {
241 self.send_to_impl(packet, destination)
242 }
243
244 pub fn set_ttl(&mut self, time_to_live: u8) -> io::Result<()> {
246 let (level, name) = match self.channel_type {
247 Layer4(Ipv4(_)) | Layer3(_) => (pnet_sys::IPPROTO_IP, pnet_sys::IP_TTL),
248 Layer4(Ipv6(_)) => (pnet_sys::IPPROTO_IPV6, pnet_sys::IPV6_UNICAST_HOPS),
249 };
250 set_sockopt_u8(self.socket.clone(), level, name, time_to_live)
251 }
252
253 #[cfg(unix)]
255 pub fn set_ecn(&mut self, tos: Ecn) -> io::Result<()> {
256 let (level, name) = match self.channel_type {
257 Layer4(Ipv4(_)) | Layer3(_) => (pnet_sys::IPPROTO_IP, pnet_sys::IP_TOS),
258 Layer4(Ipv6(_)) => (pnet_sys::IPPROTO_IPV6, pnet_sys::IPV6_TCLASS),
259 };
260 set_sockopt_u8(self.socket.clone(), level, name, tos as u8)
261 }
262
263 #[cfg(all(
264 not(target_os = "freebsd"),
265 not(any(target_os = "macos", target_os = "ios", target_os = "tvos"))
266 ))]
267 fn send_to_impl<T: Packet>(&mut self, packet: T, dst: IpAddr) -> io::Result<usize> {
268 self.send(packet, dst)
269 }
270
271 #[cfg(any(target_os = "freebsd", target_os = "macos", target_os = "ios", target_os = "tvos"))]
272 fn send_to_impl<T: Packet>(&mut self, packet: T, dst: IpAddr) -> io::Result<usize> {
273 use pnet_packet::ipv4::MutableIpv4Packet;
274 use pnet_packet::MutablePacket;
275
276 if let Layer3(_) = self.channel_type {
281 let mut mut_slice: Vec<u8> = vec![0; packet.packet().len()];
282
283 let mut new_packet = MutableIpv4Packet::new(&mut mut_slice[..]).unwrap();
284 new_packet.clone_from(&packet);
285 let length = new_packet.get_total_length().to_be();
286 new_packet.set_total_length(length);
287 {
288 let d = new_packet.packet_mut();
290 let host_order = u16::from_be((d[6] as u16) << 8 | d[7] as u16);
291 d[6] = (host_order >> 8) as u8;
292 d[7] = host_order as u8;
293 }
294 return self.send(new_packet, dst);
295 }
296
297 self.send(packet, dst)
298 }
299}
300
301#[macro_export]
310macro_rules! transport_channel_iterator {
311 ($ty:ident, $iter:ident, $func:ident) => {
312 transport_channel_iterator!($ty, $iter, $func, stringify!($ty));
313 };
314 ($ty:ident, $iter:ident, $func:ident, $tyname:expr) => {
315 #[doc = "An iterator over packets of type `"]
316 #[doc = $tyname]
317 #[doc = "`."]
318 pub struct $iter<'a> {
319 tr: &'a mut TransportReceiver,
320 }
321
322 #[doc = "Return a packet iterator with packets of type `"]
323 #[doc = $tyname]
324 #[doc = "` for some transport receiver."]
325 pub fn $func(tr: &mut TransportReceiver) -> $iter {
326 $iter { tr: tr }
327 }
328
329 impl<'a> $iter<'a> {
330 #[doc = "Get the next (`"]
331 #[doc = $tyname ]
332 #[doc = "`, `IpAddr`) pair for the given channel."]
333 pub fn next(&mut self) -> io::Result<($ty, IpAddr)> {
334 let mut caddr: pnet_sys::SockAddrStorage = unsafe { mem::zeroed() };
335 let res =
336 pnet_sys::recv_from(self.tr.socket.fd, &mut self.tr.buffer[..], &mut caddr);
337
338 let offset = match self.tr.channel_type {
339 Layer4(Ipv4(_)) => {
340 let ip_header = Ipv4Packet::new(&self.tr.buffer[..]).unwrap();
341
342 ip_header.get_header_length() as usize * 4usize
343 }
344 Layer3(_) => {
345 fixup_packet(&mut self.tr.buffer[..]);
346
347 0
348 }
349 _ => 0,
350 };
351 return match res {
352 Ok(len) => {
353 let packet = $ty::new(&self.tr.buffer[offset..len]).unwrap();
354 let addr = pnet_sys::sockaddr_to_addr(
355 &caddr,
356 mem::size_of::<pnet_sys::SockAddrStorage>(),
357 );
358 let ip = match addr.unwrap() {
359 net::SocketAddr::V4(sa) => IpAddr::V4(*sa.ip()),
360 net::SocketAddr::V6(sa) => IpAddr::V6(*sa.ip()),
361 };
362 Ok((packet, ip))
363 }
364 Err(e) => Err(e),
365 };
366
367 #[cfg(any(
368 target_os = "freebsd",
369 target_os = "macos",
370 target_os = "ios",
371 target_os = "tvos"
372 ))]
373 fn fixup_packet(buffer: &mut [u8]) {
374 use pnet_packet::ipv4::MutableIpv4Packet;
375
376 let buflen = buffer.len();
377 let mut new_packet = MutableIpv4Packet::new(buffer).unwrap();
378
379 let length = u16::from_be(new_packet.get_total_length());
380 new_packet.set_total_length(length);
381
382 let length = new_packet.get_total_length() as usize
385 + (new_packet.get_header_length() as usize * 4usize);
386 if length == buflen {
387 new_packet.set_total_length(length as u16)
388 }
389
390 let offset = u16::from_be(new_packet.get_fragment_offset());
391 new_packet.set_fragment_offset(offset);
392 }
393
394 #[cfg(all(
395 not(target_os = "freebsd"),
396 not(any(target_os = "macos", target_os = "ios", target_os = "tvos"))
397 ))]
398 fn fixup_packet(_buffer: &mut [u8]) {}
399 }
400
401 #[cfg(unix)]
404 pub fn next_with_timeout(&mut self, t: Duration) -> io::Result<Option<($ty, IpAddr)>> {
405 let socket_fd = self.tr.socket.fd;
406
407 let old_timeout = match pnet_sys::get_socket_receive_timeout(socket_fd) {
408 Err(e) => {
409 eprintln!("Can not get socket timeout before receiving: {}", e);
410 return Err(e);
411 }
412 Ok(t) => t,
413 };
414
415 match pnet_sys::set_socket_receive_timeout(socket_fd, t) {
416 Err(e) => {
417 eprintln!("Can not set socket timeout for receiving: {}", e);
418 return Err(e);
419 }
420 Ok(_) => {}
421 }
422
423 let r = match self.next() {
424 Ok(r) => Ok(Some(r)),
425 Err(e) => match e.kind() {
426 ErrorKind::WouldBlock => Ok(None),
427 _ => Err(e),
428 },
429 };
430
431 match pnet_sys::set_socket_receive_timeout(socket_fd, old_timeout) {
432 Err(e) => {
433 eprintln!("Can not reset socket timeout after receiving: {}", e);
434 }
435 _ => {}
436 };
437
438 r
439 }
440 }
441 };
442}
443
444transport_channel_iterator!(Ipv4Packet, Ipv4TransportChannelIterator, ipv4_packet_iter);
445
446transport_channel_iterator!(UdpPacket, UdpTransportChannelIterator, udp_packet_iter);
447
448transport_channel_iterator!(IcmpPacket, IcmpTransportChannelIterator, icmp_packet_iter);
449
450transport_channel_iterator!(
451 Icmpv6Packet,
452 Icmpv6TransportChannelIterator,
453 icmpv6_packet_iter
454);
455
456transport_channel_iterator!(TcpPacket, TcpTransportChannelIterator, tcp_packet_iter);