?? ndr.pm
字號:
################################################### Samba4 NDR parser generator for IDL structures# Copyright tridge@samba.org 2000-2003# Copyright tpot@samba.org 2001,2005# Copyright jelmer@samba.org 2004-2007# Portions based on idl2eth.c by Ronnie Sahlberg# released under the GNU GPL=pod=head1 NAMEParse::Pidl::Wireshark::NDR - Parser generator for Wireshark=cutpackage Parse::Pidl::Wireshark::NDR;use Exporter;@ISA = qw(Exporter);@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);use strict;use Parse::Pidl qw(error warning);use Parse::Pidl::Typelist qw(getType);use Parse::Pidl::Util qw(has_property property_matches make_str);use Parse::Pidl::NDR qw(ContainsString GetNextLevel);use Parse::Pidl::Dump qw(DumpType DumpFunction);use Parse::Pidl::Wireshark::Conformance qw(ReadConformance);use File::Basename; use vars qw($VERSION);$VERSION = '0.01';my %return_types = ();my %dissector_used = ();my %ptrtype_mappings = ( "unique" => "NDR_POINTER_UNIQUE", "ref" => "NDR_POINTER_REF", "ptr" => "NDR_POINTER_PTR");sub StripPrefixes($$){ my ($s, $prefixes) = @_; foreach (@$prefixes) { $s =~ s/^$_\_//g; } return $s;}# Convert a IDL structure field name (e.g access_mask) to a prettier# string like 'Access Mask'.sub field2name($){ my($field) = shift; $field =~ s/_/ /g; # Replace underscores with spaces $field =~ s/(\w+)/\u\L$1/g; # Capitalise each word return $field;}sub new($){ my ($class) = @_; my $self = {res => {hdr => "", def => "", code => ""}, tabs => "", cur_fn => undef, hf_used => {}, ett => [], conformance => undef }; bless($self, $class);}sub pidl_fn_start($$){ my ($self, $fn) = @_; $self->{cur_fn} = $fn;}sub pidl_fn_end($$){ my ($self, $fn) = @_; die("Inconsistent state: $fn != $self->{cur_fn}") if ($fn ne $self->{cur_fn}); $self->{cur_fn} = undef;}sub pidl_code($$){ my ($self, $d) = @_; return if (defined($self->{cur_fn}) and defined($self->{conformance}->{manual}->{$self->{cur_fn}})); if ($d) { $self->{res}->{code} .= $self->{tabs}; $self->{res}->{code} .= $d; } $self->{res}->{code} .="\n";}sub pidl_hdr($$) { my ($self,$x) = @_; $self->{res}->{hdr} .= "$x\n"; }sub pidl_def($$) { my ($self,$x) = @_; $self->{res}->{def} .= "$x\n"; }sub indent($){ my ($self) = @_; $self->{tabs} .= "\t";}sub deindent($){ my ($self) = @_; $self->{tabs} = substr($self->{tabs}, 0, -1);}sub PrintIdl($$){ my ($self, $idl) = @_; foreach (split /\n/, $idl) { $self->pidl_code("/* IDL: $_ */"); } $self->pidl_code("");}###################################################################### parse the interface definitionssub Interface($$){ my($self, $interface) = @_; $self->Const($_,$interface->{NAME}) foreach (@{$interface->{CONSTS}}); $self->Type($_, $_->{NAME}, $interface->{NAME}) foreach (@{$interface->{TYPES}}); $self->Function($_,$interface->{NAME}) foreach (@{$interface->{FUNCTIONS}});}sub Enum($$$$){ my ($self, $e,$name,$ifname) = @_; my $valsstring = "$ifname\_$name\_vals"; my $dissectorname = "$ifname\_dissect\_enum\_".StripPrefixes($name, $self->{conformance}->{strip_prefixes}); return if (defined($self->{conformance}->{noemit}->{StripPrefixes($name, $self->{conformance}->{strip_prefixes})})); foreach (@{$e->{ELEMENTS}}) { if (/([^=]*)=(.*)/) { $self->pidl_hdr("#define $1 ($2)"); } } $self->pidl_hdr("extern const value_string $valsstring\[];"); $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_);"); $self->pidl_def("const value_string ".$valsstring."[] = {"); foreach (@{$e->{ELEMENTS}}) { next unless (/([^=]*)=(.*)/); $self->pidl_def("\t{ $1, \"$1\" },"); } $self->pidl_def("{ 0, NULL }"); $self->pidl_def("};"); $self->pidl_fn_start($dissectorname); $self->pidl_code("int"); $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_)"); $self->pidl_code("{"); $self->indent; $self->pidl_code("g$e->{BASE_TYPE} parameter=0;"); $self->pidl_code("if(param){"); $self->indent; $self->pidl_code("parameter=(g$e->{BASE_TYPE})*param;"); $self->deindent; $self->pidl_code("}"); $self->pidl_code("offset = dissect_ndr_$e->{BASE_TYPE}(tvb, offset, pinfo, tree, drep, hf_index, ¶meter);"); $self->pidl_code("if(param){"); $self->indent; $self->pidl_code("*param=(guint32)parameter;"); $self->deindent; $self->pidl_code("}"); $self->pidl_code("return offset;"); $self->deindent; $self->pidl_code("}\n"); $self->pidl_fn_end($dissectorname); my $enum_size = $e->{BASE_TYPE}; $enum_size =~ s/uint//g; $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);}sub Bitmap($$$$){ my ($self,$e,$name,$ifname) = @_; my $dissectorname = "$ifname\_dissect\_bitmap\_".StripPrefixes($name, $self->{conformance}->{strip_prefixes}); $self->register_ett("ett_$ifname\_$name"); $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_);"); $self->pidl_fn_start($dissectorname); $self->pidl_code("int"); $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_)"); $self->pidl_code("{"); $self->indent; $self->pidl_code("proto_item *item = NULL;"); $self->pidl_code("proto_tree *tree = NULL;"); $self->pidl_code(""); $self->pidl_code("g$e->{BASE_TYPE} flags;"); if ($e->{ALIGN} > 1) { $self->pidl_code("ALIGN_TO_$e->{ALIGN}_BYTES;"); } $self->pidl_code(""); $self->pidl_code("if (parent_tree) {"); $self->indent; $self->pidl_code("item = proto_tree_add_item(parent_tree, hf_index, tvb, offset, $e->{ALIGN}, TRUE);"); $self->pidl_code("tree = proto_item_add_subtree(item,ett_$ifname\_$name);"); $self->deindent; $self->pidl_code("}\n"); $self->pidl_code("offset = dissect_ndr_$e->{BASE_TYPE}(tvb, offset, pinfo, NULL, drep, -1, &flags);"); $self->pidl_code("proto_item_append_text(item, \": \");\n"); $self->pidl_code("if (!flags)"); $self->pidl_code("\tproto_item_append_text(item, \"(No values set)\");\n"); foreach (@{$e->{ELEMENTS}}) { next unless (/([^ ]*) (.*)/); my ($en,$ev) = ($1,$2); my $hf_bitname = "hf_$ifname\_$name\_$en"; my $filtername = "$ifname\.$name\.$en"; $self->{hf_used}->{$hf_bitname} = 1; $self->register_hf_field($hf_bitname, field2name($en), $filtername, "FT_BOOLEAN", $e->{ALIGN} * 8, "TFS(&$name\_$en\_tfs)", $ev, ""); $self->pidl_def("static const true_false_string $name\_$en\_tfs = {"); if (defined($self->{conformance}->{tfs}->{$hf_bitname})) { $self->pidl_def(" $self->{conformance}->{tfs}->{$hf_bitname}->{TRUE_STRING},"); $self->pidl_def(" $self->{conformance}->{tfs}->{$hf_bitname}->{FALSE_STRING},"); $self->{conformance}->{tfs}->{$hf_bitname}->{USED} = 1; } else { $self->pidl_def(" \"$en is SET\","); $self->pidl_def(" \"$en is NOT SET\","); } $self->pidl_def("};"); $self->pidl_code("proto_tree_add_boolean(tree, $hf_bitname, tvb, offset-$e->{ALIGN}, $e->{ALIGN}, flags);"); $self->pidl_code("if (flags&$ev){"); $self->pidl_code("\tproto_item_append_text(item, \"$en\");"); $self->pidl_code("\tif (flags & (~$ev))"); $self->pidl_code("\t\tproto_item_append_text(item, \", \");"); $self->pidl_code("}"); $self->pidl_code("flags&=(~$ev);"); $self->pidl_code(""); } $self->pidl_code("if (flags) {"); $self->pidl_code("\tproto_item_append_text(item, \"Unknown bitmap value 0x%x\", flags);"); $self->pidl_code("}\n"); $self->pidl_code("return offset;"); $self->deindent; $self->pidl_code("}\n"); $self->pidl_fn_end($dissectorname); my $size = $e->{BASE_TYPE}; $size =~ s/uint//g; $self->register_type($name, "offset = $dissectorname(tvb, offset, pinfo, tree, drep, \@HF\@, \@PARAM\@);", "FT_UINT$size", "BASE_HEX", "0", "NULL", $size/8);}sub ElementLevel($$$$$$$){ my ($self,$e,$l,$hf,$myname,$pn,$ifname) = @_; my $param = 0; if (defined($self->{conformance}->{dissectorparams}->{$myname})) { $param = $self->{conformance}->{dissectorparams}->{$myname}->{PARAM}; } if ($l->{TYPE} eq "POINTER") { my $type; if ($l->{LEVEL} eq "TOP") { $type = "toplevel"; } elsif ($l->{LEVEL} eq "EMBEDDED") { $type = "embedded"; } $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);"); } elsif ($l->{TYPE} eq "ARRAY") { if ($l->{IS_INLINE}) { error($e->{ORIGINAL}, "Inline arrays not supported"); } elsif ($l->{IS_FIXED}) { $self->pidl_code("int i;"); $self->pidl_code("for (i = 0; i < $l->{SIZE_IS}; i++)"); $self->pidl_code("\toffset = $myname\_(tvb, offset, pinfo, tree, drep);"); } else { my $type = ""; $type .= "c" if ($l->{IS_CONFORMANT}); $type .= "v" if ($l->{IS_VARYING}); unless ($l->{IS_ZERO_TERMINATED}) { $self->pidl_code("offset = dissect_ndr_u" . $type . "array(tvb, offset, pinfo, tree, drep, $myname\_);"); } else { my $nl = GetNextLevel($e,$l); $self->pidl_code("char *data;"); $self->pidl_code(""); $self->pidl_code("offset = dissect_ndr_$type" . "string(tvb, offset, pinfo, tree, drep, sizeof(g$nl->{DATA_TYPE}), $hf, FALSE, &data);"); $self->pidl_code("proto_item_append_text(tree, \": %s\", data);"); } } } elsif ($l->{TYPE} eq "DATA") { if ($l->{DATA_TYPE} eq "string") { my $bs = 2; # Byte size defaults to that of UCS2 ($bs = 1) if (property_matches($e, "flag", ".*LIBNDR_FLAG_STR_ASCII.*")); if (property_matches($e, "flag", ".*LIBNDR_FLAG_STR_SIZE4.*") and property_matches($e, "flag", ".*LIBNDR_FLAG_STR_LEN4.*")) { $self->pidl_code("char *data;\n"); $self->pidl_code("offset = dissect_ndr_cvstring(tvb, offset, pinfo, tree, drep, $bs, $hf, FALSE, &data);"); $self->pidl_code("proto_item_append_text(tree, \": %s\", data);"); } elsif (property_matches($e, "flag", ".*LIBNDR_FLAG_STR_SIZE4.*")) { $self->pidl_code("offset = dissect_ndr_vstring(tvb, offset, pinfo, tree, drep, $bs, $hf, FALSE, NULL);"); } else { warn("Unable to handle string with flags $e->{PROPERTIES}->{flag}"); } } else { my $call; if ($self->{conformance}->{imports}->{$l->{DATA_TYPE}}) { $call = $self->{conformance}->{imports}->{$l->{DATA_TYPE}}->{DATA}; $self->{conformance}->{imports}->{$l->{DATA_TYPE}}->{USED} = 1; } elsif (defined($self->{conformance}->{imports}->{"$pn.$e->{NAME}"})) { $call = $self->{conformance}->{imports}->{"$pn.$e->{NAME}"}->{DATA}; $self->{conformance}->{imports}->{"$pn.$e->{NAME}"}->{USED} = 1; } elsif (defined($self->{conformance}->{types}->{$l->{DATA_TYPE}})) { $call= $self->{conformance}->{types}->{$l->{DATA_TYPE}}->{DISSECTOR_NAME}; $self->{conformance}->{types}->{$l->{DATA_TYPE}}->{USED} = 1; } else { $self->pidl_code("offset = $ifname\_dissect_struct_" . $l->{DATA_TYPE} . "(tvb,offset,pinfo,tree,drep,$hf,$param);"); return; } $call =~ s/\@HF\@/$hf/g; $call =~ s/\@PARAM\@/$param/g; $self->pidl_code($call); } } elsif ($_->{TYPE} eq "SUBCONTEXT") { my $num_bits = ($l->{HEADER_SIZE}*8); $self->pidl_code("guint$num_bits size;"); $self->pidl_code("int start_offset = offset;"); $self->pidl_code("tvbuff_t *subtvb;"); $self->pidl_code("offset = dissect_ndr_uint$num_bits(tvb, offset, pinfo, tree, drep, $hf, &size);"); $self->pidl_code("proto_tree_add_text(tree, tvb, start_offset, offset - start_offset + size, \"Subcontext size\");"); $self->pidl_code("subtvb = tvb_new_subset(tvb, offset, size, -1);"); $self->pidl_code("$myname\_(subtvb, 0, pinfo, tree, drep);"); } else { die("Unknown type `$_->{TYPE}'"); }}sub Element($$$){ my ($self,$e,$pn,$ifname) = @_; my $dissectorname = "$ifname\_dissect\_element\_".StripPrefixes($pn, $self->{conformance}->{strip_prefixes})."\_".StripPrefixes($e->{NAME}, $self->{conformance}->{strip_prefixes}); my $call_code = "offset = $dissectorname(tvb, offset, pinfo, tree, drep);"; my $type = $self->find_type($e->{TYPE}); if (not defined($type)) { # default settings $type = { MASK => 0,
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -