c - UDP Checksum Function in Perl -
i have searched need function calculate udp header checksum in perl.
i find function in c: http://www.netfor2.com/udpsum.htm don't know how use , try convert perl not managed
this try:
sub udp_checksum(my $len_udp, @src_addr, @dest_addr, $padding, @buff) { $proto_udp = 17; $padd = 0; $word16; $sum; # find out if length of data or odd number. if odd, # add padding byte = 0 @ end of packet if ($padding&1==1){ $padd = 1; $buff[$len_udp] = 0; } # initialize sum 0 $sum = 0; # make 16 bit words out of every 2 adjacent 8 bit words , # calculate sum of 16 bit words (my $i = 0; $i < $len_udp + $padd; $i = $i + 2){ $word16 =(($buff[i] << 8) & 0xff00) + ($buff[i+1] & 0xff); $sum = $sum + $word16; } # add udp pseudo header contains ip source , destinationn addresses (my $i = 0; $i < 4; $i = $i + 2){ $word16 =(($src_addr[i] << 8) & 0xff00) + ($src_addr[i+1] & 0xff); $sum = $sum + $word16; } (my $i = 0; $i < 4; $i = $i + 2){ $word16 =(($dest_addr[i] << 8) & 0xff00) + ($dest_addr[i+1] & 0xff); $sum = $sum + $word16; } # protocol number , length of udp packet $sum = $sum + $prot_udp + $len_udp; # keep last 16 bits of 32 bit calculated sum , add carries while ($sum >> 16){ $sum = ($sum & 0xffff) + ($sum >> 16); } # take one's complement of sum $sum = ~$sum; return $sum; } please me.
use list::util qw( sum ); use socket qw( ipproto_udp ); sub udp_checksum { $packed_src_addr = shift; # 4-char string, e.g. returned inet_aton. $packed_dst_addr = shift; # 4-char string, e.g. returned inet_aton. $udp_packet = shift; # udp header , data string. $sum = sum( ipproto_udp, length($udp_packet), map({ unpack('n*', $_) } $packed_src_addr, $packed_dst_addr, $udp_packet."\0", # byte ignored if length($udp_packet) even. ), ); while (my $hi = $sum >> 16) { $sum = ($sum & 0xffff) + $hi; } return ~$sum & 0xffff; } to build udp packet,
my $udp_packet = pack('nnnna*', $src_port, $dst_port, 8+length($body), 0, $body); $checksum = udp_checksum($packed_src_addr, $packed_dst_addr, $udp_packet); substr($udp_packet, 6, 2, pack('n', $checksum)); to verify udp packet's checksum,
udp_checksum($packed_src_addr, $packed_dst_addr, $udp_packet) , die("invalid checksum\n"); example:
#!/usr/bin/perl use strict; use socket; use warnings; use list::util qw(sum); use socket qw(ipproto_udp); use socket qw(inet_aton); main(); sub main { $src_port = 27005; $dst_port = 27015; $body = pack("h*", "92380000621f008063d5179000927df3a2e09bf319a66bf300c239aa9393d8eaa244119a"); $packed_src_addr = inet_aton("156.215.205.76"); $packed_dst_addr = inet_aton("31.186.251.163"); $udp_packet = pack('nnnna*', $src_port, $dst_port, 8+length($body), 0, $body); $checksum = udp_checksum($packed_src_addr, $packed_dst_addr, $udp_packet); print "\n\nudp checksum: $checksum\n\n"; } sub udp_checksum { $packed_src_addr = shift; # 4-char string, e.g. returned inet_aton. $packed_dst_addr = shift; # 4-char string, e.g. returned inet_aton. $udp_packet = shift; # udp header , data string. $sum = sum( ipproto_udp, length($udp_packet), map({ unpack('n*', $_) } $packed_src_addr, $packed_dst_addr, $udp_packet."\0", # byte ignored if length($udp_packet) even. ), ); while (my $hi = $sum >> 16) { $sum = ($sum & 0xffff) + $hi; } return ~$sum & 0xffff; }
Comments
Post a Comment