File Coverage

blib/lib/Fsdb/Filter/tcpdump_to_db.pm
Criterion Covered Total %
statement 15 82 18.2
branch 0 20 0.0
condition n/a
subroutine 5 16 31.2
pod 5 5 100.0
total 25 123 20.3


line stmt bran cond sub pod time code
1             #!/usr/bin/perl -w
2              
3             #
4             # tcpdump_to_db.pm
5             # Copyright (C) 1999-2007 by John Heidemann
6             # $Id: 43409abf10f685dcc1abf480ced38d92f914c5c6 $
7             #
8             # This program is distributed under terms of the GNU general
9             # public license, version 2. See the file COPYING
10             # in $dblib for details.
11             #
12              
13              
14             package Fsdb::Filter::tcpdump_to_db;
15              
16             =head1 NAME
17              
18             tcpdump_to_db - convert tcpdump textual output to fsdb
19              
20             =head1 SYNOPSIS
21              
22             tcpdump_to_db [-T] < source.tcpdump > target.fsdb
23              
24             =head1 DESCRIPTION
25              
26             Converts a tcpdump data stream to Fsdb format.
27              
28             B
29             Awaiting enhancement... you're welcome to help.
30              
31              
32             =head1 OPTIONS
33              
34             =over 4
35              
36             =item B<-t> or B<--daytime>
37              
38             Adjust times relative to the first timestamp.
39             (Defaults on.)
40              
41             =back
42              
43              
44             =for comment
45             begin_standard_fsdb_options
46              
47             This module also supports the standard fsdb options:
48              
49             =over 4
50              
51             =item B<-d>
52              
53             Enable debugging output.
54              
55             =item B<-i> or B<--input> InputSource
56              
57             Read from InputSource, typically a file name, or C<-> for standard input,
58             or (if in Perl) a IO::Handle, Fsdb::IO or Fsdb::BoundedQueue objects.
59              
60             =item B<-o> or B<--output> OutputDestination
61              
62             Write to OutputDestination, typically a file name, or C<-> for standard output,
63             or (if in Perl) a IO::Handle, Fsdb::IO or Fsdb::BoundedQueue objects.
64              
65             =item B<--autorun> or B<--noautorun>
66              
67             By default, programs process automatically,
68             but Fsdb::Filter objects in Perl do not run until you invoke
69             the run() method.
70             The C<--(no)autorun> option controls that behavior within Perl.
71              
72             =item B<--help>
73              
74             Show help.
75              
76             =item B<--man>
77              
78             Show full manual.
79              
80             =back
81              
82             =for comment
83             end_standard_fsdb_options
84              
85              
86             =head1 SAMPLE USAGE
87              
88             =head2 Input:
89              
90             14:11:12.556781 dash.isi.edu.1023 > excalibur.usc.edu.ssh: S 2306448962:2306448962(0) win 32120 (DF)
91             14:11:12.561734 excalibur.usc.edu.ssh > dash.isi.edu.1023: S 1968320001:1968320001(0) ack 2306448963 win 4096
92             14:11:12.561875 dash.isi.edu.1023 > excalibur.usc.edu.ssh: . ack 1 win 32120 (DF)
93             14:11:18.746567 excalibur.usc.edu.ssh > dash.isi.edu.1023: P 316:328(12) ack 348 win 4096
94             14:11:18.755176 dash.isi.edu.1023 > excalibur.usc.edu.ssh: P 348:488(140) ack 328 win 32696 (DF) [tos 0x10]
95             14:11:18.847937 excalibur.usc.edu.ssh > dash.isi.edu.1023: P 328:468(140) ack 488 win 4096
96             14:11:18.860047 dash.isi.edu.1023 > excalibur.usc.edu.ssh: . ack 468 win 32696 (DF) [tos 0x10]
97             14:11:18.936255 dash.isi.edu.1023 > excalibur.usc.edu.ssh: P 488:516(28) ack 468 win 32696 (DF) [tos 0x10]
98              
99             =head2 Command:
100              
101             tcpdump_to_db
102              
103             =head2 Output:
104              
105             #fsdb time proto src dest flags start end len ack win
106             51072.556781 tcp dash.isi.edu.1023 excalibur.usc.edu.ssh S 2306448962 2306448962 0 - 32120
107             51072.561734 tcp excalibur.usc.edu.ssh dash.isi.edu.1023 S 1968320001 1968320001 0 2306448963 4096
108             51072.561875 tcp dash.isi.edu.1023 excalibur.usc.edu.ssh . - - - 1 32120
109             51078.746567 tcp excalibur.usc.edu.ssh dash.isi.edu.1023 P 316 328 12 348 4096
110             51078.755176 tcp dash.isi.edu.1023 excalibur.usc.edu.ssh P 348 488 140 328 32696
111             51078.847937 tcp excalibur.usc.edu.ssh dash.isi.edu.1023 P 328 468 140 488 4096
112             51078.860047 tcp dash.isi.edu.1023 excalibur.usc.edu.ssh . - - - 468 32696
113             51078.936255 tcp dash.isi.edu.1023 excalibur.usc.edu.ssh P 488 516 28 468 32696
114             # | tcpdump_to_db
115              
116              
117             =head1 SEE ALSO
118              
119             L.
120              
121              
122             =head1 CLASS FUNCTIONS
123              
124             =cut
125              
126             @ISA = qw(Fsdb::Filter);
127             $VERSION = 2.0;
128              
129 1     1   5541 use strict;
  1         2  
  1         38  
130 1     1   5 use Pod::Usage;
  1         2  
  1         135  
131 1     1   4 use Carp;
  1         3  
  1         57  
132              
133 1     1   5 use Fsdb::Filter;
  1         1  
  1         20  
