Net::Frame::Dump - base-class for a tcpdump like implementation


Net-Frame-Dump documentation Contained in the Net-Frame-Dump distribution.

Index


Code Index:

NAME

Top

Net::Frame::Dump - base-class for a tcpdump like implementation

DESCRIPTION

Top

Net::Frame::Dump is the base class for all dump modules. With them, you can open a device for live capture, for offline analysis, or for creating a pcap file.

See Net::Frame::Dump::Offline, Net::Frame::Dump::Online, Net::Frame::Dump::Writer for specific usage.

METHODS

Top

new (%h)

Base-class object constructor.

CONSTANTS

Top

Load them: use Net::Frame::Dump qw(:consts);

NF_DUMP_LAYER_NULL
NF_DUMP_LAYER_ETH
NF_DUMP_LAYER_RAW
NF_DUMP_LAYER_SLL
NF_DUMP_LAYER_PPP
NF_DUMP_LAYER_80211_RADIOTAP
NF_DUMP_LAYER_80211

Various supported link layers.

SEE ALSO

Top

Net::Frame::Dump::Online, Net::Frame::Dump::Offline, Net::Frame::Dump::Writer

AUTHOR

Top

Patrice <GomoR> Auffret

COPYRIGHT AND LICENSE

Top


Net-Frame-Dump documentation Contained in the Net-Frame-Dump distribution.

#
# $Id: Dump.pm 349 2011-03-26 13:12:44Z gomor $
#
package Net::Frame::Dump;
use strict;
use warnings;

our $VERSION = '1.09';

use base qw(Class::Gomor::Array Exporter);

our %EXPORT_TAGS = (
   consts => [qw(
      NF_DUMP_LAYER_NULL
      NF_DUMP_LAYER_ETH
      NF_DUMP_LAYER_RAW
      NF_DUMP_LAYER_SLL
      NF_DUMP_LAYER_PPP
      NF_DUMP_LAYER_80211_RADIOTAP
      NF_DUMP_LAYER_80211
      NF_DUMP_LAYER_ERF
   )],
);
our @EXPORT_OK = (
   @{$EXPORT_TAGS{consts}},
);

use constant NF_DUMP_LAYER_NULL           => 0;
use constant NF_DUMP_LAYER_ETH            => 1;
use constant NF_DUMP_LAYER_PPP            => 9;
use constant NF_DUMP_LAYER_RAW            => 12;
use constant NF_DUMP_LAYER_80211          => 105;
use constant NF_DUMP_LAYER_SLL            => 113;
use constant NF_DUMP_LAYER_80211_RADIOTAP => 127;
use constant NF_DUMP_LAYER_ERF            => 175;

our @AS = qw(
   file
   filter
   overwrite
   firstLayer
   isRunning
   keepTimestamp
   _framesStored
   _pcapd
   _dumper
);
our @AA = qw(
   frames
);
__PACKAGE__->cgBuildIndices;
__PACKAGE__->cgBuildAccessorsScalar(\@AS);
__PACKAGE__->cgBuildAccessorsArray(\@AA);

use Carp;
use Net::Pcap;
use Time::HiRes qw(gettimeofday);
use Net::Frame::Layer qw(:consts :subs);

sub new {
   my $self = shift->SUPER::new(
      filter        => '',
      overwrite     => 0,
      isRunning     => 0,
      keepTimestamp => 0,
      frames        => [],
      _framesStored => {},
      @_,
   );

   if (!defined($self->file)) {
      my $int = getRandom32bitsInt();
      $self->file("netframe-tmp-$$.$int.pcap");
   }

   return $self;
}

sub flush {
   my $self = shift;
   $self->frames([]);
   $self->_framesStored({});
}

sub _addStore {
   my $self = shift;
   my ($oSimple) = @_;

   # If parameter, we store it
   if ($oSimple) {
      my $key = $oSimple->getKey;
      push @{$self->_framesStored->{$key}}, $oSimple;

      # If it is ICMPv4, we store a second time
      if (exists $oSimple->ref->{ICMPv4}) {
         push @{$self->_framesStored->{$oSimple->ref->{ICMPv4}->getKey}},
            $oSimple;
      }
   }

   # We return the hash ref
   return $self->_framesStored;
}

sub store {
   my $self = shift;
   my ($oSimple) = @_;

   $self->_addStore($oSimple);

   my @frames = $self->frames;
   push @frames, $oSimple;
   return $self->frames(\@frames);
}

sub _getTimestamp {
   my $self = shift;
   my ($hdr) = @_;
   $hdr->{tv_sec}.'.'.sprintf("%06d", $hdr->{tv_usec});
}

sub _setTimestamp {
   my $self = shift;
   my @time = Time::HiRes::gettimeofday();
   $time[0].'.'.sprintf("%06d", $time[1]);
}

my $mapLinks = {
   NF_DUMP_LAYER_NULL()           => 'NULL',
   NF_DUMP_LAYER_ETH()            => 'ETH',
   NF_DUMP_LAYER_RAW()            => 'RAW',
   NF_DUMP_LAYER_SLL()            => 'SLL',
   NF_DUMP_LAYER_PPP()            => 'PPP',
   NF_DUMP_LAYER_80211()          => '80211',
   NF_DUMP_LAYER_80211_RADIOTAP() => '80211::Radiotap',
   NF_DUMP_LAYER_ERF()            => 'ERF',
};

sub getFirstLayer {
   my $self = shift;
   my $link = Net::Pcap::datalink($self->_pcapd);
   $self->firstLayer($mapLinks->{$link} || NF_LAYER_UNKNOWN);
}

sub next {
   my $self = shift;

   my %hdr;
   if (my $raw = Net::Pcap::next($self->_pcapd, \%hdr)) {
      my $ts = $self->keepTimestamp ? $self->_getTimestamp(\%hdr)
                                    : $self->_setTimestamp;
      return {
         firstLayer => $self->firstLayer,
         timestamp  => $ts,
         raw        => $raw,
      };
   }

   return;
}

sub nextEx {
   my $self = shift;

   my %hdr;
   my $raw;
   my $r;
   if ($r = Net::Pcap::next_ex($self->_pcapd, \%hdr, \$raw) > 0) {
      my $ts = $self->keepTimestamp ? $self->_getTimestamp(\%hdr)
                                    : $self->_setTimestamp;
      return {
         firstLayer => $self->firstLayer,
         timestamp  => $ts,
         raw        => $raw,
      };
   }

   return $r;
}

sub getFramesFor {
   my $self = shift;
   my ($oSimple) = @_;

   my $results;
   my $key = $oSimple->getKeyReverse;
   push @$results, @{$self->_framesStored->{$key}}
      if exists $self->_framesStored->{$key};

   # Add also ICMPv4
   if (exists $self->_framesStored->{ICMPv4}) {
      push @$results, @{$self->_framesStored->{ICMPv4}};
   }

   return $results ? @$results : ();
}

1;

__END__