1
###################################################
2
# parse an Wireshark conformance file
3
# Copyright jelmer@samba.org 2005
4
# released under the GNU GPL
10
Parse::Pidl::Wireshark::Conformance - Conformance file parser for Wireshark
14
This module supports parsing Wireshark conformance files (*.cnf).
18
Pidl needs additional data for Wireshark output. This data is read from
19
so-called conformance files. This section describes the format of these
22
Conformance files are simple text files with a single command on each line.
23
Empty lines and lines starting with a '#' character are ignored.
24
Arguments to commands are seperated by spaces.
26
The following commands are currently supported:
30
=item I<TYPE> name dissector ft_type base_type mask valsstring alignment
32
Register new data type with specified name, what dissector function to call
33
and what properties to give header fields for elements of this type.
37
Suppress emitting a dissect_type function for the specified type
39
=item I<PARAM_VALUE> type param
41
Set parameter to specify to dissector function for given type.
43
=item I<HF_FIELD> hf title filter ft_type base_type valsstring mask description
45
Generate a custom header field with specified properties.
47
=item I<HF_RENAME> old_hf_name new_hf_name
49
Force the use of new_hf_name when the parser generator was going to
52
This can be used in conjunction with HF_FIELD in order to make more than
53
one element use the same filter name.
55
=item I<ETT_FIELD> ett
57
Register a custom ett field
59
=item I<STRIP_PREFIX> prefix
61
Remove the specified prefix from all function names (if present).
63
=item I<PROTOCOL> longname shortname filtername
65
Change the short-, long- and filter-name for the current interface in
68
=item I<FIELD_DESCRIPTION> field desc
70
Change description for the specified header field. `field' is the hf name of the field.
72
=item I<IMPORT> dissector code...
74
Code to insert when generating the specified dissector. @HF@ and
75
@PARAM@ will be substituted.
77
=item I<INCLUDE> filename
79
Include conformance data from the specified filename in the dissector.
81
=item I<TFS> hf_name "true string" "false string"
83
Override the text shown when a bitmap boolean value is enabled or disabled.
85
=item I<MANUAL> fn_name
87
Force pidl to not generate a particular function but allow the user
88
to write a function manually. This can be used to remove the function
89
for only one level for a particular element rather than all the functions and
90
ett/hf variables for a particular element as the NOEMIT command does.
100
package Parse::Pidl::Wireshark::Conformance;
103
use vars qw($VERSION);
107
@EXPORT_OK = qw(ReadConformance ReadConformanceFH valid_ft_type valid_base_type);
111
use Parse::Pidl qw(fatal warning error);
112
use Parse::Pidl::Util qw(has_property);
114
sub handle_type($$$$$$$$$$)
116
my ($pos,$data,$name,$dissectorname,$ft_type,$base_type,$mask,$valsstring,$alignment) = @_;
118
unless(defined($alignment)) {
119
error($pos, "incomplete TYPE command");
123
unless ($dissectorname =~ /.*dissect_.*/) {
124
warning($pos, "dissector name does not contain `dissect'");
127
unless(valid_ft_type($ft_type)) {
128
warning($pos, "invalid FT_TYPE `$ft_type'");
131
unless (valid_base_type($base_type)) {
132
warning($pos, "invalid BASE_TYPE `$base_type'");
135
$dissectorname =~ s/^\"(.*)\"$/$1/g;
137
if (not ($dissectorname =~ /;$/)) {
138
warning($pos, "missing semicolon");
141
$data->{types}->{$name} = {
145
DISSECTOR_NAME => $dissectorname,
147
BASE_TYPE => $base_type,
149
VALSSTRING => $valsstring,
150
ALIGNMENT => $alignment
154
sub handle_tfs($$$$$)
156
my ($pos,$data,$hf,$trues,$falses) = @_;
158
unless(defined($falses)) {
159
error($pos, "incomplete TFS command");
163
$data->{tfs}->{$hf} = {
164
TRUE_STRING => $trues,
165
FALSE_STRING => $falses
169
sub handle_hf_rename($$$$)
171
my ($pos,$data,$old,$new) = @_;
173
unless(defined($new)) {
174
warning($pos, "incomplete HF_RENAME command");
178
$data->{hf_renames}->{$old} = {
186
sub handle_param_value($$$$)
188
my ($pos,$data,$dissector_name,$value) = @_;
190
unless(defined($value)) {
191
error($pos, "incomplete PARAM_VALUE command");
195
$data->{dissectorparams}->{$dissector_name} = {
196
DISSECTOR => $dissector_name,
203
sub valid_base_type($)
206
return 0 unless($t =~ /^BASE_.*/);
213
return 0 unless($t =~ /^FT_.*/);
217
sub handle_hf_field($$$$$$$$$$)
219
my ($pos,$data,$index,$name,$filter,$ft_type,$base_type,$valsstring,$mask,$blurb) = @_;
221
unless(defined($blurb)) {
222
error($pos, "incomplete HF_FIELD command");
226
unless(valid_ft_type($ft_type)) {
227
warning($pos, "invalid FT_TYPE `$ft_type'");
230
unless(valid_base_type($base_type)) {
231
warning($pos, "invalid BASE_TYPE `$base_type'");
234
$data->{header_fields}->{$index} = {
241
BASE_TYPE => $base_type,
242
VALSSTRING => $valsstring,
248
sub handle_strip_prefix($$$)
250
my ($pos,$data,$x) = @_;
252
push (@{$data->{strip_prefixes}}, $x);
255
sub handle_noemit($$$)
257
my ($pos,$data,$type) = @_;
259
if (defined($type)) {
260
$data->{noemit}->{$type} = 1;
262
$data->{noemit_dissector} = 1;
266
sub handle_manual($$$)
268
my ($pos,$data,$fn) = @_;
270
unless(defined($fn)) {
271
warning($pos, "incomplete MANUAL command");
275
$data->{manual}->{$fn} = 1;
278
sub handle_protocol($$$$$$)
280
my ($pos, $data, $name, $longname, $shortname, $filtername) = @_;
282
$data->{protocols}->{$name} = {
283
LONGNAME => $longname,
284
SHORTNAME => $shortname,
285
FILTERNAME => $filtername
289
sub handle_fielddescription($$$$)
291
my ($pos,$data,$field,$desc) = @_;
293
unless(defined($desc)) {
294
warning($pos, "incomplete FIELD_DESCRIPTION command");
298
$data->{fielddescription}->{$field} = {
299
DESCRIPTION => $desc,
309
my $dissectorname = shift @_;
311
unless(defined($dissectorname)) {
312
error($pos, "no dissectorname specified");
316
$data->{imports}->{$dissectorname} = {
317
NAME => $dissectorname,
318
DATA => join(' ', @_),
330
unless(defined($ett)) {
331
error($pos, "incomplete ETT_FIELD command");
335
push (@{$data->{ett}}, $ett);
344
unless(defined($fn)) {
345
error($pos, "incomplete INCLUDE command");
349
ReadConformance($fn, $data);
352
my %field_handlers = (
353
TYPE => \&handle_type,
354
NOEMIT => \&handle_noemit,
355
MANUAL => \&handle_manual,
356
PARAM_VALUE => \&handle_param_value,
357
HF_FIELD => \&handle_hf_field,
358
HF_RENAME => \&handle_hf_rename,
359
ETT_FIELD => \&handle_ett_field,
361
STRIP_PREFIX => \&handle_strip_prefix,
362
PROTOCOL => \&handle_protocol,
363
FIELD_DESCRIPTION => \&handle_fielddescription,
364
IMPORT => \&handle_import,
365
INCLUDE => \&handle_include
368
sub ReadConformance($$)
373
open(IN,"<$f") or return undef;
375
$ret = ReadConformanceFH(*IN, $data, $f);
382
sub ReadConformanceFH($$$)
384
my ($fh,$data,$f) = @_;
397
if ($_ eq "CODE START") {
400
} elsif ($incodeblock and $_ eq "CODE END") {
403
} elsif ($incodeblock) {
404
if (exists $data->{override}) {
405
$data->{override}.="$_\n";
407
$data->{override} = "$_\n";
412
my @fields = /([^ "]+|"[^"]+")/g;
414
my $cmd = $fields[0];
418
my $pos = { FILE => $f, LINE => $ln };
420
next unless(defined($cmd));
422
if (not defined($field_handlers{$cmd})) {
423
warning($pos, "Unknown command `$cmd'");
427
$field_handlers{$cmd}($pos, $data, @fields);
431
warning({ FILE => $f, LINE => $ln },
432
"Expecting CODE END");