我已经搜索了很多我需要函数来计算Perl中的UDP头校验和。
我在C中找到了这个函数:http://www.netfor2.com/udpsum.htm 但我不知道如何使用它,我尝试将其转换为Perl但不管理
这是我尝试的:
sub udp_checksum(my $len_udp, my @src_addr, my @dest_addr, my $padding, my @buff)
{
my $proto_udp = 17;
my $padd = 0;
my $word16;
my $sum;
# Find out if the length of data is even or odd number. If odd,
# add a padding byte = 0 at the end of packet
if ($padding&1==1){
$padd = 1;
$buff[$len_udp] = 0;
}
# initialize sum to zero
$sum = 0;
# make 16 bit words out of every two adjacent 8 bit words and
# calculate the sum of all 16 bit words
for (my $i = 0; $i < $len_udp + $padd; $i = $i + 2){
$word16 =(($buff[i] << 8) & 0xFF00) + ($buff[i+1] & 0xFF);
$sum = $sum + $word16;
}
# add the UDP pseudo header which contains the IP source and destinationn addresses
for (my $i = 0; $i < 4; $i = $i + 2){
$word16 =(($src_addr[i] << 8) & 0xFF00) + ($src_addr[i+1] & 0xFF);
$sum = $sum + $word16;
}
for (my $i = 0; $i < 4; $i = $i + 2){
$word16 =(($dest_addr[i] << 8) & 0xFF00) + ($dest_addr[i+1] & 0xFF);
$sum = $sum + $word16;
}
# the protocol number and the length of the UDP packet
$sum = $sum + $prot_udp + $len_udp;
# keep only the last 16 bits of the 32 bit calculated sum and add the carries
while ($sum >> 16){
$sum = ($sum & 0xFFFF) + ($sum >> 16);
}
# Take the one's complement of sum
$sum = ~$sum;
return $sum;
}
请帮帮我。
答案 0 :(得分:4)
use List::Util qw( sum );
use Socket qw( IPPROTO_UDP );
sub udp_checksum {
my $packed_src_addr = shift; # As 4-char string, e.g. as returned by inet_aton.
my $packed_dst_addr = shift; # As 4-char string, e.g. as returned by inet_aton.
my $udp_packet = shift; # UDP header and data as a string.
my $sum = sum(
IPPROTO_UDP,
length($udp_packet),
map({ unpack('n*', $_) }
$packed_src_addr,
$packed_dst_addr,
$udp_packet."\0", # Extra byte ignored if length($udp_packet) is even.
),
);
while (my $hi = $sum >> 16) {
$sum = ($sum & 0xFFFF) + $hi;
}
return ~$sum & 0xFFFF;
}
构建UDP数据包
my $udp_packet = pack('nnnna*', $src_port, $dst_port, 8+length($body), 0, $body);
my $checksum = udp_checksum($packed_src_addr, $packed_dst_addr, $udp_packet);
substr($udp_packet, 6, 2, pack('n', $checksum));
验证UDP数据包的校验和,
udp_checksum($packed_src_addr, $packed_dst_addr, $udp_packet)
and die("Invalid checksum\n");
示例:
#!/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 {
my $src_port = 27005;
my $dst_port = 27015;
my $body = pack("H*", "92380000621f008063d5179000927df3a2e09bf319a66bf300c239aa9393d8eaa244119a");
my $packed_src_addr = inet_aton("156.215.205.76");
my $packed_dst_addr = inet_aton("31.186.251.163");
my $udp_packet = pack('nnnna*', $src_port, $dst_port, 8+length($body), 0, $body);
my $checksum = udp_checksum($packed_src_addr, $packed_dst_addr, $udp_packet);
print "\n\nUDP Checksum: $checksum\n\n";
}
sub udp_checksum {
my $packed_src_addr = shift; # As 4-char string, e.g. as returned by inet_aton.
my $packed_dst_addr = shift; # As 4-char string, e.g. as returned by inet_aton.
my $udp_packet = shift; # UDP header and data as a string.
my $sum = sum(
IPPROTO_UDP,
length($udp_packet),
map({ unpack('n*', $_) }
$packed_src_addr,
$packed_dst_addr,
$udp_packet."\0", # Extra byte ignored if length($udp_packet) is even.
),
);
while (my $hi = $sum >> 16) {
$sum = ($sum & 0xFFFF) + $hi;
}
return ~$sum & 0xFFFF;
}