1use std::io;
2use std::net::IpAddr;
3use std::ops::Deref;
4
5use pnet_packet::ip::IpNextHeaderProtocols;
6
7use crate::ip::IpSocket;
8use crate::ip_stack::{IpStack, UNSPECIFIED_ADDR_V4, UNSPECIFIED_ADDR_V6};
9
10pub struct IcmpSocket {
11 raw_ip_socket: IpSocket,
12}
13#[cfg(feature = "global-ip-stack")]
14impl IcmpSocket {
15 pub async fn bind_all() -> io::Result<Self> {
16 Self::bind(UNSPECIFIED_ADDR_V4.ip()).await
17 }
18 pub async fn bind(local_ip: IpAddr) -> io::Result<Self> {
19 if local_ip.is_ipv6() {
20 return Err(io::Error::new(io::ErrorKind::Unsupported, "need to use IcmpV6Socket"));
21 }
22 let ip_stack = IpStack::get()?;
23 let raw_ip_socket = IpSocket::bind0(
24 ip_stack.config.icmp_channel_size,
25 Some(IpNextHeaderProtocols::Icmp),
26 ip_stack,
27 Some(local_ip),
28 )
29 .await?;
30 Ok(Self { raw_ip_socket })
31 }
32}
33#[cfg(not(feature = "global-ip-stack"))]
34impl IcmpSocket {
35 pub async fn bind_all(ip_stack: IpStack) -> io::Result<Self> {
36 Self::bind(ip_stack, UNSPECIFIED_ADDR_V4.ip()).await
37 }
38 pub async fn bind(ip_stack: IpStack, local_ip: IpAddr) -> io::Result<Self> {
39 if local_ip.is_ipv6() {
40 return Err(io::Error::new(io::ErrorKind::Unsupported, "need to use IcmpV6Socket"));
41 }
42 let raw_ip_socket = IpSocket::bind0(
43 ip_stack.config.icmp_channel_size,
44 Some(IpNextHeaderProtocols::Icmp),
45 ip_stack,
46 Some(local_ip),
47 )
48 .await?;
49 Ok(Self { raw_ip_socket })
50 }
51}
52
53impl Deref for IcmpSocket {
54 type Target = IpSocket;
55
56 fn deref(&self) -> &Self::Target {
57 &self.raw_ip_socket
58 }
59}
60
61pub struct IcmpV6Socket {
62 raw_ip_socket: IpSocket,
63}
64#[cfg(feature = "global-ip-stack")]
65impl IcmpV6Socket {
66 pub async fn bind_all() -> io::Result<Self> {
67 Self::bind(UNSPECIFIED_ADDR_V6.ip()).await
68 }
69 pub async fn bind(local_ip: IpAddr) -> io::Result<Self> {
70 if local_ip.is_ipv4() {
71 return Err(io::Error::new(io::ErrorKind::Unsupported, "need to use IcmpSocket"));
72 }
73 let ip_stack = IpStack::get()?;
74 let raw_ip_socket = IpSocket::bind0(
75 ip_stack.config.icmp_channel_size,
76 Some(IpNextHeaderProtocols::Icmpv6),
77 ip_stack,
78 Some(local_ip),
79 )
80 .await?;
81 Ok(Self { raw_ip_socket })
82 }
83}
84#[cfg(not(feature = "global-ip-stack"))]
85impl IcmpV6Socket {
86 pub async fn bind_all(ip_stack: IpStack) -> io::Result<Self> {
87 Self::bind(ip_stack, UNSPECIFIED_ADDR_V6.ip()).await
88 }
89 pub async fn bind(ip_stack: IpStack, local_ip: IpAddr) -> io::Result<Self> {
90 if local_ip.is_ipv4() {
91 return Err(io::Error::new(io::ErrorKind::Unsupported, "need to use IcmpSocket"));
92 }
93 let raw_ip_socket = IpSocket::bind0(
94 ip_stack.config.icmp_channel_size,
95 Some(IpNextHeaderProtocols::Icmpv6),
96 ip_stack,
97 Some(local_ip),
98 )
99 .await?;
100 Ok(Self { raw_ip_socket })
101 }
102}
103
104impl Deref for IcmpV6Socket {
105 type Target = IpSocket;
106
107 fn deref(&self) -> &Self::Target {
108 &self.raw_ip_socket
109 }
110}