#!/usr/bin/perl # Has been created by ShaD0w # This is free software; you can redistribute it and/or modify it under the # same terms as Perl itself. # Look at user configurable section for set defaults use Net::RawIP qw(:pcap); use Socket; require 'getopts.pl'; Getopts('m:q:w:t:h'); $|=1; $dest = $opt_t; if ($opt_h || !$opt_t){ print "Usage $0 [ -h ] [-w timeout(sec)] [-q nqueries] [-m max_ttl] -t host\n "; exit } $max_ttl = ($opt_m ? $opt_m : 30); $n_pakets = ($opt_q ? $opt_q : 3); $timeout = ($opt_w ? $opt_w: 5); ($name,$ip) = (gethostbyname($dest))[0,4]; die "$dest: host not found" if $?; ############# # User configurable section # If rdev and ifaddrlist functions are not implemented # $dev='eth0'; # set your device # $ip_addr = 'amk.lan'; # set your ip address # The rdev and ifaddrlist functions are implemented (auto) $dev = rdev($dest); $ip_addr = ${ifaddrlist()}{$dev}; ############# print "traceroute to $name ("; printf ("%u.%u.%u.%u",unpack("C4",$ip)); print ") , $max_ttl hops max, 40 byte packets\n"; srand(); $packet = new Net::RawIP({udp=>{}}); $icmp = new Net::RawIP({icmp=>{}}); $udp = new Net::RawIP({udp=>{}}); $filt="ip proto \\icmp and dst host $ip_addr and (icmp[0]==3 or icmp[0]==11)"; $pcap = $packet->pcapinit($dev,$filt,1500,60); $offset = linkoffset($pcap); $packet->set({ip=> {saddr=>$ip_addr, daddr=>$dest, frag_off=>0, tos=>0, id=>$$}, udp=> {data=>'a'x12}}); for($i=1;$i<=$max_ttl;$i++){ print "$i. "; $printed = 0; for($np=0;$np<$n_pakets;$np++){ $gen=10000+int(rand(1000)); $packet->set({ip=>{ttl=>$i},udp=>{source=>$gen, dest=>$gen+1}}); undef($ipacket); $packet->send(); $stime = timem(); $drop = 1; do { $end = 1 if($p_type==3); $p_addr=$p_type=$p_code=0; $ipacket = &next($pcap,$temp); $etime=timem(); if($ipacket) { $icmp->bset(substr($ipacket,$offset)); ($addr,$type,$code,$data) = $icmp->get({ip=>['saddr'],icmp=>['type','code','data']}); $udp->bset($data); ($sign) = $udp->get({udp=>['source']}); if($sign eq $gen){ $drop = 0; ($p_addr, $p_type, $p_code) = ($addr, $type, $code); } } } while((($etime-$stime)<$timeout) && $drop); unless(($etime-$stime)<$timeout){ print "* "; next; } $dtime = ($etime-$stime); unless($printed){ print ip2name($p_addr), " (",ip2dot($p_addr), ") ",destun($type,$p_code) ? rtt_ms($dtime):cod2name($dtime,$p_code); $printed = 1; } else { print " ",destun($type,$p_code) ? rtt_ms($dtime):cod2name($dtime,$p_code); } } print "\n"; exit if $end; } sub ip2dot { sprintf("%u.%u.%u.%u",unpack "C4", pack "N1", shift); } sub ip2name { my $addr = shift; (gethostbyaddr(pack("N",$addr),AF_INET))[0] || ip2dot($addr); } sub rtt_ms { sprintf("%.2f ms", 1000*shift); } sub cod2name { my @str = qw( !N !H !P 0 !F !S); return rtt_ms($_[0])." ".$str[$_[1]]; } sub destun { $_[0]!=3 || ($_[0]==3 && $_[1] == 3) }