As previously pointed out, Net::Ping isn't the best choice for this task, but if you do use it, here are some things to bear in mind:-
- Using the 'icmp' protocol requires you to run as root.
- The TTL value can only be set at object construction, so you are using a new socket for each ping. This means that the route may well change between pings.
- Most hosts won't reply to an icmp ping.
- There is no documented way of retrieving the IP of the returning host.
If that still hasn't put you off, the following code sort of does what you want - bear in mind the caveat that the route may change between pings, and that from_ip is an undocumented property of the Net::Ping class obtained by reading the source - it's almost never a good idea to use stuff like that.
#!/usr/bin/perl
use strict;
use warnings;
use Net::Ping;
my $target_name = 'www.bbc.co.uk';
# The name doesn't always resolve to the same IP, so we pick one
# and stick with it
my (undef, undef, $target_ip) = Net::Ping->new("icmp")
->ping($target_name);
for my $ttl (1..30){
# Only way to change the ttl is at object construction time
# ALL the intermediate parameters are required; skipping or using
# 'undef' doesn't work
my $p = Net::Ping->new("icmp", 0.5, 0, 0, 0, $ttl);
$p->ping($target_ip);
# Not all pings will return a 'from_ip', so initialise it here
my $from_ip = '*.*.*.*';
# If the intermediate host returned an IP, it will be in the
# undocumented 'from_ip' element of the object
$from_ip = join('.',unpack('C4', $p->{from_ip})) if $p->{from_ip};
print "$ttl \t $from_ip \n";
# If the 'from_ip' is the same as the target, we're done
last if $from_ip eq $target_ip;
}
0;
__END__
|