#!/usr/bin/perl -w

#
# tcpdump_to_db
# Copyright (C) 1999 by John Heidemann <johnh@ficus.cs.ucla.edu>
# $Id: tcpdump_to_db,v 1.2 1999/08/05 17:44:52 johnh Exp $
#
# This program is distributed under terms of the GNU general
# public license, version 2.  See the file COPYING
# in $dblib for details.
#

sub usage {
    print STDERR <<END;
usage: $0 [registers] <kitrace_data_stream

Converts a tcpdump data stream to JDB format.

CURRENTLY IT HANDLES ONLY TCP AND SILENTLY FAILS ON OTHER TRAFFIC!
Awaiting enhancement... you're welcome to help.


Sample input:
14:11:12.556781 dash.isi.edu.1023 > excalibur.usc.edu.ssh: S 2306448962:2306448962(0) win 32120 <mss 1460,sackOK,timestamp 82802652[|tcp]> (DF)
14:11:12.561734 excalibur.usc.edu.ssh > dash.isi.edu.1023: S 1968320001:1968320001(0) ack 2306448963 win 4096
14:11:12.561875 dash.isi.edu.1023 > excalibur.usc.edu.ssh: . ack 1 win 32120 (DF)
14:11:18.746567 excalibur.usc.edu.ssh > dash.isi.edu.1023: P 316:328(12) ack 348 win 4096
14:11:18.755176 dash.isi.edu.1023 > excalibur.usc.edu.ssh: P 348:488(140) ack 328 win 32696 (DF) [tos 0x10]
14:11:18.847937 excalibur.usc.edu.ssh > dash.isi.edu.1023: P 328:468(140) ack 488 win 4096
14:11:18.860047 dash.isi.edu.1023 > excalibur.usc.edu.ssh: . ack 468 win 32696 (DF) [tos 0x10]
14:11:18.936255 dash.isi.edu.1023 > excalibur.usc.edu.ssh: P 488:516(28) ack 468 win 32696 (DF) [tos 0x10]

Sample command:
tcpdump_to_db

Sample output:
#h time proto src dest flags start end len ack win
51072.556781 tcp dash.isi.edu.1023 excalibur.usc.edu.ssh S 2306448962 2306448962 0 - 32120
51072.561734 tcp excalibur.usc.edu.ssh dash.isi.edu.1023 S 1968320001 1968320001 0 2306448963 4096
51072.561875 tcp dash.isi.edu.1023 excalibur.usc.edu.ssh . - - - 1 32120
51078.746567 tcp excalibur.usc.edu.ssh dash.isi.edu.1023 P 316 328 12 348 4096
51078.755176 tcp dash.isi.edu.1023 excalibur.usc.edu.ssh P 348 488 140 328 32696
51078.847937 tcp excalibur.usc.edu.ssh dash.isi.edu.1023 P 328 468 140 488 4096
51078.860047 tcp dash.isi.edu.1023 excalibur.usc.edu.ssh . - - - 468 32696
51078.936255 tcp dash.isi.edu.1023 excalibur.usc.edu.ssh P 488 516 28 468 32696
#  | tcpdump_to_db 
END
    #'
    exit 1;
}

require 5.000;
BEGIN {
    $dblibdir = "/usr/local/lib/jdb";
    push(@INC, $dblibdir);
}
require "$dblibdir/dblib.pl";
use DbGetopt;

my(@orig_argv) = @ARGV;
my($prog) = &progname;
my($debug) = 0;
my($dbopts) = new DbGetopt("dT?", \@ARGV);
my($daytime) = 1;
my($ch);
while ($dbopts->getopt) {
    $ch = $dbopts->opt;
    if ($ch eq 'd') {
	$debug++;
    } elsif ($ch eq 'T') {
	$daytime = undef;
    } else {
	&usage;
    };
};


my($time_origin_S, $time_origin_f);

sub conv_time {
    my($raw) = @_;
    my($h, $m, $s, $f) = ($raw =~ /^\s*(\d+):(\d+):(\d+)\.(\d+)\s*$/);
    die "$0: input doesn't look like an ascii formatted tcpdump.  Giving up.\n"
	if (!defined($h));
    $S = (($h * 60) + $m) * 60 + $s;
    if (!defined($daytime)) {
	if (!defined($time_origin_S)) {
	    $time_origin_S = $S;
	    $time_origin_f = $f;
	};
	$S -= $time_origin_S;
	$f -= $time_origin_f;
	while ($f < 0) {
	    $S -= 1;
	    $f += 1000000;
	};
	$f = sprintf("%06d", $f);
    }; 
    return "$S.$f";
}

print "#h time proto src dest flags start end len ack win\n";
while (<STDIN>) {
    next if (!/^\d/);
    @F = split;
    my($proto, $raw_time, $src, $dummy, $dest, $flags, $ack, $win, $start, $end, $len) = ("-") x 20;
    $raw_time = shift @F;
    # xxx: should support other protos!
    # Currently silently fails on them.
    $proto = 'tcp';
    $src = shift @F;
    # The src field may have "truncated-ip" instead of the src.
    # If the entry is truncated then silently ignore it.
    next if ($src =~ /truncated/);

    $dummy = shift @F;
    $dest = shift @F;
    $dest =~ s/:$//;
    $flags = shift @F;
    if ($F[0] =~ /^\d/) {
	($start, $end, $len) = ($F[0] =~ /^\s*(\d+):(\d+)\((\d+)\)\s*$/);
	shift @F;
    };
    if ($F[0] eq 'ack') {
	shift @F;
	$ack = shift @F;
    };
    if ($F[0] eq 'win') {
	shift @F;
	$win = shift @F;
    };

    print conv_time($raw_time) . " $proto $src $dest $flags $start $end $len $ack $win\n";
}

print "#  | $prog " . join(" ", @orig_argv) . "\n";
exit 0;
