~ubuntu-branches/ubuntu/maverick/samba/maverick-security

« back to all changes in this revision

Viewing changes to source/pidl/lib/Parse/Pidl/Wireshark/NDR.pm

  • Committer: Bazaar Package Importer
  • Author(s): Steve Langasek
  • Date: 2009-03-03 22:02:23 UTC
  • mfrom: (0.28.1 squeeze)
  • Revision ID: james.westby@ubuntu.com-20090303220223-3bdlm2d9fwx1p1ye
Tags: 2:3.3.1-1ubuntu1
* Merge from Debian unstable (LP: #337094), remaining changes:
  + debian/patches/VERSION.patch:
    - setup SAMBA_VERSION_SUFFIX to Ubuntu.
  + debian/smb.conf:
    - add "(Samba, Ubuntu)" to server string.
    - comment out the default [homes] share, and add a comment about
      "valid users = %S" to show users how to restrict access to
      \\server\username to only username.
    - Set 'usershare allow guests', so that usershare admins are 
      allowed to create public shares in addition to authenticated
      ones.
    - add map to guest = Bad user, maps bad username to guest access. 
  + debian/samba-common.config:
    - Do not change priority to high if dhclient3 is installed.
    - Use priority medium instead of high for the workgroup question.
  + debian/mksambapasswd.awk:
    - Do not add user with UID less than 1000 to smbpasswd.
  + debian/control:
    - Make libwbclient0 replace/conflict with hardy's likewise-open.
    - Don't build against ctdb.
  + debian/rules:
    - enable "native" PIE hardening.
  + Add ufw integration:
    - Created debian/samba.ufw.profile
    - debian/rules, debian/samba.dirs, debian/samba.files: install
      profile
    - debian/control: have samba suggest ufw
* Dropped changes, merged in Debian:
  + debian/libpam-smbpass.pam-config, debian/libpam-smbpass.postinst,
    debian/libpam-smbpass.prerm, debian/libpam-smbpass.files,
    debian/rules:
    - Make libpam-smbpasswd depend on libpam-runtime to allow 
      libpam-smbpasswd for auto-configuration.
  + debian/control:
    - Provide a config block for the new PAM framework to auto-configure
      itself
  + debian/samba.postinst:
    - When populating the new sambashare group, it is not an error
      if the user simply does not exist; test for this case and let
      the install continue instead of aborting.
  + debian/winbind.files:
    - include additional files

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
##################################################
 
2
# Samba4 NDR parser generator for IDL structures
 
3
# Copyright tridge@samba.org 2000-2003
 
4
# Copyright tpot@samba.org 2001,2005
 
5
# Copyright jelmer@samba.org 2004-2007
 
6
# Portions based on idl2eth.c by Ronnie Sahlberg
 
7
# released under the GNU GPL
 
8
 
 
9
=pod
 
10
 
 
11
=head1 NAME
 
12
 
 
13
Parse::Pidl::Wireshark::NDR - Parser generator for Wireshark
 
14
 
 
15
=cut
 
16
 
 
17
package Parse::Pidl::Wireshark::NDR;
 
18
 
 
19
use Exporter;
 
20
@ISA = qw(Exporter);
 
21
@EXPORT_OK = qw(field2name %res PrintIdl StripPrefixes RegisterInterfaceHandoff register_hf_field CheckUsed ProcessImport ProcessInclude find_type DumpEttList DumpEttDeclaration DumpHfList DumpHfDeclaration DumpFunctionTable register_type register_ett);
 
22
 
 
23
use strict;
 
24
use Parse::Pidl qw(error warning);
 
25
use Parse::Pidl::Typelist qw(getType);
 
26
use Parse::Pidl::Util qw(has_property property_matches make_str);
 
27
use Parse::Pidl::NDR qw(ContainsString GetNextLevel);
 
28
use Parse::Pidl::Dump qw(DumpType DumpFunction);
 
29
use Parse::Pidl::Wireshark::Conformance qw(ReadConformance);
 
30
use File::Basename;
 
31
 
 
32
use vars qw($VERSION);
 
33
$VERSION = '0.01';
 
34
 
 
35
my %return_types = ();
 
36
my %dissector_used = ();
 
37
 
 
38
my %ptrtype_mappings = (
 
39
        "unique" => "NDR_POINTER_UNIQUE",
 
40
        "ref" => "NDR_POINTER_REF",
 
41
        "ptr" => "NDR_POINTER_PTR"
 
42
);
 
43
 
 
44
sub StripPrefixes($$)
 
45
{
 
46
        my ($s, $prefixes) = @_;
 
47
 
 
48
        foreach (@$prefixes) {
 
49
                $s =~ s/^$_\_//g;
 
50
        }
 
51
 
 
52
        return $s;
 
53
}
 
54
 
 
55
# Convert a IDL structure field name (e.g access_mask) to a prettier
 
56
# string like 'Access Mask'.
 
57
 
 
58
sub field2name($)
 
59
{
 
60
    my($field) = shift;
 
61
 
 
62
    $field =~ s/_/ /g;          # Replace underscores with spaces
 
63
    $field =~ s/(\w+)/\u\L$1/g; # Capitalise each word
 
64
 
 
65
    return $field;
 
66
}
 
67
 
 
68
sub new($)
 
69
{
 
70
        my ($class) = @_;
 
71
        my $self = {res => {hdr => "", def => "", code => ""}, tabs => "", cur_fn => undef,
 
72
                hf_used => {}, ett => [], conformance => undef
 
73
 
 
74
        };
 
75
        bless($self, $class);
 
76
}
 
77
 
 
78
sub pidl_fn_start($$)
 
79
{
 
80
        my ($self, $fn) = @_;
 
81
        $self->{cur_fn} = $fn;
 
82
}
 
83
sub pidl_fn_end($$)
 
84
{
 
85
        my ($self, $fn) = @_;
 
86
        die("Inconsistent state: $fn != $self->{cur_fn}") if ($fn ne $self->{cur_fn});
 
87
        $self->{cur_fn} = undef;
 
88
}
 
89
 
 
90
sub pidl_code($$)
 
91
{
 
92
        my ($self, $d) = @_;
 
93
        return if (defined($self->{cur_fn}) and defined($self->{conformance}->{manual}->{$self->{cur_fn}}));
 
94
 
 
95
        if ($d) {
 
96
                $self->{res}->{code} .= $self->{tabs};
 
97
                $self->{res}->{code} .= $d;
 
98
        }
 
99
        $self->{res}->{code} .="\n";
 
100
}
 
101
 
 
102
sub pidl_hdr($$) { my ($self,$x) = @_; $self->{res}->{hdr} .= "$x\n"; }
 
103
sub pidl_def($$) { my ($self,$x) = @_; $self->{res}->{def} .= "$x\n"; }
 
104
 
 
105
sub indent($)
 
106
{
 
107
        my ($self) = @_;
 
108
        $self->{tabs} .= "\t";
 
109
}
 
110
 
 
111
sub deindent($)
 
112
{
 
113
        my ($self) = @_;
 
114
        $self->{tabs} = substr($self->{tabs}, 0, -1);
 
115
}
 
116
 
 
117
sub PrintIdl($$)
 
118
{
 
119
        my ($self, $idl) = @_;
 
120
 
 
121
        foreach (split /\n/, $idl) {
 
122
                $self->pidl_code("/* IDL: $_ */");
 
123
        }
 
124
 
 
125
        $self->pidl_code("");
 
126
}
 
127
 
 
128
#####################################################################
 
129
# parse the interface definitions
 
130
sub Interface($$)
 
131
{
 
132
        my($self, $interface) = @_;
 
133
        $self->Const($_,$interface->{NAME}) foreach (@{$interface->{CONSTS}});
 
134
        $self->Type($_, $_->{NAME}, $interface->{NAME}) foreach (@{$interface->{TYPES}});
 
135
        $self->Function($_,$interface->{NAME}) foreach (@{$interface->{FUNCTIONS}});
 
136
}
 
137
 
 
138
sub Enum($$$$)
 
139
{
 
140
        my ($self, $e,$name,$ifname) = @_;
 
141
        my $valsstring = "$ifname\_$name\_vals";
 
142
        my $dissectorname = "$ifname\_dissect\_enum\_".StripPrefixes($name, $self->{conformance}->{strip_prefixes});
 
143
 
 
144
        return if (defined($self->{conformance}->{noemit}->{StripPrefixes($name, $self->{conformance}->{strip_prefixes})}));
 
145
 
 
146
        foreach (@{$e->{ELEMENTS}}) {
 
147
                if (/([^=]*)=(.*)/) {
 
148
                        $self->pidl_hdr("#define $1 ($2)");
 
149
                }
 
150
        }
 
151
 
 
152
        $self->pidl_hdr("extern const value_string $valsstring\[];");
 
153
        $self->pidl_hdr("int $dissectorname(tvbuff_t *tvb _U_, int offset _U_, packet_info *pinfo _U_, proto_tree *tree _U_, guint8 *drep _U_, int hf_index _U_, guint32 *param _U_);");
 
154
 
 
155
        $self->pidl_def("const value_string ".$valsstring."[] = {");
 
156
        foreach (@{$e->{ELEMENTS}}) {
 
157
                next unless (/([^=]*)=(.*)/);
 
158
                $self->pidl_def("\t{ $1, \"$1\" },");
 
159
        }
 
160
 
 
161
        $self->pidl_def("{ 0, NULL }");
 
162
        $self->pidl_def("};");
 
163
 
 
164
        $self->pidl_fn_start($dissectorname);
 
165
        $self->pidl_code("int");
 
166
        $self->pidl_code("$dissectorname(tvbuff_t *tvb _U_, int offset _U_, packet_info *pinfo _U_, proto_tree *tree _U_, guint8 *drep _U_, int hf_index _U_, guint32 *param _U_)");
 
167
        $self->pidl_code("{");
 
168
        $self->indent;
 
169
        $self->pidl_code("g$e->{BASE_TYPE} parameter=0;");
 
170
        $self->pidl_code("if(param){");
 
171
        $self->indent;
 
172
        $self->pidl_code("parameter=(g$e->{BASE_TYPE})*param;");
 
173
        $self->deindent;
 
174
        $self->pidl_code("}");
 
175
        $self->pidl_code("offset = dissect_ndr_$e->{BASE_TYPE}(tvb, offset, pinfo, tree, drep, hf_index, &parameter);");
 
176
        $self->pidl_code("if(param){");
 
177
        $self->indent;
 
178
        $self->pidl_code("*param=(guint32)parameter;");
 
179
        $self->deindent;
 
180
        $self->pidl_code("}");
 
181
        $self->pidl_code("return offset;");
 
182
        $self->deindent;
 
183
        $self->pidl_code("}\n");
 
184
        $self->pidl_fn_end($dissectorname);
 
185
 
 
186
        my $enum_size = $e->{BASE_TYPE};
 
187
        $enum_size =~ s/uint//g;
 
188
        $self->register_type($name, "offset = $dissectorname(tvb, offset, pinfo, tree, drep, \@HF\@, \@PARAM\@);", "FT_UINT$enum_size", "BASE_DEC", "0", "VALS($valsstring)", $enum_size / 8);
 
189
}
 
190
 
 
191
sub Bitmap($$$$)
 
192
{
 
193
        my ($self,$e,$name,$ifname) = @_;
 
194
        my $dissectorname = "$ifname\_dissect\_bitmap\_".StripPrefixes($name, $self->{conformance}->{strip_prefixes});
 
195
 
 
196
        $self->register_ett("ett_$ifname\_$name");
 
197
 
 
198
        $self->pidl_hdr("int $dissectorname(tvbuff_t *tvb _U_, int offset _U_, packet_info *pinfo _U_, proto_tree *tree _U_, guint8 *drep _U_, int hf_index _U_, guint32 param _U_);");
 
199
 
 
200
        $self->pidl_fn_start($dissectorname);
 
201
        $self->pidl_code("int");
 
202
        $self->pidl_code("$dissectorname(tvbuff_t *tvb _U_, int offset _U_, packet_info *pinfo _U_, proto_tree *parent_tree _U_, guint8 *drep _U_, int hf_index _U_, guint32 param _U_)");
 
203
        $self->pidl_code("{");
 
204
        $self->indent;
 
205
        $self->pidl_code("proto_item *item = NULL;");
 
206
        $self->pidl_code("proto_tree *tree = NULL;");
 
207
        $self->pidl_code("");
 
208
 
 
209
        $self->pidl_code("g$e->{BASE_TYPE} flags;");
 
210
        if ($e->{ALIGN} > 1) {
 
211
                $self->pidl_code("ALIGN_TO_$e->{ALIGN}_BYTES;");
 
212
        }
 
213
 
 
214
        $self->pidl_code("");
 
215
 
 
216
        $self->pidl_code("if (parent_tree) {");
 
217
        $self->indent;
 
218
        $self->pidl_code("item = proto_tree_add_item(parent_tree, hf_index, tvb, offset, $e->{ALIGN}, TRUE);");
 
219
        $self->pidl_code("tree = proto_item_add_subtree(item,ett_$ifname\_$name);");
 
220
        $self->deindent;
 
221
        $self->pidl_code("}\n");
 
222
 
 
223
        $self->pidl_code("offset = dissect_ndr_$e->{BASE_TYPE}(tvb, offset, pinfo, NULL, drep, -1, &flags);");
 
224
 
 
225
        $self->pidl_code("proto_item_append_text(item, \": \");\n");
 
226
        $self->pidl_code("if (!flags)");
 
227
        $self->pidl_code("\tproto_item_append_text(item, \"(No values set)\");\n");
 
228
 
 
229
        foreach (@{$e->{ELEMENTS}}) {
 
230
                next unless (/([^ ]*) (.*)/);
 
231
                my ($en,$ev) = ($1,$2);
 
232
                my $hf_bitname = "hf_$ifname\_$name\_$en";
 
233
                my $filtername = "$ifname\.$name\.$en";
 
234
 
 
235
                $self->{hf_used}->{$hf_bitname} = 1;
 
236
 
 
237
                $self->register_hf_field($hf_bitname, field2name($en), $filtername, "FT_BOOLEAN", $e->{ALIGN} * 8, "TFS(&$name\_$en\_tfs)", $ev, "");
 
238
 
 
239
                $self->pidl_def("static const true_false_string $name\_$en\_tfs = {");
 
240
                if (defined($self->{conformance}->{tfs}->{$hf_bitname})) {
 
241
                        $self->pidl_def("   $self->{conformance}->{tfs}->{$hf_bitname}->{TRUE_STRING},");
 
242
                        $self->pidl_def("   $self->{conformance}->{tfs}->{$hf_bitname}->{FALSE_STRING},");
 
243
                        $self->{conformance}->{tfs}->{$hf_bitname}->{USED} = 1;
 
244
                } else {
 
245
                        $self->pidl_def("   \"$en is SET\",");
 
246
                        $self->pidl_def("   \"$en is NOT SET\",");
 
247
                }
 
248
                $self->pidl_def("};");
 
249
 
 
250
                $self->pidl_code("proto_tree_add_boolean(tree, $hf_bitname, tvb, offset-$e->{ALIGN}, $e->{ALIGN}, flags);");
 
251
                $self->pidl_code("if (flags&$ev){");
 
252
                $self->pidl_code("\tproto_item_append_text(item, \"$en\");");
 
253
                $self->pidl_code("\tif (flags & (~$ev))");
 
254
                $self->pidl_code("\t\tproto_item_append_text(item, \", \");");
 
255
                $self->pidl_code("}");
 
256
                $self->pidl_code("flags&=(~$ev);");
 
257
                $self->pidl_code("");
 
258
        }
 
259
 
 
260
        $self->pidl_code("if (flags) {");
 
261
        $self->pidl_code("\tproto_item_append_text(item, \"Unknown bitmap value 0x%x\", flags);");
 
262
        $self->pidl_code("}\n");
 
263
        $self->pidl_code("return offset;");
 
264
        $self->deindent;
 
265
        $self->pidl_code("}\n");
 
266
        $self->pidl_fn_end($dissectorname);
 
267
 
 
268
        my $size = $e->{BASE_TYPE};
 
269
        $size =~ s/uint//g;
 
270
        $self->register_type($name, "offset = $dissectorname(tvb, offset, pinfo, tree, drep, \@HF\@, \@PARAM\@);", "FT_UINT$size", "BASE_HEX", "0", "NULL", $size/8);
 
271
}
 
272
 
 
273
sub ElementLevel($$$$$$$)
 
274
{
 
275
        my ($self,$e,$l,$hf,$myname,$pn,$ifname) = @_;
 
276
 
 
277
        my $param = 0;
 
278
 
 
279
        if (defined($self->{conformance}->{dissectorparams}->{$myname})) {
 
280
                $param = $self->{conformance}->{dissectorparams}->{$myname}->{PARAM};
 
281
        }
 
282
 
 
283
        if ($l->{TYPE} eq "POINTER") {
 
284
                my $type;
 
285
                if ($l->{LEVEL} eq "TOP") {
 
286
                        $type = "toplevel";
 
287
                } elsif ($l->{LEVEL} eq "EMBEDDED") {
 
288
                        $type = "embedded";
 
289
                }
 
290
                $self->pidl_code("offset = dissect_ndr_$type\_pointer(tvb, offset, pinfo, tree, drep, $myname\_, $ptrtype_mappings{$l->{POINTER_TYPE}}, \"Pointer to ".field2name(StripPrefixes($e->{NAME}, $self->{conformance}->{strip_prefixes})) . " ($e->{TYPE})\",$hf);");
 
291
        } elsif ($l->{TYPE} eq "ARRAY") {
 
292
                if ($l->{IS_INLINE}) {
 
293
                        error($e->{ORIGINAL}, "Inline arrays not supported");
 
294
                } elsif ($l->{IS_FIXED}) {
 
295
                        $self->pidl_code("int i;");
 
296
                        $self->pidl_code("for (i = 0; i < $l->{SIZE_IS}; i++)");
 
297
                        $self->pidl_code("\toffset = $myname\_(tvb, offset, pinfo, tree, drep);");
 
298
                } else {
 
299
                        my $type = "";
 
300
                        $type .= "c" if ($l->{IS_CONFORMANT});
 
301
                        $type .= "v" if ($l->{IS_VARYING});
 
302
 
 
303
                        unless ($l->{IS_ZERO_TERMINATED}) {
 
304
                                $self->pidl_code("offset = dissect_ndr_u" . $type . "array(tvb, offset, pinfo, tree, drep, $myname\_);");
 
305
                        } else {
 
306
                                my $nl = GetNextLevel($e,$l);
 
307
                                $self->pidl_code("char *data;");
 
308
                                $self->pidl_code("");
 
309
                                $self->pidl_code("offset = dissect_ndr_$type" . "string(tvb, offset, pinfo, tree, drep, sizeof(g$nl->{DATA_TYPE}), $hf, FALSE, &data);");
 
310
                                $self->pidl_code("proto_item_append_text(tree, \": %s\", data);");
 
311
                        }
 
312
                }
 
313
        } elsif ($l->{TYPE} eq "DATA") {
 
314
                if ($l->{DATA_TYPE} eq "string") {
 
315
                        my $bs = 2; # Byte size defaults to that of UCS2
 
316
 
 
317
 
 
318
                        ($bs = 1) if (property_matches($e, "flag", ".*LIBNDR_FLAG_STR_ASCII.*"));
 
319
 
 
320
                        if (property_matches($e, "flag", ".*LIBNDR_FLAG_STR_SIZE4.*") and property_matches($e, "flag", ".*LIBNDR_FLAG_STR_LEN4.*")) {
 
321
                                $self->pidl_code("char *data;\n");
 
322
                                $self->pidl_code("offset = dissect_ndr_cvstring(tvb, offset, pinfo, tree, drep, $bs, $hf, FALSE, &data);");
 
323
                                $self->pidl_code("proto_item_append_text(tree, \": %s\", data);");
 
324
                        } elsif (property_matches($e, "flag", ".*LIBNDR_FLAG_STR_SIZE4.*")) {
 
325
                                $self->pidl_code("offset = dissect_ndr_vstring(tvb, offset, pinfo, tree, drep, $bs, $hf, FALSE, NULL);");
 
326
                        } else {
 
327
                                warn("Unable to handle string with flags $e->{PROPERTIES}->{flag}");
 
328
                        }
 
329
                } else {
 
330
                        my $call;
 
331
 
 
332
                        if ($self->{conformance}->{imports}->{$l->{DATA_TYPE}}) {
 
333
                                $call = $self->{conformance}->{imports}->{$l->{DATA_TYPE}}->{DATA};
 
334
                                $self->{conformance}->{imports}->{$l->{DATA_TYPE}}->{USED} = 1;
 
335
                        } elsif (defined($self->{conformance}->{imports}->{"$pn.$e->{NAME}"})) {
 
336
                                $call = $self->{conformance}->{imports}->{"$pn.$e->{NAME}"}->{DATA};
 
337
                                $self->{conformance}->{imports}->{"$pn.$e->{NAME}"}->{USED} = 1;
 
338
 
 
339
                        } elsif (defined($self->{conformance}->{types}->{$l->{DATA_TYPE}})) {
 
340
                                $call= $self->{conformance}->{types}->{$l->{DATA_TYPE}}->{DISSECTOR_NAME};
 
341
                                $self->{conformance}->{types}->{$l->{DATA_TYPE}}->{USED} = 1;
 
342
                        } else {
 
343
                                $self->pidl_code("offset = $ifname\_dissect_struct_" . $l->{DATA_TYPE} . "(tvb,offset,pinfo,tree,drep,$hf,$param);");
 
344
 
 
345
                                return;
 
346
                        }
 
347
 
 
348
                        $call =~ s/\@HF\@/$hf/g;
 
349
                        $call =~ s/\@PARAM\@/$param/g;
 
350
                        $self->pidl_code($call);
 
351
                }
 
352
        } elsif ($_->{TYPE} eq "SUBCONTEXT") {
 
353
                my $num_bits = ($l->{HEADER_SIZE}*8);
 
354
                $self->pidl_code("guint$num_bits size;");
 
355
                $self->pidl_code("int start_offset = offset;");
 
356
                $self->pidl_code("tvbuff_t *subtvb;");
 
357
                $self->pidl_code("offset = dissect_ndr_uint$num_bits(tvb, offset, pinfo, tree, drep, $hf, &size);");
 
358
                $self->pidl_code("proto_tree_add_text(tree, tvb, start_offset, offset - start_offset + size, \"Subcontext size\");");
 
359
 
 
360
                $self->pidl_code("subtvb = tvb_new_subset(tvb, offset, size, -1);");
 
361
                $self->pidl_code("$myname\_(subtvb, 0, pinfo, tree, drep);");
 
362
        } else {
 
363
                die("Unknown type `$_->{TYPE}'");
 
364
        }
 
365
}
 
366
 
 
367
sub Element($$$)
 
368
{
 
369
        my ($self,$e,$pn,$ifname) = @_;
 
370
 
 
371
        my $dissectorname = "$ifname\_dissect\_element\_".StripPrefixes($pn, $self->{conformance}->{strip_prefixes})."\_".StripPrefixes($e->{NAME}, $self->{conformance}->{strip_prefixes});
 
372
 
 
373
        my $call_code = "offset = $dissectorname(tvb, offset, pinfo, tree, drep);";
 
374
 
 
375
        my $type = $self->find_type($e->{TYPE});
 
376
 
 
377
        if (not defined($type)) {
 
378
                # default settings
 
379
                $type = {
 
380
                        MASK => 0,
 
381
                        VALSSTRING => "NULL",
 
382
                        FT_TYPE => "FT_NONE",
 
383
                        BASE_TYPE => "BASE_HEX"
 
384
                };
 
385
        }
 
386
 
 
387
        if (ContainsString($e)) {
 
388
                $type = {
 
389
                        MASK => 0,
 
390
                        VALSSTRING => "NULL",
 
391
                        FT_TYPE => "FT_STRING",
 
392
                        BASE_TYPE => "BASE_DEC"
 
393
                };
 
394
        }
 
395
 
 
396
        my $hf = $self->register_hf_field("hf_$ifname\_$pn\_$e->{NAME}", field2name($e->{NAME}), "$ifname.$pn.$e->{NAME}", $type->{FT_TYPE}, $type->{BASE_TYPE}, $type->{VALSSTRING}, $type->{MASK}, "");
 
397
        $self->{hf_used}->{$hf} = 1;
 
398
 
 
399
        my $eltname = StripPrefixes($pn, $self->{conformance}->{strip_prefixes}) . ".$e->{NAME}";
 
400
        if (defined($self->{conformance}->{noemit}->{$eltname})) {
 
401
                return $call_code;
 
402
        }
 
403
 
 
404
        my $add = "";
 
405
 
 
406
        foreach (@{$e->{LEVELS}}) {
 
407
                next if ($_->{TYPE} eq "SWITCH");
 
408
                $self->pidl_def("static int $dissectorname$add(tvbuff_t *tvb _U_, int offset _U_, packet_info *pinfo _U_, proto_tree *tree _U_, guint8 *drep _U_);");
 
409
                $self->pidl_fn_start("$dissectorname$add");
 
410
                $self->pidl_code("static int");
 
411
                $self->pidl_code("$dissectorname$add(tvbuff_t *tvb _U_, int offset _U_, packet_info *pinfo _U_, proto_tree *tree _U_, guint8 *drep _U_)");
 
412
                $self->pidl_code("{");
 
413
                $self->indent;
 
414
 
 
415
                $self->ElementLevel($e,$_,$hf,$dissectorname.$add,$pn,$ifname);
 
416
 
 
417
                $self->pidl_code("");
 
418
                $self->pidl_code("return offset;");
 
419
                $self->deindent;
 
420
                $self->pidl_code("}\n");
 
421
                $self->pidl_fn_end("$dissectorname$add");
 
422
                $add.="_";
 
423
                last if ($_->{TYPE} eq "ARRAY" and $_->{IS_ZERO_TERMINATED});
 
424
        }
 
425
 
 
426
        return $call_code;
 
427
}
 
428
 
 
429
sub Function($$$)
 
430
{
 
431
        my ($self, $fn,$ifname) = @_;
 
432
 
 
433
        my %dissectornames;
 
434
 
 
435
        foreach (@{$fn->{ELEMENTS}}) {
 
436
            $dissectornames{$_->{NAME}} = $self->Element($_, $fn->{NAME}, $ifname) if not defined($dissectornames{$_->{NAME}});
 
437
        }
 
438
 
 
439
        my $fn_name = $_->{NAME};
 
440
        $fn_name =~ s/^${ifname}_//;
 
441
 
 
442
        $self->PrintIdl(DumpFunction($fn->{ORIGINAL}));
 
443
        $self->pidl_fn_start("$ifname\_dissect\_$fn_name\_response");
 
444
        $self->pidl_code("static int");
 
445
        $self->pidl_code("$ifname\_dissect\_${fn_name}_response(tvbuff_t *tvb _U_, int offset _U_, packet_info *pinfo _U_, proto_tree *tree _U_, guint8 *drep _U_)");
 
446
        $self->pidl_code("{");
 
447
        $self->indent;
 
448
        if ( not defined($fn->{RETURN_TYPE})) {
 
449
        } elsif ($fn->{RETURN_TYPE} eq "NTSTATUS" or $fn->{RETURN_TYPE} eq "WERROR")
 
450
        {
 
451
                $self->pidl_code("guint32 status;\n");
 
452
        } elsif (my $type = getType($fn->{RETURN_TYPE})) {
 
453
                if ($type->{DATA}->{TYPE} eq "ENUM") {
 
454
                        $self->pidl_code("g".Parse::Pidl::Typelist::enum_type_fn($type->{DATA}) . " status;\n");
 
455
                } elsif ($type->{DATA}->{TYPE} eq "SCALAR") {
 
456
                        $self->pidl_code("g$fn->{RETURN_TYPE} status;\n");
 
457
                } else {
 
458
                error($fn, "return type `$fn->{RETURN_TYPE}' not yet supported");
 
459
                }
 
460
        } else {
 
461
                error($fn, "unknown return type `$fn->{RETURN_TYPE}'");
 
462
        }
 
463
 
 
464
        $self->pidl_code("pinfo->dcerpc_procedure_name=\"${fn_name}\";");
 
465
        foreach (@{$fn->{ELEMENTS}}) {
 
466
                if (grep(/out/,@{$_->{DIRECTION}})) {
 
467
                        $self->pidl_code("$dissectornames{$_->{NAME}}");
 
468
                        $self->pidl_code("offset = dissect_deferred_pointers(pinfo, tvb, offset, drep);");
 
469
                        $self->pidl_code("");
 
470
                }
 
471
        }
 
472
 
 
473
        if (not defined($fn->{RETURN_TYPE})) {
 
474
        } elsif ($fn->{RETURN_TYPE} eq "NTSTATUS") {
 
475
                $self->pidl_code("offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep, hf\_$ifname\_status, &status);\n");
 
476
                $self->pidl_code("if (status != 0 && check_col(pinfo->cinfo, COL_INFO))");
 
477
                $self->pidl_code("\tcol_append_fstr(pinfo->cinfo, COL_INFO, \", Error: %s\", val_to_str(status, NT_errors, \"Unknown NT status 0x%08x\"));\n");
 
478
                $return_types{$ifname}->{"status"} = ["NTSTATUS", "NT Error"];
 
479
        } elsif ($fn->{RETURN_TYPE} eq "WERROR") {
 
480
                $self->pidl_code("offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep, hf\_$ifname\_werror, &status);\n");
 
481
                $self->pidl_code("if (status != 0 && check_col(pinfo->cinfo, COL_INFO))");
 
482
                $self->pidl_code("\tcol_append_fstr(pinfo->cinfo, COL_INFO, \", Error: %s\", val_to_str(status, WERR_errors, \"Unknown DOS error 0x%08x\"));\n");
 
483
 
 
484
                $return_types{$ifname}->{"werror"} = ["WERROR", "Windows Error"];
 
485
        } elsif (my $type = getType($fn->{RETURN_TYPE})) {
 
486
                if ($type->{DATA}->{TYPE} eq "ENUM") {
 
487
                        my $return_type = "g".Parse::Pidl::Typelist::enum_type_fn($type->{DATA});
 
488
                        my $return_dissect = "dissect_ndr_" .Parse::Pidl::Typelist::enum_type_fn($type->{DATA});
 
489
 
 
490
                        $self->pidl_code("offset = $return_dissect(tvb, offset, pinfo, tree, drep, hf\_$ifname\_$fn->{RETURN_TYPE}_status, &status);");
 
491
                        $self->pidl_code("if (status != 0 && check_col(pinfo->cinfo, COL_INFO))");
 
492
                        $self->pidl_code("\tcol_append_fstr(pinfo->cinfo, COL_INFO, \", Status: %s\", val_to_str(status, $ifname\_$fn->{RETURN_TYPE}\_vals, \"Unknown " . $fn->{RETURN_TYPE} . " error 0x%08x\"));\n");
 
493
                        $return_types{$ifname}->{$fn->{RETURN_TYPE}."_status"} = [$fn->{RETURN_TYPE}, $fn->{RETURN_TYPE}];
 
494
                } elsif ($type->{DATA}->{TYPE} eq "SCALAR") {
 
495
                        $self->pidl_code("offset = dissect_ndr_$fn->{RETURN_TYPE}(tvb, offset, pinfo, tree, drep, hf\_$ifname\_$fn->{RETURN_TYPE}_status, &status);");
 
496
                        $self->pidl_code("if (status != 0 && check_col(pinfo->cinfo, COL_INFO))");
 
497
                        $self->pidl_code("\tcol_append_fstr(pinfo->cinfo, COL_INFO, \", Status: %d\", status);\n");
 
498
                        $return_types{$ifname}->{$fn->{RETURN_TYPE}."_status"} = [$fn->{RETURN_TYPE}, $fn->{RETURN_TYPE}];
 
499
                }
 
500
        }
 
501
 
 
502
        $self->pidl_code("return offset;");
 
503
        $self->deindent;
 
504
        $self->pidl_code("}\n");
 
505
        $self->pidl_fn_end("$ifname\_dissect\_$fn_name\_response");
 
506
 
 
507
        $self->pidl_fn_start("$ifname\_dissect\_$fn_name\_request");
 
508
        $self->pidl_code("static int");
 
509
        $self->pidl_code("$ifname\_dissect\_${fn_name}_request(tvbuff_t *tvb _U_, int offset _U_, packet_info *pinfo _U_, proto_tree *tree _U_, guint8 *drep _U_)");
 
510
        $self->pidl_code("{");
 
511
        $self->indent;
 
512
        $self->pidl_code("pinfo->dcerpc_procedure_name=\"${fn_name}\";");
 
513
        foreach (@{$fn->{ELEMENTS}}) {
 
514
                if (grep(/in/,@{$_->{DIRECTION}})) {
 
515
                        $self->pidl_code("$dissectornames{$_->{NAME}}");
 
516
                        $self->pidl_code("offset = dissect_deferred_pointers(pinfo, tvb, offset, drep);");
 
517
                }
 
518
 
 
519
        }
 
520
 
 
521
        $self->pidl_code("return offset;");
 
522
        $self->deindent;
 
523
        $self->pidl_code("}\n");
 
524
        $self->pidl_fn_end("$ifname\_dissect\_$fn_name\_request");
 
525
}
 
526
 
 
527
sub Struct($$$$)
 
528
{
 
529
        my ($self,$e,$name,$ifname) = @_;
 
530
        my $dissectorname = "$ifname\_dissect\_struct\_".StripPrefixes($name, $self->{conformance}->{strip_prefixes});
 
531
 
 
532
        return if (defined($self->{conformance}->{noemit}->{StripPrefixes($name, $self->{conformance}->{strip_prefixes})}));
 
533
 
 
534
        $self->register_ett("ett_$ifname\_$name");
 
535
 
 
536
        my $res = "";
 
537
        ($res.="\t".$self->Element($_, $name, $ifname)."\n\n") foreach (@{$e->{ELEMENTS}});
 
538
 
 
539
        $self->pidl_hdr("int $dissectorname(tvbuff_t *tvb _U_, int offset _U_, packet_info *pinfo _U_, proto_tree *parent_tree _U_, guint8 *drep _U_, int hf_index _U_, guint32 param _U_);");
 
540
 
 
541
        $self->pidl_fn_start($dissectorname);
 
542
        $self->pidl_code("int");
 
543
        $self->pidl_code("$dissectorname(tvbuff_t *tvb _U_, int offset _U_, packet_info *pinfo _U_, proto_tree *parent_tree _U_, guint8 *drep _U_, int hf_index _U_, guint32 param _U_)");
 
544
        $self->pidl_code("{");
 
545
        $self->indent;
 
546
        $self->pidl_code("proto_item *item = NULL;");
 
547
        $self->pidl_code("proto_tree *tree = NULL;");
 
548
        $self->pidl_code("int old_offset;");
 
549
        $self->pidl_code("");
 
550
 
 
551
        if ($e->{ALIGN} > 1) {
 
552
                $self->pidl_code("ALIGN_TO_$e->{ALIGN}_BYTES;");
 
553
        }
 
554
        $self->pidl_code("");
 
555
 
 
556
        $self->pidl_code("old_offset = offset;");
 
557
        $self->pidl_code("");
 
558
        $self->pidl_code("if (parent_tree) {");
 
559
        $self->indent;
 
560
        $self->pidl_code("item = proto_tree_add_item(parent_tree, hf_index, tvb, offset, -1, TRUE);");
 
561
        $self->pidl_code("tree = proto_item_add_subtree(item, ett_$ifname\_$name);");
 
562
        $self->deindent;
 
563
        $self->pidl_code("}");
 
564
 
 
565
        $self->pidl_code("\n$res");
 
566
 
 
567
        $self->pidl_code("proto_item_set_len(item, offset-old_offset);\n");
 
568
        $self->pidl_code("return offset;");
 
569
        $self->deindent;
 
570
        $self->pidl_code("}\n");
 
571
        $self->pidl_fn_end($dissectorname);
 
572
 
 
573
        $self->register_type($name, "offset = $dissectorname(tvb,offset,pinfo,tree,drep,\@HF\@,\@PARAM\@);", "FT_NONE", "BASE_NONE", 0, "NULL", 0);
 
574
}
 
575
 
 
576
sub Union($$$$)
 
577
{
 
578
        my ($self,$e,$name,$ifname) = @_;
 
579
 
 
580
        my $dissectorname = "$ifname\_dissect_".StripPrefixes($name, $self->{conformance}->{strip_prefixes});
 
581
 
 
582
        return if (defined($self->{conformance}->{noemit}->{StripPrefixes($name, $self->{conformance}->{strip_prefixes})}));
 
583
 
 
584
        $self->register_ett("ett_$ifname\_$name");
 
585
 
 
586
        my $res = "";
 
587
        foreach (@{$e->{ELEMENTS}}) {
 
588
                $res.="\n\t\t$_->{CASE}:\n";
 
589
                if ($_->{TYPE} ne "EMPTY") {
 
590
                        $res.="\t\t\t".$self->Element($_, $name, $ifname)."\n";
 
591
                }
 
592
                $res.="\t\tbreak;\n";
 
593
        }
 
594
 
 
595
        my $switch_type;
 
596
        my $switch_dissect;
 
597
        my $switch_dt = getType($e->{SWITCH_TYPE});
 
598
        if ($switch_dt->{DATA}->{TYPE} eq "ENUM") {
 
599
                $switch_type = "g".Parse::Pidl::Typelist::enum_type_fn($switch_dt->{DATA});
 
600
                $switch_dissect = "dissect_ndr_" .Parse::Pidl::Typelist::enum_type_fn($switch_dt->{DATA});
 
601
        } elsif ($switch_dt->{DATA}->{TYPE} eq "SCALAR") {
 
602
                $switch_type = "g$e->{SWITCH_TYPE}";
 
603
                $switch_dissect = "dissect_ndr_$e->{SWITCH_TYPE}";
 
604
        }
 
605
 
 
606
        $self->pidl_fn_start($dissectorname);
 
607
        $self->pidl_code("static int");
 
608
        $self->pidl_code("$dissectorname(tvbuff_t *tvb _U_, int offset _U_, packet_info *pinfo _U_, proto_tree *parent_tree _U_, guint8 *drep _U_, int hf_index _U_, guint32 param _U_)");
 
609
        $self->pidl_code("{");
 
610
        $self->indent;
 
611
        $self->pidl_code("proto_item *item = NULL;");
 
612
        $self->pidl_code("proto_tree *tree = NULL;");
 
613
        $self->pidl_code("int old_offset;");
 
614
        $self->pidl_code("$switch_type level;");
 
615
        $self->pidl_code("");
 
616
 
 
617
        $self->pidl_code("old_offset = offset;");
 
618
        $self->pidl_code("if (parent_tree) {");
 
619
        $self->indent;
 
620
        $self->pidl_code("item = proto_tree_add_text(parent_tree, tvb, offset, -1, \"$name\");");
 
621
        $self->pidl_code("tree = proto_item_add_subtree(item, ett_$ifname\_$name);");
 
622
        $self->deindent;
 
623
        $self->pidl_code("}");
 
624
 
 
625
        $self->pidl_code("");
 
626
 
 
627
        $self->pidl_code("offset = $switch_dissect(tvb, offset, pinfo, tree, drep, hf_index, &level);");
 
628
 
 
629
        if ($e->{ALIGN} > 1) {
 
630
                $self->pidl_code("ALIGN_TO_$e->{ALIGN}_BYTES;");
 
631
                $self->pidl_code("");
 
632
        }
 
633
 
 
634
 
 
635
        $self->pidl_code("switch(level) {$res\t}");
 
636
        $self->pidl_code("proto_item_set_len(item, offset-old_offset);\n");
 
637
        $self->pidl_code("return offset;");
 
638
        $self->deindent;
 
639
        $self->pidl_code("}");
 
640
        $self->pidl_fn_end($dissectorname);
 
641
 
 
642
        $self->register_type($name, "offset = $dissectorname(tvb, offset, pinfo, tree, drep, \@HF\@, \@PARAM\@);", "FT_NONE", "BASE_NONE", 0, "NULL", 0);
 
643
}
 
644
 
 
645
sub Const($$$)
 
646
{
 
647
        my ($self,$const,$ifname) = @_;
 
648
 
 
649
        if (!defined($const->{ARRAY_LEN}[0])) {
 
650
                $self->pidl_hdr("#define $const->{NAME}\t( $const->{VALUE} )\n");
 
651
        } else {
 
652
                $self->pidl_hdr("#define $const->{NAME}\t $const->{VALUE}\n");
 
653
        }
 
654
}
 
655
 
 
656
sub Typedef($$$$)
 
657
{
 
658
        my ($self,$e,$name,$ifname) = @_;
 
659
 
 
660
        $self->Type($e->{DATA}, $name, $ifname);
 
661
}
 
662
 
 
663
sub Type($$$$)
 
664
{
 
665
        my ($self, $e, $name, $ifname) = @_;
 
666
 
 
667
        $self->PrintIdl(DumpType($e->{ORIGINAL}));
 
668
 
 
669
        {
 
670
                ENUM => \&Enum,
 
671
                STRUCT => \&Struct,
 
672
                UNION => \&Union,
 
673
                BITMAP => \&Bitmap,
 
674
                TYPEDEF => \&Typedef
 
675
        }->{$e->{TYPE}}->($self, $e, $name, $ifname);
 
676
}
 
677
 
 
678
sub RegisterInterface($$)
 
679
{
 
680
        my ($self, $x) = @_;
 
681
 
 
682
        $self->pidl_fn_start("proto_register_dcerpc_$x->{NAME}");
 
683
        $self->pidl_code("void proto_register_dcerpc_$x->{NAME}(void)");
 
684
        $self->pidl_code("{");
 
685
        $self->indent;
 
686
 
 
687
        $self->{res}->{code}.=$self->DumpHfList()."\n";
 
688
        $self->{res}->{code}.="\n".DumpEttList($self->{ett})."\n";
 
689
 
 
690
        if (defined($x->{UUID})) {
 
691
            # These can be changed to non-pidl_code names if the old dissectors
 
692
            # in epan/dissctors are deleted.
 
693
 
 
694
            my $name = uc($x->{NAME}) . " (pidl)";
 
695
            my $short_name = uc($x->{NAME});
 
696
            my $filter_name = $x->{NAME};
 
697
 
 
698
            if (has_property($x, "helpstring")) {
 
699
                $name = $x->{PROPERTIES}->{helpstring};
 
700
            }
 
701
 
 
702
            if (defined($self->{conformance}->{protocols}->{$x->{NAME}})) {
 
703
                $short_name = $self->{conformance}->{protocols}->{$x->{NAME}}->{SHORTNAME};
 
704
                $name = $self->{conformance}->{protocols}->{$x->{NAME}}->{LONGNAME};
 
705
                $filter_name = $self->{conformance}->{protocols}->{$x->{NAME}}->{FILTERNAME};
 
706
            }
 
707
 
 
708
            $self->pidl_code("proto_dcerpc_$x->{NAME} = proto_register_protocol(".make_str($name).", ".make_str($short_name).", ".make_str($filter_name).");");
 
709
 
 
710
            $self->pidl_code("proto_register_field_array(proto_dcerpc_$x->{NAME}, hf, array_length (hf));");
 
711
            $self->pidl_code("proto_register_subtree_array(ett, array_length(ett));");
 
712
        } else {
 
713
            $self->pidl_code("proto_dcerpc = proto_get_id_by_filter_name(\"dcerpc\");");
 
714
            $self->pidl_code("proto_register_field_array(proto_dcerpc, hf, array_length(hf));");
 
715
            $self->pidl_code("proto_register_subtree_array(ett, array_length(ett));");
 
716
        }
 
717
 
 
718
        $self->deindent;
 
719
        $self->pidl_code("}\n");
 
720
        $self->pidl_fn_end("proto_register_dcerpc_$x->{NAME}");
 
721
}
 
722
 
 
723
sub RegisterInterfaceHandoff($$)
 
724
{
 
725
        my ($self,$x) = @_;
 
726
 
 
727
        if (defined($x->{UUID})) {
 
728
                $self->pidl_fn_start("proto_reg_handoff_dcerpc_$x->{NAME}");
 
729
            $self->pidl_code("void proto_reg_handoff_dcerpc_$x->{NAME}(void)");
 
730
            $self->pidl_code("{");
 
731
            $self->indent;
 
732
            $self->pidl_code("dcerpc_init_uuid(proto_dcerpc_$x->{NAME}, ett_dcerpc_$x->{NAME},");
 
733
            $self->pidl_code("\t&uuid_dcerpc_$x->{NAME}, ver_dcerpc_$x->{NAME},");
 
734
            $self->pidl_code("\t$x->{NAME}_dissectors, hf_$x->{NAME}_opnum);");
 
735
            $self->deindent;
 
736
            $self->pidl_code("}");
 
737
                $self->pidl_fn_end("proto_reg_handoff_dcerpc_$x->{NAME}");
 
738
 
 
739
                $self->{hf_used}->{"hf_$x->{NAME}_opnum"} = 1;
 
740
        }
 
741
}
 
742
 
 
743
sub ProcessInclude
 
744
{
 
745
        my $self = shift;
 
746
        my @includes = @_;
 
747
        foreach (@includes) {
 
748
                $self->pidl_hdr("#include \"$_\"");
 
749
        }
 
750
        $self->pidl_hdr("");
 
751
}
 
752
 
 
753
sub ProcessImport
 
754
{
 
755
        my $self = shift;
 
756
        my @imports = @_;
 
757
        foreach (@imports) {
 
758
                next if($_ eq "security");
 
759
                s/\.idl\"$//;
 
760
                s/^\"//;
 
761
                $self->pidl_hdr("#include \"packet-dcerpc-$_\.h\"");
 
762
        }
 
763
        $self->pidl_hdr("");
 
764
}
 
765
 
 
766
sub ProcessInterface($$)
 
767
{
 
768
        my ($self, $x) = @_;
 
769
 
 
770
        push(@{$self->{conformance}->{strip_prefixes}}, $x->{NAME});
 
771
 
 
772
        my $define = "__PACKET_DCERPC_" . uc($_->{NAME}) . "_H";
 
773
        $self->pidl_hdr("#ifndef $define");
 
774
        $self->pidl_hdr("#define $define");
 
775
        $self->pidl_hdr("");
 
776
 
 
777
        $self->pidl_def("static gint proto_dcerpc_$x->{NAME} = -1;");
 
778
        $self->register_ett("ett_dcerpc_$x->{NAME}");
 
779
        $self->register_hf_field("hf_$x->{NAME}_opnum", "Operation", "$x->{NAME}.opnum", "FT_UINT16", "BASE_DEC", "NULL", 0, "");
 
780
 
 
781
        if (defined($x->{UUID})) {
 
782
                my $if_uuid = $x->{UUID};
 
783
 
 
784
            $self->pidl_def("/* Version information */\n\n");
 
785
 
 
786
            $self->pidl_def("static e_uuid_t uuid_dcerpc_$x->{NAME} = {");
 
787
            $self->pidl_def("\t0x" . substr($if_uuid, 1, 8)
 
788
                . ", 0x" . substr($if_uuid, 10, 4)
 
789
            . ", 0x" . substr($if_uuid, 15, 4) . ",");
 
790
            $self->pidl_def("\t{ 0x" . substr($if_uuid, 20, 2)
 
791
                . ", 0x" . substr($if_uuid, 22, 2)
 
792
            . ", 0x" . substr($if_uuid, 25, 2)
 
793
            . ", 0x" . substr($if_uuid, 27, 2)
 
794
            . ", 0x" . substr($if_uuid, 29, 2)
 
795
            . ", 0x" . substr($if_uuid, 31, 2)
 
796
            . ", 0x" . substr($if_uuid, 33, 2)
 
797
            . ", 0x" . substr($if_uuid, 35, 2) . " }");
 
798
            $self->pidl_def("};");
 
799
 
 
800
            my $maj = $x->{VERSION};
 
801
            $maj =~ s/\.(.*)$//g;
 
802
            $self->pidl_def("static guint16 ver_dcerpc_$x->{NAME} = $maj;");
 
803
            $self->pidl_def("");
 
804
        }
 
805
 
 
806
        $return_types{$x->{NAME}} = {};
 
807
 
 
808
        $self->Interface($x);
 
809
 
 
810
        $self->pidl_code("\n".DumpFunctionTable($x));
 
811
 
 
812
        foreach (keys %{$return_types{$x->{NAME}}}) {
 
813
                my ($type, $desc) = @{$return_types{$x->{NAME}}->{$_}};
 
814
                my $dt = $self->find_type($type);
 
815
                $dt or die("Unable to find information about return type `$type'");
 
816
                $self->register_hf_field("hf_$x->{NAME}_$_", $desc, "$x->{NAME}.$_", $dt->{FT_TYPE}, "BASE_HEX", $dt->{VALSSTRING}, 0, "");
 
817
                $self->{hf_used}->{"hf_$x->{NAME}_$_"} = 1;
 
818
        }
 
819
 
 
820
        $self->RegisterInterface($x);
 
821
        $self->RegisterInterfaceHandoff($x);
 
822
 
 
823
        $self->pidl_hdr("#endif /* $define */");
 
824
}
 
825
 
 
826
sub find_type($$)
 
827
{
 
828
        my ($self, $n) = @_;
 
829
 
 
830
        return $self->{conformance}->{types}->{$n};
 
831
}
 
832
 
 
833
sub register_type($$$$$$$$)
 
834
{
 
835
        my ($self, $type,$call,$ft,$base,$mask,$vals,$length) = @_;
 
836
 
 
837
        return if (defined($self->{conformance}->{types}->{$type}));
 
838
 
 
839
        $self->{conformance}->{types}->{$type} = {
 
840
                NAME => $type,
 
841
                DISSECTOR_NAME => $call,
 
842
                FT_TYPE => $ft,
 
843
                BASE_TYPE => $base,
 
844
                MASK => $mask,
 
845
                VALSSTRING => $vals,
 
846
                ALIGNMENT => $length
 
847
        };
 
848
}
 
849
 
 
850
# Loads the default types
 
851
sub Initialize($$)
 
852
{
 
853
        my ($self, $cnf_file) = @_;
 
854
 
 
855
        $self->{conformance} = {
 
856
                imports => {},
 
857
                header_fields=> {}
 
858
        };
 
859
 
 
860
        ReadConformance($cnf_file, $self->{conformance}) or print STDERR "warning: No conformance file `$cnf_file'\n";
 
861
 
 
862
        foreach my $bytes (qw(1 2 4 8)) {
 
863
                my $bits = $bytes * 8;
 
864
                $self->register_type("uint$bits", "offset = PIDL_dissect_uint$bits(tvb, offset, pinfo, tree, drep, \@HF\@, \@PARAM\@);", "FT_UINT$bits", "BASE_DEC", 0, "NULL", $bytes);
 
865
                $self->register_type("int$bits", "offset = PIDL_dissect_uint$bits(tvb, offset, pinfo, tree, drep, \@HF\@, \@PARAM\@);", "FT_INT$bits", "BASE_DEC", 0, "NULL", $bytes);
 
866
        }
 
867
 
 
868
        $self->register_type("udlong", "offset = dissect_ndr_duint32(tvb, offset, pinfo, tree, drep, \@HF\@, NULL);", "FT_UINT64", "BASE_DEC", 0, "NULL", 4);
 
869
        $self->register_type("bool8", "offset = PIDL_dissect_uint8(tvb, offset, pinfo, tree, drep, \@HF\@, \@PARAM\@);","FT_INT8", "BASE_DEC", 0, "NULL", 1);
 
870
        $self->register_type("char", "offset = PIDL_dissect_uint8(tvb, offset, pinfo, tree, drep, \@HF\@, \@PARAM\@);","FT_INT8", "BASE_DEC", 0, "NULL", 1);
 
871
        $self->register_type("long", "offset = PIDL_dissect_uint32(tvb, offset, pinfo, tree, drep, \@HF\@, \@PARAM\@);","FT_INT32", "BASE_DEC", 0, "NULL", 4);
 
872
        $self->register_type("dlong", "offset = dissect_ndr_duint32(tvb, offset, pinfo, tree, drep, \@HF\@, NULL);","FT_INT64", "BASE_DEC", 0, "NULL", 8);
 
873
        $self->register_type("GUID", "offset = dissect_ndr_uuid_t(tvb, offset, pinfo, tree, drep, \@HF\@, NULL);","FT_GUID", "BASE_NONE", 0, "NULL", 4);
 
874
        $self->register_type("policy_handle", "offset = PIDL_dissect_policy_hnd(tvb, offset, pinfo, tree, drep, \@HF\@, \@PARAM\@);","FT_BYTES", "BASE_NONE", 0, "NULL", 4);
 
875
        $self->register_type("NTTIME", "offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep, \@HF\@);","FT_ABSOLUTE_TIME", "BASE_NONE", 0, "NULL", 4);
 
876
        $self->register_type("NTTIME_hyper", "offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep, \@HF\@);","FT_ABSOLUTE_TIME", "BASE_NONE", 0, "NULL", 4);
 
877
        $self->register_type("time_t", "offset = dissect_ndr_time_t(tvb, offset, pinfo,tree, drep, \@HF\@, NULL);","FT_ABSOLUTE_TIME", "BASE_DEC", 0, "NULL", 4);
 
878
        $self->register_type("NTTIME_1sec", "offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep, \@HF\@);", "FT_ABSOLUTE_TIME", "BASE_NONE", 0, "NULL", 4);
 
879
        $self->register_type("SID", "
 
880
                dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
 
881
 
 
882
                di->hf_index = \@HF\@;
 
883
 
 
884
                offset = dissect_ndr_nt_SID_with_options(tvb, offset, pinfo, tree, drep, param);
 
885
        ","FT_STRING", "BASE_DEC", 0, "NULL", 4);
 
886
        $self->register_type("WERROR",
 
887
                "offset = PIDL_dissect_uint32(tvb, offset, pinfo, tree, drep, \@HF\@, \@PARAM\@);","FT_UINT32", "BASE_DEC", 0, "VALS(WERR_errors)", 4);
 
888
        $self->register_type("NTSTATUS",
 
889
                "offset = PIDL_dissect_uint32(tvb, offset, pinfo, tree, drep, \@HF\@, \@PARAM\@);","FT_UINT32", "BASE_DEC", 0, "VALS(NT_errors)", 4);
 
890
 
 
891
}
 
892
 
 
893
#####################################################################
 
894
# Generate Wireshark parser and header code
 
895
sub Parse($$$$$)
 
896
{
 
897
        my($self,$ndr,$idl_file,$h_filename,$cnf_file) = @_;
 
898
 
 
899
        $self->Initialize($cnf_file);
 
900
 
 
901
        return (undef, undef) if defined($self->{conformance}->{noemit_dissector});
 
902
 
 
903
        my $notice =
 
904
"/* DO NOT EDIT
 
905
        This filter was automatically generated
 
906
        from $idl_file and $cnf_file.
 
907
 
 
908
        Pidl is a perl based IDL compiler for DCE/RPC idl files.
 
909
        It is maintained by the Samba team, not the Wireshark team.
 
910
        Instructions on how to download and install Pidl can be
 
911
        found at http://wiki.wireshark.org/Pidl
 
912
*/
 
913
 
 
914
";
 
915
 
 
916
        $self->pidl_hdr($notice);
 
917
 
 
918
        $self->{res}->{headers} = "\n";
 
919
        $self->{res}->{headers} .= "#ifdef HAVE_CONFIG_H\n";
 
920
        $self->{res}->{headers} .= "#include \"config.h\"\n";
 
921
        $self->{res}->{headers} .= "#endif\n\n";
 
922
 
 
923
        $self->{res}->{headers} .= "#ifdef _MSC_VER\n";
 
924
        $self->{res}->{headers} .= "#pragma warning(disable:4005)\n";
 
925
        $self->{res}->{headers} .= "#pragma warning(disable:4013)\n";
 
926
        $self->{res}->{headers} .= "#pragma warning(disable:4018)\n";
 
927
        $self->{res}->{headers} .= "#pragma warning(disable:4101)\n";
 
928
        $self->{res}->{headers} .= "#endif\n\n";
 
929
 
 
930
        $self->{res}->{headers} .= "#include <glib.h>\n";
 
931
        $self->{res}->{headers} .= "#include <string.h>\n";
 
932
        $self->{res}->{headers} .= "#include <epan/packet.h>\n\n";
 
933
 
 
934
        $self->{res}->{headers} .= "#include \"packet-dcerpc.h\"\n";
 
935
        $self->{res}->{headers} .= "#include \"packet-dcerpc-nt.h\"\n";
 
936
        $self->{res}->{headers} .= "#include \"packet-windows-common.h\"\n";
 
937
 
 
938
        my $h_basename = basename($h_filename);
 
939
 
 
940
        $self->{res}->{headers} .= "#include \"$h_basename\"\n";
 
941
        $self->pidl_code("");
 
942
 
 
943
        if (defined($self->{conformance}->{ett})) {
 
944
                register_ett($self,$_) foreach(@{$self->{conformance}->{ett}})
 
945
        }
 
946
 
 
947
        # Wireshark protocol registration
 
948
 
 
949
        foreach (@$ndr) {
 
950
                $self->ProcessInterface($_) if ($_->{TYPE} eq "INTERFACE");
 
951
                $self->ProcessImport(@{$_->{PATHS}}) if ($_->{TYPE} eq "IMPORT");
 
952
                $self->ProcessInclude(@{$_->{PATHS}}) if ($_->{TYPE} eq "INCLUDE");
 
953
        }
 
954
 
 
955
        $self->{res}->{ett} = DumpEttDeclaration($self->{ett});
 
956
        $self->{res}->{hf} = $self->DumpHfDeclaration();
 
957
 
 
958
        my $parser = $notice;
 
959
        $parser.= $self->{res}->{headers};
 
960
        $parser.=$self->{res}->{ett};
 
961
        $parser.=$self->{res}->{hf};
 
962
        $parser.=$self->{res}->{def};
 
963
        if (exists ($self->{conformance}->{override})) {
 
964
                $parser.=$self->{conformance}->{override};
 
965
        }
 
966
        $parser.=$self->{res}->{code};
 
967
 
 
968
        my $header = "/* autogenerated by pidl */\n\n";
 
969
        $header.=$self->{res}->{hdr};
 
970
 
 
971
        $self->CheckUsed($self->{conformance});
 
972
 
 
973
        return ($parser,$header);
 
974
}
 
975
 
 
976
###############################################################################
 
977
# ETT
 
978
###############################################################################
 
979
 
 
980
sub register_ett($$)
 
981
{
 
982
        my ($self, $name) = @_;
 
983
 
 
984
        push (@{$self->{ett}}, $name);
 
985
}
 
986
 
 
987
sub DumpEttList
 
988
{
 
989
        my ($ett) = @_;
 
990
        my $res = "\tstatic gint *ett[] = {\n";
 
991
        foreach (@$ett) {
 
992
                $res .= "\t\t&$_,\n";
 
993
        }
 
994
 
 
995
        return "$res\t};\n";
 
996
}
 
997
 
 
998
sub DumpEttDeclaration
 
999
{
 
1000
        my ($ett) = @_;
 
1001
        my $res = "\n/* Ett declarations */\n";
 
1002
        foreach (@$ett) {
 
1003
                $res .= "static gint $_ = -1;\n";
 
1004
        }
 
1005
 
 
1006
        return "$res\n";
 
1007
}
 
1008
 
 
1009
###############################################################################
 
1010
# HF
 
1011
###############################################################################
 
1012
 
 
1013
sub register_hf_field($$$$$$$$$)
 
1014
{
 
1015
        my ($self,$index,$name,$filter_name,$ft_type,$base_type,$valsstring,$mask,$blurb) = @_;
 
1016
 
 
1017
        if (defined ($self->{conformance}->{hf_renames}->{$index})) {
 
1018
                $self->{conformance}->{hf_renames}->{$index}->{USED} = 1;
 
1019
                return $self->{conformance}->{hf_renames}->{$index}->{NEWNAME};
 
1020
        }
 
1021
 
 
1022
        $self->{conformance}->{header_fields}->{$index} = {
 
1023
                INDEX => $index,
 
1024
                NAME => $name,
 
1025
                FILTER => $filter_name,
 
1026
                FT_TYPE => $ft_type,
 
1027
                BASE_TYPE => $base_type,
 
1028
                VALSSTRING => $valsstring,
 
1029
                MASK => $mask,
 
1030
                BLURB => $blurb
 
1031
        };
 
1032
 
 
1033
        if ((not defined($blurb) or $blurb eq "") and
 
1034
                        defined($self->{conformance}->{fielddescription}->{$index})) {
 
1035
                $self->{conformance}->{header_fields}->{$index}->{BLURB} =
 
1036
                        $self->{conformance}->{fielddescription}->{$index}->{DESCRIPTION};
 
1037
                $self->{conformance}->{fielddescription}->{$index}->{USED} = 1;
 
1038
        }
 
1039
 
 
1040
        return $index;
 
1041
}
 
1042
 
 
1043
sub DumpHfDeclaration($)
 
1044
{
 
1045
        my ($self) = @_;
 
1046
        my $res = "";
 
1047
 
 
1048
        $res = "\n/* Header field declarations */\n";
 
1049
 
 
1050
        foreach (keys %{$self->{conformance}->{header_fields}})
 
1051
        {
 
1052
                $res .= "static gint $_ = -1;\n";
 
1053
        }
 
1054
 
 
1055
        return "$res\n";
 
1056
}
 
1057
 
 
1058
sub DumpHfList($)
 
1059
{
 
1060
        my ($self) = @_;
 
1061
        my $res = "\tstatic hf_register_info hf[] = {\n";
 
1062
 
 
1063
        foreach (values %{$self->{conformance}->{header_fields}})
 
1064
        {
 
1065
                $res .= "\t{ &$_->{INDEX},
 
1066
          { ".make_str($_->{NAME}).", ".make_str($_->{FILTER}).", $_->{FT_TYPE}, $_->{BASE_TYPE}, $_->{VALSSTRING}, $_->{MASK}, ".make_str($_->{BLURB}).", HFILL }},
 
1067
";
 
1068
        }
 
1069
 
 
1070
        return $res."\t};\n";
 
1071
}
 
1072
 
 
1073
 
 
1074
###############################################################################
 
1075
# Function table
 
1076
###############################################################################
 
1077
 
 
1078
sub DumpFunctionTable($)
 
1079
{
 
1080
        my $if = shift;
 
1081
 
 
1082
        my $res = "static dcerpc_sub_dissector $if->{NAME}\_dissectors[] = {\n";
 
1083
        foreach (@{$if->{FUNCTIONS}}) {
 
1084
                my $fn_name = $_->{NAME};
 
1085
                $fn_name =~ s/^$if->{NAME}_//;
 
1086
                $res.= "\t{ $_->{OPNUM}, \"$fn_name\",\n";
 
1087
                $res.= "\t   $if->{NAME}_dissect_${fn_name}_request, $if->{NAME}_dissect_${fn_name}_response},\n";
 
1088
        }
 
1089
 
 
1090
        $res .= "\t{ 0, NULL, NULL, NULL }\n";
 
1091
 
 
1092
        return "$res};\n";
 
1093
}
 
1094
 
 
1095
sub CheckUsed($$)
 
1096
{
 
1097
        my ($self, $conformance) = @_;
 
1098
        foreach (values %{$conformance->{header_fields}}) {
 
1099
                if (not defined($self->{hf_used}->{$_->{INDEX}})) {
 
1100
                        warning($_->{POS}, "hf field `$_->{INDEX}' not used");
 
1101
                }
 
1102
        }
 
1103
 
 
1104
        foreach (values %{$conformance->{hf_renames}}) {
 
1105
                if (not $_->{USED}) {
 
1106
                        warning($_->{POS}, "hf field `$_->{OLDNAME}' not used");
 
1107
                }
 
1108
        }
 
1109
 
 
1110
        foreach (values %{$conformance->{dissectorparams}}) {
 
1111
                if (not $_->{USED}) {
 
1112
                        warning($_->{POS}, "dissector param never used");
 
1113
                }
 
1114
        }
 
1115
 
 
1116
        foreach (values %{$conformance->{imports}}) {
 
1117
                if (not $_->{USED}) {
 
1118
                        warning($_->{POS}, "import never used");
 
1119
                }
 
1120
        }
 
1121
 
 
1122
        foreach (values %{$conformance->{types}}) {
 
1123
                if (not $_->{USED} and defined($_->{POS})) {
 
1124
                        warning($_->{POS}, "type never used");
 
1125
                }
 
1126
        }
 
1127
 
 
1128
        foreach (values %{$conformance->{fielddescription}}) {
 
1129
                if (not $_->{USED}) {
 
1130
                        warning($_->{POS}, "description never used");
 
1131
                }
 
1132
        }
 
1133
 
 
1134
        foreach (values %{$conformance->{tfs}}) {
 
1135
                if (not $_->{USED}) {
 
1136
                        warning($_->{POS}, "True/False description never used");
 
1137
                }
 
1138
        }
 
1139
}
 
1140
 
 
1141
1;