diff options
| author | luwenpeng <[email protected]> | 2023-09-06 18:30:14 +0800 |
|---|---|---|
| committer | luwenpeng <[email protected]> | 2023-09-07 14:27:24 +0800 |
| commit | e16b028be675ee35f4d08521accbc52ee6e6b182 (patch) | |
| tree | 03ea80f57d4f2c2b98dd125fa9baa2cfd770dc88 /src/packet | |
| parent | 142e30257e2d852b381f1ca47257095b888627cd (diff) | |
[refactor] Decouple packets from sessions/events
Diffstat (limited to 'src/packet')
| -rw-r--r-- | src/packet/error.rs | 7 | ||||
| -rw-r--r-- | src/packet/packet.rs | 339 |
2 files changed, 77 insertions, 269 deletions
diff --git a/src/packet/error.rs b/src/packet/error.rs index fe0620e..174930c 100644 --- a/src/packet/error.rs +++ b/src/packet/error.rs @@ -18,10 +18,6 @@ pub enum PacketError { // L4 IncompleteUdpHeader, IncompleteTcpHeader, - - // L7 - IncompleteAppHeader, - UnsupportAppProtocol, } impl core::fmt::Display for PacketError { @@ -40,9 +36,6 @@ impl core::fmt::Display for PacketError { // L4 PacketError::IncompleteUdpHeader => write!(f, "Incomplete UDP Header"), PacketError::IncompleteTcpHeader => write!(f, "Incomplete TCP Header"), - // L7 - PacketError::IncompleteAppHeader => write!(f, "Incomplete App Header"), - PacketError::UnsupportAppProtocol => write!(f, "Unsupport App Protocol"), } } } diff --git a/src/packet/packet.rs b/src/packet/packet.rs index f80f4d6..2336946 100644 --- a/src/packet/packet.rs +++ b/src/packet/packet.rs @@ -1,38 +1,37 @@ -use crate::event::event::BuildInEvent; use crate::packet::error::PacketError; use crate::protocol::codec::Decode; -use crate::protocol::dns::DNS_MESSAGE; use crate::protocol::ethernet::EtherType; use crate::protocol::ethernet::EthernetFrame; -use crate::protocol::http::HTTP_MESSAGE; use crate::protocol::ip::IPProtocol; use crate::protocol::ipv4::IPv4Header; use crate::protocol::ipv6::IPv6Header; use crate::protocol::tcp::TcpHeader; use crate::protocol::udp::UdpHeader; -use crate::session::session::packet2session; -use crate::session::session::Session; -use crate::session::session::SessionProto; -use crate::session::session::SessionState; -use crate::thread::thread::ThreadContex; -use std::cell::RefCell; -use std::rc::Rc; #[allow(non_camel_case_types)] #[derive(Clone, Debug, PartialEq)] pub enum Encapsulation<'a> { L2_ETH(EthernetFrame, &'a [u8]), - L3_IP4(IPv4Header, &'a [u8]), - L3_IP6(IPv6Header, &'a [u8]), + L3_IPV4(IPv4Header, &'a [u8]), + L3_IPV6(IPv6Header, &'a [u8]), L4_TCP(TcpHeader, &'a [u8]), L4_UDP(UdpHeader, &'a [u8]), - L7_DNS(DNS_MESSAGE, &'a [u8]), - L7_HTTP(HTTP_MESSAGE, &'a [u8]), + UNSUPPORTED(&'a [u8]), +} - Unsupported(&'a [u8]), +#[allow(non_camel_case_types)] +#[derive(Clone, Debug, PartialEq)] +pub enum PacketEvent { + L2_EVENT, + L3_EVENT, + IPV4_EVENT, + IPV6_EVENT, + L4_EVENT, + TCP_EVENT, + UDP_EVENT, } #[derive(Debug)] @@ -40,6 +39,7 @@ pub struct Packet<'a> { pub orig_data: &'a [u8], pub orig_len: u32, pub encapsulation: Vec<Encapsulation<'a>>, + pub event: Vec<PacketEvent>, } impl Packet<'_> { @@ -48,24 +48,25 @@ impl Packet<'_> { orig_data: data, orig_len: len, encapsulation: vec![], + event: vec![], } } - pub fn handle(&mut self, ctx: Rc<RefCell<ThreadContex>>) -> Result<(), PacketError> { + pub fn handle(&mut self) -> Result<(), PacketError> { if self.orig_data.len() != self.orig_len as usize { return Err(PacketError::InvalidPacketLength); } - return handle_l2(self, self.orig_data, ctx); + return handle_l2(self, self.orig_data); } pub fn get_outer_l3_layer(&self) -> Option<Encapsulation> { let num = self.encapsulation.len(); for i in 0..num { match self.encapsulation[i] { - Encapsulation::L3_IP4(_, _) => { + Encapsulation::L3_IPV4(_, _) => { return Some(self.encapsulation[i].clone()); } - Encapsulation::L3_IP6(_, _) => { + Encapsulation::L3_IPV6(_, _) => { return Some(self.encapsulation[i].clone()); } _ => continue, @@ -79,10 +80,10 @@ impl Packet<'_> { let num = self.encapsulation.len(); for i in (0..num).rev() { match self.encapsulation[i] { - Encapsulation::L3_IP4(_, _) => { + Encapsulation::L3_IPV4(_, _) => { return Some(self.encapsulation[i].clone()); } - Encapsulation::L3_IP6(_, _) => { + Encapsulation::L3_IPV6(_, _) => { return Some(self.encapsulation[i].clone()); } _ => continue, @@ -130,13 +131,13 @@ impl Packet<'_> { let num = self.encapsulation.len(); for i in 0..num { match self.encapsulation[i] { - Encapsulation::L3_IP4(ref header, _) => { + Encapsulation::L3_IPV4(ref header, _) => { return Some(( header.source_address.to_string(), header.dest_address.to_string(), )); } - Encapsulation::L3_IP6(ref header, _) => { + Encapsulation::L3_IPV6(ref header, _) => { return Some(( header.source_address.to_string(), header.dest_address.to_string(), @@ -153,13 +154,13 @@ impl Packet<'_> { let num = self.encapsulation.len(); for i in (0..num).rev() { match self.encapsulation[i] { - Encapsulation::L3_IP4(ref header, _) => { + Encapsulation::L3_IPV4(ref header, _) => { return Some(( header.source_address.to_string(), header.dest_address.to_string(), )); } - Encapsulation::L3_IP6(ref header, _) => { + Encapsulation::L3_IPV6(ref header, _) => { return Some(( header.source_address.to_string(), header.dest_address.to_string(), @@ -213,7 +214,7 @@ impl Packet<'_> { } for i in 0..num - 1 { match self.encapsulation[i] { - Encapsulation::L3_IP4(ref l3_header, _) => match self.encapsulation[i + 1] { + Encapsulation::L3_IPV4(ref l3_header, _) => match self.encapsulation[i + 1] { Encapsulation::L4_TCP(ref l4_header, _) => { return Some(( l3_header.source_address.to_string(), @@ -232,7 +233,7 @@ impl Packet<'_> { } _ => continue, }, - Encapsulation::L3_IP6(ref l3_header, _) => match self.encapsulation[i + 1] { + Encapsulation::L3_IPV6(ref l3_header, _) => match self.encapsulation[i + 1] { Encapsulation::L4_TCP(ref l4_header, _) => { return Some(( l3_header.source_address.to_string(), @@ -266,7 +267,7 @@ impl Packet<'_> { for i in (1..num).rev() { match self.encapsulation[i] { Encapsulation::L4_TCP(ref l4_header, _) => match self.encapsulation[i - 1] { - Encapsulation::L3_IP4(ref l3_header, _) => { + Encapsulation::L3_IPV4(ref l3_header, _) => { return Some(( l3_header.source_address.to_string(), l4_header.source_port, @@ -274,7 +275,7 @@ impl Packet<'_> { l4_header.dest_port, )); } - Encapsulation::L3_IP6(ref l3_header, _) => { + Encapsulation::L3_IPV6(ref l3_header, _) => { return Some(( l3_header.source_address.to_string(), l4_header.source_port, @@ -285,7 +286,7 @@ impl Packet<'_> { _ => continue, }, Encapsulation::L4_UDP(ref l4_header, _) => match self.encapsulation[i - 1] { - Encapsulation::L3_IP4(ref l3_header, _) => { + Encapsulation::L3_IPV4(ref l3_header, _) => { return Some(( l3_header.source_address.to_string(), l4_header.source_port, @@ -293,7 +294,7 @@ impl Packet<'_> { l4_header.dest_port, )); } - Encapsulation::L3_IP6(ref l3_header, _) => { + Encapsulation::L3_IPV6(ref l3_header, _) => { return Some(( l3_header.source_address.to_string(), l4_header.source_port, @@ -310,116 +311,55 @@ impl Packet<'_> { return None; } - pub fn get_trace_id(&self) -> Option<String> { - let num = self.encapsulation.len(); - let mut trace_id = String::new(); - for i in 0..num { - match self.encapsulation[i] { - Encapsulation::L3_IP4(ref l3_header, _) => { - trace_id.push_str("IP4->IP4;"); - trace_id.push_str(&l3_header.source_address.to_string()); - trace_id.push_str("->"); - trace_id.push_str(&l3_header.dest_address.to_string()); - trace_id.push_str(";"); - } - Encapsulation::L3_IP6(ref l3_header, _) => { - trace_id.push_str("IP6->IP6;"); - trace_id.push_str(&l3_header.source_address.to_string()); - trace_id.push_str("->"); - trace_id.push_str(&l3_header.dest_address.to_string()); - trace_id.push_str(";"); - } - Encapsulation::L4_TCP(ref l4_header, _) => { - trace_id.push_str("TCP->TCP;"); - trace_id.push_str(&l4_header.source_port.to_string()); - trace_id.push_str("->"); - trace_id.push_str(&l4_header.dest_port.to_string()); - trace_id.push_str(";"); - } - Encapsulation::L4_UDP(ref l4_header, _) => { - trace_id.push_str("UDP->UDP;"); - trace_id.push_str(&l4_header.source_port.to_string()); - trace_id.push_str("->"); - trace_id.push_str(&l4_header.dest_port.to_string()); - trace_id.push_str(";"); - } - _ => continue, - } - } - - Some(trace_id) - } - - pub fn get_reversed_trace_id(&self) -> Option<String> { + pub fn get_flow_id(&self) -> Option<String> { let num = self.encapsulation.len(); - let mut trace_id = String::new(); + let mut flow_id = String::new(); for i in 0..num { match self.encapsulation[i] { - Encapsulation::L3_IP4(ref l3_header, _) => { - trace_id.push_str("IP4->IP4;"); - trace_id.push_str(&l3_header.dest_address.to_string()); - trace_id.push_str("->"); - trace_id.push_str(&l3_header.source_address.to_string()); - trace_id.push_str(";"); + Encapsulation::L3_IPV4(ref l3_header, _) => { + flow_id.push_str(&l3_header.source_address.to_string()); + flow_id.push_str("->"); + flow_id.push_str(&l3_header.dest_address.to_string()); + flow_id.push_str(";"); } - Encapsulation::L3_IP6(ref l3_header, _) => { - trace_id.push_str("IP6->IP6;"); - trace_id.push_str(&l3_header.dest_address.to_string()); - trace_id.push_str("->"); - trace_id.push_str(&l3_header.source_address.to_string()); - trace_id.push_str(";"); + Encapsulation::L3_IPV6(ref l3_header, _) => { + flow_id.push_str(&l3_header.source_address.to_string()); + flow_id.push_str("->"); + flow_id.push_str(&l3_header.dest_address.to_string()); + flow_id.push_str(";"); } Encapsulation::L4_TCP(ref l4_header, _) => { - trace_id.push_str("TCP->TCP;"); - trace_id.push_str(&l4_header.dest_port.to_string()); - trace_id.push_str("->"); - trace_id.push_str(&l4_header.source_port.to_string()); - trace_id.push_str(";"); + flow_id.push_str("TCP->TCP;"); + flow_id.push_str(&l4_header.source_port.to_string()); + flow_id.push_str("->"); + flow_id.push_str(&l4_header.dest_port.to_string()); + flow_id.push_str(";"); } Encapsulation::L4_UDP(ref l4_header, _) => { - trace_id.push_str("UDP->UDP;"); - trace_id.push_str(&l4_header.dest_port.to_string()); - trace_id.push_str("->"); - trace_id.push_str(&l4_header.source_port.to_string()); - trace_id.push_str(";"); + flow_id.push_str("UDP->UDP;"); + flow_id.push_str(&l4_header.source_port.to_string()); + flow_id.push_str("->"); + flow_id.push_str(&l4_header.dest_port.to_string()); + flow_id.push_str(";"); } _ => continue, } } - Some(trace_id) + Some(flow_id) } } -pub fn reverse_trace_id(trace_id: &String) -> String { - let mut reversed_trace_id = String::new(); - let mut trace_id_vec: Vec<&str> = trace_id.split(";").collect(); - trace_id_vec.pop(); - for item in trace_id_vec.iter() { - let mut item_vec: Vec<&str> = item.split("->").collect(); - item_vec.reverse(); - reversed_trace_id.push_str(&item_vec.join("->")); - reversed_trace_id.push_str(";"); - } - reversed_trace_id -} - -fn handle_l2<'a>( - packet: &mut Packet<'a>, - input: &'a [u8], - ctx: Rc<RefCell<ThreadContex>>, -) -> Result<(), PacketError> { - let event_mgr = ctx.borrow().get_event_mgr(); +fn handle_l2<'a>(packet: &mut Packet<'a>, input: &'a [u8]) -> Result<(), PacketError> { + packet.event.push(PacketEvent::L2_EVENT); let result = EthernetFrame::decode(input); if let Ok((payload, header)) = result { dbg!(&header); packet .encapsulation .push(Encapsulation::L2_ETH(header, payload)); - BuildInEvent::trigger_l2_event(event_mgr, None); - return handle_l3(packet, payload, header.ether_type, ctx); + return handle_l3(packet, payload, header.ether_type); } else { - BuildInEvent::trigger_l2_event(event_mgr, None); return Err(PacketError::IncompleteEthernetFrame); } } @@ -428,9 +368,8 @@ fn handle_l3<'a>( packet: &mut Packet<'a>, input: &'a [u8], next_proto: EtherType, - ctx: Rc<RefCell<ThreadContex>>, ) -> Result<(), PacketError> { - let event_mgr = ctx.borrow().get_event_mgr(); + packet.event.push(PacketEvent::L3_EVENT); match next_proto { EtherType::IPv4 => { let result = IPv4Header::decode(input); @@ -443,15 +382,13 @@ fn handle_l3<'a>( packet .encapsulation - .push(Encapsulation::L3_IP4(header, payload)); + .push(Encapsulation::L3_IPV4(header, payload)); // TODO IPv4 Fragment - BuildInEvent::trigger_l3_event(event_mgr.clone(), None); - BuildInEvent::trigger_ip4_event(event_mgr, None); - return handle_l4(packet, payload, header.protocol, ctx); + packet.event.push(PacketEvent::IPV4_EVENT); + return handle_l4(packet, payload, header.protocol); } else { - BuildInEvent::trigger_l3_event(event_mgr, None); return Err(PacketError::IncompleteIpv4Header); } } @@ -466,20 +403,17 @@ fn handle_l3<'a>( packet .encapsulation - .push(Encapsulation::L3_IP6(header, payload)); + .push(Encapsulation::L3_IPV6(header, payload)); // TODO IPv6 Fragment - BuildInEvent::trigger_l3_event(event_mgr.clone(), None); - BuildInEvent::trigger_ip6_event(event_mgr, None); - return handle_l4(packet, payload, header.next_header, ctx); + packet.event.push(PacketEvent::IPV6_EVENT); + return handle_l4(packet, payload, header.next_header); } else { - BuildInEvent::trigger_l3_event(event_mgr, None); return Err(PacketError::IncompleteIpv6Header); } } _e => { - BuildInEvent::trigger_l3_event(event_mgr, None); return Err(PacketError::UnsupportEthernetType); } } @@ -489,10 +423,8 @@ fn handle_l4<'a>( packet: &mut Packet<'a>, input: &'a [u8], next_proto: IPProtocol, - ctx: Rc<RefCell<ThreadContex>>, ) -> Result<(), PacketError> { - let event_mgr = ctx.borrow().get_event_mgr(); - let session_mgr = ctx.borrow().get_session_mgr(); + packet.event.push(PacketEvent::L4_EVENT); match next_proto { IPProtocol::UDP => { let result = UdpHeader::decode(input); @@ -502,23 +434,9 @@ fn handle_l4<'a>( .encapsulation .push(Encapsulation::L4_UDP(header, payload)); - let session = packet2session(&packet, session_mgr); - BuildInEvent::trigger_l4_event(event_mgr.clone(), Some(session.clone())); - session.borrow_mut().set_session_proto(SessionProto::UDP); - match session.borrow().get_session_state() { - SessionState::New => { - BuildInEvent::trigger_udp_opening_event(event_mgr, Some(session.clone())); - } - SessionState::Active => { - BuildInEvent::trigger_udp_active_event(event_mgr, Some(session.clone())); - } - SessionState::Inactive | SessionState::Expired => { - BuildInEvent::trigger_udp_expire_event(event_mgr, Some(session.clone())); - } - } - return handle_l7(packet, payload, session, ctx); + packet.event.push(PacketEvent::UDP_EVENT); + return Ok(()); } else { - BuildInEvent::trigger_l4_event(event_mgr, None); return Err(PacketError::IncompleteUdpHeader); } } @@ -527,119 +445,24 @@ fn handle_l4<'a>( if let Ok((payload, header)) = result { dbg!(&header); - let tcp_need_closed = header.flag_rst || header.flag_fin; packet .encapsulation .push(Encapsulation::L4_TCP(header, payload)); // TODO TCP Reassembly - let session = packet2session(&packet, session_mgr); - BuildInEvent::trigger_l4_event(event_mgr.clone(), Some(session.clone())); - if tcp_need_closed { - session - .borrow_mut() - .set_session_state(SessionState::Inactive); - } - session.borrow_mut().set_session_proto(SessionProto::TCP); - match session.borrow().get_session_state() { - SessionState::New => { - BuildInEvent::trigger_tcp_opening_event(event_mgr, Some(session.clone())); - } - SessionState::Active => { - BuildInEvent::trigger_tcp_active_event(event_mgr, Some(session.clone())); - } - SessionState::Expired => { - BuildInEvent::trigger_tcp_expire_event(event_mgr, Some(session.clone())); - } - SessionState::Inactive => { - BuildInEvent::trigger_tcp_closed_event(event_mgr, Some(session.clone())); - } - } - - return handle_l7(packet, payload, session, ctx); + packet.event.push(PacketEvent::TCP_EVENT); + return Ok(()); } else { - BuildInEvent::trigger_l4_event(event_mgr, None); return Err(PacketError::IncompleteTcpHeader); } } _e => { - BuildInEvent::trigger_l4_event(event_mgr, None); return Err(PacketError::UnsupportIPProtocol); } } } -fn handle_l7<'a>( - packet: &mut Packet<'a>, - input: &'a [u8], - session: Rc<RefCell<Session>>, - ctx: Rc<RefCell<ThreadContex>>, -) -> Result<(), PacketError> { - let event_mgr = ctx.borrow().get_event_mgr(); - let next_proto = l7_identify(packet); - match next_proto { - L7Protocol::DNS => { - let result = DNS_MESSAGE::decode(input); - if let Ok((payload, header)) = result { - dbg!(&header); - packet - .encapsulation - .push(Encapsulation::L7_DNS(header, payload)); - BuildInEvent::trigger_l7_event(event_mgr.clone(), Some(session.clone())); - BuildInEvent::trigger_dns_event(event_mgr, Some(session)); - return Ok(()); - } else { - BuildInEvent::trigger_l7_event(event_mgr, Some(session)); - return Err(PacketError::IncompleteAppHeader); - } - } - L7Protocol::HTTP => { - let result = HTTP_MESSAGE::decode(input); - if let Ok((payload, header)) = result { - dbg!(&header); - packet - .encapsulation - .push(Encapsulation::L7_HTTP(header, payload)); - BuildInEvent::trigger_l7_event(event_mgr.clone(), Some(session.clone())); - BuildInEvent::trigger_http_event(event_mgr, Some(session)); - return Ok(()); - } else { - BuildInEvent::trigger_l7_event(event_mgr, Some(session)); - return Err(PacketError::IncompleteAppHeader); - } - } - L7Protocol::Unsupported => { - BuildInEvent::trigger_l7_event(event_mgr, Some(session)); - return Err(PacketError::UnsupportAppProtocol); - } - } -} - -enum L7Protocol { - DNS, - HTTP, - Unsupported, -} - -fn l7_identify(packet: &Packet) -> L7Protocol { - let option = packet.get_inner_port(); - if option.is_none() { - return L7Protocol::Unsupported; - } - - let (src_port, dst_port) = option.unwrap(); - if src_port == 80 || dst_port == 80 { - return L7Protocol::HTTP; - } - - if src_port == 53 || dst_port == 53 { - return L7Protocol::DNS; - } - - return L7Protocol::Unsupported; -} - /****************************************************************************** * TEST ******************************************************************************/ @@ -648,17 +471,13 @@ fn l7_identify(packet: &Packet) -> L7Protocol { mod tests { use super::Encapsulation; use super::Packet; - use crate::packet::packet::reverse_trace_id; use crate::protocol::ip::IPProtocol; use crate::protocol::ipv4::IPv4Header; use crate::protocol::ipv6::IPv6Header; use crate::protocol::tcp::TcpHeader; use crate::protocol::udp::UdpHeader; - use crate::thread::thread::ThreadContex; - use std::cell::RefCell; use std::net::Ipv4Addr; use std::net::Ipv6Addr; - use std::rc::Rc; #[test] fn test_packet_handle1() { @@ -756,9 +575,8 @@ mod tests { 0x00, 0x01, 0x00, 0x01, /* DNS END */ ]; - let thread_ctx = Rc::new(RefCell::new(ThreadContex::new())); let mut packet = Packet::new(&bytes, bytes.len() as u32); - let result = packet.handle(thread_ctx); + let result = packet.handle(); match result { Ok(v) => { @@ -898,9 +716,8 @@ mod tests { 0x2a, 0x0d, 0x0a, 0x0d, 0x0a, /* HTTP END */ ]; - let thread_ctx = Rc::new(RefCell::new(ThreadContex::new())); let mut packet = Packet::new(&bytes, bytes.len() as u32); - let result = packet.handle(thread_ctx); + let result = packet.handle(); match result { Ok(v) => { @@ -976,13 +793,13 @@ mod tests { packet .encapsulation - .push(Encapsulation::L3_IP4(ipv4_hdr.clone(), b"1")); + .push(Encapsulation::L3_IPV4(ipv4_hdr.clone(), b"1")); packet .encapsulation .push(Encapsulation::L4_TCP(tcp_hdr.clone(), b"2")); packet .encapsulation - .push(Encapsulation::L3_IP6(ipv6_hdr.clone(), b"3")); + .push(Encapsulation::L3_IPV6(ipv6_hdr.clone(), b"3")); packet .encapsulation .push(Encapsulation::L4_UDP(udp_hdr.clone(), b"4")); @@ -1023,11 +840,11 @@ mod tests { assert_eq!( packet.get_outer_l3_layer(), - Some(Encapsulation::L3_IP4(ipv4_hdr, b"1")) + Some(Encapsulation::L3_IPV4(ipv4_hdr, b"1")) ); assert_eq!( packet.get_inner_l3_layer(), - Some(Encapsulation::L3_IP6(ipv6_hdr, b"3")) + Some(Encapsulation::L3_IPV6(ipv6_hdr, b"3")) ); assert_eq!( packet.get_outer_l4_layer(), @@ -1038,8 +855,6 @@ mod tests { Some(Encapsulation::L4_UDP(udp_hdr, b"4")) ); - assert_eq!(packet.get_trace_id(), Some("IP4->IP4;192.168.0.101->121.14.154.93;TCP->TCP;50081->443;IP6->IP6;2409:8034:4025::50:a31->2409:8034:4040:5301::204;UDP->UDP;9993->9994;".to_string())); - assert_eq!(packet.get_reversed_trace_id() ,Some("IP4->IP4;121.14.154.93->192.168.0.101;TCP->TCP;443->50081;IP6->IP6;2409:8034:4040:5301::204->2409:8034:4025::50:a31;UDP->UDP;9994->9993;".to_string())); - assert_eq!(reverse_trace_id(&packet.get_trace_id().unwrap()), "IP4->IP4;121.14.154.93->192.168.0.101;TCP->TCP;443->50081;IP6->IP6;2409:8034:4040:5301::204->2409:8034:4025::50:a31;UDP->UDP;9994->9993;".to_string()); + assert_eq!(packet.get_flow_id(), Some("192.168.0.101->121.14.154.93;TCP->TCP;50081->443;2409:8034:4025::50:a31->2409:8034:4040:5301::204;UDP->UDP;9993->9994;".to_string())); } } |
