Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
JeffreyYuENL committed Sep 14, 2024
0 parents commit 7d89886
Show file tree
Hide file tree
Showing 5 changed files with 351 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/target
8 changes: 8 additions & 0 deletions .idea/.gitignore

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

260 changes: 260 additions & 0 deletions Cargo.lock

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

9 changes: 9 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[package]
name = "traceroute_rust"
version = "0.1.0"
edition = "2021"

[dependencies]
pnet = "0.31.0"
pnet_packet = "0.31.0"
pnet_transport = "0.31.0"
73 changes: 73 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
use pnet_packet::icmp::{echo_request::MutableEchoRequestPacket, IcmpPacket, IcmpTypes};
use pnet_packet::ip::IpNextHeaderProtocols;
use pnet_packet::{icmp, Packet};
use pnet_transport::{icmp_packet_iter, transport_channel, TransportChannelType::Layer3};
use std::net::IpAddr;
use std::time::{Duration, Instant};

const MAX_TTL: u8 = 30;
const TIMEOUT: Duration = Duration::from_secs(3);

fn main() {
let destination = "8.8.8.8";
let dest_ip: IpAddr = destination.parse().expect("Invalid IP address");

println!("Traceroute to {}", dest_ip);

for ttl in 1..=MAX_TTL {
let start = Instant::now();
match send_echo_request(dest_ip, ttl) {
Ok(ip) => {
let duration = start.elapsed();
println!("{} \t{} \t{:.2?}", ttl, ip, duration);
if ip == dest_ip {
println!("Destination reached.");
break;
}
}
Err(e) => {
println!("{} \t* \t{}", ttl, e);
}
}
}
}

fn send_echo_request(dest: IpAddr, ttl: u8) -> Result<IpAddr, &'static str> {
let protocol = Layer3(IpNextHeaderProtocols::Icmp);
let (mut tx, mut rx) = transport_channel(1024, protocol).map_err(|_| "Failed to open channel")?;

tx.set_ttl(ttl).map_err(|_| "Failed to set TTL")?;

let mut buffer = [0u8; 64];
let mut packet = MutableEchoRequestPacket::new(&mut buffer).ok_or("Failed to create packet")?;

// Set the packet fields
packet.set_icmp_type(IcmpTypes::EchoRequest);
packet.set_sequence_number(1);
packet.set_identifier(0);

// Create an ICMP packet for checksum calculation
let icmp_packet = IcmpPacket::new(packet.packet()).ok_or("Failed to create ICMP packet")?;
let checksum = icmp::checksum(&icmp_packet);
packet.set_checksum(checksum);

tx.send_to(packet, dest).map_err(|_| "Failed to send packet")?;

let mut iter = icmp_packet_iter(&mut rx);

let start_time = Instant::now();
loop {
if start_time.elapsed() > TIMEOUT {
return Err("Request timed out");
}

if let Ok((packet, addr)) = iter.next() {
match packet.get_icmp_type() {
IcmpTypes::TimeExceeded | IcmpTypes::EchoReply => {
return Ok(addr);
}
_ => continue,
}
}
}
}

0 comments on commit 7d89886

Please sign in to comment.