scion_stack/scionstack/
scmp_handler.rs1use std::{pin::Pin, sync::Arc};
17
18use scion_proto::{
19 packet::{ByEndpoint, ScionPacketScmp},
20 scmp::{ScmpEchoReply, ScmpMessage},
21 wire_encoding::WireEncodeVec as _,
22};
23
24use crate::snap_tunnel::SnapTunnel;
25
26pub trait ScmpHandler: Send + Sync {
30 fn handle_packet(
32 &self,
33 packet: ScionPacketScmp,
34 ) -> Pin<Box<dyn Future<Output = ()> + Send + '_>>;
35}
36
37pub struct DefaultScmpHandler {
39 tunnel_sender: Arc<SnapTunnel>,
40}
41
42impl Clone for DefaultScmpHandler {
43 fn clone(&self) -> Self {
44 Self {
45 tunnel_sender: self.tunnel_sender.clone(),
46 }
47 }
48}
49
50impl DefaultScmpHandler {
51 pub fn new(tunnel_sender: Arc<SnapTunnel>) -> Self {
53 Self { tunnel_sender }
54 }
55}
56
57impl ScmpHandler for DefaultScmpHandler {
58 fn handle_packet(&self, p: ScionPacketScmp) -> Pin<Box<dyn Future<Output = ()> + Send + '_>> {
59 Box::pin(async move {
60 let reply = match p.message {
61 ScmpMessage::EchoRequest(r) => {
62 tracing::debug!("Echo request received, sending echo reply");
63 ScmpMessage::EchoReply(ScmpEchoReply::new(
64 r.identifier,
65 r.sequence_number,
66 r.data,
67 ))
68 }
69 _ => return,
70 };
71
72 let reply_path = match p.headers.reversed_path(None) {
73 Ok(path) => path.data_plane_path,
74 Err(e) => {
75 tracing::debug!(error = %e, "Error reversing path of SCMP packet");
76 return;
77 }
78 };
79
80 let src = match p.headers.address.source() {
81 Some(src) => src,
82 None => {
83 tracing::debug!("Error decoding source address of SCMP packet");
84 return;
85 }
86 };
87 let dst = match p.headers.address.destination() {
88 Some(dst) => dst,
89 None => {
90 tracing::debug!("Error decoding destination address of SCMP packet");
91 return;
92 }
93 };
94
95 let reply_packet = match ScionPacketScmp::new(
96 ByEndpoint {
97 source: dst,
98 destination: src,
99 },
100 reply_path,
101 reply,
102 ) {
103 Ok(packet) => packet,
104 Err(e) => {
105 tracing::debug!(error = %e, "Error encoding SCMP reply");
106 return;
107 }
108 };
109 match self
110 .tunnel_sender
111 .send_datagram(reply_packet.encode_to_bytes_vec().concat().into())
112 {
113 Ok(_) => {}
114 Err(e) => {
115 tracing::warn!(error = %e, "Error sending SCMP reply");
116 }
117 }
118 })
119 }
120}