diff options
author | Chris Maynard <Christopher.Maynard@GTECH.COM> | 2011-08-08 17:42:26 +0000 |
---|---|---|
committer | Chris Maynard <Christopher.Maynard@GTECH.COM> | 2011-08-08 17:42:26 +0000 |
commit | 237cfb674f3764634e74cd0e3ec2d9cc9324cc3b (patch) | |
tree | b8f5b89760750464524239751b4b2050a750946b /tools | |
parent | 713a85de8a0330bec508a754f1d8ac630bca83dd (diff) |
From Michael Mann via bug 2794: A Perl script to expose "questionable" display filter field names.
svn path=/trunk/; revision=38411
Diffstat (limited to 'tools')
-rwxr-xr-x | tools/checkfiltername.pl | 468 |
1 files changed, 468 insertions, 0 deletions
diff --git a/tools/checkfiltername.pl b/tools/checkfiltername.pl new file mode 100755 index 0000000000..96454b56da --- /dev/null +++ b/tools/checkfiltername.pl @@ -0,0 +1,468 @@ +#!/usr/bin/perl + +my $debug = 0; +# 0: off +# 1: specific debug +# 2: full debug + +# +# verify that display filter names correspond with the PROTABBREV of +# of the dissector. Enforces the dissector to have a source +# filename of format packet-PROTABBREV.c +# +# Usage: checkfiltername.pl <file or files> + +# $Id: + +# +# Copyright 2011 Michael Mann (see AUTHORS file) +# +# Wireshark - Network traffic analyzer +# By Gerald Combs <gerald@wireshark.org> +# Copyright 1998 Gerald Combs +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# +# Example: +# ~/work/wireshark/trunk/epan/dissectors> ../../tools/checkfiltername.pl packet-3com-xns.c +# packet-3com-xns.c (2 (of 2) fields) +# 102 3comxns.type doesn't match PROTOABBREV of 3com-xns +# 106 3comxns.type doesn't match PROTOABBREV of 3com-xns +# +# or checkfiltername.pl packet-*.c, which will check all the dissector files. +# +# + +use warnings; +use strict; + +my @elements; +my @elements_dup; +my @protocols; +my %filters; +my @acceptedprefixes = ("dcerpc-"); +my @asn1automatedfilelist; +my @dcerpcautomatedfilelist; +my @filemanipulationfilelist; +my @prefixfilelist; +my @nofieldfilelist; +my %unique; +my @uniquefilelist; +my @noregprotocolfilelist; + +my $state; +# "s_unknown", +# "s_start", +# "s_in_hf_register_info", +# "s_hf_register_info_entry", +# "s_header_field_info_entry", +# "s_header_field_info_entry_start", +# "s_header_field_info_entry_name", +# "s_header_field_info_entry_abbrev", +# "s_header_field_info_entry_abbrev_end", +# "s_nofields" + +my $restofline; +my $currfile = ""; +my $protabbrev = ""; +my $protabbrev_index; +my $linenumber = 1; +my $totalerrorcount = 0; +my $errorfilecount = 0; +my $onefield = 0; +my $nofields = 0; +my $noregprotocol = 1; +my $automated = 0; +my $more_tokens; +my $showall = 0; + +my $comment = 0; + +my $error = 0; + +sub checkprotoabbrev { + my $abbrev = ""; + my $abbrevpos; + my $afterabbrev = ""; + my $modprotabbrev = ""; + my $errorline = 0; + my $prefix; + + if (($automated == 0) || ($showall == 1)) { + $abbrevpos = index($_[0], "."); + if ($abbrevpos == -1) { + $abbrev = $_[0]; + } + else { + $abbrev = substr($_[0], 0, $abbrevpos); + $afterabbrev = substr($_[0], $abbrevpos+1, length($_[0])-$abbrevpos); + $afterabbrev = substr($afterabbrev, 0, length($abbrev)); + } + + if ($abbrev ne $protabbrev) { + $errorline = 1; + + #check if there is a supported protocol that matches the abbrev. + #This may be a case of filename != PROTOABBREV + foreach (@protocols) { + if ($abbrev eq $_) { + $errorline = 0; + } + } + } + + if (($errorline == 1) && ($showall == 0)) { + #try some "accepted" variations of PROTOABBREV + + #replace '-' with '_' + $modprotabbrev = $protabbrev; + $modprotabbrev =~ s/-/_/g; + if ($abbrev eq $modprotabbrev) { + $errorline = 0; + } + + #remove '-' + if ($errorline == 1) { + $modprotabbrev = $protabbrev; + $modprotabbrev =~ s/-//g; + if ($abbrev eq $modprotabbrev) { + $errorline = 0; + } + } + + #remove '_' + if ($errorline == 1) { + $modprotabbrev = $protabbrev; + $modprotabbrev =~ s/_//g; + if ($abbrev eq $modprotabbrev) { + $errorline = 0; + } + } + + if ($errorline == 1) { + #remove any "accepted" prefix to see if there is still a problem + foreach (@acceptedprefixes) { + if ($protabbrev =~ /^$_/) { + $modprotabbrev = substr($protabbrev, length($_)); + if ($abbrev eq $modprotabbrev) { + push(@prefixfilelist, "$currfile\n"); + $errorline = 0; + } + } + } + } else { + push(@filemanipulationfilelist, "$currfile\n"); + } + } + + if ($errorline == 1) { + $debug>1 && print "$_[1] $_[0] doesn't match PROTOABBREV of $protabbrev\n"; + push(@elements, "$_[1] $_[0] doesn't match PROTOABBREV of $protabbrev\n"); + } + + if (lc($abbrev) eq lc($afterabbrev)) { + push(@elements_dup, "$_[1] $_[0] duplicates PROTOABBREV of $abbrev\n"); + } + } +} + +sub printprevfile { + my $totalfields = keys(%filters); + my $count_ele; + my $count_dup; + my $total_count; + + foreach (sort keys %filters) { + checkprotoabbrev ($filters{$_}, $_); + } + + $count_ele = @elements; + $count_dup = @elements_dup; + $total_count = $count_ele+$count_dup; + + if ($noregprotocol == 1) { + #if no protocol is registered, only worry about duplicates + if ($currfile ne "") { + push(@noregprotocolfilelist, "$currfile\n"); + } + + if ($count_dup > 0) { + $errorfilecount++; + $totalerrorcount += $count_dup; + } + + if (($showall == 1) || ($count_dup > 0)) { + print "\n\n$currfile - NO PROTOCOL REGISTERED\n"; + if ($showall == 1) { + #everything is included, so count all errors + $totalerrorcount += $count_ele; + if (($count_ele > 0) && ($count_dup == 0)) { + $errorfilecount++; + } + + foreach (@elements) { + print $_; + } + } + foreach (@elements_dup) { + print $_; + } + } + } else { + if ($total_count > 0) { + $errorfilecount++; + $totalerrorcount += $total_count; + } + + if (($automated == 0) || ($showall == 1)) { + if ($total_count > 0) { + if ($automated == 1) { + if ($showall == 1) { + print "\n\n$currfile - AUTOMATED ($total_count (of $totalfields) fields)\n"; + } + } else { + print "\n\n$currfile ($total_count (of $totalfields) fields)\n"; + } + + foreach (@elements) { + print $_; + } + foreach (@elements_dup) { + print $_; + } + } + + if ((($nofields) || ($totalfields == 0)) && ($currfile ne "")) { + if ($showall == 1) { + print "\n\n$currfile - NO FIELDS\n"; + } + push(@nofieldfilelist, "$currfile\n"); + } + } + } +} + +while (<>) { + if ($currfile !~ /$ARGV/) { + &printprevfile(); + + # New file - reset array and state + $currfile = $ARGV; + + #determine PROTABBREV for dissector based on file name format of (dirs)/packet-PROTABBREV.c + $protabbrev_index = rindex($currfile, "packet-"); + if ($protabbrev_index == -1) { + print "$currfile doesn't fit format of packet-PROTABBREV.c\n"; + next; + } + + $protabbrev = substr($currfile, $protabbrev_index+length("packet-")); + $protabbrev_index = rindex($protabbrev, "."); + if ($protabbrev_index == -1) { + print "$currfile doesn't fit format of packet-PROTABBREV.c\n"; + next; + } + $protabbrev = substr($protabbrev, 0, $protabbrev_index); + + $noregprotocol = 1; + $automated = 0; + $nofields = 0; + $onefield = 0; + $linenumber = 1; + %filters = ( ); + @protocols = ( ); + @elements = ( ); + @elements_dup = ( ); + $state = "s_unknown"; + } + + if ($automated == 0) { + #DCERPC automated files + if ($_ =~ "DO NOT EDIT") { + push(@dcerpcautomatedfilelist, "$currfile\n"); + $automated = 1; + next; + } + #ASN.1 automated files + elsif ($_ =~ "It is created automatically by the ASN.1 to Wireshark dissector compiler") { + push(@asn1automatedfilelist, "$currfile\n"); + $automated = 1; + next; + } + } + + # opening then closing comment + if (/(.*?)\/\*.*\*\/(.*)/) { + $comment = 0; + $_ = "$1$2"; + # closing then opening comment + } elsif (/.*?\*\/(.*?)\/\*/) { + $comment = 1; + $_ = "$1"; + # opening comment + } elsif (/(.*?)\/\*/) { + $comment = 1; + $_ = "$1"; + # closing comment + } elsif (/\*\/(.*?)/) { + $comment = 0; + $_ = "$1"; + } elsif ($comment == 1) { + $linenumber++; + next; + } + # unhandled: more than one complete comment per line + + chomp; + + #proto_register_protocol state machine + $restofline = $_; + $more_tokens = 1; + + until ($more_tokens == 0) { + if ($restofline =~ /proto_register_protocol\s*\((.*)/) { + $noregprotocol = 0; + $restofline = $1; + $state = "s_proto_start"; + } elsif (($state eq "s_proto_start") && ($restofline =~ /^(\s*\"([^\"]*)\"\s*,)\s*(.*)/)) { + $restofline = $3; + $state = "s_proto_long_name"; + $debug>1 && print "proto long name: '$2'\n"; + } elsif (($state eq "s_proto_start") && ($restofline =~ /^(\s*(([\w\d])+)\s*,)\s*(.*)/)) { + $restofline = $4; + $state = "s_proto_long_name"; + $debug>1 && print "proto long name: '$2'\n"; + } elsif (($state eq "s_proto_long_name") && ($restofline =~ /^(\s*\"([^\"]*)\"\s*,)\s*(.*)/)) { + $restofline = $3; + $state = "s_proto_short_name"; + $debug>1 && print "proto short name: '$2'\n"; + } elsif (($state eq "s_proto_long_name") && ($restofline =~ /^(\s*(([\w\d])+)\s*,)\s*(.*)/)) { + $restofline = $4; + $state = "s_proto_short_name"; + $debug>1 && print "proto short name: '$2'\n"; + } elsif (($state eq "s_proto_short_name") && ($restofline =~ /\s*\"([^\"]*)\"\s*(.*)/)) { + $more_tokens = 0; + $state = "s_proto_filter_name"; + push(@protocols, $1); + $debug>1 && print "proto filter name: '$1'\n"; + } elsif (($state eq "s_proto_short_name") && ($restofline =~ /\s*(([\w\d])+)\s*(.*)/)) { + $more_tokens = 0; + $state = "s_proto_filter_name"; + $debug>1 && print "proto filter name: '$1'\n"; + } else { + $more_tokens = 0; + } + } + + #retrieving display filters state machine + $restofline = $_; + $more_tokens = 1; + until ($more_tokens == 0) { + if ($restofline =~ /\s*static\s*hf_register_info\s*(\w+)\[\](.*)/) { + $restofline = $2; + $state = "s_start"; + $debug>1 && print "$linenumber $state\n"; + } elsif (($state eq "s_start") && ($restofline =~ /\W+{(.*)/)) { + $restofline = $1; + $state = "s_in_hf_register_info"; + $debug>1 && print "$linenumber $state\n"; + } elsif (($state eq "s_in_hf_register_info") && ($restofline =~ /\W+{(.*)/)) { + $restofline = $1; + $state = "s_hf_register_info_entry"; + $debug>1 && print "$linenumber $state\n"; + $onefield = 1; + } elsif (($state eq "s_in_hf_register_info") && ($restofline =~ /\s*};(.*)/)) { + $restofline = $1; + if ($onefield == 0) { + $debug && print "$linenumber NO FIELDS!!!\n"; + $nofields = 1; + $state = "s_nofields"; + $more_tokens = 0; + } else { + $state = "s_unknown"; + } + } elsif (($state eq "s_hf_register_info_entry") && ($restofline =~ /\s*&\s*(hf_\w*(\[w*\])?)\s*,?(.*)/)) { + $restofline = $3; + $debug>1 && print "$linenumber hf_register_info_entry: $1\n"; + $state = "s_header_field_info_entry"; + } elsif (($state eq "s_header_field_info_entry") && ($restofline =~ /\s*{(.*)/)) { + $restofline = $1; + $state = "s_header_field_info_entry_start"; + $debug>1 && print "$linenumber $state\n"; + } elsif (($state eq "s_header_field_info_entry_start") && ($restofline =~ /\"([^\"]*)\"\s*,(.*)/)) { + $restofline = $2; + $debug>1 && print "$linenumber header_field_info_entry_name: $1\n"; + $state = "s_header_field_info_entry_name"; + } elsif (($state eq "s_header_field_info_entry_name") && ($restofline =~ /\"([^\"]*)\"\s*,?(.*)/)) { + $restofline = $2; + $debug>1 && print "$linenumber header_field_info_entry_abbrev: $1\n"; + $state = "s_header_field_info_entry_abbrev"; + $filters{$linenumber} = $1; + } elsif (($state eq "s_header_field_info_entry_abbrev") && ($restofline =~ /[^}]*}(.*)/)) { + $restofline = $1; + $state = "s_header_field_info_entry_abbrev_end"; + $debug>1 && print "$linenumber $state\n"; + } elsif (($state eq "s_header_field_info_entry_abbrev_end") && ($restofline =~ /[^}]*}(.*)/)) { + $restofline = $1; + $state = "s_in_hf_register_info"; + $debug>1 && print "$linenumber $state\n"; + } else { + $more_tokens = 0; + } + } + + $linenumber++; +} + +&printprevfile(); + +print "\n\nTOTAL ERRORS: $totalerrorcount ($errorfilecount files)\n"; +print "NO FIELDS: " . scalar(@nofieldfilelist) . "\n"; +print "AUTOMATED: " . (scalar(@asn1automatedfilelist) + scalar(@dcerpcautomatedfilelist)) . "\n"; +print "NO PROTOCOL: " . scalar(@noregprotocolfilelist) . "\n"; + +print "\nASN.1 AUTOMATED FILE LIST\n"; +foreach (@asn1automatedfilelist) { + print $_; +} +print "\nDCE/RPC AUTOMATED FILE LIST\n"; +foreach (@dcerpcautomatedfilelist) { + print $_; +} +print "\n\"FILE MANIPULATION\" FILE LIST\n"; +@uniquefilelist = grep{ not $unique{$_}++} @filemanipulationfilelist; +foreach (@uniquefilelist) { + print $_; +} +print "\nREMOVE PREFIX FILE LIST\n"; +@uniquefilelist = grep{ not $unique{$_}++} @prefixfilelist; +foreach (@uniquefilelist) { + print $_; +} +print "\nNO PROTOCOL REGISTERED FILE LIST\n"; +foreach (@noregprotocolfilelist) { + print $_; +} +print "\nNO FIELDS FILE LIST\n"; +foreach (@nofieldfilelist) { + print $_; +} +print "\n"; + + +exit $error; + +__END__ |