doctor_moron has asked for the wisdom of the Perl Monks concerning the following question:
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"; use constant SUBCODE => 0; use constant ICMP_FLAGS => 0; use constant ICMP_PORT => 0; my $seq=1; my $msg = pack(ICMP_STRUCT,ICMP_ECHO,SUBCODE,$checksum,$$,$seq); my $chks = &ceksum($msg); $msg = pack(ICMP_STRUCT,ICMP_ECHO,SUBCODE,$chks,$$,$seq); 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); }
##Update-2##
Since i have no idea why this script wont work in my LAN, i asked someone in yahoo chat (thanks Chad_Lewis_89 for your time) to test it, and he said the script's working fine.
I re-checked all lines in this code, and seems its fine, so i remade a script (shorter than before), here's the code:
use Socket; socket(SOCK,PF_INET,SOCK_RAW,getprotobyname('icmp')) || die "Error: $! +\n"; $msg = pack("C2 n3",8,0,32127,0,1); print "the value of checksum is:", unpack('H4', pack('n',32127)), "\n" +; print "[And you should see this in your tcpdump -i lo icmp -xxx]\n"; send(SOCK,$msg,0,sockaddr_in(0,inet_aton('localhost'))) || die "Error: + $! \n";
As you can see, there's no subroutine to calculate checksum, yea, because im going to try it to LOCALHOST and as far as i know, no 'valid checksum' needed for localhost (so i add 32127 for checksum).
I ran this script, i got the response (echo reply) and i can see '32127' or '0x7d7f' (in hex) in tcpdump, here's tcpdump log :
01:55:23.930771 zacko > zacko: icmp: echo request (DF)
4500 001c 0000 4000 4001 3cdf 7f00 0001
7f00 0001 0800 7d7f 0000 0001
01:55:23.930852 zacko > zacko: icmp: echo reply
4500 001c cbff 0000 4001 b0df 7f00 0001
7f00 0001 0000 fffe 0000 0001
everything's work normal.
let's try to change the checksum value, change all 32127 (in code above) to 32128, well i still got the response (echo reply), but when i look closer into tcpdump log, i feel something wrong there, there's no 32128 or '0x7d80' (in hex) , here's tcpdump log :
02:09:11.912392 zacko > zacko: icmp: echo request (DF)
4500 001d 0000 4000 4001 3cde 7f00 0001
7f00 0001 0800 7dc2 8000 0000 01
02:09:11.912502 zacko > zacko: icmp: echo reply
4500 001d cc01 0000 4001 b0dc 7f00 0001
7f00 0001 0000 7eff 8000 0000 01
There's no 0x7d80 but 7dc2 (and i think 7dc2 is 32194).
If ICMP_ECHO=8, SUBCODE=0, $pid=0, and $seq=1, and then we pass these variables to subroutine checksum, we'll get 63486, and of course if i send icmp packet to another host, with checksum value=63486, i'll get no response back (as long as checksum value > 32127).
Well, i have no idea, what's going on here, by the way, i am using celeron 300 233 Mhz, 64 MB SDRAM, 1.2 GB Hdd, and my pc's screwed up, everytime this pc turned on, i need to go to BIOS setup
My OS's Redhat Fedora 2.0.20-8, libcap version 0.7.2
##EndOfUpdate-2##
##update-3##
The problem is SOLVED when i switched to SuSe, with kernel 2-4-21.99
##EndOfUpdate-3##
I wish, i can explain this problem in better english, i'll ask my friend to translate this question :[
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: icmp code, w/o Net::Ping and problem
by InfiniteSilence (Curate) on Aug 31, 2005 at 21:23 UTC | |
|
Re: icmp code, w/o Net::Ping and problem
by merlyn (Sage) on Aug 31, 2005 at 21:19 UTC | |
by doctor_moron (Scribe) on Sep 01, 2005 at 02:29 UTC | |
by Knom (Beadle) on Sep 02, 2005 at 03:58 UTC | |
by doctor_moron (Scribe) on Sep 10, 2005 at 10:59 UTC |