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

Dear Monks,

Please enlighten me about Net::Ping.

Here's my script:
#!/usr/bin/perl -w use strict; use Net::Ping; use Getopt::Std; my $protocal = "icmp"; my $network = "user must enter"; my $start = 0; my $end = 255; my $timeOut = 1; use vars qw/ $opt_p $opt_N $opt_S $opt_E $opt_T $opt_h/; getopt( "p:N:S:E:T:h" ); if( $opt_p ) {$protocal = $opt_p;} if( $opt_N ) {$network = $opt_N} else { &usage(); exit(); } if( $opt_S ) {$start = $opt_S} if( $opt_E ) {$end = $opt_E} if( $opt_T ) {$timeOut = $opt_T} if( $opt_h ) {&useage(); exit();} my $p = Net::Ping->new($protocal,$timeOut); for(my $node=$start; $node<$end; $node++){ my $address = "$network.$node"; print $address,($p->ping($address) ? ' is alive' : ' is not alive' +),"\n"; } $p->close(); sub usage { print<<DOIT; $0 -N<network> [-p<protocal>][-S<start>][-E<end>][-T<timeout>][-h] network actually first 3 octects of an IP address protocal can be icmp, tcp or udp default is icmp start default 0 end default 255 timeout default 1 DOIT }

I have been executing it on a NT system from a cygwin bash
shell (if that makes a difference)

Here's the output from various runs of the script:
$ ./ping.pl -N 123.321.12 -ptcp 123.321.12.0 is not alive 123.321.12.1 is not alive ^C // script seemed to hang $ ./ping.pl -N 123.321.12 -pudp 123.321.12.0 is not alive 123.321.12.1 is not alive 123.321.12.2 is not alive 123.321.12.3 is not alive 123.321.12.4 is not alive 123.321.12.5 is not alive 123.321.12.6 is not alive 123.321.12.7 is not alive ... 123.321.12.254 is not alive $ ./ping.pl -N 123.321.12 icmp ping requires root privilege at ./ping.pl line 21

My questions:

1) Why did ping.pl -N 123.321.12 -ptcp hang?
2) Why didn't ping.pl -N 123.321.12 -pudp not ping anything?
3) Why did ping.pl -N 123.321.12 get that error message?

I don't know much ... about networks :)

Replies are listed 'Best First'.
Re: Why does Net::Ping behave this way?
by Fletch (Bishop) on Apr 02, 2002 at 23:21 UTC

    The TCP and UDP pings require the echo service to be running. Most security concious folk will have this disabled by default (or probably blocked at a firewall) as it serves no real useful purpose (other than for people using Net::Ping :).

    To answer the questions, in the first case the TCP connection probably hit a real machine with no TCP echo service running (which promptly returned something telling your TCP stack that a connection couldn't be made). Then it hit an address that was either firewalled or not there, so it didn't hang in as much as it was waiting for the connection to be established (most implementations will wait about 2 minutes before returning an error in this case).

    In the second case, there probably was nothing running a UDP echo service so you saw no replies (or a firewall was dropping all UDP traffic).

    As for the final case, the error message sums it up: you were trying to do something that requires root privledges on most real OSen. Sending ICMP traffic requires access to a raw network socket, which means you can pretty much send whatever packets you'd like (meaning you could inject spoofed traffic onto the network). J Random User isn't allowed to do this (which is a good thing). You'd need to run the program as root (or have it setuid to root; in which case you'd need to be aware of the security implications that brings :) in order for it to work. If you look at your system's ping utility you'll see that it's setuid to root.

      Thanks for the info Fletch.
      I found this node, 24583, out there you might find it interesting
      too. As it seems to be a work around for icmp problem
      I was having without having to setuid.
Re: Why does Net::Ping behave this way?
by gav^ (Curate) on Apr 02, 2002 at 23:39 UTC
    Net::Ping::External is a nifty module which tries to make running the ping command somewhat cross platform.

    gav^

(tye)Re: Why does Net::Ping behave this way?
by tye (Sage) on Apr 03, 2002 at 20:58 UTC
Re: Why does Net::Ping behave this way?
by brianarn (Chaplain) on Apr 03, 2002 at 19:37 UTC
    Fletch gave an excellent response, so I'll leave it at that.

    However, in the interest of promoting Good Coding Practices ©, I'd make a few subtle comments about the code.
    • Personally, I like using Getopt::Long versus Getopt::Std, as it allows for more verbose options and short ones together.
    • Look into Pod::Usage, which is part of the core set of modules. It comes with a pod2usage function that allows you to write POD at the end of your file, and then present it at various levels of verbosity, including an error message if you desire. For such a short script, it might be a bit of overkill, but in a lot of cases, short scripts tend to grow up, and putting in a good solid foundation really allows for one's code to grow nicely, rather than being deliquent hackery.
    • Your for loop will iterate from 0 to 254, not 0 to 255. The conditional is that current is less than end, and end is 255, so technically it'll never do the 255th IP.
    =)

    ~Brian