tcp_ip/icmp/
mod.rs

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}