#!/usr/bin/perl

#    =====================================================================
#    |                   SPALEWARE LICENSE (Revision 0.1)                |
#    |-------------------------------------------------------------------|
#    | This is a little script called "ircsniffer" and is                |
#    | licensed under SPALEWARE. You may freely modify and distribute    |
#    | this script or parts of it. But you MUST keep the SPALWARE        |
#    | license in it!                                                    |
#    |                                                                   |
#    =====================================================================
#
# Author  : Pascal Gloor
# Date    : 19.10.2003
# Contact : spale@undernet.org
# Version : 1.0

# Terminal width, does take care of \n when they are needed. this value may be tuned.
$term_w = 100;

### END OF CONFIGURABLE STUFF, DONT TOUCH THE STUFF BELOW ;p

$tcpdump = `which tcpdump`; chop $tcpdump;

if ( !$tcpdump ) {
	print STDERR "FATAL ERROR: tcpdump not found\n";
	print STDERR "make sure tcpdump is in the PATH\n";
	exit 1;
}

if ( @ARGV ) {
	foreach(@ARGV) { $options .= sprintf(" %s",$_); }
	print "Starting decoder with '$tcpdump -lnx -s 1500$options'\n";
} else {
	print "usage:   $0 <tcpdump_options>\n";
	print "example: $0 -i eth0 tcp and dst port 6667\n";
	print "\n";
	print "WARNING: you must ensure that you will only match IRC traffic,\n";
	print "matching non-IRC traffic may break your terminal by displaying\n";
	print "non-printable chars!\n\n";
	exit;
}


$|=1;
open (STDIN,"$tcpdump -lnx -s 1500 $options |");
while (<STDIN>) {
	s/(\r|\n)+$//;
	if  ( /^[0-9]/ ) {
		# trying to guess which is the server side.
		if ( $from =~ /\.(666[0-9]|7000|7777|8000|9000)$/ ) {
			$peer = $to;
			$dir  = 'server';
		} else {
			$peer = $from;
			$dir  = 'client';
		}
		
		undef $offset;
		$len = length($packet);
		# so, how long is this header?
		$ip_head_len = unpack("B8",pack('H2',substr($packet,$offset,2)));
		$ip_head_len =~ s/.*(....)$/$1/;
		$ip_head_len = hex(unpack("H1",pack("B4",$ip_head_len))) * 4;
		$offset += $ip_head_len * 2;
		# so, where does data start, must be somewhere in the TCP header .. ;p
		$tcp_head_len = unpack("B8",pack('H2',substr($packet,$offset+24,2)));
		$tcp_head_len =~ s/^(.{4}).*/$1/;
		$tcp_head_len = hex(unpack("H1",pack("B4",$tcp_head_len))) * 4;
		$offset += $tcp_head_len * 2;
		undef $char;
		undef $poscount;
		for ( $pos = $offset; $pos < $len; $pos+=2 ) {
			$poscount++;
			if ( $poscount >= $term_w ) { print "\n                             "; undef $poscount; }
			$char = chr(hex(substr($packet,$pos,2)));
			$char =~ s/\c[/^/;
			if ( $char =~ /\n/ ) { undef $poscount; }
			if ( $pos eq $offset || $lchar =~ /\n/ ) { printf("%21s %s ",$peer,$dir); }
			print $char;
			$lchar = $char;
		}

		($time,$from,undef,$to)=split(/ /);
		$to =~ s/:$//;
		undef $packet;
	} else {
		s/^	+//;
		s/ //g;
		$packet .= $_;
	}
}
