#
# $Id: Writer.pm,v 1.5 2007/01/08 22:07:24 gomor Exp $
#
package Net::Frame::Dump::Writer;
use strict;
use warnings;
use Net::Frame::Dump qw(:consts);
our @ISA = qw(Net::Frame::Dump);
__PACKAGE__->cgBuildIndices;
no strict 'vars';
use Carp;
use Net::Pcap;
sub new {
shift->_dumpNew(
firstLayer => 'RAW',
@_,
);
}
my $mapLinks = {
NULL => NF_DUMP_LAYER_NULL(),
ETH => NF_DUMP_LAYER_ETH(),
RAW => NF_DUMP_LAYER_RAW(),
SLL => NF_DUMP_LAYER_SLL(),
PPP => NF_DUMP_LAYER_PPP(),
};
sub _getPcapHeader {
my $self = shift;
my $val = $mapLinks->{$self->[$__firstLayer]}
or croak("Can't get pcap header information for this layer type\n");
# 24 bytes header
"\xd4\xc3\xb2\xa1\x02\x00\x04\x00\x00\x00\x00\x00".
"\x00\x00\x00\x00\xdc\x05\x00\x00".
pack('C', $val).
"\x00\x00\x00";
}
sub _openFile {
my $self = shift;
my $file = $self->[$__file];
my $hdr = $self->_getPcapHeader;
open(my $fh, '>', $file)
or croak("@{[(caller(0))[3]]}: open: $file: $!\n");
syswrite($fh, $hdr, length($hdr));
close($fh);
my $err;
my $pcapd = Net::Pcap::open_offline($file, \$err);
unless ($pcapd) {
croak("@{[(caller(0))[3]]}: Net::Pcap::open_offline: ".
"$file: $err\n");
}
$self->[$___pcapd] = $pcapd;
$self->[$___dumper] = Net::Pcap::dump_open($pcapd, $file);
unless ($self->[$___dumper]) {
croak("@{[(caller(0))[3]]}: Net::Pcap::dump_open: ".
Net::Pcap::geterr($pcapd)."\n");
}
1;
}
sub start {
my $self = shift;
$self->[$__isRunning] = 1;
if (-f $self->[$__file] && ! $self->[$__overwrite]) {
croak("We will not overwrite a file by default. Use `overwrite' ".
"attribute to do it\n");
}
$self->_openFile;
1;
}
sub stop {
my $self = shift;
return unless $self->[$__isRunning];
Net::Pcap::dump_close($self->[$___dumper]);
Net::Pcap::close($self->[$___pcapd]);
$self->[$__isRunning] = 0;
1;
}
sub write {
my $self = shift;
my ($h) = @_;
my $len = length($h->{raw});
# Create pcap header
my ($sec, $usec) = split('\.', $h->{timestamp});
my $hdr = {
len => $len,
caplen => $len,
tv_sec => $sec,
tv_usec => $usec,
};
Net::Pcap::pcap_dump($self->[$___dumper], $hdr, $h->{raw});
Net::Pcap::dump_flush($self->[$___dumper]);
}
1;
__END__
=head1 NAME
Net::Frame::Dump::Writer - tcpdump like implementation, writer mode
=head1 SYNOPSIS
use Net::Frame::Dump::Writer;
my $oDump = Net::Frame::Dump::Writer->new(
file => 'new-file.pcap',
firstLayer => 'ETH',
);
$oDump->start;
$oDump->write({ timestamp => '10.10', raw => ('A' x 14) });
$oDump->stop;
=head1 DESCRIPTION
This module implements a pcap file builder. You will be able to create frames, then write them in the pcap file format to a file.
=head1 ATTRIBUTES
The following are inherited attributes:
=over 4
=item B<file>
Name of the .pcap file to generate.
=item B<overwrite>
Overwrites a .pcap file that already exists. Default to not.
=item B<firstLayer>
Stores information about the first layer type. It is used to write .pcap file header information.
=item B<isRunning>
Returns true if a call to B<start> has been done, false otherwise or if a call to B<stop> has been done.
=back
=head1 METHODS
=over 4
=item B<new>
=item B<new> (hash)
Object constructor. You can pass attributes that will overwrite default ones. See B<SYNOPSIS> for default values.
=item B<start>
When you want to start writing frames to the file, call this method.
=item B<stop>
When you want to stop writing frames to the file, call this method.
=item B<write> ({ timestamp => $value, raw => $rawFrame })
Takes a hashref as a parameter. This hashref MUST have timestamp and raw keys, with values. The raw data will be stored to the .pcap file.
=back
=head1 SEE ALSO
L<Net::Frame::Dump>
=head1 AUTHOR
Patrice E<lt>GomoRE<gt> Auffret
=head1 COPYRIGHT AND LICENSE
Copyright (c) 2006-2007, 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.
=cut
syntax highlighted by Code2HTML, v. 0.9.1