Net::Frame::Dump::Online2 - tcpdump like implementation, online mode and non-blocking


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

Index


Code Index:

NAME

Top

Net::Frame::Dump::Online2 - tcpdump like implementation, online mode and non-blocking

SYNOPSIS

Top

   use Net::Frame::Dump::Online2;

   #
   # Simply create a Dump object
   #
   my $oDump = Net::Frame::Dump::Online2->new(
      dev => 'eth0',
   );

   $oDump->start;

   # Gather frames
   while (1) {
      if (my $f = $oDump->next) {
         my $raw            = $f->{raw};
         my $firstLayerType = $f->{firstLayer};
         my $timestamp      = $f->{timestamp};
      }
   }

   $oDump->stop;

   #
   # Default parameters on creation
   #
   my $oDumpDefault = Net::Frame::Dump::Online->new(
      dev            => undef,
      timeoutOnNext  => 3,
      timeout        => 0,
      promisc        => 0,
      filter         => '',
      isRunning      => 0,
      keepTimestamp  => 0,
      frames         => [],
   );

DESCRIPTION

Top

This module implements a tcpdump-like program, for live capture from networks.

ATTRIBUTES

Top

dev

The network interface to listen on. No default value.

timeoutOnNext

Each time you call next method, an internal counter is updated. This counter tells you if you have not received any data since timeoutOnNext seconds. When a timeout occure, timeout is set to true.

timeout

When timeoutOnNext seconds has been reached, this variable is set to true, and never reset. See timeoutReset if you want to reset it.

snaplen

If you want to capture a different snaplen, set it a number. Default to 1514.

promisc

By default, interface is not put into promiscuous mode, set this parameter to true if you want it.

The following are inherited attributes:

filter

Pcap filter to use. Default to no filter.

firstLayer

Stores information about the first layer type contained on read frame. This attribute is filled only after a call to start method.

isRunning

Returns true if a call to start has been done, false otherwise or if a call to stop has been done.

keepTimestamp

Sometimes, when frames are captured and saved to a .pcap file, timestamps sucks. That is, you send a frame, and receive the reply, but your request appear to have been sent after the reply. So, to correct that, you can use Net::Frame::Dump own timestamping system. The default is 0. Set it manually to 1 if you need original .pcap frames timestamps.

METHODS

Top

new
new (hash)

Object constructor. You can pass attributes that will overwrite default ones. See SYNOPSIS for default values.

start

When you want to start reading frames from network, call this method.

stop

When you want to stop reading frames from network, call this method.

next

Returns the next captured frame; undef if none awaiting. Each time this method is called, a comparison is done to see if no frame has been captured during timeoutOnNext number of seconds. If so, timeout attribute is set to 1 to reflect the pending timeout.

store (Net::Frame::Simple object)

This method will store internally, sorted, the Net::Frame::Simple object passed as a single parameter. getKey methods, implemented in various Net::Frame::Layer objects will be used to efficiently retrieve (via getKeyReverse method) frames.

Basically, it is used to make recv method (from Net::Frame::Simple) to retrieve quickly the reply frame for a request frame.

getFramesFor (Net::Frame::Simple object)

This will return an array of possible reply frames for the specified Net::Frame::Simple object. For example, reply frames for a UDP probe will be all the frames which have the same source port and destination port as the request.

flush

Will flush stored frames, the one which have been stored via store method.

timeoutReset

Reset the internal timeout state (timeout attribute).

getStats

Tries to get packet statistics on an open descriptor. It returns a reference to a hash that has to following fields: ps_recv, ps_drop, ps_ifdrop.

SEE ALSO

Top

Net::Frame::Dump

AUTHOR

Top

Patrice <GomoR> Auffret

COPYRIGHT AND LICENSE

Top


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

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

use base qw(Net::Frame::Dump);
our @AS = qw(
   dev
   timeoutOnNext
   timeout
   promisc
   snaplen
   _firstTime
);
__PACKAGE__->cgBuildIndices;
__PACKAGE__->cgBuildAccessorsScalar(\@AS);

BEGIN {
   my $osname = {
      cygwin  => [ \&_checkWin32, ],
      MSWin32 => [ \&_checkWin32, ],
   };

   *_check = $osname->{$^O}->[0] || \&_checkOther;
}

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

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

