nex_socket/icmp/
sync_impl.rs1use crate::SocketFamily;
2use crate::icmp::{IcmpConfig, IcmpKind, IcmpSocketType};
3use socket2::{Domain, Protocol, Socket, Type as SockType};
4use std::io;
5use std::net::{SocketAddr, UdpSocket};
6
7#[derive(Debug)]
9pub struct IcmpSocket {
10 inner: UdpSocket,
11 socket_type: IcmpSocketType,
12 socket_family: SocketFamily,
13}
14
15impl IcmpSocket {
16 pub fn new(config: &IcmpConfig) -> io::Result<Self> {
18 config.validate()?;
19
20 let (domain, proto) = match config.socket_family {
21 SocketFamily::IPV4 => (Domain::IPV4, Some(Protocol::ICMPV4)),
22 SocketFamily::IPV6 => (Domain::IPV6, Some(Protocol::ICMPV6)),
23 };
24
25 let socket = match Socket::new(domain, config.sock_type_hint.to_sock_type(), proto) {
26 Ok(s) => s,
27 Err(_) => {
28 let alt_type = if config.sock_type_hint.is_dgram() {
29 SockType::RAW
30 } else {
31 SockType::DGRAM
32 };
33 Socket::new(domain, alt_type, proto)?
34 }
35 };
36
37 socket.set_nonblocking(false)?;
38
39 if let Some(ttl) = config.ttl {
41 socket.set_ttl(ttl)?;
42 }
43 if let Some(hoplimit) = config.hoplimit {
44 socket.set_unicast_hops_v6(hoplimit)?;
45 }
46 if let Some(timeout) = config.read_timeout {
47 socket.set_read_timeout(Some(timeout))?;
48 }
49 if let Some(timeout) = config.write_timeout {
50 socket.set_write_timeout(Some(timeout))?;
51 }
52 #[cfg(target_os = "freebsd")]
54 if let Some(fib) = config.fib {
55 socket.set_fib(fib)?;
56 }
57 #[cfg(any(target_os = "linux", target_os = "android", target_os = "fuchsia"))]
59 if let Some(interface) = &config.interface {
60 socket.bind_device(Some(interface.as_bytes()))?;
61 }
62
63 if let Some(addr) = &config.bind {
65 socket.bind(&(*addr).into())?;
66 }
67
68 let sock_type = socket.r#type()?;
69
70 let std_socket: UdpSocket = socket.into();
72
73 Ok(Self {
74 inner: std_socket,
75 socket_type: IcmpSocketType::try_from_sock_type(sock_type)?,
76 socket_family: config.socket_family,
77 })
78 }
79
80 pub fn send_to(&self, buf: &[u8], target: SocketAddr) -> io::Result<usize> {
82 self.inner.send_to(buf, target)
83 }
84
85 pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
87 self.inner.recv_from(buf)
88 }
89
90 pub fn local_addr(&self) -> io::Result<SocketAddr> {
92 self.inner.local_addr()
93 }
94
95 pub fn socket_type(&self) -> IcmpSocketType {
97 self.socket_type
98 }
99
100 pub fn socket_family(&self) -> SocketFamily {
102 self.socket_family
103 }
104
105 pub fn icmp_kind(&self) -> IcmpKind {
107 match self.socket_family {
108 SocketFamily::IPV4 => IcmpKind::V4,
109 SocketFamily::IPV6 => IcmpKind::V6,
110 }
111 }
112
113 #[cfg(unix)]
115 pub fn as_raw_fd(&self) -> std::os::unix::io::RawFd {
116 use std::os::fd::AsRawFd;
117 self.inner.as_raw_fd()
118 }
119
120 #[cfg(windows)]
122 pub fn as_raw_socket(&self) -> std::os::windows::io::RawSocket {
123 use std::os::windows::io::AsRawSocket;
124 self.inner.as_raw_socket()
125 }
126}