#!perl # # this script analyzes a gsmbufmon logfile, and extracts ppp frames from it # # use strict; package FCSCalc; use strict; use integer; our @EXPORT=qw(pppfcs16); my @fcs16tab; INIT { #print("func FCSCalc::INIT\n"); my $poly= 0x8408; for (my $b=0 ; $b<256 ; $b++) { my $v= $b; my $i= 8; while ($i--) { $v = $v&1 ? ($v>>1)^$poly : $v>>1; } push @fcs16tab, $v&0xffff; } } sub pppfcs16 { my $fcs= @_>1 ? $_[1] : 0xffff; #printf("func FCSCalc::pppfcs16\n"); $fcs = ($fcs>>8) ^ $fcs16tab[($fcs^ord(substr($_[0],$_,1)))&0xff] for (0..length($_[0])-1); return $fcs; } package main; use strict; $|=1; my $type; my $time; binmode STDOUT; print pack_file_header(create_file_header()); while (<>) { s/\s+$//; if (/^#TIME.*@(\w+).*data:wincerequest/) { $type="_XMIT_"; $time= $1; } elsif (/^#TIME.*@(\w+).*data:gsmresponse/) { $type="_RECV_"; $time= $1; } elsif (/^#TIME/) { $type= undef; } elsif ($type && /^\s(.*)/) { my $datahex= $1; $datahex =~ s/\s//g; my $frame= pack("H*", $datahex); my $uframe= ppp_unescape($frame); if (my ($type, $dframe)= ppp_deframe ($uframe)) { my $data=pack("na*", $type, $dframe); print pack_pkt_header(create_pkt_header($time, length($data))); print $data; } } else { warn sprintf("unhandled: %s\n", $_) if ($_ ne ""); } } sub create_file_header { return { magic=>0xa1b2c3d4, version_major=>2, version_minor=>4, thiszone=>0, sigfigs=>0, snaplen=>4096, linktype=>50, }; } sub pack_file_header { my ($hdr)= @_; return pack("VvvVVVV", $hdr->{magic}, $hdr->{version_major}, $hdr->{version_minor}, $hdr->{thiszone}, $hdr->{sigfigs}, $hdr->{snaplen}, $hdr->{linktype}, ); } sub pack_pkt_header { my ($hdr)= @_; return pack("a8VV", $hdr->{ts}, $hdr->{caplen}, $hdr->{len}, ); } sub create_pkt_header { my ($time, $len)= @_; return { ts=>pack("CCVCC", 0,0,$time,0,0), caplen=>$len, len=>$len }; } sub ppp_unescape { my ($data)= @_; $data =~ s/\x7d(.)/$1^' '/egs; return $data; } sub ppp_deframe { my ($frame)= @_; if ($frame =~ /^\x7e(..)(.*?)(..)\x7e$/s) { my ($type, $data, $lcs)= (unpack("n", $1), $2, unpack("n", $3)); my $calcfcs= calc_fcs(substr($frame, 1, length($frame)-2)); if ($calcfcs!=0xf0b8) { warn sprintf("frame check error fcs(%s) = %04x\n", unpack("H*", substr($frame,1,length($frame)-2)), $calcfcs); return; } return ($type, $data); } else { warn sprintf("unknown frame: %s\n", unpack("H*", $frame)); } } sub calc_fcs { return FCSCalc::pppfcs16(@_); }