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 )