Skip to content

Commit

Permalink
exploratory code for supporting icmp extensions
Browse files Browse the repository at this point in the history
  • Loading branch information
fujiapple852 committed Oct 3, 2023
1 parent e466af0 commit fd0f569
Show file tree
Hide file tree
Showing 7 changed files with 801 additions and 29 deletions.
7 changes: 7 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ windows-sys = { version = "0.48.0", features = [
] }

[dev-dependencies]
hex-literal = "0.4.1"
rand = "0.8.5"
test-case = "3.2.1"

Expand Down
6 changes: 5 additions & 1 deletion src/tracing/net/channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,11 @@ impl TracerChannel {
fn recv_icmp_probe(&mut self) -> TraceResult<Option<ProbeResponse>> {
if self.recv_socket.is_readable(self.read_timeout)? {
match self.dest_addr {
IpAddr::V4(_) => ipv4::recv_icmp_probe(&mut self.recv_socket, self.protocol),
IpAddr::V4(_) => ipv4::recv_icmp_probe(
&mut self.recv_socket,
self.protocol,
self.ipv4_length_order,
),
IpAddr::V6(_) => ipv6::recv_icmp_probe(&mut self.recv_socket, self.protocol),
}
} else {
Expand Down
64 changes: 59 additions & 5 deletions src/tracing/net/ipv4.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ use crate::tracing::packet::checksum::{icmp_ipv4_checksum, udp_ipv4_checksum};
use crate::tracing::packet::icmpv4::destination_unreachable::DestinationUnreachablePacket;
use crate::tracing::packet::icmpv4::echo_reply::EchoReplyPacket;
use crate::tracing::packet::icmpv4::echo_request::EchoRequestPacket;
use crate::tracing::packet::icmpv4::extension::extension_header::ExtensionHeader;
use crate::tracing::packet::icmpv4::extension::extension_structure::ExtensionStructure;
use crate::tracing::packet::icmpv4::time_exceeded::TimeExceededPacket;
use crate::tracing::packet::icmpv4::{IcmpCode, IcmpPacket, IcmpType};
use crate::tracing::packet::ipv4::Ipv4Packet;
use crate::tracing::packet::tcp::TcpPacket;
use crate::tracing::packet::udp::UdpPacket;
use crate::tracing::packet::IpProtocol;
use crate::tracing::packet::{fmt_payload, IpProtocol};
use crate::tracing::probe::{
ProbeResponse, ProbeResponseData, ProbeResponseSeq, ProbeResponseSeqIcmp, ProbeResponseSeqTcp,
ProbeResponseSeqUdp,
Expand Down Expand Up @@ -187,12 +189,13 @@ pub fn dispatch_tcp_probe(
pub fn recv_icmp_probe(
recv_socket: &mut Socket,
protocol: TracerProtocol,
ipv4_byte_order: platform::PlatformIpv4FieldByteOrder,
) -> TraceResult<Option<ProbeResponse>> {
let mut buf = [0_u8; MAX_PACKET_SIZE];
match recv_socket.read(&mut buf) {
Ok(_bytes_read) => {
let ipv4 = Ipv4Packet::new_view(&buf).req()?;
Ok(extract_probe_resp(protocol, &ipv4)?)
Ok(extract_probe_resp(protocol, ipv4_byte_order, &ipv4)?)
}
Err(err) => match err.kind() {
ErrorKind::WouldBlock => Ok(None),
Expand Down Expand Up @@ -324,22 +327,73 @@ fn udp_payload_size(packet_size: usize) -> usize {
#[instrument]
fn extract_probe_resp(
protocol: TracerProtocol,
ipv4_byte_order: platform::PlatformIpv4FieldByteOrder,
ipv4: &Ipv4Packet<'_>,
) -> TraceResult<Option<ProbeResponse>> {
let recv = SystemTime::now();
let src = IpAddr::V4(ipv4.get_source());
let icmp_v4 = IcmpPacket::new_view(ipv4.payload()).req()?;

// if ipv4.get_source() == Ipv4Addr::new(129, 250,2, 50) {
// println!("found");
// }

// should this include the IP header? Seems it does not
//
// wireshark: 45 20 00 38
// We get: 45 20 24 00
//
// we convert 24 00 to be 00 24 which is 36
// we then subtract 20 the Ipv4 header (20) and get 16
//
// we set set_header_included(true) on the ipv4 recv socket, so I guess macOS subtracts it already?
// TODO how does this behave on other platforms?

let total_length = ipv4_byte_order.adjust_length(ipv4.get_total_length());
// let header_length = ipv4.get_header_length() as usize * 4;
// let payload_length = total_length as usize; //.saturating_sub(header_length);
let ipv4_payload = &ipv4.payload_new()[..total_length as usize];

let icmp_v4 = IcmpPacket::new_view(ipv4_payload).req()?;

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)?;
let payload = packet.payload();
let extension = packet.extension();
if let Some(ext) = extension {
let extensions = ExtensionStructure::new_view(ext).req()?;
let ext_header = ExtensionHeader::new_view(extensions.header()).req()?;
println!(
"extension header: version={}, checksum={}",
ext_header.get_version(),
ext_header.get_checksum()
);
for obj in extensions.iter() {
println!("extension object: length={:?}, class_num={:?}, class_subtype={:?}, payload={}", obj.get_length(), obj.get_class_num(), obj.get_class_subtype(), fmt_payload(obj.payload()));
}
}
let resp_seq = extract_probe_resp_seq(payload, protocol)?;
Some(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)?;
let payload = packet.payload();
let extension = packet.extension();
if let Some(ext) = extension {
let extensions = ExtensionStructure::new_view(ext).req()?;
let ext_header = ExtensionHeader::new_view(extensions.header()).req()?;
println!(
"extension header: version={}, checksum={}",
ext_header.get_version(),
ext_header.get_checksum()
);
for obj in extensions.iter() {
println!("extension object: length={:?}, class_num={:?}, class_subtype={:?}, payload={}", obj.get_length(), obj.get_class_num(), obj.get_class_subtype(), fmt_payload(obj.payload()));
}
}
let resp_seq = extract_probe_resp_seq(payload, protocol)?;
Some(ProbeResponse::DestinationUnreachable(
ProbeResponseData::new(recv, src, resp_seq),
))
Expand Down
2 changes: 1 addition & 1 deletion src/tracing/packet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ pub mod udp;
/// `TCP` packets.
pub mod tcp;

fn fmt_payload(bytes: &[u8]) -> String {
pub fn fmt_payload(bytes: &[u8]) -> String {
use itertools::Itertools as _;
format!("{:02x}", bytes.iter().format(" "))
}
Expand Down
Loading

0 comments on commit fd0f569

Please sign in to comment.