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 separated 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);
113 use Parse
::Pidl
::Typelist
qw(addType);
115 sub handle_type
($$$$$$$$$$)
117 my ($pos,$data,$name,$dissectorname,$ft_type,$base_type,$mask,$valsstring,$alignment) = @_;
119 unless(defined($alignment)) {
120 error
($pos, "incomplete TYPE command");
124 unless ($dissectorname =~ /.*dissect_.*/) {
125 warning
($pos, "dissector name does not contain `dissect'");
128 unless(valid_ft_type
($ft_type)) {
129 warning
($pos, "invalid FT_TYPE `$ft_type'");
132 unless (valid_base_type
($base_type)) {
133 warning
($pos, "invalid BASE_TYPE `$base_type'");
136 $dissectorname =~ s/^\"(.*)\"$/$1/g;
138 if (not ($dissectorname =~ /;$/)) {
139 warning
($pos, "missing semicolon");
142 $data->{types
}->{$name} = {
146 DISSECTOR_NAME
=> $dissectorname,
148 BASE_TYPE
=> $base_type,
150 VALSSTRING
=> $valsstring,
151 ALIGNMENT
=> $alignment
156 TYPE
=> "CONFORMANCE",
157 BASEFILE
=> "conformance file",
160 TYPE
=> "CONFORMANCE",
166 sub handle_tfs
($$$$$)
168 my ($pos,$data,$hf,$trues,$falses) = @_;
170 unless(defined($falses)) {
171 error
($pos, "incomplete TFS command");
175 $data->{tfs
}->{$hf} = {
176 TRUE_STRING
=> $trues,
177 FALSE_STRING
=> $falses
181 sub handle_hf_rename
($$$$)
183 my ($pos,$data,$old,$new) = @_;
185 unless(defined($new)) {
186 warning
($pos, "incomplete HF_RENAME command");
190 $data->{hf_renames
}->{$old} = {
198 sub handle_param_value
($$$$)
200 my ($pos,$data,$dissector_name,$value) = @_;
202 unless(defined($value)) {
203 error
($pos, "incomplete PARAM_VALUE command");
207 $data->{dissectorparams
}->{$dissector_name} = {
208 DISSECTOR
=> $dissector_name,
215 sub valid_base_type
($)
218 return 0 unless($t =~ /^BASE_.*/);
225 return 0 unless($t =~ /^FT_.*/);
229 sub handle_hf_field
($$$$$$$$$$)
231 my ($pos,$data,$index,$name,$filter,$ft_type,$base_type,$valsstring,$mask,$blurb) = @_;
233 unless(defined($blurb)) {
234 error
($pos, "incomplete HF_FIELD command");
238 unless(valid_ft_type
($ft_type)) {
239 warning
($pos, "invalid FT_TYPE `$ft_type'");
242 unless(valid_base_type
($base_type)) {
243 warning
($pos, "invalid BASE_TYPE `$base_type'");
246 $data->{header_fields
}->{$index} = {
253 BASE_TYPE
=> $base_type,
254 VALSSTRING
=> $valsstring,
260 sub handle_strip_prefix
($$$)
262 my ($pos,$data,$x) = @_;
264 push (@
{$data->{strip_prefixes
}}, $x);
267 sub handle_noemit
($$$)
269 my ($pos,$data,$type) = @_;
271 if (defined($type)) {
272 $data->{noemit
}->{$type} = 1;
274 $data->{noemit_dissector
} = 1;
278 sub handle_manual
($$$)
280 my ($pos,$data,$fn) = @_;
282 unless(defined($fn)) {
283 warning
($pos, "incomplete MANUAL command");
287 $data->{manual
}->{$fn} = 1;
290 sub handle_protocol
($$$$$$)
292 my ($pos, $data, $name, $longname, $shortname, $filtername) = @_;
294 $data->{protocols
}->{$name} = {
295 LONGNAME
=> $longname,
296 SHORTNAME
=> $shortname,
297 FILTERNAME
=> $filtername
301 sub handle_fielddescription
($$$$)
303 my ($pos,$data,$field,$desc) = @_;
305 unless(defined($desc)) {
306 warning
($pos, "incomplete FIELD_DESCRIPTION command");
310 $data->{fielddescription
}->{$field} = {
311 DESCRIPTION
=> $desc,
321 my $dissectorname = shift @_;
323 unless(defined($dissectorname)) {
324 error
($pos, "no dissectorname specified");
328 $data->{imports
}->{$dissectorname} = {
329 NAME
=> $dissectorname,
330 DATA
=> join(' ', @_),
342 unless(defined($ett)) {
343 error
($pos, "incomplete ETT_FIELD command");
347 push (@
{$data->{ett
}}, $ett);
356 unless(defined($fn)) {
357 error
($pos, "incomplete INCLUDE command");
361 ReadConformance
($fn, $data);
364 my %field_handlers = (
365 TYPE
=> \
&handle_type
,
366 NOEMIT
=> \
&handle_noemit
,
367 MANUAL
=> \
&handle_manual
,
368 PARAM_VALUE
=> \
&handle_param_value
,
369 HF_FIELD
=> \
&handle_hf_field
,
370 HF_RENAME
=> \
&handle_hf_rename
,
371 ETT_FIELD
=> \
&handle_ett_field
,
373 STRIP_PREFIX
=> \
&handle_strip_prefix
,
374 PROTOCOL
=> \
&handle_protocol
,
375 FIELD_DESCRIPTION
=> \
&handle_fielddescription
,
376 IMPORT
=> \
&handle_import
,
377 INCLUDE
=> \
&handle_include
380 sub ReadConformance
($$)
385 open(IN
,"<$f") or return undef;
387 $ret = ReadConformanceFH
(*IN
, $data, $f);
394 sub ReadConformanceFH
($$$)
396 my ($fh,$data,$f) = @_;
409 if ($_ eq "CODE START") {
412 } elsif ($incodeblock and $_ eq "CODE END") {
415 } elsif ($incodeblock) {
416 if (exists $data->{override
}) {
417 $data->{override
}.="$_\n";
419 $data->{override
} = "$_\n";
424 my @fields = /([^ "]+|"[^"]+")/g;
426 my $cmd = $fields[0];
430 my $pos = { FILE
=> $f, LINE
=> $ln };
432 next unless(defined($cmd));
434 if (not defined($field_handlers{$cmd})) {
435 warning
($pos, "Unknown command `$cmd'");
439 $field_handlers{$cmd}($pos, $data, @fields);
443 warning
({ FILE
=> $f, LINE
=> $ln },
444 "Expecting CODE END");