@@ -0,0 +1,27 @@
+#
+# $Id: Build.PL 363 2014-11-30 11:23:39Z gomor $
+#
+use strict;
+use warnings;
+
+use Module::Build;
+
+my $builder = Module::Build->new(
+ module_name => 'Net::Frame::Dump',
+ license => 'artistic',
+ dist_author => 'GomoR <gomor-cpan_at_gomor.org>',
+ dist_version_from => 'lib/Net/Frame/Dump.pm',
+ requires => {
+ 'perl' => '5.6.1',
+ 'Class::Gomor' => '1.00',
+ 'Net::Pcap' => '0.12',
+ 'Net::Frame' => 0,
+ 'Time::HiRes' => 0,
+ 'IO::Select' => 0,
+ },
+ configure_requires => {
+ 'Module::Build' => 0,
+ },
+);
+
+$builder->create_build_script;
@@ -1,5 +1,14 @@
Revision history for Perl extension Net::Frame::Dump.
+1.14 Tue Dec 9 19:12:25 CET 2014
+ - BUGFIX: Dump::Online2: do not eat 100% and do not block for timeoutOnNext
+ seconds when it is not REALLY needed. We had to remove the
+ setnonblock option and to use pcap_dispatch i/o pcap_next_ex.
+ This should be the final bugfix...
+ There was also an infinite loop condition.
+ - new: Dump::Online2: maxRunTime() option to stop looping on next() forever
+ when we do not want. Default to loop forever.
+
1.13 Sun Dec 2 15:44:14 CET 2012
- BUGFIX: Dump::Online2: in non-blocking mode, we must handle our internal
received frame ring buffer. Many packets were missed because of
@@ -1,3 +1,4 @@
+Build.PL
Changes
LICENSE
LICENSE.Artistic
@@ -19,5 +20,5 @@ lib/Net/Frame/Dump/Writer.pm
t/01-use.t
t/02-pod-coverage.t
t/03-test-pod.t
-META.yml Module YAML meta-data (added by MakeMaker)
-META.json Module JSON meta-data (added by MakeMaker)
+META.yml
+META.json
@@ -4,7 +4,7 @@
"GomoR <gomor-cpan_at_gomor.org>"
],
"dynamic_config" : 1,
- "generated_by" : "ExtUtils::MakeMaker version 6.62, CPAN::Meta::Converter version 2.112150",
+ "generated_by" : "Module::Build version 0.421",
"license" : [
"artistic_1"
],
@@ -13,34 +13,46 @@
"version" : "2"
},
"name" : "Net-Frame-Dump",
- "no_index" : {
- "directory" : [
- "t",
- "inc"
- ]
- },
"prereqs" : {
- "build" : {
- "requires" : {
- "ExtUtils::MakeMaker" : 0
- }
- },
"configure" : {
"requires" : {
- "ExtUtils::MakeMaker" : 0
+ "Module::Build" : "0"
}
},
"runtime" : {
"requires" : {
"Class::Gomor" : "1.00",
- "IO::Select" : 0,
- "Net::Frame" : 0,
+ "IO::Select" : "0",
+ "Net::Frame" : "0",
"Net::Pcap" : "0.12",
- "Time::HiRes" : 0,
- "perl" : "5.006001"
+ "Time::HiRes" : "0",
+ "perl" : "v5.6.1"
}
}
},
+ "provides" : {
+ "Net::Frame::Dump" : {
+ "file" : "lib/Net/Frame/Dump.pm",
+ "version" : "1.14"
+ },
+ "Net::Frame::Dump::Offline" : {
+ "file" : "lib/Net/Frame/Dump/Offline.pm"
+ },
+ "Net::Frame::Dump::Online" : {
+ "file" : "lib/Net/Frame/Dump/Online.pm"
+ },
+ "Net::Frame::Dump::Online2" : {
+ "file" : "lib/Net/Frame/Dump/Online2.pm"
+ },
+ "Net::Frame::Dump::Writer" : {
+ "file" : "lib/Net/Frame/Dump/Writer.pm"
+ }
+ },
"release_status" : "stable",
- "version" : "1.13"
+ "resources" : {
+ "license" : [
+ "http://www.perlfoundation.org/artistic_license_1_0"
+ ]
+ },
+ "version" : "1.14"
}
@@ -2,26 +2,35 @@
abstract: 'base-class for a tcpdump like implementation'
author:
- 'GomoR <gomor-cpan_at_gomor.org>'
-build_requires:
- ExtUtils::MakeMaker: 0
+build_requires: {}
configure_requires:
- ExtUtils::MakeMaker: 0
+ Module::Build: '0'
dynamic_config: 1
-generated_by: 'ExtUtils::MakeMaker version 6.62, CPAN::Meta::Converter version 2.112150'
+generated_by: 'Module::Build version 0.421, CPAN::Meta::Converter version 2.142060'
license: artistic
meta-spec:
url: http://module-build.sourceforge.net/META-spec-v1.4.html
- version: 1.4
+ version: '1.4'
name: Net-Frame-Dump
-no_index:
- directory:
- - t
- - inc
+provides:
+ Net::Frame::Dump:
+ file: lib/Net/Frame/Dump.pm
+ version: '1.14'
+ Net::Frame::Dump::Offline:
+ file: lib/Net/Frame/Dump/Offline.pm
+ Net::Frame::Dump::Online:
+ file: lib/Net/Frame/Dump/Online.pm
+ Net::Frame::Dump::Online2:
+ file: lib/Net/Frame/Dump/Online2.pm
+ Net::Frame::Dump::Writer:
+ file: lib/Net/Frame/Dump/Writer.pm
requires:
- Class::Gomor: 1.00
- IO::Select: 0
- Net::Frame: 0
- Net::Pcap: 0.12
- Time::HiRes: 0
- perl: 5.006001
-version: 1.13
+ Class::Gomor: '1.00'
+ IO::Select: '0'
+ Net::Frame: '0'
+ Net::Pcap: '0.12'
+ Time::HiRes: '0'
+ perl: v5.6.1
+resources:
+ license: http://www.perlfoundation.org/artistic_license_1_0
+version: '1.14'
@@ -19,6 +19,7 @@ This module requires these other modules and libraries:
Net::Frame
Net::Pcap
Time::HiRes
+ IO::Select
GETTING HELP
@@ -30,5 +31,5 @@ COPYRIGHT AND LICENSE
You may distribute this module under the terms of the Artistic license.
See LICENSE.Artistic file in the source distribution archive.
-Copyright (c) 2006-2012, Patrice <GomoR> Auffret
+Copyright (c) 2006-2014, Patrice <GomoR> Auffret
@@ -1,5 +1,5 @@
#
-# $Id: Offline.pm 353 2012-09-12 18:15:33Z gomor $
+# $Id: Offline.pm 364 2014-11-30 11:26:27Z gomor $
#
package Net::Frame::Dump::Offline;
use strict;
@@ -199,7 +199,7 @@ Patrice E<lt>GomoRE<gt> Auffret
=head1 COPYRIGHT AND LICENSE
-Copyright (c) 2006-2012, Patrice E<lt>GomoRE<gt> Auffret
+Copyright (c) 2006-2014, Patrice E<lt>GomoRE<gt> Auffret
You may distribute this module under the terms of the Artistic license.
See LICENSE.Artistic file in the source distribution archive.
@@ -1,5 +1,5 @@
#
-# $Id: Online.pm 353 2012-09-12 18:15:33Z gomor $
+# $Id: Online.pm 364 2014-11-30 11:26:27Z gomor $
#
package Net::Frame::Dump::Online;
use strict;
@@ -631,7 +631,7 @@ Patrice E<lt>GomoRE<gt> Auffret
=head1 COPYRIGHT AND LICENSE
-Copyright (c) 2006-2012, Patrice E<lt>GomoRE<gt> Auffret
+Copyright (c) 2006-2014, Patrice E<lt>GomoRE<gt> Auffret
You may distribute this module under the terms of the Artistic license.
See LICENSE.Artistic file in the source distribution archive.
@@ -1,5 +1,5 @@
#
-# $Id: Online2.pm 360 2012-12-02 14:44:41Z gomor $
+# $Id: Online2.pm 365 2014-12-09 18:08:01Z gomor $
#
package Net::Frame::Dump::Online2;
use strict;
@@ -10,14 +10,16 @@ our @AS = qw(
dev
timeoutOnNext
timeout
+ maxRunTime
promisc
snaplen
file
overwrite
- _firstTime
+ _startTime
_pid
_sel
_frames
+ _timeWithoutReceiving
);
__PACKAGE__->cgBuildIndices;
__PACKAGE__->cgBuildAccessorsScalar(\@AS);
@@ -56,8 +58,10 @@ sub new {
snaplen => 1514,
file => '',
overwrite => 0,
- _firstTime => 0,
+ maxRunTime => 0,
+ _startTime => 0,
_frames => [],
+ _timeWithoutReceiving => 0,
@_,
);
@@ -89,7 +93,7 @@ sub start {
$self->dev,
$self->snaplen,
$self->promisc,
- 100,
+ 100, # 100 ms timeout
\$err,
);
unless ($pd) {
@@ -115,19 +119,24 @@ sub start {
return;
}
- # Avoid nonblock mode when capture only mode chosen: don't eat 100% CPU
if (! length($self->file)) {
- my $r = Net::Pcap::setnonblock($pd, 1, \$err);
- if ($r == -1) {
- print("[-] ".__PACKAGE__.": setnonblock: $err\n");
- return;
- }
+ #my $r = Net::Pcap::setnonblock($pd, 1, \$err);
+ #if ($r == -1) {
+ #print("[-] ".__PACKAGE__.": setnonblock: $err\n");
+ #return;
+ #}
# Gather a file descriptor to use by select()
- my $fd = Net::Pcap::get_selectable_fd($pd);
+ # Avoid eating 100% CPU
+ my $fd = Net::Pcap::get_selectable_fd($pd);
+ if ($fd < 0) {
+ print("[-] ".__PACKAGE__.": get_selectable_fd failed\n");
+ return;
+ }
my $sel = IO::Select->new;
$sel->add($fd);
$self->_sel($sel);
+ $self->_startTime(gettimeofday());
}
$self->_pcapd($pd);
@@ -236,35 +245,34 @@ sub _printStats {
return 1;
}
-sub _getNextAwaitingFrame {
+sub timeoutReset {
my $self = shift;
- return $self->nextEx;
+
+ $self->_timeWithoutReceiving(0);
+ $self->timeout(0);
+
+ return 1;
}
-sub _nextTimeoutHandle {
- my $self = shift;
+sub _dispatch {
+ my ($user, $header, $packet) = @_;
- # Handle timeout
- my $thisTime = gettimeofday();
- if ($self->timeoutOnNext && !$self->_firstTime) {
- $self->_firstTime($thisTime);
- }
+ my $self = $user->{self};
+ my $frames = $user->{frames};
- if ($self->timeoutOnNext && $self->_firstTime) {
- if (($thisTime - $self->_firstTime) > $self->timeoutOnNext) {
- $self->timeout(1);
- $self->_firstTime(0);
- $self->cgDebugPrint(1, "Timeout occured");
- return;
- }
- }
+ my $ts = $self->keepTimestamp ? $self->_getTimestamp($header)
+ : $self->_setTimestamp;
- return 1;
-}
+ my $frame = {
+ firstLayer => 'ETH',
+ timestamp => $ts,
+ raw => $packet,
+ };
-sub _nextTimeoutReset { shift->_firstTime(0) }
+ push @$frames, $frame;
-sub timeoutReset { shift->timeout(0) }
+ $user->{frames} = $frames;
+}
sub next {
my $self = shift;
@@ -274,27 +282,59 @@ sub next {
"capture mode.\n");
}
+ # We look ar our internal ring buffer
my $frames = $self->_frames;
if (@$frames > 0) {
- $self->_nextTimeoutReset;
my $next = shift @$frames;
$self->_frames($frames);
return $next;
}
+ # If we reach here, we don't have frames anymore in our buffer,
+ # we ask for more except if we have a timeout condition.
+ if ($self->timeout) {
+ return;
+ }
+
+ # We fetch new awaiting frames, if no timeout occured yet.
+ # can_read will return as soon as there is something to read,
+ # or will block if nothing to read for timeoutOnNext seconds.
my $sel = $self->_sel;
- if (my @read = $sel->can_read($self->timeoutOnNext)) {
- $self->_nextTimeoutReset;
- while (my $frame = $self->_getNextAwaitingFrame) {
- push @$frames, $frame;
- }
- my $next = shift @$frames;
- $self->_frames($frames);
- return $next;
+ my $some_received = 0;
+ my $thisTime = gettimeofday();
+
+ # Gather all available frames
+ my $h = { self => $self, frames => $frames };
+ Net::Pcap::pcap_dispatch($self->_pcapd, -1, \&_dispatch, $h);
+ $some_received = scalar(@{$h->{frames}});
+
+ # Update the ring buffer, or we loose those frames
+ $self->_frames($frames);
+
+ # Check if we didn't received frames during $timeoutOnNext seconds,
+ my $endTime = gettimeofday();
+ my $diff = $endTime - $thisTime;
+ if (! $some_received) {
+ $self->_timeWithoutReceiving($self->_timeWithoutReceiving + $diff);
+ }
+ else {
+ $self->_timeWithoutReceiving(0);
}
- # If we are here, a timeout has occured
- $self->_nextTimeoutHandle;
+ #print STDERR "*** diff [$diff] received [$some_received] thisTime [$thisTime] endTime [$endTime]\n";
+
+ if ($self->_timeWithoutReceiving > $self->timeoutOnNext) {
+ #print STDERR "*** Timeout occured\n";
+ $self->timeout(1);
+ }
+
+ # Check if maximum run time has been reached
+ my $maxRunTime = $self->maxRunTime;
+ my $startTime = $self->_startTime;
+ if ($maxRunTime && ($endTime - $startTime) > $startTime) {
+ #print STDERR "*** Max running time reached\n";
+ $self->timeout(1);
+ }
return;
}
@@ -451,7 +491,7 @@ Patrice E<lt>GomoRE<gt> Auffret
=head1 COPYRIGHT AND LICENSE
-Copyright (c) 2006-2012, Patrice E<lt>GomoRE<gt> Auffret
+Copyright (c) 2006-2014, Patrice E<lt>GomoRE<gt> Auffret
You may distribute this module under the terms of the Artistic license.
See LICENSE.Artistic file in the source distribution archive.
@@ -1,5 +1,5 @@
#
-# $Id: Writer.pm 353 2012-09-12 18:15:33Z gomor $
+# $Id: Writer.pm 364 2014-11-30 11:26:27Z gomor $
#
package Net::Frame::Dump::Writer;
use strict;
@@ -239,7 +239,7 @@ Patrice E<lt>GomoRE<gt> Auffret
=head1 COPYRIGHT AND LICENSE
-Copyright (c) 2006-2012, Patrice E<lt>GomoRE<gt> Auffret
+Copyright (c) 2006-2014, Patrice E<lt>GomoRE<gt> Auffret
You may distribute this module under the terms of the Artistic license.
See LICENSE.Artistic file in the source distribution archive.
@@ -1,11 +1,11 @@
#
-# $Id: Dump.pm 360 2012-12-02 14:44:41Z gomor $
+# $Id: Dump.pm 364 2014-11-30 11:26:27Z gomor $
#
package Net::Frame::Dump;
use strict;
use warnings;
-our $VERSION = '1.13';
+our $VERSION = '1.14';
use base qw(Class::Gomor::Array Exporter);
@@ -163,8 +163,8 @@ sub nextEx {
my %hdr;
my $raw;
- my $r;
- if ($r = Net::Pcap::next_ex($self->_pcapd, \%hdr, \$raw) > 0) {
+ my $r = Net::Pcap::next_ex($self->_pcapd, \%hdr, \$raw);
+ if ($r > 0) {
my $ts = $self->keepTimestamp ? $self->_getTimestamp(\%hdr)
: $self->_setTimestamp;
return {
@@ -252,7 +252,7 @@ Patrice E<lt>GomoRE<gt> Auffret
=head1 COPYRIGHT AND LICENSE
-Copyright (c) 2006-2012, Patrice E<lt>GomoRE<gt> Auffret
+Copyright (c) 2006-2014, Patrice E<lt>GomoRE<gt> Auffret
You may distribute this module under the terms of the Artistic license.
See LICENSE.Artistic file in the source distribution archive.