Skip Menu |

This queue is for tickets about the Net-Ping CPAN distribution.

Report information
The Basics
Id: 49588
Status: resolved
Priority: 0/
Queue: Net-Ping

People
Owner: Nobody in particular
Requestors: rolek [...] bokxing.nl
Cc:
AdminCc:

Bug Information
Severity: Wishlist
Broken in: 2.36
Fixed in: (no value)



Subject: enable setting of TTL and handling of ICMP_TIME_EXCEEDED response
I wanted to use Net::Ping with lower TTL's to find out intermediate routers (tracerout-ish behaviour), so I added support for setting the TTL and properly handling ICMP_TIME_EXCEEDED responses. If it is to your liking, you can include it. I have only tested this on a linux platform, though.
Subject: Net-Ping-TTL.patch
diff -ruN src/MANIFEST Net-Ping-2.36/MANIFEST --- src/MANIFEST 2009-09-10 09:20:36.000000000 +0200 +++ Net-Ping-2.36/MANIFEST 2009-06-08 18:29:23.000000000 +0200 @@ -18,5 +18,4 @@ t/450_service.t t/500_ping_icmp.t t/510_ping_udp.t -t/520_ping_icmp_ttl.t META.yml Module meta-data (added by MakeMaker) diff -ruN src/lib/Net/Ping.pm Net-Ping-2.36/lib/Net/Ping.pm --- src/lib/Net/Ping.pm 2009-09-10 09:11:00.000000000 +0200 +++ Net-Ping-2.36/lib/Net/Ping.pm 2009-06-08 18:30:57.000000000 +0200 @@ -18,9 +18,8 @@ @EXPORT = qw(pingecho); $VERSION = "2.36"; -use constant SOL_IP => 0; -use constant IP_TOS => 1; -use constant IP_TTL => 2; +sub SOL_IP { 0; }; +sub IP_TOS { 1; }; # Constants @@ -88,7 +87,6 @@ $data_size, # Optional additional bytes of data $device, # Optional device to use $tos, # Optional ToS to set - $ttl, # Optional TTL to set ) = @_; my $class = ref($this) || $this; my $self = {}; @@ -112,12 +110,6 @@ $self->{"tos"} = $tos; - if ($self->{"proto"} eq 'icmp') { - croak('TTL must be from 0 to 255') - if ($ttl && ($ttl < 0 || $ttl > 255)); - $self->{"ttl"} = $ttl; - } - $min_datasize = ($proto eq "udp") ? 1 : 0; # Determine data size $data_size = $min_datasize unless defined($data_size) && $proto ne "tcp"; croak("Data for ping must be from $min_datasize to $max_datasize bytes") @@ -151,7 +143,7 @@ or croak "error binding to device $self->{'device'} $!"; } if ($self->{'tos'}) { - setsockopt($self->{"fh"}, SOL_IP, IP_TOS, pack("I*", $self->{'tos'})) + setsockopt($self->{"fh"}, SOL_IP, IP_TOS(), pack("I*", $self->{'tos'})) or croak "error configuring tos to $self->{'tos'} $!"; } } @@ -169,13 +161,9 @@ or croak "error binding to device $self->{'device'} $!"; } if ($self->{'tos'}) { - setsockopt($self->{"fh"}, SOL_IP, IP_TOS, pack("I*", $self->{'tos'})) + setsockopt($self->{"fh"}, SOL_IP, IP_TOS(), pack("I*", $self->{'tos'})) or croak "error configuring tos to $self->{'tos'} $!"; } - if ($self->{'ttl'}) { - setsockopt($self->{"fh"}, SOL_IP, IP_TTL, pack("I*", $self->{'ttl'})) - or croak "error configuring ttl to $self->{'ttl'} $!"; - } } elsif ($self->{"proto"} eq "tcp" || $self->{"proto"} eq "stream") { @@ -421,8 +409,6 @@ use constant ICMP_ECHOREPLY => 0; # ICMP packet types use constant ICMP_UNREACHABLE => 3; # ICMP packet types -use constant ICMP_TIME_EXCEEDED => 11; # ICMP packet types -use constant ICMP_PARAMETERPROB => 12; # ICMP packet types use constant ICMP_ECHO => 8; use constant ICMP_STRUCT => "C2 n3 A"; # Structure of a minimal ICMP packet use constant SUBCODE => 0; # No ICMP subcode for ECHO and ECHOREPLY @@ -503,18 +489,15 @@ $self->{"from_ip"} = $from_ip; $self->{"from_type"} = $from_type; $self->{"from_subcode"} = $from_subcode; - next if ($from_pid != $self->{"pid"}); - next if ($from_seq != $self->{"seq"}); - if (! $source_verify || (inet_ntoa($from_ip) eq inet_ntoa($ip))) { # Does the packet check out? + if (($from_pid == $self->{"pid"}) && # Does the packet check out? + (! $source_verify || (inet_ntoa($from_ip) eq inet_ntoa($ip))) && + ($from_seq == $self->{"seq"})) { if ($from_type == ICMP_ECHOREPLY) { $ret = 1; $done = 1; } elsif ($from_type == ICMP_UNREACHABLE) { $done = 1; } - } elsif ($from_type == ICMP_TIME_EXCEEDED) { - $ret = 0; - $done = 1; } } else { # Oops, timed out $done = 1; @@ -610,7 +593,7 @@ or croak("error binding to device $self->{'device'} $!"); } if ($self->{'tos'}) { - setsockopt($self->{"fh"}, SOL_IP, IP_TOS, pack("I*", $self->{'tos'})) + setsockopt($self->{"fh"}, SOL_IP, IP_TOS(), pack("I*", $self->{'tos'})) or croak "error configuring tos to $self->{'tos'} $!"; } }; @@ -1054,7 +1037,7 @@ or croak("error binding to device $self->{'device'} $!"); } if ($self->{'tos'}) { - setsockopt($fh, SOL_IP, IP_TOS, pack("I*", $self->{'tos'})) + setsockopt($fh, SOL_IP, IP_TOS(), pack("I*", $self->{'tos'})) or croak "error configuring tos to $self->{'tos'} $!"; } # Set O_NONBLOCK property on filehandle @@ -1123,7 +1106,7 @@ or croak("error binding to device $self->{'device'} $!"); } if ($self->{'tos'}) { - setsockopt($self->{"fh"}, SOL_IP, IP_TOS, pack("I*", $self->{'tos'})) + setsockopt($self->{"fh"}, SOL_IP, IP_TOS(), pack("I*", $self->{'tos'})) or croak "error configuring tos to $self->{'tos'} $!"; } @@ -1526,7 +1509,7 @@ =over 4 -=item Net::Ping->new([$proto [, $def_timeout [, $bytes [, $device [, $tos [, $ttl ]]]]]]); +=item Net::Ping->new([$proto [, $def_timeout [, $bytes [, $device [, $tos ]]]]]); Create a new ping object. All of the parameters are optional. $proto specifies the protocol to use when doing a ping. The current choices @@ -1550,8 +1533,6 @@ If $tos is given, this ToS is configured into the socket. -For icmp, $ttl can be specified to set the TTL of the outgoing packet. - =item $p->ping($host [, $timeout]); Ping the remote host and wait for a response. $host can be either the @@ -1791,6 +1772,6 @@ This program is free software; you may redistribute it and/or modify it under the same terms as Perl itself. -$Id: Ping.pm,v 1.1 2009/09/09 12:36:52 rolek Exp $ +$Id: Ping.pm,v 1.86 2003/06/27 21:31:07 rob Exp $ =cut diff -ruN src/t/520_ping_icmp_ttl.t Net-Ping-2.36/t/520_ping_icmp_ttl.t --- src/t/520_ping_icmp_ttl.t 2009-09-10 09:05:00.000000000 +0200 +++ Net-Ping-2.36/t/520_ping_icmp_ttl.t 1970-01-01 01:00:00.000000000 +0100 @@ -1,59 +0,0 @@ -# Test to perform icmp protocol testing. -# Root access is required. - -BEGIN { - unless (eval "require Socket") { - print "1..0 \# Skip: no Socket\n"; - exit; - } -} - -use Test; -use Net::Ping; -plan tests => 8; - -# Everything loaded fine -ok 1; - -if (($> and $^O ne 'VMS') - or (($^O eq 'MSWin32' or $^O eq 'cygwin') - and !IsAdminUser()) - or ($^O eq 'VMS' - and (`write sys\$output f\$privilege("SYSPRV")` =~ m/FALSE/))) { - skip "icmp ping requires root privileges.", 1; -} elsif ($^O eq 'MacOS') { - skip "icmp protocol not supported.", 1; -} else { - my $p = new Net::Ping ("icmp",undef,undef,undef,undef,undef); - ok $p->ping("127.0.0.1"); - $p->close(); - $p = new Net::Ping ("icmp",undef,undef,undef,undef,0); - ok $p->ping("127.0.0.1"); - $p->close(); - $p = undef(); - $p = eval 'new Net::Ping ("icmp",undef,undef,undef,undef,1)'; - ok(defined($p)); - $p = undef(); - $p = eval 'new Net::Ping ("icmp",undef,undef,undef,undef,-1)'; - ok(!defined($p)); - $p = undef(); - $p = eval 'new Net::Ping ("icmp",undef,undef,undef,undef,256)'; - ok(!defined($p)); - $p = new Net::Ping ("icmp",undef,undef,undef,undef,10); - ok $p->ping("127.0.0.1"); - $p->close(); - $p = new Net::Ping ("icmp",undef,undef,undef,undef,64); - my $pr = $p->ping("www.cpan.org"); - $q = new Net::Ping ("icmp",undef,undef,undef,undef,1); - my $qr = $q->ping("www.cpan.org"); - skip (!$pr, !$qr); - $p->close(); - $q->close(); -} - -sub IsAdminUser { - return unless $^O eq 'MSWin32' or $^O eq "cygwin"; - return unless eval { require Win32 }; - return unless defined &Win32::IsAdminUser; - return Win32::IsAdminUser(); -}
Thanks you for the patch, especially the tests! I couldn't apply the patch directly due to some other changes, but most of your code was used directly. I should have a new release of Net::Ping within the month. For now, you can grab the code from https://github.com/smpeters/net-ping