#!/usr/local/bin/perl -w use strict; use Getopt::Std; use vars qw($opt_q); # VH size id flag TL P sum source-IP # 4500 0072 bdfd 4000 3f06 f8a5 c0a8 0202 # # dest-IP s-pt d-pt sequence# ack-numbr # # c0a8 0190 0438 0406 3470 7a31 000a 04cd # HFlg win sum urg # 5018 4470 cde2 0000 1080 fe00 0011 0042 # # 0010 8100 6966 0000 0000 0000 0000 0000 my $address = 0; sub nz($;$) { return defined($_[0]) ? $_[0] : (defined($_[1]) ? $_[1] : ""); } sub iskanjiout($$$) { my ($a, $b, $c) = @_; return nz($a, 0) == 0x1b && nz($b, 0) == 0x28 && (nz($c, 0) == 0x42 || nz($c, 0) == 0x4a); } sub iskanjiin($$$) { my ($a, $b, $c) = @_; return nz($a, 0) == 0x1b && nz($b, 0) == 0x24 && nz($c, 0) == 0x42; } sub print_data($) { my ($s) = @_; my @v = unpack("C*", $s); my $total = $#v + 1; my $i; my $inkanji = 0; for ($i = 0; $i < $total; $i++) { my $c = $v[$i]; if ($c == 0x0d) { } elsif ($inkanji && iskanjiout($c, $v[$i + 1], $v[$i + 2])) { print "\x1b"; $inkanji = 0; } elsif (iskanjiin($c, $v[$i + 1], $v[$i + 2])) { my $match = 0; my $j; for ($j = $i; !$match && $j < $total - 2; $j++) { $match = iskanjiout($v[$j], $v[$j + 1], $v[$j + 2]); } if ($match) { print "\x1b"; $inkanji = 1; } else { print "^["; } } elsif ($c == 0x0a) { } elsif ($c >= 0x20 && $c < 0x7f) { printf("%c", $c); } else { print "."; } } if ($total > 0) { printf("\n"); } } sub tcpdata(@) { my (@v) = @_; my $i; my $s = ""; #printf(">> %s\n", $ss); #for ($i = 0; $i <= $#v; $i++) { # printf(" %02x", $v[$i]); #} my $ver = ($v[0] >> 4) & 0xf; if ($ver == 4) { my $ip_hlen = ($v[0] & 0xf) * 4; my $ip_total = $v[2] * 256 + $v[3]; my $proto = $v[9]; if ($proto == 6) { # tcp # sport(2) dport(2) seq(4) ack(4) HFlg(2) win(2) cksum(2) urg(2) my $tcp_hlen = (($v[$ip_hlen + 12] >> 4) & 0xf) * 4; my $tcp_data_top = $ip_hlen + $tcp_hlen; #printf("tcp_hlen=$tcp_hlen tcp_data_top=$tcp_data_top ip_total=$ip_total\n"); if ($ip_total > $#v + 1) { $ip_total = $#v + 1; } if ($tcp_data_top < $ip_total) { splice(@v, 0, $tcp_data_top); $s = pack("C*", @v); } } } return $s; } sub view($$) { my ($hdr, $ss) = @_; my @v = split(/ /, $ss); #printf(">> %s\n", $ss); my $i; for ($i = 0; $i <= $#v; $i++) { $v[$i] = hex($v[$i]); } my $ver = ($v[0] >> 4) & 0xf; if ($ver != 4 && $v[12] == 0x08 && $v[13] == 0x00 && (($v[14] >> 4) & 0xf) == 4) { splice(@v, 0, 14); $ver = ($v[0] >> 4) & 0xf; } if ($ver == 4) { my $ip_hlen = ($v[0] & 0xf) * 4; my $ip_total = $v[2] * 256 + $v[3]; my $proto = $v[9]; if ($proto == 6) { # tcp # sport(2) dport(2) seq(4) ack(4) HFlg(2) win(2) cksum(2) urg(2) my $tcp_sport = ($v[$ip_hlen + 0] << 8) | $v[$ip_hlen + 1]; my $tcp_dport = ($v[$ip_hlen + 2] << 8) | $v[$ip_hlen + 3]; my $tcp_hlen = (($v[$ip_hlen + 12] >> 4) & 0xf) * 4; my $tcp_data_top = $ip_hlen + $tcp_hlen; my $s = tcpdata(@v); my @line = split(/\n/, $s); for ($i = 0; $i < $#line + 1; $i++) { if (!$opt_q || $line[$i] =~ /^(HELO|EHLO|MAIL|RCPT|DATA|QUIT|[0-9][0-9][0-9][- ])/i) { if ($hdr ne "") { printf("%s\n", $hdr); $hdr = ""; } printf($tcp_dport == 25 ? "<<< " : ">>> "); print_data($line[$i]); } } if (!$opt_q && $hdr ne "") { printf("%s\n", $hdr); } } elsif ($proto == 17) { # udp # sport(2) dport(2) plen(2) cksum(2) #print "UDP> ", $ss, "\n"; } elsif ($proto == 1) { # icmp #print "ICMP> ", $ss, "\n"; } } else { #print "?> ", $ss, "\n"; } } sub addhex($$) { my ($dst, $src) = @_; $src =~ s/ *$//; $src =~ s/([0-9A-Fa-f][0-9A-Fa-f])([0-9A-Fa-f][0-9A-Fa-f])/$1 $2/g; if ($dst ne "") { $dst .= " " . $src; } else { $dst = $src; } return $dst; } sub tcpdumpview() { my $lbuf; my $xbuf = ""; my $mbuf = ""; while ($lbuf = <>) { chomp($lbuf); #printf(">>>>[$lbuf]\n"); if ($lbuf =~ /^[0-9][0-9]:/) { $address = 0; if ($xbuf ne "") { view($mbuf, $xbuf); } $xbuf = ""; $mbuf = $lbuf; } if ($lbuf =~ /^[\t ]*0x/) { $lbuf =~ s/^[\t ]*0x[0-9A-Fa-f]+:?[\t ]+//; $lbuf =~ s/\t.*$//; $lbuf =~ s/ .*$//; $xbuf = addhex($xbuf, $lbuf); } elsif ($lbuf =~ /^\t/) { $lbuf =~ s/^[\t ]*//; $xbuf = addhex($xbuf, $lbuf); } else { # print $lbuf, "\n"; } } if ($xbuf ne "") { view($mbuf, $xbuf); } } sub main() { getopts('q'); tcpdumpview(); return 0; } exit main();