Posted on 2005-09-06 13:12:15-07 by zak
trying to make ping echo req script without Net::Ping ..and problem

hi..

im trying to make icmp script (send echo req and hopes there's a reply from alive host) with this script :

use Socket; use strict; socket(SOCK,PF_INET,SOCK_RAW,getprotobyname('icmp')) || die $!; my $checksum = 0; use constant ICMP_ECHOREPLY => 0; use constant ICMP_ECHO => 8; use constant ICMP_STRUCT => "C2 n3 A0"; use constant SUBCODE => 0; use constant ICMP_FLAGS => 0; use constant ICMP_PORT => 0; my $seq=1; my $data= ""; my $msg = pack(ICMP_STRUCT,ICMP_ECHO,SUBCODE,$checksum,$$,$seq,$data); my $chks = &ceksum($msg); $msg = pack(ICMP_STRUCT,ICMP_ECHO,SUBCODE,$chks,$$,$seq,$data); my $host = sockaddr_in(ICMP_PORT,inet_aton('192.168.0.1')); send(SOCK,$msg,ICMP_FLAGS,$host) || warn "$! \n"; sub ceksum { my ($msg) = @_; my ($len_msg,$num_short,$short,$chk); $len_msg = length($msg); $num_short =int($len_msg/2); $chk = 0; foreach $short(unpack("n$num_short", $msg)) { $chk += $short; } $chk +=(unpack("C",substr($msg,$len_msg-1,1)) << 8) if $len_msg % 2; $chk = ($chk >> 16) + ($chk & 0xffff); return(~(($chk >> 16) + $chk) & 0xffff); }

too bad this script is working fine FOR LOCALHOST ONLY.

so i read ping.pm from Net::Ping, i made a lil change to this pm file (dont laugh please), so ping.pm looks like this :

package Net::Ping; use strict; use Socket; ping_icmp(); use constant ICMP_ECHOREPLY => 0; # 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 use constant ICMP_FLAGS => 0; # No special flags for send or recv use constant ICMP_PORT => 0; # No port with ICMP sub ping_icmp { my ($ip) = inet_aton('192.168.0.1'); my ($saddr, # sockaddr_in with port and ip $checksum, # Checksum of ICMP packet $msg, # ICMP packet to send $len_msg, # Length of $msg $ret, # Return value ); my $seq = 1; my $pid = 5000; $checksum = 0; # No checksum for starters my $data= ""; $msg = pack(ICMP_STRUCT . 0, ICMP_ECHO, SUBCODE, $checksum, $pid, $seq, $data); $checksum =checksum($msg); $msg = pack(ICMP_STRUCT . 0, ICMP_ECHO, SUBCODE, $checksum, $pid, $seq, $data); $len_msg = length($msg); $saddr = sockaddr_in(ICMP_PORT, $ip); socket(SOCK,PF_INET,SOCK_RAW,getprotobyname('icmp')); send(SOCK,$msg,ICMP_FLAGS,$saddr); return $ret; } # Description: Do a checksum on the message. Basically sum all of # the short words and fold the high order bits into the low order bits. sub checksum { my ( $msg # The message to checksum ) = @_; my ($len_msg, # Length of the message $num_short, # The number of short words in the message $short, # One short word $chk # The checksum ); $len_msg = length($msg); $num_short = int($len_msg / 2); $chk = 0; foreach $short (unpack("n$num_short", $msg)) { $chk += $short; } # Add the odd byte in $chk += (unpack("C", substr($msg, $len_msg - 1, 1)) << 8) if $len_msg % 2; $chk = ($chk >> 16) + ($chk & 0xffff); # Fold high into low return(~(($chk >> 16) + $chk) & 0xffff); # Again and complement } 1;

and then i make a lil script (named ping1.pl) with codes like this :

require 'ping.pm'; $host=shift; $p = Net::Ping->new('icmp'); print "$host is alive \n" if $p->ping($host);

so i executed this ping1.pl and its work fine, 192.168.0.1's detected by this ping1.pl.

and my question is : is there a way to change this modified ping.pm to pl file (example : ping.pl) ?

i tried to rename ping.pm to ping.pl and commented out 'package Net::Ping', and then execute this ping.pl but there's an error.. i mean.. yea this ping.pl still send single icmp packet to 192.168.0.1 but the checksum was error ? do u know why (remember the code of ping.pm and ping.pl is still the same) ?

im not sure if this place is a right place to post my problem, and sorry for my english, i'll ask my friend to translate my prob for better english....

regs

zac

Direct Responses: Write a response
Perl Weekly newsletter
A free weekly newsletter for people who are busy to read all the blogs. click here to check it out.