Skip to content

Commit

Permalink
fix(net): ensure the actual and expected original datagram protocol m…
Browse files Browse the repository at this point in the history
…atch or discard the packet (#745)
  • Loading branch information
fujiapple852 committed Oct 31, 2023
1 parent 19c572f commit 5192b6a
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 48 deletions.
48 changes: 26 additions & 22 deletions src/tracing/net/ipv4.rs
Original file line number Diff line number Diff line change
Expand Up @@ -331,17 +331,17 @@ fn extract_probe_resp(
Ok(match icmp_v4.get_icmp_type() {
IcmpType::TimeExceeded => {
let packet = TimeExceededPacket::new_view(icmp_v4.packet()).req()?;
let resp_seq = extract_probe_resp_seq(packet.payload(), protocol)?;
Some(ProbeResponse::TimeExceeded(ProbeResponseData::new(
recv, src, resp_seq,
)))
let nested_ipv4 = Ipv4Packet::new_view(packet.payload()).req()?;
extract_probe_resp_seq(&nested_ipv4, protocol)?.map(|resp_seq| {
ProbeResponse::TimeExceeded(ProbeResponseData::new(recv, src, resp_seq))
})
}
IcmpType::DestinationUnreachable => {
let packet = DestinationUnreachablePacket::new_view(icmp_v4.packet()).req()?;
let resp_seq = extract_probe_resp_seq(packet.payload(), protocol)?;
Some(ProbeResponse::DestinationUnreachable(
ProbeResponseData::new(recv, src, resp_seq),
))
let nested_ipv4 = Ipv4Packet::new_view(packet.payload()).req()?;
extract_probe_resp_seq(&nested_ipv4, protocol)?.map(|resp_seq| {
ProbeResponse::DestinationUnreachable(ProbeResponseData::new(recv, src, resp_seq))
})
}
IcmpType::EchoReply => match protocol {
TracerProtocol::Icmp => {
Expand All @@ -361,27 +361,31 @@ fn extract_probe_resp(

#[instrument]
fn extract_probe_resp_seq(
payload: &[u8],
ipv4: &Ipv4Packet<'_>,
protocol: TracerProtocol,
) -> TraceResult<ProbeResponseSeq> {
let ipv4 = Ipv4Packet::new_view(payload).req()?;
Ok(match protocol {
TracerProtocol::Icmp => {
let echo_request = extract_echo_request(&ipv4)?;
) -> TraceResult<Option<ProbeResponseSeq>> {
Ok(match (protocol, ipv4.get_protocol()) {
(TracerProtocol::Icmp, IpProtocol::Icmp) => {
let echo_request = extract_echo_request(ipv4)?;
let identifier = echo_request.get_identifier();
let sequence = echo_request.get_sequence();
ProbeResponseSeq::Icmp(ProbeResponseSeqIcmp::new(identifier, sequence))
Some(ProbeResponseSeq::Icmp(ProbeResponseSeqIcmp::new(
identifier, sequence,
)))
}
TracerProtocol::Udp => {
let (src_port, dest_port, checksum, identifier) = extract_udp_packet(&ipv4)?;
ProbeResponseSeq::Udp(ProbeResponseSeqUdp::new(
(TracerProtocol::Udp, IpProtocol::Udp) => {
let (src_port, dest_port, checksum, identifier) = extract_udp_packet(ipv4)?;
Some(ProbeResponseSeq::Udp(ProbeResponseSeqUdp::new(
identifier, src_port, dest_port, checksum,
))
)))
}
TracerProtocol::Tcp => {
let (src_port, dest_port) = extract_tcp_packet(&ipv4)?;
ProbeResponseSeq::Tcp(ProbeResponseSeqTcp::new(src_port, dest_port))
(TracerProtocol::Tcp, IpProtocol::Tcp) => {
let (src_port, dest_port) = extract_tcp_packet(ipv4)?;
Some(ProbeResponseSeq::Tcp(ProbeResponseSeqTcp::new(
src_port, dest_port,
)))
}
_ => None,
})
}

Expand Down
57 changes: 31 additions & 26 deletions src/tracing/net/ipv6.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use crate::tracing::packet::icmpv6::{IcmpCode, IcmpPacket, IcmpType};
use crate::tracing::packet::ipv6::Ipv6Packet;
use crate::tracing::packet::tcp::TcpPacket;
use crate::tracing::packet::udp::UdpPacket;
use crate::tracing::packet::IpProtocol;
use crate::tracing::probe::{
ProbeResponse, ProbeResponseData, ProbeResponseSeq, ProbeResponseSeqIcmp, ProbeResponseSeqTcp,
ProbeResponseSeqUdp,
Expand Down Expand Up @@ -261,17 +262,17 @@ fn extract_probe_resp(
Ok(match icmp_v6.get_icmp_type() {
IcmpType::TimeExceeded => {
let packet = TimeExceededPacket::new_view(icmp_v6.packet()).req()?;
let resp_seq = extract_probe_resp_seq(packet.payload(), protocol)?;
Some(ProbeResponse::TimeExceeded(ProbeResponseData::new(
recv, ip, resp_seq,
)))
let nested_ipv6 = Ipv6Packet::new_view(packet.payload()).req()?;
extract_probe_resp_seq(&nested_ipv6, protocol)?.map(|resp_seq| {
ProbeResponse::TimeExceeded(ProbeResponseData::new(recv, ip, resp_seq))
})
}
IcmpType::DestinationUnreachable => {
let packet = DestinationUnreachablePacket::new_view(icmp_v6.packet()).req()?;
let resp_seq = extract_probe_resp_seq(packet.payload(), protocol)?;
Some(ProbeResponse::DestinationUnreachable(
ProbeResponseData::new(recv, ip, resp_seq),
))
let nested_ipv6 = Ipv6Packet::new_view(packet.payload()).req()?;
extract_probe_resp_seq(&nested_ipv6, protocol)?.map(|resp_seq| {
ProbeResponse::DestinationUnreachable(ProbeResponseData::new(recv, ip, resp_seq))
})
}
IcmpType::EchoReply => match protocol {
TracerProtocol::Icmp => {
Expand All @@ -290,36 +291,41 @@ fn extract_probe_resp(
}

fn extract_probe_resp_seq(
payload: &[u8],
ipv6: &Ipv6Packet<'_>,
protocol: TracerProtocol,
) -> TraceResult<ProbeResponseSeq> {
Ok(match protocol {
TracerProtocol::Icmp => {
let (identifier, sequence) = extract_echo_request(payload)?;
ProbeResponseSeq::Icmp(ProbeResponseSeqIcmp::new(identifier, sequence))
) -> TraceResult<Option<ProbeResponseSeq>> {
Ok(match (protocol, ipv6.get_next_header()) {
(TracerProtocol::Icmp, IpProtocol::IcmpV6) => {
let (identifier, sequence) = extract_echo_request(ipv6)?;
Some(ProbeResponseSeq::Icmp(ProbeResponseSeqIcmp::new(
identifier, sequence,
)))
}
TracerProtocol::Udp => {
let (src_port, dest_port) = extract_udp_packet(payload)?;
ProbeResponseSeq::Udp(ProbeResponseSeqUdp::new(0, src_port, dest_port, 0))
(TracerProtocol::Udp, IpProtocol::Udp) => {
let (src_port, dest_port) = extract_udp_packet(ipv6)?;
Some(ProbeResponseSeq::Udp(ProbeResponseSeqUdp::new(
0, src_port, dest_port, 0,
)))
}
TracerProtocol::Tcp => {
let (src_port, dest_port) = extract_tcp_packet(payload)?;
ProbeResponseSeq::Tcp(ProbeResponseSeqTcp::new(src_port, dest_port))
(TracerProtocol::Tcp, IpProtocol::Tcp) => {
let (src_port, dest_port) = extract_tcp_packet(ipv6)?;
Some(ProbeResponseSeq::Tcp(ProbeResponseSeqTcp::new(
src_port, dest_port,
)))
}
_ => None,
})
}

fn extract_echo_request(ipv6_bytes: &[u8]) -> TraceResult<(u16, u16)> {
let ipv6 = Ipv6Packet::new_view(ipv6_bytes).req()?;
fn extract_echo_request(ipv6: &Ipv6Packet<'_>) -> TraceResult<(u16, u16)> {
let echo_request_packet = EchoRequestPacket::new_view(ipv6.payload()).req()?;
Ok((
echo_request_packet.get_identifier(),
echo_request_packet.get_sequence(),
))
}

fn extract_udp_packet(ipv6_bytes: &[u8]) -> TraceResult<(u16, u16)> {
let ipv6 = Ipv6Packet::new_view(ipv6_bytes).req()?;
fn extract_udp_packet(ipv6: &Ipv6Packet<'_>) -> TraceResult<(u16, u16)> {
let udp_packet = UdpPacket::new_view(ipv6.payload()).req()?;
Ok((udp_packet.get_source(), udp_packet.get_destination()))
}
Expand All @@ -343,8 +349,7 @@ fn extract_udp_packet(ipv6_bytes: &[u8]) -> TraceResult<(u16, u16)> {
///
/// [rfc4443]: https://datatracker.ietf.org/doc/html/rfc4443#section-2.4
/// [rfc2460]: https://datatracker.ietf.org/doc/html/rfc2460#section-5
fn extract_tcp_packet(ipv6_bytes: &[u8]) -> TraceResult<(u16, u16)> {
let ipv6 = Ipv6Packet::new_view(ipv6_bytes).req()?;
fn extract_tcp_packet(ipv6: &Ipv6Packet<'_>) -> TraceResult<(u16, u16)> {
let tcp_packet = TcpPacket::new_view(ipv6.payload()).req()?;
Ok((tcp_packet.get_source(), tcp_packet.get_destination()))
}

0 comments on commit 5192b6a

Please sign in to comment.