134 1     1   4 use Fsdb::IO::Writer;
  1         1  
  1         967  
135              
136              
137             =head2 new
138              
139             $filter = new Fsdb::Filter::tcpdump_to_db(@arguments);
140              
141             Create a new tcpdump_to_db object, taking command-line arguments.
142              
143             =cut
144              
145             sub new ($@) {
146 0     0 1   my $class = shift @_;
147 0           my $self = $class->SUPER::new(@_);
148 0           bless $self, $class;
149 0           $self->set_defaults;
150 0           $self->parse_options(@_);
151 0           $self->SUPER::post_new();
152 0           return $self;
153             }
154              
155              
156             =head2 set_defaults
157              
158             $filter->set_defaults();
159              
160             Internal: set up defaults.
161              
162             =cut
163              
164             sub set_defaults ($) {
165 0     0 1   my($self) = @_;
166 0           $self->SUPER::set_defaults();
167             }
168              
169             =head2 parse_options
170              
171             $filter->parse_options(@ARGV);
172              
173             Internal: parse command-line arguments.
174              
175             =cut
176              
177             sub parse_options ($@) {
178 0     0 1   my $self = shift @_;
179              
180 0           my(@argv) = @_;
181             $self->get_options(
182             \@argv,
183 0     0     'help|?' => sub { pod2usage(1); },
184 0     0     'man' => sub { pod2usage(-verbose => 2); },
185             'autorun!' => \$self->{_autorun},
186             'd|debug+' => \$self->{_debug},
187 0     0     'i|input=s' => sub { $self->parse_io_option('input', @_); },
188             't|daytime!' => \$self->{_daytime},
189 0     0     'T' => sub { $self->{_daytime} = undef; },
190             'log!' => \$self->{_logprog},
191 0     0     'o|output=s' => sub { $self->parse_io_option('output', @_); },
192 0 0         ) or pod2usage(2);
193 0           push (@{$self->{_argv}}, @argv);
  0            
194             }
195              
196             =head2 setup
197              
198             $filter->setup();
199              
200             Internal: setup, parse headers.
201              
202             =cut
203              
204             sub setup ($) {
205 0     0 1   my($self) = @_;
206              
207 0           $self->finish_fh_io_option('input');
208              
209 0           $self->finish_io_option('output', -cols => [qw(time proto src dest flags start end len ack win)]);
210             }
211              
212             =head2 _conv_time
213              
214             $daytime = $self->_conv_time($raw);
215              
216             Convert tcpdump h:mm:ss.SS format to absolute seconds.
217              
218             =cut
219              
220             sub _conv_time {
221 0     0     my($self, $raw) = @_;
222 0           my($h, $m, $s, $f) = ($raw =~ /^\s*(\d+):(\d+):(\d+)\.(\d+)\s*$/);
223 0 0         die "$0: input doesn't look like an ascii formatted tcpdump. Giving up.\n"
224             if (!defined($h));
225 0           my $S = (($h * 60) + $m) * 60 + $s;
226 0 0         if ($self->{_daytime}) {
227 0 0         if (!defined($self->{_time_origin_S})) {
228 0           $self->{_time_origin_S} = $S;
229 0           $self->{_time_origin_f} = $f;
230             };
231 0           $S -= $self->{_time_origin_S};
232 0           $f -= $self->{_time_origin_f};
233 0           while ($f < 0) {
234 0           $S -= 1;
235 0           $f += 1000000;
236             };
237 0           $f = sprintf("%06d", $f);
238             };
239 0           return "$S.$f";
240             }
241              
242              
243             =head2 run
244              
245             $filter->run();
246              
247             Internal: run over each rows.
248              
249             =cut
250             sub run ($) {
251 0     0 1   my($self) = @_;
252              
253 0           my $read_fh = $self->{_in};
254 0           my $write_fastpath_sub = $self->{_out}->fastpath_sub();
255 0           my $empty = $self->{_out}->{_empty};
256              
257 0           for (;;) {
258 0           my $line = $read_fh->getline;
259 0 0         last if (!defined($line));
260              
261 0 0         next if ($line !~ /^\d/);
262 0           my(@F) = split(' ', $line);
263 0           my($proto, $raw_time, $src, $dummy, $dest, $flags, $ack, $win, $start, $end, $len) = ($empty) x 20;
264 0           $raw_time = shift @F;
265             # xxx: should support other protos!
266             # Currently silently fails on them.
267 0           $proto = 'tcp';
268 0           $src = shift @F;
269             # The src field may have "truncated-ip" instead of the src.
270             # If the entry is truncated then silently ignore it.
271 0 0         next if ($src =~ /truncated/);
272            
273 0           $dummy = shift @F;
274 0           $dest = shift @F;
275 0           $dest =~ s/:$//;
276 0           $flags = shift @F;
277 0 0         if ($F[0] =~ /^\d/) {
278 0           ($start, $end, $len) = ($F[0] =~ /^\s*(\d+):(\d+)\((\d+)\)\s*$/);
279 0           shift @F;
280             };
281 0 0         if ($F[0] eq 'ack') {
282 0           shift @F;
283 0           $ack = shift @F;
284             };
285 0 0         if ($F[0] eq 'win') {
286 0           shift @F;
287 0           $win = shift @F;
288             };
289              
290 0           my @outf = ($self->_conv_time($raw_time), $proto, $src, $dest, $flags, $start, $end, $len, $ack, $win);
291 0           &{$write_fastpath_sub}(\@outf);
  0            
292             };
293             }
294              
295              
296             =head1 AUTHOR and COPYRIGHT
297              
298             Copyright (C) 1991-2008 by John Heidemann
299              
300             This program is distributed under terms of the GNU general
301             public license, version 2. See the file COPYING
302             with the distribution for details.
303              
304             =cut
305              
306             1;