Xenos has asked for the wisdom of the Perl Monks concerning the following question:

Hi! I'm new to Perl, and one of my assignments is to write a script that produces the same output as MS-DOS's Tracert command and functions similarly, i.e. by sending ICMP Echo Requests with increasing Time-To-Live values to the specified destination and capturing the replies from the intermediate hosts. I tried achieving that with the Net::Ping module, defining the used protocol as ICMP and setting the TTL while constructing the object, but the TTL values I set didn't seem to affect anything at all, even when I deliberately gave them invalid values. I also couldn't figure how to get the IP of the host returning the reply. I'd be glad for some help. Thanks in advance!
  • Comment on Simulating traceroute using the Ping module

Replies are listed 'Best First'.
Re: Simulating traceroute using the Ping module
by Anonymous Monk on Jan 18, 2016 at 14:03 UTC

    Some more information would be helpful.

    First, why reinvent (rewrite) the wheel? (Homework?)

    Second, what OS are you on? If *NIX, Net::Ping with ICMP needs root permissions.

    Third, have you inspected the actual packets to see if the TTL setting really isn't having any effect? (e.g. Wireshark)

    If you could also provide a short, runnable example that demonstrates the problem that would help too.

Re: Simulating traceroute using the Ping module
by Myrddin Wyllt (Hermit) on Jan 19, 2016 at 02:21 UTC

    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__
Re: Simulating traceroute using the Ping module
by hotchiwawa (Scribe) on Jan 18, 2016 at 19:22 UTC