manycastr/worker/inbound/
ping.rs1use crate::custom_module::manycastr::reply::ReplyData;
2use crate::custom_module::manycastr::{
3 Address, DiscoveryReply, MeasurementReply, Reply, TraceReply,
4};
5use crate::net::ICMPPacket;
6use crate::worker::inbound::ReplyMeta;
7
8pub fn parse_icmp(
23 packet_bytes: &[u8],
24 m_id: u32,
25 is_traceroute: bool,
26 meta: ReplyMeta,
27) -> Option<Reply> {
28 if meta.src.is_v6() {
29 if packet_bytes.len() < 56 || packet_bytes[0] != 129 {
31 return None;
32 }
33 let icmp_packet = ICMPPacket::from(packet_bytes);
34 parse_icmp_inner(&icmp_packet, m_id, is_traceroute, meta)
35 } else {
36 if packet_bytes.len() < 52 || packet_bytes[20] != 0 {
38 return None;
39 }
40 let icmp_packet = ICMPPacket::from(&packet_bytes[20..]);
41 parse_icmp_inner(&icmp_packet, m_id, is_traceroute, meta)
42 }
43}
44
45fn parse_icmp_inner(
56 icmp_packet: &ICMPPacket,
57 m_id: u32,
58 is_traceroute: bool,
59 meta: ReplyMeta,
60) -> Option<Reply> {
61 let ReplyMeta { src, ttl, rx_time } = meta;
62 let pkt_probe_id = u32::from_be_bytes(icmp_packet.payload[0..4].try_into().ok()?);
64 if crate::m_id_of(pkt_probe_id) != m_id {
65 return None;
66 }
67 let session_id = crate::session_id_of(pkt_probe_id);
68
69 let is_ipv6 = src.is_v6();
70
71 let tx_time = u64::from_be_bytes(icmp_packet.payload[4..12].try_into().unwrap());
72 let mut tx_id = u32::from_be_bytes(icmp_packet.payload[12..16].try_into().unwrap());
73 let probe_dst = if is_ipv6 {
74 Address::from(u128::from_be_bytes(
75 icmp_packet.payload[32..48].try_into().unwrap(),
76 ))
77 } else {
78 Address::from(u32::from_be_bytes(
79 icmp_packet.payload[20..24].try_into().unwrap(),
80 ))
81 };
82
83 if probe_dst != src {
84 return None; }
86
87 let is_discovery = if tx_id > u16::MAX as u32 {
88 tx_id -= u16::MAX as u32;
89 true
90 } else {
91 false
92 };
93
94 if is_discovery {
95 Some(Reply {
97 reply_data: Some(ReplyData::Discovery(DiscoveryReply {
98 src: Some(src),
99 session_id,
100 })),
101 })
102 } else if is_traceroute {
103 let trace_ttl: u8 = if is_ipv6 {
105 icmp_packet.payload[48]
106 } else {
107 icmp_packet.payload[24]
108 };
109
110 Some(Reply {
111 reply_data: Some(ReplyData::Trace(TraceReply {
112 hop_addr: Some(src),
113 ttl,
114 rtt: super::rtt_ms(rx_time, tx_time, super::TxEncoding::Micros),
115 tx_id,
116 trace_dst: Some(src),
117 hop_count: trace_ttl as u32,
118 })),
119 })
120 } else {
121 Some(Reply {
123 reply_data: Some(ReplyData::Measurement(MeasurementReply {
124 src: Some(src),
125 ttl,
126 rtt: super::rtt_ms(rx_time, tx_time, super::TxEncoding::Micros),
127 tx_id,
128 chaos: None,
129 session_id,
130 })),
131 })
132 }
133}