1#!/usr/bin/perl -w 2# 3# Sniff traffic and format as a stream of packet contents 4# 5use strict; 6 7use Getopt::Long qw(:config permute); # allow mixed args. 8 9# Options variables 10my $debug = 0; 11my $saveto; 12my $readfrom; 13my $interface = 'any'; 14my $dumpspec = 'tcp port 80'; 15my $helpmeplease = 0; 16 17GetOptions ('debug!' => \$debug, 18 'write=s' => \$saveto, 19 'file=s' => \$readfrom, 20 'interface=s' => \$interface, 21 'dumpspec=s' => \$dumpspec, 22 'help' => \$helpmeplease ); 23 24usage() if ( $helpmeplease ); 25 26if ( defined($saveto) ) { 27 open( SAVETO, '>>', $saveto ) or die "Couldn't save to '$saveto'"; 28} 29 30if ( defined($readfrom) ) { 31 if ( $readfrom ne '-' ) { 32 open( STDIN, '<', $readfrom ) or die "Couldn't open '$readfrom'"; 33 } 34} 35else { 36 my @tcpdumpoptions = ('-i', $interface, '-s0', '-l', '-xx', '-n', '-q', $dumpspec ); 37 open( STDIN, '-|', "tcpdump", @tcpdumpoptions ) or die "Couldn't start tcpdump process"; 38} 39 40my $timestamp; 41my $source = ''; 42my $dest = ''; 43my $lastsource = ''; 44my $lastdest = ''; 45my $show; 46my $packet; 47my $stream; 48 49while( <STDIN> ) { 50 $show = 0; 51 if ( /^([012]\d:[0-5]\d:[0-5]\d\.\d{6})\sIP\s([0-9.:]+)\s>\s([0-9.:]+):\ tcp/ ) { 52 $timestamp = $1; 53 $source = $2; 54 $dest = $3; 55 } 56 elsif ( /^\s+(0x....):\s(( [0-9a-f]{4}){1,8})/i ) { 57 my $pos = hex($1); 58 my $hex = $2; 59 next unless defined($hex); 60 61 if ( $pos == 64 ) { 62 $hex = substr( $hex, 10 ); 63 $pos += 4; 64 } 65 66 if ( $pos >= 68 ) { 67 my @hex = split /\s+/, $hex; 68 my $ascii = ""; 69 foreach my $xch ( @hex ) { 70 next if ( $xch eq '' ); 71 $ascii .= chr(hex(substr($xch,0,2))); 72 $ascii .= chr(hex(substr($xch,2,2))); 73 } 74 $show = 1; 75 $_ = $ascii; 76 } 77 } 78 elsif ( /^\.\./ ) { 79 s/^\.\.......//; 80 $show = 1; 81 } 82 else { 83 $show = 1; 84 } 85 86 if ( $show ) { 87 if ( $source ne $lastsource || $dest ne $lastdest ) { 88 putline( "\n\n=============== $timestamp $source ==> $dest\n" ); 89 $lastsource = $source; 90 $lastdest = $dest; 91 } 92 putline( $_ ); 93 } 94} 95 96 97 98 99########################################################### 100sub putline { 101 my $line = shift; 102 print $line; 103 print SAVETO $line if ( defined($saveto) ); 104} 105 106 107########################################################### 108sub usage { 109 print <<EOERROR ; 110 111Usage: sniffstream [options] 112 113The sniffstream program will format the output of "tcpdump -s0 -n -q -xx" 114for easier reading and comparison, with a view to seeing the actions 115involved in a DAV communication session. By default it will run the 116tcpdump command internally. 117 118It will also somewhat format the output of "tcpdump -s0 -n -q -A". 119 120Options: 121 122 --write <filename> Append the stream to the named file. 123 --file (-|<filename>) Format the input from the named file, or stdin. 124 --interface <ifname> Run tcpdump against the specified interface. 125 --dumpspec <spec> Run tcpdump with that capture specification . 126 127The default interface is 'any' and the default dumpspec is 'tcp port 80'. 128 129EOERROR 130 exit 1; 131 132} 133