From Michael Mann via bug 2794: A Perl script to expose "questionable" display filter...
authorChris Maynard <Christopher.Maynard@GTECH.COM>
Mon, 8 Aug 2011 17:42:26 +0000 (17:42 -0000)
committerChris Maynard <Christopher.Maynard@GTECH.COM>
Mon, 8 Aug 2011 17:42:26 +0000 (17:42 -0000)
svn path=/trunk/; revision=38411

tools/checkfiltername.pl [new file with mode: 0755]

diff --git a/tools/checkfiltername.pl b/tools/checkfiltername.pl
new file mode 100755 (executable)
index 0000000..96454b5
--- /dev/null
@@ -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__