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");