pub mod traceroute{
use pnet::packet::ipv4::MutableIpv4Packet;
use pnet::packet::ip::IpNextHeaderProtocols;
use pnet::packet::icmp::echo_request::MutableEchoRequestPacket;
use pnet::packet::Packet;
use std::net::Ipv4Addr;
use crate::ip::ip::{make_ip_packet,send_recv_packet};
use crate::icmp::icmp::{make_icmp_echo_packet,checksum};
pub fn traceroute(dst_addr: Ipv4Addr)->Vec<Option<Ipv4Addr>>{
let mut result: Vec<Option<Ipv4Addr>> = vec![];
let mut ip_packet:[u8; 48] = [0; 48];
let mut ip = MutableIpv4Packet::new(&mut ip_packet).unwrap();
make_ip_packet(&mut ip, dst_addr,IpNextHeaderProtocols::Icmp);
let mut icmp_packet:[u8; 8] = [0; 8];
let mut icmp = MutableEchoRequestPacket::new(&mut icmp_packet).unwrap();
make_icmp_echo_packet(&mut icmp);
let checksum = checksum(icmp.packet());
icmp.set_checksum(checksum);
ip.set_payload(&icmp.packet());
for ttl in 1..255 {
let src_addr = match send_recv_packet(&mut ip,ttl,IpNextHeaderProtocols::Icmp){
Ok(addr) => Some(addr),
Err(_) => None,
};
result.push(src_addr);
match src_addr {
Some(addr) => {
if addr == dst_addr {
break;
}
}
None => {}
}
}
return result;
}
}