sub _checkWin32 { return 1; }

sub _checkOther {
   if ($>) {
      warn("Must be EUID 0 (or equivalent) to open a device for live ".
           "capture.\n");
      return;
   }
   return 1;
}

sub new {
   my $self = shift->SUPER::new(
      timeoutOnNext => 3,
      timeout       => 0,
      promisc       => 0,
      snaplen       => 1514,
      @_,
   );

   if (!defined($self->dev)) {
      warn("You MUST pass `dev' attribute\n");
      return;
   }

   return $self;
}

sub start {
   my $self = shift;

   _check() or return;

   $self->isRunning(1);

   my $err;
   my $pd = Net::Pcap::open_live(
      $self->dev,
      $self->snaplen,
      $self->promisc,
      100,
      \$err,
   );
   unless ($pd) {
      warn("@{[(caller(0))[3]]}: open_live: $err\n");
      return;
   }

   my $net  = 0;
   my $mask = 0;
   Net::Pcap::lookupnet($self->dev, \$net, \$mask, \$err);
   if ($err) {
      warn("@{[(caller(0))[3]]}: lookupnet: $err\n");
   }

   my $fcode;
   if (Net::Pcap::compile($pd, \$fcode, $self->filter, 0, $mask) < 0) {
      warn("@{[(caller(0))[3]]}: compile: ". Net::Pcap::geterr($pd). "\n");
      return;
   }

   if (Net::Pcap::setfilter($pd, $fcode) < 0) {
      warn("@{[(caller(0))[3]]}: setfilter: ". Net::Pcap::geterr($pd). "\n");
      return;
   }

   my $r = Net::Pcap::setnonblock($pd, 1, \$err);
   if ($r == -1) {
      warn("@{[(caller(0))[3]]}: setnonblock: $err\n");
      return;
   }

   $self->_pcapd($pd);
   $self->getFirstLayer;

   #$SIG{INT}  = sub { $self->_printStats };
   #$SIG{TERM} = sub { $self->_printStats };
   #$self->cgDebugPrint(1, "dev:    [@{[$self->dev]}]\n".
                          #"file:   [@{[$self->file]}]\n".
                          #"filter: [@{[$self->filter]}]");

   return 1;
}

sub stop {
   my $self = shift;

   if (!$self->isRunning) {
      return;
   }

   Net::Pcap::close($self->_pcapd);
   $self->_pcapd(undef);
   $self->isRunning(0);

   return 1;
}

sub getStats {
   my $self = shift;

   if (!defined($self->_pcapd)) {
      carp("@{[(caller(0))[3]]}: unable to get stats, no pcap descriptor ".
           "opened.\n");
      return;
   }

   my %stats;
   Net::Pcap::stats($self->_pcapd, \%stats);
   return \%stats;
}

sub _printStats {
   my $self = shift;

   my $stats = $self->getStats;
   Net::Pcap::close($self->_pcapd);

   $self->cgDebugPrint(1, 'Frames received  : '.$stats->{ps_recv});
   $self->cgDebugPrint(1, 'Frames dropped   : '.$stats->{ps_drop});
   $self->cgDebugPrint(1, 'Frames if dropped: '.$stats->{ps_ifdrop});

   return 1;
}

sub _getNextAwaitingFrame {
   my $self = shift;
   return $self->nextEx;
}

sub _nextTimeoutHandle {
   my $self = shift;

   # Handle timeout
   my $thisTime = gettimeofday();
   if ($self->timeoutOnNext && !$self->_firstTime) {
      $self->_firstTime($thisTime);
   }

   if ($self->timeoutOnNext && $self->_firstTime) {
      if (($thisTime - $self->_firstTime) > $self->timeoutOnNext) {
         $self->timeout(1);
         $self->_firstTime(0);
         $self->cgDebugPrint(1, "Timeout occured");
         return;
      }
   }

   return 1;
}

sub _nextTimeoutReset { shift->_firstTime(0) }

sub timeoutReset { shift->timeout(0) }

sub next {
   my $self = shift;

   $self->_nextTimeoutHandle or return;

   my $frame = $self->_getNextAwaitingFrame;
   $self->_nextTimeoutReset if $frame;

   return $frame;
}

1;

__END__