nex_socket/icmp/
config.rs1use socket2::Type as SockType;
2use std::{net::SocketAddr, time::Duration};
3
4use crate::SocketFamily;
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
8pub enum IcmpKind {
9 V4,
10 V6,
11}
12
13#[derive(Debug, Clone, Copy, PartialEq, Eq)]
15pub enum IcmpSocketType {
16 Dgram,
17 Raw,
18}
19
20impl IcmpSocketType {
21 pub fn is_dgram(&self) -> bool {
23 matches!(self, IcmpSocketType::Dgram)
24 }
25
26 pub fn is_raw(&self) -> bool {
28 matches!(self, IcmpSocketType::Raw)
29 }
30
31 pub(crate) fn from_sock_type(sock_type: SockType) -> Self {
33 match sock_type {
34 SockType::DGRAM => IcmpSocketType::Dgram,
35 SockType::RAW => IcmpSocketType::Raw,
36 _ => panic!("Invalid ICMP socket type"),
37 }
38 }
39
40 pub(crate) fn to_sock_type(&self) -> SockType {
42 match self {
43 IcmpSocketType::Dgram => SockType::DGRAM,
44 IcmpSocketType::Raw => SockType::RAW,
45 }
46 }
47}
48
49#[derive(Debug, Clone)]
51pub struct IcmpConfig {
52 pub socket_family: SocketFamily,
54 pub bind: Option<SocketAddr>,
56 pub ttl: Option<u32>,
58 pub hoplimit: Option<u32>,
60 pub read_timeout: Option<Duration>,
62 pub write_timeout: Option<Duration>,
64 pub interface: Option<String>,
66 pub sock_type_hint: IcmpSocketType,
68 pub fib: Option<u32>,
70}
71
72impl IcmpConfig {
73 pub fn new(kind: IcmpKind) -> Self {
75 Self {
76 socket_family: match kind {
77 IcmpKind::V4 => SocketFamily::IPV4,
78 IcmpKind::V6 => SocketFamily::IPV6,
79 },
80 bind: None,
81 ttl: None,
82 hoplimit: None,
83 read_timeout: None,
84 write_timeout: None,
85 interface: None,
86 sock_type_hint: IcmpSocketType::Dgram,
87 fib: None,
88 }
89 }
90
91 pub fn with_bind(mut self, addr: SocketAddr) -> Self {
93 self.bind = Some(addr);
94 self
95 }
96
97 pub fn with_ttl(mut self, ttl: u32) -> Self {
99 self.ttl = Some(ttl);
100 self
101 }
102
103 pub fn with_hoplimit(mut self, hops: u32) -> Self {
105 self.hoplimit = Some(hops);
106 self
107 }
108
109 pub fn with_read_timeout(mut self, timeout: Duration) -> Self {
111 self.read_timeout = Some(timeout);
112 self
113 }
114
115 pub fn with_write_timeout(mut self, timeout: Duration) -> Self {
117 self.write_timeout = Some(timeout);
118 self
119 }
120
121 pub fn with_interface(mut self, iface: impl Into<String>) -> Self {
123 self.interface = Some(iface.into());
124 self
125 }
126
127 pub fn with_sock_type(mut self, ty: IcmpSocketType) -> Self {
129 self.sock_type_hint = ty;
130 self
131 }
132
133 pub fn with_fib(mut self, fib: u32) -> Self {
135 self.fib = Some(fib);
136 self
137 }
138}
139
140#[cfg(test)]
141mod tests {
142 use super::*;
143 #[test]
144 fn icmp_config_builders() {
145 let addr: SocketAddr = "127.0.0.1:0".parse().unwrap();
146 let cfg = IcmpConfig::new(IcmpKind::V4)
147 .with_bind(addr)
148 .with_ttl(4)
149 .with_interface("eth0")
150 .with_sock_type(IcmpSocketType::Raw);
151 assert_eq!(cfg.socket_family, SocketFamily::IPV4);
152 assert_eq!(cfg.bind, Some(addr));
153 assert_eq!(cfg.ttl, Some(4));
154 assert_eq!(cfg.interface.as_deref(), Some("eth0"));
155 assert_eq!(cfg.sock_type_hint, IcmpSocketType::Raw);
156 }
157}