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