Net-Frame-Layer-ICMPv6
view release on metacpan or search on metacpan
lib/Net/Frame/Layer/ICMPv6.pm view on Meta::CPAN
my $ip;
my $rh0;
my $hbh; # Hop-by-hop Ext Hdr
my $dst; # Destination Ext Hdr
my $mob; # Mobility Ext Hdr
my $lastNextHeader;
my $fragmentFlag = 0;
my $start = 0;
my $last = $self;
my $payload = '';
for my $l (@$layers) {
if (! $ip && $l->layer eq 'IPv6') { $ip = $l; }
if (! $rh0 && $l->layer eq 'IPv6::Routing') { $rh0 = $l; }
if (! $hbh && $l->layer eq 'IPv6::HopByHop') { $hbh = $l; }
if (! $dst && $l->layer eq 'IPv6::Destination') { $dst = $l; }
if (! $mob && $l->layer eq 'IPv6::Mobility') { $mob = $l; }
if ($l->can('nextHeader')) { $lastNextHeader = $l->nextHeader; }
if ($l->layer eq 'IPv6::Fragment') { $fragmentFlag = 1; }
$last = $l;
if (! $start) {
$start++ if $l->layer eq 'ICMPv6';
next;
}
$payload .= $l->pack;
}
my $lastIpDst = $ip->dst;
my $ipPayloadLength = $ip->payloadLength;
# If RH0, need to set $ip->dst to last $rh0->addresses
# unless segmentsLeft == 0 (RFC 2460 sec 8.1)
if ($rh0 && $rh0->segmentsLeft != 0) {
for ($rh0->addresses) {
$lastIpDst = $_;
}
# Pseudo header length is upper layer minus any EH (RFC 2460 sec 8.1)
$ipPayloadLength -= $rh0->getLength;
}
# Pseudo header length is upper layer minus any EH (RFC 2460 sec 8.1)
if ($fragmentFlag) {
$ipPayloadLength -= 8; # 8 = length of fragment EH
}
if ($hbh) {
$ipPayloadLength -= $hbh->getLength;
}
if ($dst) {
$ipPayloadLength -= $dst->getLength;
}
if ($mob) {
$ipPayloadLength -= $mob->getLength;
}
# Build pseudo-header and pack ICMPv6 packet
my $zero = Bit::Vector->new_Dec(24, 0);
my $nextHeader = Bit::Vector->new_Dec( 8, $lastNextHeader);
my $v32 = $zero->Concat_List($nextHeader);
my $packed = $self->SUPER::pack('a*a*NNCCn',
inet6Aton($ip->src), inet6Aton($lastIpDst), $ipPayloadLength,
$v32->to_Dec, $self->type, $self->code, 0
) or return;
if (defined($last->payload) && length($last->payload)) {
$payload .= $last->payload;
}
if (length($payload)) {
$packed .= $self->SUPER::pack('a*', $payload)
or return;
}
$self->checksum(inetChecksum($packed));
return 1;
}
sub encapsulate {
my $self = shift;
return $self->nextLayer if $self->nextLayer;
if ($self->payload) {
my $type = $self->type;
# if ($type eq NF_ICMPv6_TYPE_REDIRECT) {
# return 'IPv6';
# }
if ($type eq NF_ICMPv6_TYPE_ECHO_REQUEST
|| $type eq NF_ICMPv6_TYPE_ECHO_REPLY) {
return 'ICMPv6::Echo';
}
elsif ($type eq NF_ICMPv6_TYPE_NEIGHBORSOLICITATION) {
return 'ICMPv6::NeighborSolicitation';
}
elsif ($type eq NF_ICMPv6_TYPE_NEIGHBORADVERTISEMENT) {
return 'ICMPv6::NeighborAdvertisement';
}
elsif ($type eq NF_ICMPv6_TYPE_ROUTERSOLICITATION) {
return 'ICMPv6::RouterSolicitation';
}
elsif ($type eq NF_ICMPv6_TYPE_ROUTERADVERTISEMENT) {
return 'ICMPv6::RouterAdvertisement';
}
elsif ($type eq NF_ICMPv6_TYPE_DESTUNREACH) {
return 'ICMPv6::DestUnreach';
}
elsif ($type eq NF_ICMPv6_TYPE_TIMEEXCEED) {
return 'ICMPv6::TimeExceed';
}
elsif ($type eq NF_ICMPv6_TYPE_TOOBIG) {
return 'ICMPv6::TooBig';
}
elsif ($type eq NF_ICMPv6_TYPE_PARAMETERPROBLEM) {
return 'ICMPv6::ParameterProblem';
}
elsif ($type eq NF_ICMPv6_TYPE_MLDQUERY
|| $type eq NF_ICMPv6_TYPE_MLDREPORTv1
|| $type eq NF_ICMPv6_TYPE_MLDDONE) {
return 'ICMPv6::MLD';
}
elsif ($type eq NF_ICMPv6_TYPE_MLDREPORTv2) {
( run in 0.568 second using v1.01-cache-2.11-cpan-39bf76dae61 )