3 # Copyright 2013 Michael Mann (see AUTHORS file)
5 # A program to help convert the "old" expert_add_info_format API calls into filterable "items" that
6 # use the other expert API calls. The program requires 2 passes. "Pass 1" (generate) collects
7 # the eligible expert_add_info_format calls and outputs the necessary data into a delimited
8 # file. "Pass 2" (fix-all) takes the data from the delimited file and replaces the
9 # expert_add_info_format calls with filterable "expert info" calls as well as
10 # generating a separate files for the ei variable declarations and array data.
11 # The ei "file" can be copy/pasted into the dissector where appropriate
13 # Note that the output from "Pass 1" won't always be a perfect conversion for "Pass 2", so
14 # "human interaction" is needed as an intermediary to verify and update the delimited file
15 # before "Pass 2" is done.
17 # Delimited file field format:
18 # <convert expert_add_info_format_call[1-4]><add ei variable[0|1]><ei var><[GROUP]><[SEVERITY]><[FIELDNAME]><[EXPERTABBREV]>
19 # <pinfo var><proto_item var><tvb var><offset><length><params>
21 # convert proto_tree_add_text_call enumerations:
23 # 2 - expert_add_info_format
24 # 3 - proto_tree_add_expert
25 # 4 - proto_tree_add_expert_format
27 # Usage: convert_expert_add_info_format.pl action=<generate|fix-all> <file or files>
29 # Based off of convert_proto_tree_add_text.pl
33 # Wireshark - Network traffic analyzer
34 # By Gerald Combs <gerald@wireshark.org>
35 # Copyright 1998 Gerald Combs
37 # This program is free software; you can redistribute it and/or
38 # modify it under the terms of the GNU General Public License
39 # as published by the Free Software Foundation; either version 2
40 # of the License, or (at your option) any later version.
42 # This program is distributed in the hope that it will be useful,
43 # but WITHOUT ANY WARRANTY; without even the implied warranty of
44 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
45 # GNU General Public License for more details.
47 # You should have received a copy of the GNU General Public License
48 # along with this program; if not, write to the Free Software
49 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
57 my %EXPERT_SEVERITY = ('PI_COMMENT' => "PI_COMMENT",
58 'PI_CHAT' => "PI_CHAT",
59 'PI_NOTE' => "PI_NOTE",
60 'PI_WARN' => "PI_WARN",
61 'PI_ERROR' => "PI_ERROR");
63 my %EXPERT_GROUPS = ('PI_CHECKSUM' => "PI_CHECKSUM",
64 'PI_SEQUENCE' => "PI_SEQUENCE",
65 'PI_RESPONSE_CODE' => "PI_RESPONSE_CODE",
66 'PI_REQUEST_CODE' => "PI_REQUEST_CODE",
67 'PI_UNDECODED' => "PI_UNDECODED",
68 'PI_REASSEMBLE' => "PI_REASSEMBLE",
69 'PI_MALFORMED' => "PI_MALFORMED",
70 'PI_DEBUG' => "PI_DEBUG",
71 'PI_PROTOCOL' => "PI_PROTOCOL",
72 'PI_SECURITY' => "PI_SECURITY",
73 'PI_COMMENTS_GROUP' => "PI_COMMENTS_GROUP");
78 # Perl trim function to remove whitespace from the start and end of the string
87 # ---------------------------------------------------------------------
92 my $action = 'generate';
95 my $result = GetOptions
(
96 'action=s' => \
$action,
97 'register' => \
$register,
98 'help|?' => \
$helpFlag
101 if (!$result || $helpFlag || !$ARGV[0]) {
106 print "\nUsage: $0 [--action=generate|fix-all|find-all] FILENAME [...]\n\n";
107 print " --action = generate (default)\n";
108 print " generate - create a delimited file (FILENAME.expert_add_info_input) with\n";
109 print " expert_add_info_format fields in FILENAME(s)\n";
110 print " fix-all - Use delimited file (FILENAME.expert_add_info_input) to convert\n";
111 print " expert_add_info_format to \"filterable\" expert API\n";
112 print " Also generates FILENAME.ei to be copy/pasted into\n";
113 print " the dissector where appropriate\n\n";
114 print " --register = generate ei_register_info and expert register function calls\n\n";
120 # XXX Outline general algorithm here
123 my $protabbrev_index;
126 while (my $fileName = $ARGV[0]) {
128 my $fileContents = '';
130 die "No such file: \"$fileName\"\n" if (! -e
$fileName);
132 # delete leading './'
133 $fileName =~ s{ ^ \. / } {}xo;
135 #determine PROTABBREV for dissector based on file name format of (dirs)/packet-PROTABBREV.c
136 $protabbrev_index = rindex($fileName, "packet-");
137 if ($protabbrev_index == -1) {
138 print "$fileName doesn't fit format of packet-PROTABBREV.c\n";
142 $protabbrev = substr($fileName, $protabbrev_index+length("packet-"));
143 $protabbrev_index = rindex($protabbrev, ".");
144 if ($protabbrev_index == -1) {
145 print "$fileName doesn't fit format of packet-PROTABBREV.c\n";
148 $protabbrev = lc(substr($protabbrev, 0, $protabbrev_index));
150 # Read in the file (ouch, but it's easier that way)
151 open(FCI
, "<", $fileName) || die("Couldn't open $fileName");
157 if ($action eq "generate") {
158 generate_eis
(\
$fileContents, $fileName);
161 if ($action eq "fix-all") {
162 # Read in the ei "input" file
165 open(FCI
, "<", $fileName . ".expert_add_info_input") || die("Couldn't open $fileName.expert_add_info_input");
166 while(my $line=<FCI
>){
167 my @expert_item = split(/;|\n/, $line);
170 $errors += verify_line
(@expert_item);
172 push(@expert_list, \
@expert_item);
177 print "Aborting conversion.\n";
181 fix_expert_add_info_format
(\
$fileContents, $fileName);
183 # Write out the ei data
184 output_ei_data
($fileName);
186 # Write out the changed version to a file
187 open(FCO
, ">", $fileName . ".expert_add_info_format");
188 print FCO
"$fileContents";
196 # ---------------------------------------------------------------------
197 # Sanity check the data in the .proto_tree_input file
199 my( @expert_item) = @_;
202 #do some basic error checking of the file
203 if (($expert_item[0] eq "1") ||
204 ($expert_item[0] eq "2") ||
205 ($expert_item[0] eq "3") ||
206 ($expert_item[0] eq "4")) {
207 #expert info conversions
208 if (!($expert_item[2] =~ /^ei_/)) {
209 print "$line_number: Poorly formed ei_ variable ($expert_item[2])!\n";
213 print "$line_number: Bad conversion value!\n";
217 if ($expert_item[1] eq "1") {
218 if (!($expert_item[2] =~ /^ei_/)) {
219 print "$line_number: Poorly formed ei_ variable ($expert_item[2])!\n";
222 if (!exists($EXPERT_SEVERITY{$expert_item[4]})) {
223 print "$line_number: Expert severity value '$expert_item[5]' unknown!\n";
226 if (!exists($EXPERT_GROUPS{$expert_item[3]})) {
227 print "$line_number: Expert group value '$expert_item[4]' unknown!\n";
231 } elsif ($expert_item[1] ne "0") {
232 print "$line_number: Bad ei variable generation value!\n";
240 my( $fileContentsRef, $fileName) = @_;
249 (?
:expert_add_info_format
)\s
* \
(
256 while ($$fileContentsRef =~ / $pat /xgso) {
258 my @expert_item = (1, 1, "ei_name", "GROUP", "SEVERITY", "fieldfullname", "fieldabbrevname",
259 "pinfo", "item", "tvb", "offset", "length", "params");
262 $str =~ tr/\t\n\r/ /d;
263 $str =~ s/ \s+ / /xg;
264 #print "$fileName: $str\n";
266 @args = split(/,/, $str);
267 #printf "ARGS(%d): %s\n", scalar @args, join("# ", @args);
268 $args[0] =~ s/expert_add_info_format\s*\(\s*//;
270 $expert_item[7] = $args[0]; #pinfo
271 $expert_item[8] = trim
($args[1]); #item
272 $expert_item[3] = trim
($args[2]); #GROUP
273 $expert_item[4] = trim
($args[3]); #SEVERITY
274 $expert_item[5] = trim
($args[4]); #fieldfullname
275 $expert_item[5] =~ s/\"//;
278 $expert_item[5] =~ s/\"\s*\)\s*;$//;
279 $expert_item[5] =~ s/\"$//;
282 $expert_item[12] = "";
283 while ($arg_loop < scalar @args) {
284 $expert_item[12] .= trim
($args[$arg_loop]);
285 if ($arg_loop+1 < scalar @args) {
286 $expert_item[12] .= ", ";
290 $expert_item[12] =~ s/\s*\)\s*;$//;
293 $expert_item[2] = sprintf("ei_%s_%s", $protabbrev, lc($expert_item[5]));
294 $expert_item[2] =~ s/\s+|-|:/_/g;
296 #field abbreviated name
297 $expert_item[6] = sprintf("%s.%s", $protabbrev, lc($expert_item[5]));
298 $expert_item[6] =~ s/\s+|-|:/_/g;
300 push(@expert_list, \
@expert_item);
305 if ($num_items > 0) {
306 open(FCO
, ">", $fileName . ".expert_add_info_input");
307 for my $item (@expert_list) {
308 print FCO
join(";", @
{$item}), "\n";
314 # ---------------------------------------------------------------------
315 # Find all expert_add_info_format calls and replace them with the data
316 # found in expert_list
317 sub fix_expert_add_info_format
{
318 my( $fileContentsRef, $fileName) = @_;
324 (?
:expert_add_info_format
)\s
* \
(
331 $$fileContentsRef =~ s/ $pat /patsub($found, $1)/xges;
334 # ---------------------------------------------------------------------
335 # Format expert info functions with expert_list data
339 #print $expert_list[$_[0]][2] . " = ";
340 #print $#{$expert_list[$_[0]]}+1;
343 if ($expert_list[$_[0]][0] eq "1") {
344 $item_str = sprintf("expert_add_info(%s, %s, &%s);",
345 $expert_list[$_[0]][7], $expert_list[$_[0]][8], $expert_list[$_[0]][2]);
346 } elsif ($expert_list[$_[0]][0] eq "2") {
347 $item_str = sprintf("expert_add_info_format(%s, %s, &%s, \"%s\"",
348 $expert_list[$_[0]][7], $expert_list[$_[0]][8],
349 $expert_list[$_[0]][2], $expert_list[$_[0]][5]);
350 if (($#{$expert_list[$_[0]]}+1 > 12 ) && ($expert_list[$_[0]][12] ne "")) {
351 $item_str .= ", $expert_list[$_[0]][12]";
354 } elsif ($expert_list[$_[0]][0] eq "3") {
355 $item_str = sprintf("proto_tree_add_expert(%s, %s, &%s, %s, %s, %s);",
356 $expert_list[$_[0]][8], $expert_list[$_[0]][7],
357 $expert_list[$_[0]][2], $expert_list[$_[0]][9],
358 $expert_list[$_[0]][10], $expert_list[$_[0]][11]);
359 } elsif ($expert_list[$_[0]][0] eq "4") {
360 $item_str = sprintf("proto_tree_add_expert_format(%s, %s, &%s, %s, %s, %s, \"%s\"",
361 $expert_list[$_[0]][8], $expert_list[$_[0]][7], $expert_list[$_[0]][2],
362 $expert_list[$_[0]][9], $expert_list[$_[0]][10],
363 $expert_list[$_[0]][11], $expert_list[$_[0]][5]);
364 if (($#{$expert_list[$_[0]]}+1 > 12) && ($expert_list[$_[0]][12] ne "")) {
365 $item_str .= ", $expert_list[$_[0]][12]";
375 # ---------------------------------------------------------------------
376 # Output the ei variable declarations and expert array. For now, write them to a file.
377 # XXX - Eventually find the right place to add it to the modified dissector file
384 #add ei to hash table to prevent against (accidental) duplicates
385 for ($index=0;$index<@expert_list;$index++) {
386 if ($expert_list[$index][1] eq "1") {
387 $eis{$expert_list[$index][2]} = $expert_list[$index][2];
391 open(FCO
, ">", $fileName . ".ei");
393 print FCO
"/* Generated from convert_expert_add_info_format.pl */\n";
395 foreach $key (keys %eis) {
396 print FCO
"static expert_field $key = EI_INIT;\n";
400 if ($register ne "") {
401 print FCO
" static ei_register_info ei[] = {\n";
405 for ($index=0;$index<@expert_list;$index++) {
406 if ($expert_list[$index][1] eq "1") {
407 if (exists($eis{$expert_list[$index][2]})) {
408 print "duplicate ei entry '$expert_list[$index][2]' found! Aborting conversion.\n";
411 $eis{$expert_list[$index][2]} = $expert_list[$index][2];
413 print FCO
" { &$expert_list[$index][2], { \"$expert_list[$index][6]\", $expert_list[$index][3], ";
414 print FCO
"$expert_list[$index][4], \"$expert_list[$index][5]\", EXPFILL }},\r\n";
418 if ($register ne "") {
419 print FCO
" };\n\n\n";
420 print FCO
" expert_module_t* expert_$protabbrev;\n\n";
422 print FCO
" expert_$protabbrev = expert_register_protocol(proto_$protabbrev);\n";
423 print FCO
" expert_register_field_array(expert_$protabbrev, ei, array_length(ei));\n\n";