9 # verify that display filter names correspond with the PROTABBREV of
10 # of the dissector. Enforces the dissector to have a source
11 # filename of format packet-PROTABBREV.c
13 # Usage: checkfiltername.pl <file or files>
18 # Copyright 2011 Michael Mann (see AUTHORS file)
20 # Wireshark - Network traffic analyzer
21 # By Gerald Combs <gerald@wireshark.org>
22 # Copyright 1998 Gerald Combs
24 # This program is free software; you can redistribute it and/or
25 # modify it under the terms of the GNU General Public License
26 # as published by the Free Software Foundation; either version 2
27 # of the License, or (at your option) any later version.
29 # This program is distributed in the hope that it will be useful,
30 # but WITHOUT ANY WARRANTY; without even the implied warranty of
31 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
32 # GNU General Public License for more details.
34 # You should have received a copy of the GNU General Public License
35 # along with this program; if not, write to the Free Software
36 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
40 # ~/work/wireshark/trunk/epan/dissectors> ../../tools/checkfiltername.pl packet-3com-xns.c
41 # packet-3com-xns.c (2 (of 2) fields)
42 # 102 3comxns.type doesn't match PROTOABBREV of 3com-xns
43 # 106 3comxns.type doesn't match PROTOABBREV of 3com-xns
45 # or checkfiltername.pl packet-*.c, which will check all the dissector files.
58 my @acceptedprefixes = ("dcerpc-");
59 my @asn1automatedfilelist;
60 my @dcerpcautomatedfilelist;
61 my @idl2wrsautomatedfilelist;
62 my @filemanipulationfilelist;
67 my @noregprotocolfilelist;
68 my @periodinfilternamefilelist;
70 my $showlinenoFlag = '';
71 my $showautomatedFlag = '';
76 # "s_in_hf_register_info",
77 # "s_hf_register_info_entry",
78 # "s_header_field_info_entry",
79 # "s_header_field_info_entry_start",
80 # "s_header_field_info_entry_name",
81 # "s_header_field_info_entry_abbrev",
82 # "s_header_field_info_entry_abbrev_end",
84 # "s_in_ei_register_info",
85 # "s_ei_register_info_entry",
86 # "s_ei_register_info_entry_start",
87 # "s_ei_register_info_entry_abbrev_end",
95 my $PFNAME_value = "";
97 my $totalerrorcount = 0;
98 my $errorfilecount = 0;
102 my $noregprotocol = 1;
111 sub checkprotoabbrev
{
114 my $proto_abbrevpos1;
115 my $proto_abbrevpos2;
116 my $afterabbrev = "";
117 my $modprotabbrev = "";
121 if (($automated == 0) || ($showall == 1)) {
122 $abbrevpos = index($_[0], ".");
123 if ($abbrevpos == -1) {
127 $abbrev = substr($_[0], 0, $abbrevpos);
128 $afterabbrev = substr($_[0], $abbrevpos+1, length($_[0])-$abbrevpos);
129 $afterabbrev = substr($afterabbrev, 0, length($abbrev));
132 if ($abbrev ne $protabbrev) {
135 #check if there is a supported protocol that matches the abbrev.
136 #This may be a case of filename != PROTOABBREV
137 foreach (@protocols) {
140 } elsif (index($_, ".") != -1) {
142 #compare from start of string for each period found
143 $proto_abbrevpos1 = 0;
144 while ((($proto_abbrevpos2 = index($_, ".", $proto_abbrevpos1)) != -1) &&
146 if ($abbrev eq substr($_, 0, $proto_abbrevpos2)) {
150 $proto_abbrevpos1 = $proto_abbrevpos2+1;
156 # find any underscores that preface or follow a period
157 if ((index($_[0], "._") >= 0) || (index($_[0], "_.") >= 0)) {
158 if ($showlinenoFlag) {
159 push(@elements, "$_[1] $_[0] contains an unnecessary \'_\'\n");
161 push(@elements, "$_[0] contains an unnecessary \'_\'\n");
165 if (($errorline == 1) && ($showall == 0)) {
166 #try some "accepted" variations of PROTOABBREV
168 #replace '-' with '_'
169 $modprotabbrev = $protabbrev;
170 $modprotabbrev =~ s/-/_/g;
171 if ($abbrev eq $modprotabbrev) {
176 if ($errorline == 1) {
177 $modprotabbrev = $protabbrev;
178 $modprotabbrev =~ s/-//g;
179 if ($abbrev eq $modprotabbrev) {
185 if ($errorline == 1) {
186 $modprotabbrev = $protabbrev;
187 $modprotabbrev =~ s/_//g;
188 if ($abbrev eq $modprotabbrev) {
193 if ($errorline == 1) {
194 #remove any "accepted" prefix to see if there is still a problem
195 foreach (@acceptedprefixes) {
196 if ($protabbrev =~ /^$_/) {
197 $modprotabbrev = substr($protabbrev, length($_));
198 if ($abbrev eq $modprotabbrev) {
199 push(@prefixfilelist, "$currfile\n");
205 push(@filemanipulationfilelist, "$currfile\n");
209 if ($errorline == 1) {
210 $debug>1 && print "$_[1] $_[0] doesn't match PROTOABBREV of $protabbrev\n";
211 if ($showlinenoFlag) {
212 push(@elements, "$_[1] $_[0] doesn't match PROTOABBREV of $protabbrev\n");
214 push(@elements, "$_[0] doesn't match PROTOABBREV of $protabbrev\n");
218 if (($abbrev ne "") && (lc($abbrev) eq lc($afterabbrev))) {
219 if ($showlinenoFlag) {
220 push(@elements_dup, "$_[1] $_[0] duplicates PROTOABBREV of $abbrev\n");
222 push(@elements_dup, "$_[0] duplicates PROTOABBREV of $abbrev\n");
229 my $totalfields = keys(%filters);
234 foreach (sort keys %filters) {
235 checkprotoabbrev
($filters{$_}, $_);
238 foreach (sort keys %expert_filters) {
239 checkprotoabbrev
($expert_filters{$_}, $_);
242 $count_ele = @elements;
243 $count_dup = @elements_dup;
244 $total_count = $count_ele+$count_dup;
246 if ($noregprotocol == 1) {
247 #if no protocol is registered, only worry about duplicates
248 if ($currfile ne "") {
249 push(@noregprotocolfilelist, "$currfile\n");
252 if ($count_dup > 0) {
254 $totalerrorcount += $count_dup;
257 if (($showall == 1) || ($count_dup > 0)) {
258 print "\n\n$currfile - NO PROTOCOL REGISTERED\n";
260 #everything is included, so count all errors
261 $totalerrorcount += $count_ele;
262 if (($count_ele > 0) && ($count_dup == 0)) {
266 foreach (@elements) {
270 foreach (@elements_dup) {
275 if ($total_count > 0) {
277 $totalerrorcount += $total_count;
280 if (($automated == 0) || ($showall == 1)) {
281 if ($total_count > 0) {
282 if ($automated == 1) {
284 print "\n\n$currfile - AUTOMATED ($total_count (of $totalfields) fields)\n";
287 print "\n\n$currfile ($total_count (of $totalfields) fields)\n";
290 foreach (@elements) {
293 foreach (@elements_dup) {
298 if ((($nofields) || ($totalfields == 0)) && ($currfile ne "")) {
300 print "\n\n$currfile - NO FIELDS\n";
302 push(@nofieldfilelist, "$currfile\n");
308 # ---------------------------------------------------------------------
313 'showlineno' => \
$showlinenoFlag,
314 'showautomated' => \
$showautomatedFlag,
318 if ($currfile !~ /$ARGV/) {
321 # New file - reset array and state
325 #determine PROTABBREV for dissector based on file name format of (dirs)/packet-PROTABBREV.c
326 $protabbrev_index = rindex($currfile, "packet-");
327 if ($protabbrev_index == -1) {
328 print "$currfile doesn't fit format of packet-PROTABBREV.c\n";
332 $protabbrev = substr($currfile, $protabbrev_index+length("packet-"));
333 $protabbrev_index = rindex($protabbrev, ".");
334 if ($protabbrev_index == -1) {
335 print "$currfile doesn't fit format of packet-PROTABBREV.c\n";
338 $protabbrev = substr($protabbrev, 0, $protabbrev_index);
348 %expert_filters = ( );
352 $state = "s_unknown";
355 if (($automated == 0) && ($showautomatedFlag eq "")) {
356 #DCERPC automated files
357 if ($_ =~ "DO NOT EDIT") {
358 push(@dcerpcautomatedfilelist, "$currfile\n");
362 #ASN.1 automated files
363 elsif ($_ =~ "It is created automatically by the ASN.1 to Wireshark dissector compiler") {
364 push(@asn1automatedfilelist, "$currfile\n");
368 #idl2wrs automated files
369 elsif ($_ =~ "Autogenerated from idl2wrs") {
370 push(@idl2wrsautomatedfilelist, "$currfile\n");
376 # opening then closing comment
377 if (/(.*?)\/\
*.*\
*\
/(.*)/) {
380 # closing then opening comment
381 } elsif (/.*?\*\/(.*?
)\
/\*/) {
385 } elsif (/(.*?)\/\
*/) {
389 } elsif (/\*\/(.*?
)/) {
392 } elsif ($comment == 1) {
396 # unhandled: more than one complete comment per line
400 #proto_register_protocol state machine
404 #PFNAME is a popular #define for the proto filter name, so use it for testing
405 if ($restofline =~ /#define\s*PFNAME\s*\"([^\"]*)\"/) {
407 $debug>1 && print "PFNAME: '$1'\n";
410 until ($more_tokens == 0) {
411 if ($restofline =~ /proto_register_protocol\s*\((.*)/) {
414 $state = "s_proto_start";
415 } elsif (($state eq "s_proto_start") && ($restofline =~ /^(\s*\"([^\"]*)\"\s*,)\s*(.*)/)) {
417 $state = "s_proto_long_name";
418 $debug>1 && print "proto long name: '$2'\n";
419 } elsif (($state eq "s_proto_start") && ($restofline =~ /^(\s*(([\w\d])+)\s*,)\s*(.*)/)) {
421 $state = "s_proto_long_name";
422 $debug>1 && print "proto long name: '$2'\n";
423 } elsif (($state eq "s_proto_long_name") && ($restofline =~ /^(\s*\"([^\"]*)\"\s*,)\s*(.*)/)) {
425 $state = "s_proto_short_name";
426 $debug>1 && print "proto short name: '$2'\n";
427 } elsif (($state eq "s_proto_long_name") && ($restofline =~ /^(\s*(([\w\d])+)\s*,)\s*(.*)/)) {
429 $state = "s_proto_short_name";
430 $debug>1 && print "proto short name: '$2'\n";
431 } elsif (($state eq "s_proto_short_name") && ($restofline =~ /\s*PFNAME\s*(.*)/)) {
433 $state = "s_proto_filter_name";
434 if ((index($PFNAME_value, ".") != -1) && ($noperiod == 0)) {
435 push(@periodinfilternamefilelist, "$currfile\n");
438 push(@protocols, $PFNAME_value);
439 $debug>1 && print "proto filter name: '$PFNAME_value'\n";
440 } elsif (($state eq "s_proto_short_name") && ($restofline =~ /\s*\"([^\"]*)\"\s*(.*)/)) {
442 $state = "s_proto_filter_name";
443 if ((index($1, ".") != -1) && ($noperiod == 0)) {
444 push(@periodinfilternamefilelist, "$currfile\n");
447 push(@protocols, $1);
448 $debug>1 && print "proto filter name: '$1'\n";
449 } elsif (($state eq "s_proto_short_name") && ($restofline =~ /\s*(([\w\d])+)\s*(.*)/)) {
451 $state = "s_proto_filter_name";
452 $debug>1 && print "proto filter name: '$1'\n";
458 #retrieving display filters state machine
461 until ($more_tokens == 0) {
462 if ($restofline =~ /\s*static\s*hf_register_info\s*(\w+)\[\](.*)/) {
465 $debug>1 && print "$linenumber $state\n";
466 } elsif ($restofline =~ /\s*static\s*ei_register_info\s*(\w+)\[\](.*)/) {
468 $state = "s_start_expert";
469 $debug>1 && print "$linenumber $state\n";
470 } elsif (($state eq "s_start") && ($restofline =~ /\W+{(.*)/)) {
472 $state = "s_in_hf_register_info";
473 $debug>1 && print "$linenumber $state\n";
474 } elsif (($state eq "s_in_hf_register_info") && ($restofline =~ /\W+{(.*)/)) {
476 $state = "s_hf_register_info_entry";
477 $debug>1 && print "$linenumber $state\n";
479 } elsif (($state eq "s_in_hf_register_info") && ($restofline =~ /\s*};(.*)/)) {
481 if ($onefield == 0) {
482 $debug && print "$linenumber NO FIELDS!!!\n";
484 $state = "s_nofields";
487 $state = "s_unknown";
489 } elsif (($state eq "s_hf_register_info_entry") && ($restofline =~ /\s*&\s*(hf_\w*(\[w*\])?)\s*,?(.*)/)) {
491 $debug>1 && print "$linenumber hf_register_info_entry: $1\n";
492 $state = "s_header_field_info_entry";
493 } elsif (($state eq "s_header_field_info_entry") && ($restofline =~ /\s*{(.*)/)) {
495 $state = "s_header_field_info_entry_start";
496 $debug>1 && print "$linenumber $state\n";
497 } elsif (($state eq "s_header_field_info_entry_start") && ($restofline =~ /\"([^\"]*)\"\s*,(.*)/)) {
499 $debug>1 && print "$linenumber header_field_info_entry_name: $1\n";
500 $state = "s_header_field_info_entry_name";
501 } elsif (($state eq "s_header_field_info_entry_name") && ($restofline =~ /\"([^\"]*)\"\s*,?(.*)/)) {
503 $debug>1 && print "$linenumber header_field_info_entry_abbrev: $1\n";
504 $state = "s_header_field_info_entry_abbrev";
505 $filters{$linenumber} = $1;
506 } elsif (($state eq "s_header_field_info_entry_abbrev") && ($restofline =~ /[^}]*}(.*)/)) {
508 $state = "s_header_field_info_entry_abbrev_end";
509 $debug>1 && print "$linenumber $state\n";
510 } elsif (($state eq "s_header_field_info_entry_abbrev_end") && ($restofline =~ /[^}]*}(.*)/)) {
512 $state = "s_in_hf_register_info";
513 $debug>1 && print "$linenumber $state\n";
514 } elsif (($state eq "s_start_expert") && ($restofline =~ /\W+{(.*)/)) {
516 $state = "s_in_ei_register_info";
517 $debug>1 && print "$linenumber $state\n";
518 } elsif (($state eq "s_in_ei_register_info") && ($restofline =~ /\W+{(.*)/)) {
520 $state = "s_ei_register_info_entry";
521 $debug>1 && print "$linenumber $state\n";
522 } elsif (($state eq "s_in_ei_register_info") && ($restofline =~ /\s*};(.*)/)) {
524 $state = "s_unknown";
525 } elsif (($state eq "s_ei_register_info_entry") && ($restofline =~ /\s*{(.*)/)) {
527 $state = "s_ei_register_info_entry_start";
528 $debug>1 && print "$linenumber $state\n";
529 } elsif (($state eq "s_ei_register_info_entry_start") && ($restofline =~ /\"([^\"]*)\"\s*,(.*)/)) {
531 $debug>1 && print "$linenumber ei_register_info_entry_abbrev: $1\n";
532 $expert_filters{$linenumber} = $1;
533 $state = "s_ei_register_info_entry_abbrev_end";
534 } elsif (($state eq "s_ei_register_info_entry_abbrev_end") && ($restofline =~ /[^}]*}(.*)/)) {
536 $state = "s_in_ei_register_info";
537 $debug>1 && print "$linenumber $state\n";
548 print "\n\nTOTAL ERRORS: $totalerrorcount";
549 if ($filecount > 1) {
550 print " ($errorfilecount files)\n";
552 print "NO FIELDS: " . scalar(@nofieldfilelist) . "\n";
553 print "AUTOMATED: " . (scalar(@asn1automatedfilelist) + scalar(@dcerpcautomatedfilelist) + scalar(@idl2wrsautomatedfilelist)) . "\n";
554 print "NO PROTOCOL: " . scalar(@noregprotocolfilelist) . "\n";
556 print "\nASN.1 AUTOMATED FILE LIST\n";
557 foreach (@asn1automatedfilelist) {
560 print "\nDCE/RPC AUTOMATED FILE LIST\n";
561 foreach (@dcerpcautomatedfilelist) {
564 print "\nIDL2WRS AUTOMATED FILE LIST\n";
565 foreach (@idl2wrsautomatedfilelist) {
568 print "\n\"FILE MANIPULATION\" FILE LIST\n";
569 @uniquefilelist = grep{ not $unique{$_}++} @filemanipulationfilelist;
570 foreach (@uniquefilelist) {
573 print "\nREMOVE PREFIX FILE LIST\n";
574 @uniquefilelist = grep{ not $unique{$_}++} @prefixfilelist;
575 foreach (@uniquefilelist) {
578 print "\nNO PROTOCOL REGISTERED FILE LIST\n";
579 foreach (@noregprotocolfilelist) {
582 print "\nNO FIELDS FILE LIST\n";
583 foreach (@nofieldfilelist) {
587 print "\nPERIOD IN PROTO FILTER NAME FILE LIST\n";
588 foreach (@periodinfilternamefilelist) {