diff options
author | Jelmer Vernooij <jelmer@samba.org> | 2005-08-05 00:30:21 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 13:31:14 -0500 |
commit | fe8296e79a3d3c34231cad70ec1c373b1868f8f0 (patch) | |
tree | ff0a8341d43cdd64c0fb2ca4bb14bf848f2189c8 /source4 | |
parent | 6243e2a30414ef059fe2fd3636563269f4b12d06 (diff) | |
download | samba-fe8296e79a3d3c34231cad70ec1c373b1868f8f0.tar.gz samba-fe8296e79a3d3c34231cad70ec1c373b1868f8f0.tar.bz2 samba-fe8296e79a3d3c34231cad70ec1c373b1868f8f0.zip |
r9081: Work on new ethereal parser generator, partially based on
Ronnie Sahlberg's idl2eth.c
(This used to be commit 561aeca6490bdb7e37f12d60a67c551e5db3fc62)
Diffstat (limited to 'source4')
-rw-r--r-- | source4/build/pidl/Parse/Pidl/Ethereal/Conformance.pm | 99 | ||||
-rw-r--r-- | source4/build/pidl/Parse/Pidl/Ethereal/NDR.pm | 595 | ||||
-rw-r--r-- | source4/build/pidl/Parse/Pidl/Ethereal/NDR/Header.pm | 103 | ||||
-rw-r--r-- | source4/build/pidl/Parse/Pidl/Ethereal/NDR/Parser.pm | 1324 | ||||
-rwxr-xr-x | source4/build/pidl/pidl | 26 |
5 files changed, 704 insertions, 1443 deletions
diff --git a/source4/build/pidl/Parse/Pidl/Ethereal/Conformance.pm b/source4/build/pidl/Parse/Pidl/Ethereal/Conformance.pm new file mode 100644 index 0000000000..aeca3d90f8 --- /dev/null +++ b/source4/build/pidl/Parse/Pidl/Ethereal/Conformance.pm @@ -0,0 +1,99 @@ +################################################### +# parse an ethereal conformance file +# Copyright jelmer@samba.org 2005 +# released under the GNU GPL + +package Parse::Pidl::Ethereal::Conformance; + +require Exporter; + +@ISA = qw(Exporter); +@EXPORT_OK = qw(EmitProhibited); + +use strict; + +use Parse::Pidl::Util qw(has_property); + +sub handle_union_tag_size($$) +{ + #FIXME +} + +sub handle_type($$$$$$$) +{ + my ($name,$dissectorname,$ft_type,$base_type,$mask,$valsstring,$alignment) = @_; + #FIXME +} + +my %hf_renames = (); + +sub handle_hf_rename($$) +{ + my ($old,$new) = @_; + $hf_renames{$old} = $new; +} + +sub handle_param_value($$) +{ + my ($dissector_name,$value) = @_; + +} + +sub handle_hf_field($$$$$$$$) +{ + my ($hf,$title,$filter,$ft_type,$base_type,$valsstring,$mask,$blub) = @_; + +} + +sub handle_strip_prefix($) +{ + #FIXME +} + +my @noemit = (); + +sub handle_noemit($) +{ + my $type = shift; + + push (@noemit, $type); +} + +my %field_handlers = ( + UNION_TAG_SIZE => \&handle_union_tag_size, + TYPE => \&handle_type, + NOEMIT => \&handle_noemit, + PARAM_VALUE => \&handle_param_value, + HF_FIELD => \&handle_hf_field, + HF_RENAME => \&handle_hf_rename, + STRIP_PREFIX => \&handle_strip_prefix +); + +sub Parse($) +{ + my $f = shift; + + open(IN,$f) or return undef; + + foreach (<IN>) { + next if (/^#.*$/); + next if (/^$/); + + my @fields = split(/ /); + + $field_handlers{$fields[0]}(@fields); + } + + close(IN); +} + +sub EmitProhibited($) +{ + my $type = shift; + + return 1 if (grep(/$type/,@noemit)); + + return 0; +} + +1; diff --git a/source4/build/pidl/Parse/Pidl/Ethereal/NDR.pm b/source4/build/pidl/Parse/Pidl/Ethereal/NDR.pm new file mode 100644 index 0000000000..c5feab26a4 --- /dev/null +++ b/source4/build/pidl/Parse/Pidl/Ethereal/NDR.pm @@ -0,0 +1,595 @@ +################################################## +# Samba4 NDR parser generator for IDL structures +# Copyright tridge@samba.org 2000-2003 +# Copyright tpot@samba.org 2001 +# Copyright jelmer@samba.org 2004-2005 +# Portions based on idl2eth.c by Ronnie Sahlberg +# released under the GNU GPL + +package Parse::Pidl::Ethereal::NDR::Parser; + +use strict; +use Parse::Pidl::Typelist; +use Parse::Pidl::Util qw(has_property ParseExpr); +use Parse::Pidl::NDR; +use Parse::Pidl::Ethereal::Conformance qw(EmitProhibited); + +my %ptrtype_define_mappings = ( + "unique" => "NDR_POINTER_UNIQUE", + "ref" => "NDR_POINTER_REF", + "ptr" => "NDR_POINTER_PTR" +); + +sub type2ft($) +{ + my($t) = shift; + + return "FT_UINT$1" if $t =~ /uint(8|16|32|64)/; + return "FT_INT$1" if $t =~ /int(8|16|32|64)/; + return "FT_UINT64", if $t eq "HYPER_T" or $t eq "NTTIME" + or $t eq "NTTIME_1sec" or $t eq "NTTIME_hyper" or $t eq "hyper"; + + # Type is an enum + + return "FT_UINT16"; +} + +# Determine the display base for an element + +sub elementbase($) +{ + my($e) = shift; + + if (my $base = has_property($e, "display")) { + return "BASE_" . uc($base); + } + + return "BASE_DEC", if $e->{TYPE} eq "ENUM"; + return "BASE_DEC", if $e->{TYPE} =~ /u?int(8|16|32|64)/; + return "BASE_DEC", if $e->{TYPE} eq "NTTIME" or $e->{TYPE} eq "HYPER_T"; + + # Probably an enum + + return "BASE_DEC"; +} + +# 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 bitmapbase($) +{ + my $e = shift; + + return "16", if has_property($e->{DATA}, "bitmap16bit"); + return "8", if has_property($e->{DATA}, "bitmap8bit"); + + return "32"; +} + +my %res = (); +my $tabs = ""; +sub pidl_code($) +{ + my $d = shift; + if ($d) { + $res{code} .= $tabs; + $res{code} .= $d; + } + $res{code} .="\n"; +} + +sub pidl_hdr($) { $res{hdr} .= shift; } +sub pidl_def($) { $res{def} .= shift; } + +sub indent() +{ + $tabs .= "\t"; +} + +sub deindent() +{ + $tabs = substr($tabs, 0, -1); +} + +##################################################################### +# parse the interface definitions +sub Interface($) +{ + my($interface) = @_; + Typedef($_) foreach (@{$interface->{TYPEDEFS}}); + Function($_) foreach (@{$interface->{FUNCTIONS}}); +} + +sub Enum($$$) +{ + my ($e,$name,$ifname) = @_; + my $valsstring = "$ifname\_$name\_vals"; + my $dissectorname = "$ifname\_dissect\_$name"; + + foreach (@{$e->{ELEMENTS}}) { + if (/([^=]*)=(.*)/) { + pidl_hdr "#define $1 $2"; + } + } + + pidl_hdr "extern const value_string $valsstring;"; + pidl_hdr "int $dissectorname(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep, int hf_index, guint32 param);"; + + pidl_def "const value_string ".$valsstring."[] = {"; + indent; + foreach (@{$e->{ELEMENTS}}) { + next unless (/([^=]*)=(.*)/); + pidl_code "{ $1, \"$2\" },"; + } + + pidl_def "{ 0, NULL }"; + deindent; + pidl_def "};"; + + pidl_code "int"; + pidl_code "$dissectorname(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep, int hf_index, guint32 param _U_)"; + pidl_code "{"; + indent; + pidl_code "offset=dissect_ndr_$e->{BASE_TYPE}(tvb, offset, pinfo, tree, drep, hf_index, NULL);"; + pidl_code "return offset;"; + pidl_code "}"; + + register_type($name, $dissectorname, enum_ft($e), "BASE_DEC", "0", "VALS($valsstring)", enum_size($e)); +} + +sub Bitmap($$$) +{ + my ($e,$name,$ifname) = @_; + my $dissectorname = "$ifname\_dissect\_$name"; + + register_ett("ett_$ifname\_$name"); + + pidl_hdr "int $dissectorname(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep, int hf_index, guint32 param);"; + + pidl_code "int"; + pidl_code "$dissectorname(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *parent_tree, guint8 *drep, int hf_index, guint32 param _U_)"; + pidl_code "{"; + indent; + pidl_code "proto_item *item=NULL;"; + pidl_code "proto_tree *tree=NULL;"; + + if ($e->{ALIGN} == 8) { + pidl_code "guint8 flags;"; + } elsif ($e->{ALIGN} == 4) { + pidl_code "guint32 flags;"; + pidl_code "ALIGN_TO_4_BYTES;"; + } + + pidl_code "if(parent_tree) {"; + indent; + pidl_code "item=proto_tree_add_item(parent_tree, hf_index, tvb, offset, $e->{ALIGN}, TRUE);"; + pidl_code "tree=proto_item_add_subtree(item,ett_$ifname\_$name);"; + deindent; + pidl_code "}"; + + pidl_code "offset=dissect_ndr_$e->{BASE_TYPE}(tvb, offset, pinfo, NULL, drep, -1, &flags);"; + + foreach (@{$e->{ELEMENTS}}) { + next unless (/([^=]*)=(.*)/); + my ($en,$ev) = ($1,$2); + my $hf_bitname = "hf_$ifname\_$name\_$en"; + my $filtername = "$ifname\.$name\.$en"; + + register_hf_field($hf_bitname, $en, $filtername, "FT_BOOLEAN", $e->{ALIGN} * 8, "TFS(&$en\_tfs)", $ev, ""); + + pidl_def "static const true_false_string $name\_tfs = {"; + pidl_def " \"$name is SET\","; + pidl_def " \"$name is NOT SET\","; + pidl_def "};"; + + pidl_code "proto_tree_add_boolean(tree, $hf_bitname, tvb, offset-$e->{ALIGN}, $e->{ALIGN}, flags);"; + pidl_code "if (flags&$ev){"; + pidl_code "\tproto_item_append_text(item,\"$en\");"; + pidl_code "}"; + pidl_code "flags&=(~$ev);"; + } + + pidl_code "if(flags){"; + pidl_code "proto_item_append_text(item, \"UNKNOWN-FLAGS\");"; + pidl_code "}"; + deindent; + pidl_code "return offset;"; + pidl_code "}"; + register_new_type($name, $dissectorname, bitmap_ft($e), "BASE_HEX", "0", "NULL", $e->{ALIGN}); +} + +sub Element($$$) +{ + my ($e,$pn,$ifname) = @_; + + my $hf_index = "hf_$ifname\_$pn\_$e->{NAME}"; + my $dissectorname = "$ifname\_dissect\_$ifname\_$pn\_$e->{NAME}"; + + return if (EmitProhibited($dissectorname)); + + my $type = FindType($e->{DATA_TYPE}); + + my $hf = register_hf_field($hf_index, $e->{NAME}, "$ifname.$pn.$e->{NAME}", $type->{FT_TYPE}, $type->{BASE_TYPE}, $type->{VALS}, $type->{MASK}, ""); + + pidl_code "static int"; + pidl_code "$dissectorname(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep)"; + pidl_code "{"; + indent; + pidl_code "guint32 param=" . Conformance::FindDissectorParam($dissectorname).";"; + pidl_code "offset=$type->{DISSECTOR}(tvb, offset, pinfo, tree, drep, $hf, param);"; + pidl_code "return offset;"; + deindent; + pidl_code "}"; +} + +sub Function($$$) +{ + my ($fn,$name,$ifname) = @_; + + register_function($ifname,$fn->{OPCODE}, $fn->{NAME}, + "$ifname\_dissect\_$fn->{NAME}_request", + "$ifname\_dissect\_$fn->{NAME}_response"); + + pidl_code "static int"; + 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_)"; + pidl_code "{"; + indent; + foreach (@{$fn->{ELEMENTS}}) { + Element($_, $name, $ifname) if (grep(/in/,@{$_->{DIRECTION}})); + } + pidl_code "return offset;"; + deindent; + pidl_code "}"; + + pidl_code "static int"; + 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_)"; + pidl_code "{"; + indent; + foreach (@{$fn->{ELEMENTS}}) { + Element($_, $name, $ifname) if (grep(/out/,@{$_->{DIRECTION}})); + } + pidl_code "return offset;"; + deindent; + pidl_code "}"; +} + +sub Struct($$$) +{ + my ($e,$name,$ifname) = @_; + my $dissectorname = "$ifname\_dissect\_$name"; + + return if (EmitProhibited($dissectorname)); + + register_ett("ett_$ifname\_$name"); + + pidl_hdr "int $dissectorname(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *parent_tree, guint8 *drep, int hf_index, guint32 param _U_);"; + pidl_code "int"; + pidl_code "$dissectorname(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *parent_tree, guint8 *drep, int hf_index, guint32 param _U_)"; + indent; + pidl_code "proto_item *item = NULL;"; + pidl_code "proto_tree *tree = NULL;"; + pidl_code "int old_offset;"; + + pidl_code "ALIGN_TO_$e->{ALIGN}_BYTES;"; + + pidl_code "old_offset=offset;"; + pidl_code "if(parent_tree){"; + indent; + pidl_code "item=proto_tree_add_item(parent_tree, hf_index, tvb, offset, -1, TRUE);"; + pidl_code "tree=proto_item_add_subtree(item, ett_$ifname\_$name);"; + deindent; + pidl_code"}"; + + Element($_, $name, $ifname) foreach (@{$e->{ELEMENTS}}); + + pidl_code "proto_item_set_len(item, offset-old_offset);"; + pidl_code "return offset;"; + deindent; + pidl_code "}"; +} + +sub Union($$$) +{ + my ($e,$name,$ifname) = @_; + + my $dissectorname = "$ifname\_dissect_union_$name"; + + register_ett("ett_$ifname\_$name"); + + pidl_code "static int"; + pidl_code "$dissectorname(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *parent_tree, guint8 *drep, int hf_index, guint32 param _U_)"; + pidl_code "{"; + indent; + pidl_code "proto_item *item=NULL;"; + pidl_code "proto_tree *tree=NULL;"; + pidl_code "int old_offset;"; + + if ($e->{ALIGN} == 2) { + pidl_code "ALIGN_TO_2_BYTES;"; + } elsif ($e->{ALIGN} == 4) { + pidl_code "ALIGN_TO_4_BYTES;"; + } + + pidl_code "g$e->{SWITCH_TYPE} level;"; + + pidl_code "old_offset=offset;"; + pidl_code "if(parent_tree){"; + indent; + pidl_code "item=proto_tree_add_text(parent_tree,tvb,offset,-1,\"$name\");"; + pidl_code "tree=proto_item_add_subtree(item,ett_$ifname\_$name);"; + pidl_code "}"; + + pidl_code "offset = dissect_ndr_$e->{SWITCH_TYPE}(tvb, offset, pinfo, tree, drep, hf_index, &level);"; + + pidl_code "switch(level) {"; + foreach (@{$e->{ELEMENTS}}) { + pidl_code "$_->{CASE}:"; + indent; + Element($_, $name, $ifname); + deindent; + pidl_code "break;"; + } + + pidl_code "proto_item_set_len(item, offset-old_offset);"; + pidl_code "return offset;"; + deindent; + pidl_code "}"; + +} + +sub Typedef($$) +{ + my ($e,$ifname) = @_; + + { + ENUM => \&Enum, + STRUCT => \&Struct, + UNION => \&Union, + BITMAP => \&Bitmap + }->{$e->{DATA}->{TYPE}}->($e->{DATA}, $e->{NAME}, $ifname); +} + +sub RegisterInterface($) +{ + my ($x) = @_; + + pidl_code "void proto_register_dcerpc_$x->{NAME}(void)"; + pidl_code "{"; + indent; + + $res{code}.=DumpHfList(); + $res{code}.=DumpEttList(); + + if (defined($x->{UUID})) { + # These can be changed to non-pidl_code names if the old dissectors + # in epan/dissctors are deleted. + + my $name = "\"" . uc($x->{NAME}) . " (pidl)\""; + if (has_property($x, "helpstring")) { + $name = $x->{PROPERTIES}->{helpstring}; + } + my $short_name = "idl_$x->{NAME}"; + my $filter_name = "idl_$x->{NAME}"; + + pidl_code "proto_dcerpc_$x->{NAME} = proto_register_protocol($name, \"$short_name\", \"$filter_name\");"; + + pidl_code "proto_register_field_array(proto_dcerpc_$x->{NAME}, hf, array_length (hf));"; + pidl_code "proto_register_subtree_array(ett, array_length(ett));"; + } else { + pidl_code "proto_dcerpc = proto_get_id_by_filter_name(\"dcerpc\");"; + pidl_code "proto_register_field_array(proto_dcerpc, hf, array_length(hf));"; + pidl_code "proto_register_subtree_array(ett, array_length(ett));"; + } + + deindent; + pidl_code "}\n"; +} + +sub RegisterInterfaceHandoff($) +{ + my $x = shift; + pidl_code "void proto_reg_handoff_dcerpc_pidl_$x->{NAME}(void)"; + pidl_code "{"; + indent; + pidl_code "dcerpc_init_uuid(proto_dcerpc_$x->{NAME}, ett_dcerpc_$x->{NAME},"; + pidl_code "\t&uuid_dcerpc_$x->{NAME}, ver_dcerpc_$x->{NAME},"; + pidl_code "\t$x->{NAME}_dissectors, hf_$x->{NAME}_opnum);"; + deindent; + pidl_code "}"; +} + +sub ProcessInterface($) +{ + my $x = shift; + + %res = (code=>"",def=>"",hdr=>""); + + if (defined($x->{UUID})) { + my $if_uuid = $x->{UUID}; + + pidl_def "static e_uuid_t uuid_dcerpc_$x->{NAME} = {"; + pidl_def "\t0x" . substr($if_uuid, 1, 8) + . ", 0x" . substr($if_uuid, 10, 4) + . ", 0x" . substr($if_uuid, 15, 4) . ","; + pidl_def "\t{ 0x" . substr($if_uuid, 20, 2) + . ", 0x" . substr($if_uuid, 22, 2) + . ", 0x" . substr($if_uuid, 25, 2) + . ", 0x" . substr($if_uuid, 27, 2) + . ", 0x" . substr($if_uuid, 29, 2) + . ", 0x" . substr($if_uuid, 31, 2) + . ", 0x" . substr($if_uuid, 33, 2) + . ", 0x" . substr($if_uuid, 35, 2) . " }"; + pidl_def "};\n"; + + pidl_def "static guint16 ver_dcerpc_$x->{NAME} = $x->{VERSION};"; + } + + Interface($x); + + $res{functiontable} = DumpFunctionTable($x->{NAME}); + + RegisterInterface($x); + RegisterInterfaceHandoff($x); +} + +##################################################################### +# Generate ethereal parser and header code +sub Parse($$$) +{ + my($ndr,$module,$filename) = @_; + + $tabs = ""; + my $h_filename = $filename; + + if ($h_filename =~ /(.*)\.c/) { + $h_filename = "$1.h"; + } + + pidl_code "/* parser auto-generated by pidl */"; + pidl_code "#include \"packet-dcerpc.h\""; + pidl_code "#include \"$h_filename\""; + pidl_code ""; + pidl_code "static int hf_ptr = -1;"; + pidl_code "static int hf_array_size = -1;"; + pidl_code ""; + + # Ethereal protocol registration + + ProcessInterface($_) foreach (@$ndr); + + $res{ett} = DumpEttDeclaration(); + $res{hf} = DumpHfDeclaration(); + + my $parser = $res{ett}.$res{hf}.$res{def}.$res{code}; + my $header = $res{hdr}; + + return ($parser,$header); +} + +############################################################################### +# ETT +############################################################################### + +my @ett = (); + +sub register_ett($) +{ + my $name = shift; + + push (@ett, $name); +} + +sub DumpEttList() +{ + my $res = "\tstatic gint *ett[] = {\n"; + foreach (@ett) { + $res = "\t\t&$_,\n"; + } + + return "$res\t};\n"; +} + +sub DumpEttDeclaration() +{ + my $res = ""; + foreach (@ett) { + $res .= "static gint $_ = -1;\n"; + } + + return $res; +} + +############################################################################### +# HF +############################################################################### + +my %hf = (); + +sub register_hf_field($$$$$$$$) +{ + my ($index,$name,$filter_name,$ft_type,$base_type,$valsstring,$mask,$fixme) = @_; + + $hf{$index} = { + INDEX => $index, + NAME => $name, + FILTER => $filter_name, + FT_TYPE => $ft_type, + BASE_TYPE => $base_type, + VALS => $valsstring, + MASK => $mask + }; +} + +sub DumpHfDeclaration() +{ + my $res = ""; + + foreach (keys %hf) + { + $res .= "static gint $_ = -1;\n"; + } + + return $res; +} + +sub DumpHfList() +{ + my $res = "\tstatic hf_register_info hf[] = {\n"; + + foreach (values %hf) + { + $res .= "\t{ &$_->{INDEX}, + { \"$_->{NAME}\", \"$_->{FILTER}\", $_->{FT_TYPE}, $_->{BASE_TYPE}, $_->{VALS}, $_->{MASK}, FIXME, HFILL }}, +"; + } + + return $res."\t};\n"; +} + + +############################################################################### +# Function table +############################################################################### + +my %functions = (); + +sub register_function($$$$$) +{ + my ($ifname, $opcode, $name, $req, $repl) = @_; + + $functions{$ifname}->{$name} = { + NAME => $name, + OPCODE => $opcode, + REQUEST_FUNC => $req, + REPLY_FUNC => $repl + }; +} + +sub DumpFunctionTable($) +{ + my $name = shift; + + my $res = "static dcerpc_sub_dissector $name\_dissectors[] = {\n"; + + foreach (values %{$functions{$name}}) { + $res.= "\t{ $_->{OPCODE}, \"$_->{NAME},\n"; + $res.= "\t $_->{REQUEST_FUNC}, $_->{REPLY_FUNC} },\n"; + } + + $res .= "\t{ 0, NULL, NULL, NULL },\n"; + + return "$res\t}\n"; +} + + +1; diff --git a/source4/build/pidl/Parse/Pidl/Ethereal/NDR/Header.pm b/source4/build/pidl/Parse/Pidl/Ethereal/NDR/Header.pm deleted file mode 100644 index 6fcf949811..0000000000 --- a/source4/build/pidl/Parse/Pidl/Ethereal/NDR/Header.pm +++ /dev/null @@ -1,103 +0,0 @@ -################################################### -# create C header files for an IDL structure -# Copyright tridge@samba.org 2000 -# Copyright jelmer@samba.org 2005 -# released under the GNU GPL - -package Parse::Pidl::Ethereal::NDR::Header; - -use strict; - -use Parse::Pidl::Util qw(has_property); - -my($res); -my($tab_depth); - -sub pidl ($) -{ - $res .= shift; -} - -sub tabs() -{ - for (my($i)=0; $i < $tab_depth; $i++) { - pidl "\t"; - } -} - -##################################################################### -# prototype a typedef -sub HeaderTypedefProto($) -{ - my($d) = shift; - - my $tf = Parse::Pidl::Ethereal::NDR::Parser::get_typefamily($d->{DATA}{TYPE}); - - return unless has_property($d, "public"); - - unless (has_property($d, "nopull")) { - pidl "dcerpc_dissect_fnct_t $d->{NAME};\n"; - } -} - -##################################################################### -# parse a const -sub HeaderConst($) -{ - my($const) = shift; - if (!defined($const->{ARRAY_LEN}[0])) { - pidl "#define $const->{NAME}\t( $const->{VALUE} )\n"; - } else { - pidl "#define $const->{NAME}\t $const->{VALUE}\n"; - } -} - -my %headerstructs = (); - -##################################################################### -# parse the interface definitions -sub HeaderInterface($) -{ - my($interface) = shift; - - my $count = 0; - - pidl "#ifndef _HEADER_NDR_$interface->{NAME}\n"; - pidl "#define _HEADER_NDR_$interface->{NAME}\n\n"; - - if (defined $interface->{PROPERTIES}->{depends}) { - my @d = split / /, $interface->{PROPERTIES}->{depends}; - foreach my $i (@d) { - pidl "#include \"packet-dcerpc-$i\.h\"\n"; - } - } - - foreach my $d (@{$interface->{CONSTS}}) { - HeaderConst($d); - } - - foreach my $d (@{$interface->{TYPEDEFS}}) { - HeaderTypedefProto($d); - } - - pidl "#endif /* _HEADER_NDR_$interface->{NAME} */\n"; -} - -##################################################################### -# parse a parsed IDL into a C header -sub Parse($) -{ - my($idl) = shift; - $tab_depth = 0; - - $res = ""; - pidl "/* header auto-generated by pidl */\n\n"; - foreach my $x (@{$idl}) { - if ($x->{TYPE} eq "INTERFACE") { - HeaderInterface($x); - } - } - return $res; -} - -1; diff --git a/source4/build/pidl/Parse/Pidl/Ethereal/NDR/Parser.pm b/source4/build/pidl/Parse/Pidl/Ethereal/NDR/Parser.pm deleted file mode 100644 index 1038a64b42..0000000000 --- a/source4/build/pidl/Parse/Pidl/Ethereal/NDR/Parser.pm +++ /dev/null @@ -1,1324 +0,0 @@ -################################################## -# Samba4 NDR parser generator for IDL structures -# Copyright tridge@samba.org 2000-2003 -# Copyright tpot@samba.org 2001 -# Copyright jelmer@samba.org 2004-2005 -# released under the GNU GPL - -package Parse::Pidl::Ethereal::NDR::Parser; - -use strict; -use Parse::Pidl::Typelist; -use Parse::Pidl::Util qw(has_property ParseExpr); -use Parse::Pidl::NDR; - -# the list of needed functions - -# list of known types -my %typefamily; - - -sub NeededFunction($$) -{ - my $fn = shift; - my $needed = shift; - $needed->{"pull_$fn->{NAME}"} = 1; - foreach my $e (@{$fn->{ELEMENTS}}) { - $e->{PARENT} = $fn; - unless(defined($needed->{"pull_$e->{TYPE}"})) { - $needed->{"pull_$e->{TYPE}"} = 1; - } - - # for Ethereal - $needed->{"hf_$fn->{NAME}_$e->{NAME}"} = { - 'name' => field2name($e->{NAME}), - 'type' => $e->{TYPE}, - 'ft' => type2ft($e->{TYPE}), - 'base' => elementbase($e) - }; - $needed->{"hf_$e->{TYPE}"} = { - 'name' => field2name($e->{NAME}), - 'type' => $e->{TYPE}, - 'ft' => type2ft($e->{TYPE}), - 'base' => elementbase($e) - }; - $needed->{"ett_$e->{TYPE}"} = 1; - } - - # Add entry for return value - if (defined($fn->{RETURN_TYPE})) { - $needed->{"hf_$fn->{NAME}_result"} = { - 'name' => field2name('result'), - 'type' => $fn->{RETURN_TYPE}, - 'ft' => type2ft($fn->{RETURN_TYPE}), - 'base' => elementbase($fn) - }; - } -} - -sub NeededTypedef($$) -{ - my $t = shift; - my $needed = shift; - - if (has_property($t, "public")) { - $needed->{"pull_$t->{NAME}"} = not has_property($t, "nopull"); - $needed->{"decl_$t->{NAME}"} = not has_property($t, "nopull"); - } - - if ($t->{DATA}->{TYPE} eq "STRUCT" or $t->{DATA}->{TYPE} eq "UNION") { - - for my $e (@{$t->{DATA}->{ELEMENTS}}) { - $e->{PARENT} = $t->{DATA}; - if ($needed->{"pull_$t->{NAME}"} and - not defined($needed->{"pull_$e->{TYPE}"})) { - $needed->{"decl_$e->{TYPE}"} = $needed->{"pull_$e->{TYPE}"} = 1; - } - - $needed->{"hf_$t->{NAME}_$e->{NAME}"} = { - 'name' => field2name($e->{NAME}), - 'type' => $e->{TYPE}, - 'ft' => type2ft($e->{TYPE}), - 'base' => elementbase($e) - }; - $needed->{"ett_$e->{TYPE}"} = 1; - } - } - - if ($t->{DATA}->{TYPE} eq "ENUM") { - - $needed->{"hf_$t->{NAME}"} = { - 'name' => field2name($t->{NAME}), - 'ft' => 'FT_UINT16', - 'base' => 'BASE_DEC', - 'strings' => "VALS($t->{NAME}_vals)" - }; - $needed->{"ett_$t->{NAME}"} = 1; - } - - if ($t->{DATA}->{TYPE} eq "BITMAP") { - $needed->{BITMAPS}->{$t->{NAME}} = $t; - - foreach my $e (@{$t->{DATA}{ELEMENTS}}) { - $e =~ /^(.*?) \( (.*?) \)$/; - $needed->{"hf_$t->{NAME}_$1"} = { - 'name' => "$1", - 'ft' => "FT_BOOLEAN", - 'base' => bitmapbase($t), - 'bitmask' => "$2" - }; - } - $needed->{"ett_$t->{NAME}"} = 1; - } -} - -##################################################################### -# work out what parse functions are needed -sub NeededInterface($) -{ - my($interface) = shift; - my %needed = (); - - $needed{"hf_$interface->{NAME}_opnum"} = { - 'name' => "Operation", - 'ft' => "FT_UINT16", - 'base' => "BASE_DEC" - }; - - $needed{"ett_dcerpc_$interface->{NAME}"} = 1; - - foreach my $d (@{$interface->{FUNCTIONS}}) { - NeededFunction($d, \%needed); - } - foreach my $d (reverse @{$interface->{TYPEDEFS}}) { - NeededTypedef($d, \%needed); - } - - return \%needed; -} - -sub type2ft($) -{ - my($t) = shift; - - return "FT_UINT$1" if $t =~ /uint(8|16|32|64)/; - return "FT_INT$1" if $t =~ /int(8|16|32|64)/; - return "FT_UINT64", if $t eq "HYPER_T" or $t eq "NTTIME" - or $t eq "NTTIME_1sec" or $t eq "NTTIME_hyper" or $t eq "hyper"; - - # Type is an enum - - return "FT_UINT16"; -} - -# Determine the display base for an element - -sub elementbase($) -{ - my($e) = shift; - - if (my $base = has_property($e, "display")) { - return "BASE_" . uc($base); - } - - return "BASE_DEC", if $e->{TYPE} eq "ENUM"; - return "BASE_DEC", if $e->{TYPE} =~ /u?int(8|16|32|64)/; - return "BASE_DEC", if $e->{TYPE} eq "NTTIME" or $e->{TYPE} eq "HYPER_T"; - - # Probably an enum - - return "BASE_DEC"; -} - -# 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 bitmapbase($) -{ - my $e = shift; - - return "16", if has_property($e->{DATA}, "bitmap16bit"); - return "8", if has_property($e->{DATA}, "bitmap8bit"); - - return "32"; -} - -sub get_typefamily($) -{ - my $n = shift; - return $typefamily{$n}; -} - -sub append_prefix($$) -{ - my $e = shift; - my $var_name = shift; - my $pointers = 0; - - foreach my $l (@{$e->{LEVELS}}) { - if ($l->{TYPE} eq "POINTER") { - $pointers++; - } elsif ($l->{TYPE} eq "ARRAY") { - if (($pointers == 0) and - (not $l->{IS_FIXED}) and - (not $l->{IS_INLINE})) { - return get_value_of($var_name) - } - } elsif ($l->{TYPE} eq "DATA") { - if (typelist::scalar_is_reference($l->{DATA_TYPE})) { - return get_value_of($var_name) unless ($pointers); - } - } - } - - return $var_name; -} - -# see if a variable needs to be allocated by the NDR subsystem on pull -sub need_alloc($) -{ - my $e = shift; - - return 0; -} - -sub get_pointer_to($) -{ - my $var_name = shift; - - if ($var_name =~ /^\*(.*)$/) { - return $1; - } elsif ($var_name =~ /^\&(.*)$/) { - return $var_name; -# return "&($var_name)"; - } else { - return "&$var_name"; - } -} - -sub get_value_of($) -{ - my $var_name = shift; - - if ($var_name =~ /^\&(.*)$/) { - return $1; - } else { - return "*$var_name"; - } -} - -my $res; -my $tabs = ""; -sub pidl($) -{ - my $d = shift; - if ($d) { - $res .= $tabs; - $res .= $d; - } - $res .="\n"; -} - -sub indent() -{ - $tabs .= "\t"; -} - -sub deindent() -{ - $tabs = substr($tabs, 0, -1); -} - -##################################################################### -# check that a variable we get from ParseExpr isn't a null pointer -sub check_null_pointer($) -{ - my $size = shift; - if ($size =~ /^\*/) { - my $size2 = substr($size, 1); - pidl "if ($size2 == NULL) return NT_STATUS_INVALID_PARAMETER_MIX;"; - } -} - -##################################################################### -# check that a variable we get from ParseExpr isn't a null pointer -# void return varient -sub check_null_pointer_void($) -{ - my $size = shift; - if ($size =~ /^\*/) { - my $size2 = substr($size, 1); - pidl "if ($size2 == NULL) return;"; - } -} - -##################################################################### -# work out is a parse function should be declared static or not -sub fn_prefix($) -{ - my $fn = shift; - - return "" if (has_property($fn, "public")); - return "static "; -} - -################################################################### -# setup any special flags for an element or structure -sub start_flags($) -{ - my $e = shift; - my $flags = has_property($e, "flag"); - if (defined $flags) { - pidl "{ uint32_t _flags_save_$e->{TYPE} = ndr->flags;"; - pidl "ndr_set_flags(&ndr->flags, $flags);"; - indent; - } -} - -################################################################### -# end any special flags for an element or structure -sub end_flags($) -{ - my $e = shift; - my $flags = has_property($e, "flag"); - if (defined $flags) { - pidl "ndr->flags = _flags_save_$e->{TYPE};\n\t}"; - deindent; - } -} - -sub GenerateStructEnv($) -{ - my $x = shift; - my %env; - - foreach my $e (@{$x->{ELEMENTS}}) { - $env{$e->{NAME}} = "r->$e->{NAME}"; - } - - $env{"this"} = "r"; - - return \%env; -} - -sub GenerateFunctionEnv($) -{ - my $fn = shift; - my %env; - - foreach my $e (@{$fn->{ELEMENTS}}) { - if (grep (/out/, @{$e->{DIRECTION}})) { - $env{$e->{NAME}} = "r->out.$e->{NAME}"; - } - if (grep (/in/, @{$e->{DIRECTION}})) { - $env{$e->{NAME}} = "r->in.$e->{NAME}"; - } - } - - return \%env; -} - -##################################################################### -sub ParseArrayPreceding($$$) -{ - my $e = shift; - my $l = shift; - my $var_name = shift; - - return if ($l->{NO_METADATA}); - - # non fixed arrays encode the size just before the array - pidl "ndr_pull_array_size(ndr, tree, " . get_pointer_to($var_name) . ");"; -} - -sub compression_alg($$) -{ - my $e = shift; - my $l = shift; - my $compression = $l->{COMPRESSION}; - my ($alg, $clen, $dlen) = split(/ /, $compression); - - return $alg; -} - -sub compression_clen($$$) -{ - my $e = shift; - my $l = shift; - my $env = shift; - my $compression = $l->{COMPRESSION}; - my ($alg, $clen, $dlen) = split(/ /, $compression); - - return ParseExpr($clen, $env); -} - -sub compression_dlen($$$) -{ - my $e = shift; - my $l = shift; - my $env = shift; - my $compression = $l->{COMPRESSION}; - my ($alg, $clen, $dlen) = split(/ /, $compression); - - return ParseExpr($dlen, $env); -} - -sub ParseCompressionStart($$$$) -{ - my $e = shift; - my $l = shift; - my $subndr = shift; - my $env = shift; - my $comndr = $subndr."_compressed"; - my $alg = compression_alg($e, $l); - my $dlen = compression_dlen($e, $l, $env); - - pidl "{"; - indent; - pidl "struct pidl_pull *$comndr;"; - pidl "NDR_ALLOC($subndr, $comndr);"; - pidl "ndr_pull_compression($subndr, $comndr, $alg, $dlen);"; - - return $comndr; -} - -sub ParseCompressionEnd($$$) -{ - my $e = shift; - my $l = shift; - my $subndr = shift; - my $comndr = $subndr."_compressed"; - - deindent; - pidl "}"; -} - -sub ParseObfuscationStart($$) -{ - my $e = shift; - my $ndr = shift; - my $obfuscation = has_property($e, "obfuscation"); - - pidl "ndr_pull_obfuscation($ndr, $obfuscation);"; - - return $ndr; -} - -sub ParseObfuscationEnd($$) -{ - my $e = shift; - my $ndr = shift; - - # nothing to do here -} - -sub ParseSubcontextStart($$$$$$) -{ - my $e = shift; - my $l = shift; - my $ndr = shift; - my $var_name = shift; - my $ndr_flags = shift; - my $env = shift; - my $retndr = "_ndr_$e->{NAME}"; - - pidl "/* NDR_FLAGS $ndr_flags */"; - pidl "if ((ndr_flags) & NDR_SCALARS) {"; - indent; - pidl "struct pidl_pull *$retndr;"; - pidl "NDR_ALLOC(ndr, $retndr);"; - pidl "ndr_pull_subcontext_header($ndr, $l->{HEADER_SIZE}, $l->{SUBCONTEXT_SIZE}, $retndr);"; - - if (defined $l->{COMPRESSION}) { - $retndr = ParseCompressionStart($e, $l, $retndr, $env); - } - - if (defined $l->{OBFUSCATION}) { - $retndr = ParseObfuscationStart($e, $retndr); - } - - return ($retndr,$var_name); -} - -sub ParseSubcontextEnd($$) -{ - my $e = shift; - my $l = shift; - my $ndr = "_ndr_$e->{NAME}"; - - if (defined $l->{COMPRESSION}) { - ParseCompressionEnd($e, $l, $ndr); - } - - if (defined $l->{OBFUSCATION}) { - ParseObfuscationEnd($e, $ndr); - } - - my $advance; - if (defined($l->{SUBCONTEXT_SIZE}) and ($l->{SUBCONTEXT_SIZE} ne "-1")) { - $advance = $l->{SUBCONTEXT_SIZE}; - } elsif ($l->{HEADER_SIZE}) { - $advance = "$ndr->data_size"; - } else { - $advance = "$ndr->offset"; - } - pidl "ndr_pull_advance(ndr, $advance);"; - deindent; - pidl "}"; -} - -##################################################################### -# parse scalars in a structure element - pull size -sub ParseSwitch($$$$$$) -{ - my($e) = shift; - my $l = shift; - my $ndr = shift; - my($var_name) = shift; - my($ndr_flags) = shift; - my $env = shift; - my $switch_var = ParseExpr($l->{SWITCH_IS}, $env); - - check_null_pointer($switch_var); - - $var_name = get_pointer_to($var_name); - pidl "ndr_pull_set_switch_value($ndr, $var_name, $switch_var);"; - -} - -sub ParseData($$$$$) -{ - my $e = shift; - my $l = shift; - my $ndr = shift; - my $var_name = shift; - my $ndr_flags = shift; - - # - # ALAND! for packet-dcerpc-lsa.c, uncommenting this code - # produces constructs like &(&r->string), to pass to another - # function, which gives compiler errors. - # - if (typelist::scalar_is_reference($l->{DATA_TYPE})) { - $var_name = get_pointer_to($var_name); - } - - $var_name = get_pointer_to($var_name); - - pidl "offset += dissect_$l->{DATA_TYPE}(tvb, offset, pinfo, tree, drep, hf_FIXME, NULL);"; - - if (my $range = has_property($e, "range")) { - $var_name = get_value_of($var_name); - my ($low, $high) = split(/ /, $range, 2); - if (($l->{DATA_TYPE} =~ /^uint/) and ($low eq "0")) { - pidl "if ($var_name > $high) {"; - } else { - pidl "if ($var_name < $low || $var_name > $high) {"; - } - pidl "\treturn NT_STATUS_OK;"; - pidl "}"; - } -} - -sub CalcNdrFlags($$$) -{ - my $l = shift; - my $primitives = shift; - my $deferred = shift; - - my $scalars = 0; - my $buffers = 0; - - # Add NDR_SCALARS if this one is deferred - # and deferreds may be pushed - $scalars = 1 if ($l->{IS_DEFERRED} and $deferred); - - # Add NDR_SCALARS if this one is not deferred and - # primitives may be pushed - $scalars = 1 if (!$l->{IS_DEFERRED} and $primitives); - - # Add NDR_BUFFERS if this one contains deferred stuff - # and deferreds may be pushed - $buffers = 1 if ($l->{CONTAINS_DEFERRED} and $deferred); - - return "NDR_SCALARS|NDR_BUFFERS" if ($scalars and $buffers); - return "NDR_SCALARS" if ($scalars); - return "NDR_BUFFERS" if ($buffers); - return undef; -} - - -sub ParseElementLevel -{ - my($e) = shift; - my $l = shift; - my $ndr = shift; - my($var_name) = shift; - my $env = shift; - my $primitives = shift; - my $deferred = shift; - - my $ndr_flags = CalcNdrFlags($l, $primitives, $deferred); - - # Only pull something if there's actually something to be pulled - if (defined($ndr_flags)) { - if ($l->{TYPE} eq "SUBCONTEXT") { - ($ndr,$var_name) = ParseSubcontextStart($e, $l, $ndr, $var_name, $ndr_flags, $env); - ParseElementLevel($e,Ndr::GetNextLevel($e,$l), $ndr, $var_name, $env, $primitives, $deferred); - ParseSubcontextEnd($e, $l); - } elsif ($l->{TYPE} eq "ARRAY") { - my $length = ParseArrayHeader($e, $l, $ndr, $var_name, $env); - } elsif ($l->{TYPE} eq "POINTER") { - ParsePtr($e, $l, $ndr, $var_name); - } elsif ($l->{TYPE} eq "SWITCH") { - ParseSwitch($e, $l, $ndr, $var_name, $ndr_flags, $env); - } elsif ($l->{TYPE} eq "DATA") { - ParseData($e, $l, $ndr, $var_name, $ndr_flags); - } - } - - # add additional constructions - if ($l->{TYPE} eq "POINTER" and $deferred) { - if ($l->{POINTER_TYPE} ne "ref") { - pidl "if ($var_name) {"; - indent; - - if ($l->{POINTER_TYPE} eq "relative") { - pidl "struct ndr_pull_save _relative_save;"; - pidl "ndr_pull_save(ndr, &_relative_save);"; - pidl "NDR_CHECK(ndr_pull_relative_ptr2(ndr, $var_name));"; - } - } - - $var_name = get_value_of($var_name); - ParseElementLevel($e,Ndr::GetNextLevel($e,$l), $ndr, $var_name, $env, $primitives, $deferred); - - if ($l->{POINTER_TYPE} ne "ref") { - if ($l->{POINTER_TYPE} eq "relative") { - pidl "ndr_pull_restore(ndr, &_relative_save);"; - } - deindent; - pidl "}"; - } - } elsif ($l->{TYPE} eq "ARRAY") { - my $length = ParseExpr($l->{LENGTH_IS}, $env); - my $counter = "cntr_$e->{NAME}_$l->{LEVEL_INDEX}"; - - $var_name = $var_name . "[$counter]"; - unless ($l->{NO_METADATA}) { - $var_name = get_pointer_to($var_name); - } - - if (($primitives and not $l->{IS_DEFERRED}) or ($deferred and $l->{IS_DEFERRED})) { - pidl "for ($counter = 0; $counter < $length; $counter++) {"; - indent; - ParseElementLevel($e,Ndr::GetNextLevel($e,$l), $ndr, $var_name, $env, 1, 0); - deindent; - pidl "}"; - } - - if ($deferred and Ndr::ContainsDeferred($e, $l)) { - pidl "for ($counter = 0; $counter < $length; $counter++) {"; - indent; - ParseElementLevel($e,Ndr::GetNextLevel($e,$l), $ndr, $var_name, $env, 0, 1); - deindent; - pidl "}"; - } - } elsif ($l->{TYPE} eq "SWITCH") { - ParseElementLevel($e,Ndr::GetNextLevel($e,$l), $ndr, $var_name, $env, $primitives, $deferred); - } -} - -##################################################################### -# parse scalars in a structure element - pull size -sub ParseElement($$$$$$) -{ - my($e) = shift; - my $ndr = shift; - my($var_prefix) = shift; - my $env = shift; - my $primitives = shift; - my $deferred = shift; - - my $var_name = $var_prefix.$e->{NAME}; - - $var_name = append_prefix($e, $var_name); - - return unless $primitives or ($deferred and Ndr::ContainsDeferred($e, $e->{LEVELS}[0])); - - start_flags($e); - - ParseElementLevel($e,$e->{LEVELS}[0],$ndr,$var_name,$env,$primitives,$deferred); - - end_flags($e); -} - -##################################################################### -# parse a pointer in a struct element or function -sub ParsePtr($$$$) -{ - my($e) = shift; - my $l = shift; - my $ndr = shift; - my($var_name) = shift; - - my $nl = Ndr::GetNextLevel($e, $l); - my $next_is_array = ($nl->{TYPE} eq "ARRAY"); - - if ($l->{LEVEL} eq "EMBEDDED") { - pidl "dissect_ndr_embedded_pointer(FIXME);"; - } elsif ($l->{POINTER_TYPE} ne "ref") { - pidl "dissect_ndr_toplevel_pointer(FIXME);"; - } - - #pidl "memset($var_name, 0, sizeof($var_name));"; - if ($l->{POINTER_TYPE} eq "relative") { - pidl "ndr_pull_relative_ptr1($ndr, $var_name, _ptr_$e->{NAME});"; - } -} - -$typefamily{ENUM} = { - DECL => \&DeclEnum, -}; - -##################################################################### -# generate a pull function for an bitmap -sub ParseBitmap($$) -{ - my($bitmap) = shift; - my $name = shift; - my $type_fn = $bitmap->{BASE_TYPE}; - my($type_decl) = typelist::mapType($bitmap->{BASE_TYPE}); - - pidl "$type_decl v_bitmap;"; - start_flags($bitmap); - pidl "dissect_$type_fn(ndr, tree, hf, &v_bitmap);"; - - pidl "{\n\tproto_tree *subtree = NULL;"; - pidl ""; - pidl "\tif (tree->proto_tree)\n\t\tsubtree = proto_item_add_subtree(tree->proto_tree->last_child, ett_$name);"; - pidl ""; - foreach my $e (@{$bitmap->{DATA}{ELEMENTS}}) { - $e =~ /^(.*?) \( (.*?) \)$/; - pidl "\tproto_tree_add_boolean(subtree, hf_${name}_$1, ndr->tvb, ndr->offset - sizeof(v_bitmap), sizeof(v_bitmap), v_bitmap);"; - } - pidl "}"; - - pidl "*r = v_bitmap;"; - - end_flags($bitmap); -} - -$typefamily{BITMAP} = { - FN_BODY => \&ParseBitmap, -}; - -##################################################################### -# parse a struct - pull side -sub ParseStruct($$) -{ - my($struct) = shift; - my $name = shift; - my $conform_e; - - return unless defined $struct->{ELEMENTS}; - - my $env = GenerateStructEnv($struct); - - # see if the structure contains a conformant array. If it - # does, then it must be the last element of the structure, and - # we need to pull the conformant length early, as it fits on - # the wire before the structure (and even before the structure - # alignment) - $conform_e = $struct->{SURROUNDING_ELEMENT}; - - # declare any internal pointers we need - foreach my $e (@{$struct->{ELEMENTS}}) { - foreach my $l (@{$e->{LEVELS}}) { - if ($l->{TYPE} eq "POINTER" and not ($l->{POINTER_TYPE} eq "ref" and $l->{LEVEL} eq "TOP")) { - pidl "uint32_t _ptr_$e->{NAME};"; - last; - } - } - } - - start_flags($struct); - - pidl "if (ndr_flags & NDR_SCALARS) {"; - indent; - - if (defined $conform_e) { - ParseArrayPreceding($conform_e, $conform_e->{LEVELS}[0], "r->$conform_e->{NAME}"); - } - - pidl "ndr_pull_align(ndr, $struct->{ALIGN});"; - - foreach my $e (@{$struct->{ELEMENTS}}) { - ParseElement($e, "ndr", "r->", $env, 1, 0); - } - deindent; - pidl "}"; - - pidl "if (ndr_flags & NDR_BUFFERS) {"; - indent; - foreach my $e (@{$struct->{ELEMENTS}}) { - ParseElement($e, "ndr", "r->", $env, 0, 0); - } - - pidl "proto_item_set_end(tree->proto_tree, ndr->tvb, ndr->offset);"; - deindent; - pidl "}"; - - end_flags($struct); -} - -$typefamily{STRUCT} = { - FN_BODY => \&ParseStruct, -}; - -##################################################################### -# parse a union - pull side -sub ParseUnion($$$) -{ - my $e = shift; - my $name = shift; - my $have_default = 0; - my $switch_type = $e->{SWITCH_TYPE}; - - pidl "int level;"; - if (defined($switch_type)) { - if (typelist::typeIs($switch_type, "ENUM")) { - $switch_type = typelist::enum_type_fn(typelist::getType($switch_type)); - } - pidl typelist::mapType($switch_type) . " _level;"; - } - - start_flags($e); - - pidl "level = ndr_pull_get_switch_value(ndr, r);"; - - pidl "if (ndr_flags & NDR_SCALARS) {"; - indent; - - if (defined($switch_type)) { - pidl "ndr_pull_$switch_type(ndr, tree, hf_${name}, &_level);"; - pidl "if (_level != level) {"; - pidl "\treturn NT_STATUS_OK;"; - pidl "}"; - } - -# my $align = union_alignment($e); -# pidl "\tndr_pull_align(ndr, $align);\n"; - - pidl "switch (level) {"; - indent; - foreach my $el (@{$e->{ELEMENTS}}) { - if ($el->{CASE} eq "default") { - $have_default = 1; - } - pidl "$el->{CASE}: {"; - - if ($el->{TYPE} ne "EMPTY") { - indent; - foreach my $l (@{$el->{LEVELS}}) { - if ($l->{TYPE} eq "POINTER" and not ($l->{POINTER_TYPE} eq "ref" and $l->{LEVEL} eq "TOP")) { - pidl "uint32_t _ptr_$el->{NAME};"; - last; - } - } - ParseElement($el, "ndr", "r->", {}, 1, 0); - deindent; - } - pidl "break; }"; - pidl ""; - } - if (! $have_default) { - pidl "default:"; - pidl "\treturn NT_STATUS_OK;"; - } - deindent; - pidl "}"; - deindent; - pidl "}"; - pidl "if (ndr_flags & NDR_BUFFERS) {"; - indent; - pidl "switch (level) {"; - indent; - foreach my $el (@{$e->{ELEMENTS}}) { - pidl "$el->{CASE}:"; - if ($el->{TYPE} ne "EMPTY") { - indent; - ParseElement($el, "ndr", "r->", {}, 0, 1); - deindent; - } - pidl "break;"; - pidl ""; - } - if (! $have_default) { - pidl "default:"; - pidl "\treturn NT_STATUS_OK;"; - } - deindent; - pidl "}"; - pidl "proto_item_set_end(tree->proto_tree, ndr->tvb, ndr->offset);"; - deindent; - pidl "}"; - end_flags($e); -} - -$typefamily{UNION} = { - FN_BODY => \&ParseUnion, -}; - -##################################################################### -# parse an array -sub ParseArrayHeader($$$$$) -{ - my $e = shift; - my $l = shift; - my $ndr = shift; - my $var_name = shift; - my $env = shift; - - unless ($l->{NO_METADATA}) { - $var_name = get_pointer_to($var_name); - } - - # $var_name contains the name of the first argument here - - my $length = ParseExpr($l->{SIZE_IS}, $env); - my $size = $length; - - if ($l->{IS_CONFORMANT}) { - $length = $size = "ndr_get_array_size($ndr, " . get_pointer_to($var_name) . ")"; - } - - # if this is a conformant array then we use that size to allocate, and make sure - # we allocate enough to pull the elements - if (!$l->{IS_SURROUNDING}) { - ParseArrayPreceding($e, $l, $var_name); - } - - - if ($l->{IS_VARYING}) { - pidl "NDR_CHECK(ndr_pull_array_length($ndr, " . get_pointer_to($var_name) . "));"; - $length = "ndr_get_array_length($ndr, " . get_pointer_to($var_name) .")"; - } - - check_null_pointer($length); - - if ($length ne $size) { - pidl "if ($length > $size) {"; - indent; - pidl "return ndr_pull_error($ndr, NDR_ERR_ARRAY_SIZE, \"Bad array size %u should exceed array length %u\", $size, $length);"; - deindent; - pidl "}"; - } - - if ($l->{IS_CONFORMANT}) { - my $size = ParseExpr($l->{SIZE_IS}, $env); - check_null_pointer($size); - pidl "NDR_CHECK(ndr_check_array_size(ndr, (void*)" . get_pointer_to($var_name) . ", $size));"; - } - - if ($l->{IS_VARYING}) { - my $length = ParseExpr($l->{LENGTH_IS}, $env); - check_null_pointer($length); - pidl "NDR_CHECK(ndr_check_array_length(ndr, (void*)" . get_pointer_to($var_name) . ", $length));"; - } - - return $length; -} - -##################################################################### -# parse a typedef - pull side -sub ParseTypedef($) -{ - my($e) = shift; - - return unless (defined ($typefamily{$e->{DATA}->{TYPE}})); - - pidl fn_prefix($e) . "int dissect_$e->{NAME}(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, int hf_index, guint32 param)"; - - pidl "{"; - indent; - $typefamily{$e->{DATA}->{TYPE}}->{FN_BODY}->($e->{DATA}, $e->{NAME}); - pidl "return NT_STATUS_OK;"; - deindent; - pidl "}"; - pidl ""; -} - -##################################################################### -# parse a function -sub ParseFunctionRqst($) -{ - my($fn) = shift; - - my $env = GenerateFunctionEnv($fn); - - # request function - pidl "static int dissect_$fn->{NAME}_rqst(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep)"; - pidl "{"; - indent; - - pidl "struct pidl_pull *ndr = pidl_pull_init(tvb, offset, pinfo, drep);"; - - # declare any internal pointers we need - foreach my $e (@{$fn->{ELEMENTS}}) { - next unless (grep (/in/, @{$e->{DIRECTIONS}})); - foreach my $l (@{$e->{LEVELS}}) { - if ($l->{TYPE} eq "POINTER" and - not ($l->{POINTER_TYPE} eq "ref" and - $l->{LEVEL} eq "TOP")) { - pidl "uint32_t _ptr_$e->{NAME};"; - last; - } - } - } - - foreach my $e (@{$fn->{ELEMENTS}}) { - next unless (grep(/in/, @{$e->{DIRECTION}})); - ParseElement($e, "ndr", "r->in.", $env, 1, 1); - } - - pidl "return offset;"; - deindent; - pidl "}"; - pidl ""; -} - -sub ParseFunctionResp($) -{ - my($fn) = shift; - - my $env = GenerateFunctionEnv($fn); - - # response function - pidl "static int dissect_$fn->{NAME}_resp(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep)"; - pidl "{"; - indent; - - pidl "struct pidl_pull *ndr = pidl_pull_init(tvb, offset, pinfo, drep);"; - - # declare any internal pointers we need - foreach my $e (@{$fn->{ELEMENTS}}) { - next unless (grep (/out/, @{$e->{DIRECTIONS}})); - foreach my $l (@{$e->{LEVELS}}) { - if ($l->{TYPE} eq "POINTER" and - not ($l->{POINTER_TYPE} eq "ref" and - $l->{LEVEL} eq "TOP")) { - pidl "uint32_t _ptr_$e->{NAME};"; - last; - } - } - } - - foreach my $e (@{$fn->{ELEMENTS}}) { - next unless grep(/out/, @{$e->{DIRECTION}}); - ParseElement($e, "ndr", "r->out.", $env, 1, 1); - } - - if ($fn->{RETURN_TYPE}) { - pidl "dissect_$fn->{RETURN_TYPE}(ndr, tree, hf_$fn->{NAME}_result, drep);"; - } - - pidl "return offset;"; - deindent; - pidl "}"; - pidl ""; -} - -##################################################################### -# produce a function call table -sub FunctionTable($) -{ - my($interface) = shift; - - pidl "static dcerpc_sub_dissector dcerpc_dissectors[] = {"; - my $num = 0; - foreach my $d (@{$interface->{FUNCTIONS}}) { - # Strip interface name from function name, if present - my($n) = $d->{NAME}; - $n = substr($d->{NAME}, length($interface->{NAME}) + 1), - if $interface->{NAME} eq substr($d->{NAME}, 0, length($interface->{NAME})); - pidl "\t{ $num, \"$n\","; - pidl "\t\tdissect_$d->{NAME}_rqst,"; - pidl "\t\tdissect_$d->{NAME}_resp },"; - $num++; - } - pidl "};\n"; -} - -##################################################################### -# parse the interface definitions -sub ParseInterface($$) -{ - my($interface) = shift; - my $needed = shift; - - # Typedefs - foreach my $d (@{$interface->{TYPEDEFS}}) { - ($needed->{"pull_$d->{NAME}"}) && ParseTypedef($d); - # Make sure we don't generate a function twice... - $needed->{"pull_$d->{NAME}"} = 0; - } - - # Functions - foreach my $d (@{$interface->{FUNCTIONS}}) { - if ($needed->{"pull_$d->{NAME}"}) { - ParseFunctionRqst($d); - ParseFunctionResp($d); - } - - # Make sure we don't generate a function twice... - $needed->{"pull_$d->{NAME}"} = 0; - } -} - -##################################################################### -# generate code to parse an enum -sub DeclEnum($$) -{ - my ($e) = shift; - my $n = shift; - - pidl "static const value_string $n\_vals[] ="; - pidl "{"; - - foreach my $x (@{$e->{ELEMENTS}}) { - $x =~ /([^=]*)=(.*)/; - pidl "\t{ $1, \"$1\" },"; - } - - pidl "};\n"; -} - -sub DeclInterface($$) -{ - my($interface) = shift; - my $needed = shift; - - # Typedefs - foreach my $d (@{$interface->{TYPEDEFS}}) { - ($needed->{"decl_$d->{NAME}"}) && DeclTypedef($d, $needed); - } -} - -sub DeclTypedef($$) -{ - my $e = shift; - my $needed = shift; - - if (defined($typefamily{$e->{DATA}->{TYPE}}->{DECL})) { - $typefamily{$e->{DATA}->{TYPE}}->{DECL}->($e->{DATA}, $e->{NAME}); - - # Make sure we don't generate a function twice... - $needed->{"decl_$e->{NAME}"} = 0; - } -} - -sub RegisterInterface($$) -{ - my $x = shift; - my $needed = shift; - - pidl "void proto_register_dcerpc_pidl_$x->{NAME}(void)"; - pidl "{"; - indent; - - pidl "static hf_register_info hf[] = {"; - pidl "{ &hf_ptr, { \"Pointer\", \"$x->{NAME}.ptr\", FT_UINT32, BASE_HEX, NULL, 0x0, \"Pointer\", HFILL }},"; - - foreach my $x (sort keys(%{$needed})) { - next, if !($x =~ /^hf_/); - pidl "{ &$x,"; - $needed->{$x}->{strings} = "NULL", if !defined($needed->{$x}->{strings}); - $needed->{$x}->{bitmask} = "0", if !defined($needed->{$x}->{bitmask}); - pidl " { \"$needed->{$x}->{name}\", \"$x\", $needed->{$x}->{ft}, $needed->{$x}->{base}, $needed->{$x}->{strings}, $needed->{$x}->{bitmask}, \"$x\", HFILL }},"; - } - - pidl "};\n"; - - pidl "static gint *ett[] = {"; - indent; - foreach my $x (sort keys(%{$needed})) { - pidl "&$x,", if $x =~ /^ett_/; - } - deindent; - - pidl "};\n"; - - if (defined($x->{UUID})) { - # These can be changed to non-pidl names if the old dissectors - # in epan/dissctors are deleted. - - my $name = "\"" . uc($x->{NAME}) . " (pidl)\""; - if (has_property($x, "helpstring")) { - $name = $x->{PROPERTIES}->{helpstring}; - } - my $short_name = "pidl_$x->{NAME}"; - my $filter_name = "pidl_$x->{NAME}"; - - pidl "proto_dcerpc_pidl_$x->{NAME} = proto_register_protocol($name, \"$short_name\", \"$filter_name\");"; - - pidl "proto_register_field_array(proto_dcerpc_pidl_$x->{NAME}, hf, array_length (hf));"; - pidl "proto_register_subtree_array(ett, array_length(ett));"; - } else { - pidl "int proto_dcerpc;"; - pidl "proto_dcerpc = proto_get_id_by_filter_name(\"dcerpc\");"; - pidl "proto_register_field_array(proto_dcerpc, hf, array_length(hf));"; - pidl "proto_register_subtree_array(ett, array_length(ett));"; - } - - deindent; - pidl "}\n"; -} - -sub RegisterInterfaceHandoff($) -{ - my $x = shift; - pidl "void proto_reg_handoff_dcerpc_pidl_$x->{NAME}(void)"; - pidl "{"; - indent; - pidl "dcerpc_init_uuid(proto_dcerpc_pidl_$x->{NAME}, ett_dcerpc_$x->{NAME},"; - pidl "\t&uuid_dcerpc_$x->{NAME}, ver_dcerpc_$x->{NAME},"; - pidl "\tdcerpc_dissectors, hf_$x->{NAME}_opnum);"; - deindent; - pidl "}"; -} - -sub ProcessInterface($) -{ - my $x = shift; - my $needed = NeededInterface($x); - - # Required global declarations - DeclInterface($x, $needed); - - foreach my $y (sort keys(%{$needed})) { - pidl "static int $y = -1;", if $y =~ /^hf_/; - } - pidl ""; - - foreach my $y (sort keys(%{$needed})) { - pidl "static gint $y = -1;", if $y =~ /^ett_/; - } - pidl ""; - - pidl "int proto_dcerpc_pidl_$x->{NAME} = -1;\n"; - - if (defined($x->{UUID})) { - my $if_uuid = $x->{UUID}; - - pidl "static e_uuid_t uuid_dcerpc_$x->{NAME} = {"; - pidl "\t0x" . substr($if_uuid, 1, 8) - . ", 0x" . substr($if_uuid, 10, 4) - . ", 0x" . substr($if_uuid, 15, 4) . ","; - pidl "\t{ 0x" . substr($if_uuid, 20, 2) - . ", 0x" . substr($if_uuid, 22, 2) - . ", 0x" . substr($if_uuid, 25, 2) - . ", 0x" . substr($if_uuid, 27, 2) - . ", 0x" . substr($if_uuid, 29, 2) - . ", 0x" . substr($if_uuid, 31, 2) - . ", 0x" . substr($if_uuid, 33, 2) - . ", 0x" . substr($if_uuid, 35, 2) . " }"; - pidl "};\n"; - - pidl "static guint16 ver_dcerpc_$x->{NAME} = $x->{VERSION};"; - } - - # dissect_* functions - ParseInterface($x, $needed); - - # Function call tables - FunctionTable($x); - - RegisterInterface($x, $needed); - RegisterInterfaceHandoff($x); -} - -##################################################################### -# parse a parsed IDL structure back into an IDL file -sub Parse($$$) -{ - my($ndr) = shift; - my $module = shift; - my($filename) = shift; - - $tabs = ""; - my $h_filename = $filename; - $res = ""; - - if ($h_filename =~ /(.*)\.c/) { - $h_filename = "$1.h"; - } - - pidl "/* parser auto-generated by pidl */"; - pidl "#include \"packet-dcerpc.h\""; - pidl "#include \"$h_filename\""; - pidl ""; - pidl "static int hf_ptr = -1;"; - pidl "static int hf_array_size = -1;"; - pidl ""; - -# print keys %{$needed->{hf_atsvc_JobGetInfo_result}}, "\n"; - - # Ethereal protocol registration - - ProcessInterface($_) foreach (@$ndr); - - return $res; -} - -1; diff --git a/source4/build/pidl/pidl b/source4/build/pidl/pidl index 699497549a..c24a0a0007 100755 --- a/source4/build/pidl/pidl +++ b/source4/build/pidl/pidl @@ -75,7 +75,6 @@ my($opt_ndr_parser); my($opt_tdr_header); my($opt_tdr_parser); my($opt_eth_parser); -my($opt_eth_header); my($opt_keep); my($opt_swig); my($opt_dcom_proxy); @@ -111,8 +110,7 @@ Options: --client[=OUTFILE] create a C NDR client --server[=OUTFILE] create server boilerplate --template print a template for a pipe - --eth-parser[=OUTFILE]create an ethereal parser - --eth-header[=OUTFILE]create an ethereal header file + --eth-parser[=OUTFILE]create ethereal parser and header --swig[=OUTFILE] create swig wrapper file --diff run diff on the idl and dumped output --keep[=OUTFILE] keep the .pidl file @@ -142,7 +140,6 @@ GetOptions ( 'ndr-parser:s' => \$opt_ndr_parser, 'client:s' => \$opt_client, 'eth-parser:s' => \$opt_eth_parser, - 'eth-header:s' => \$opt_eth_header, 'ejs' => \$opt_ejs, 'diff' => \$opt_diff, 'odl' => \$opt_odl, @@ -242,9 +239,8 @@ sub process_file($) } if (defined($opt_ndr_header) or defined($opt_eth_parser) or - defined($opt_eth_header) or defined($opt_client) or - defined($opt_server) or defined($opt_ndr_parser) or - defined($opt_ejs)) { + defined($opt_client) or defined($opt_server) or + defined($opt_ndr_parser) or defined($opt_ejs)) { require Parse::Pidl::NDR; Parse::Pidl::NDR::Validate($pidl); $ndr = Parse::Pidl::NDR::Parse($pidl); @@ -267,13 +263,6 @@ sub process_file($) } } - if (defined($opt_eth_header)) { - require Parse::Pidl::Ethereal::NDR::Header; - my($eparserhdr) = ($opt_eth_header or "$outputdir/packet-dcerpc-$basename.h"); - - FileSave($eparserhdr, Parse::Pidl::Ethereal::NDR::Header::Parse($ndr)); - } - my $h_filename = "$outputdir/ndr_$basename.h"; if (defined($opt_client)) { require Parse::Pidl::Samba::NDR::Client; @@ -325,9 +314,14 @@ $dcom } if (defined($opt_eth_parser)) { - require Parse::Pidl::Ethereal::NDR::Parser; + require Parse::Pidl::Ethereal::NDR; my($eparser) = ($opt_eth_parser or "$outputdir/packet-dcerpc-$basename.c"); - FileSave($eparser, Parse::Pidl::Ethereal::NDR::Parser::Parse($ndr, $basename, $eparser)); + my $eheader = $eparser; + $eheader =~ s/\.c$/\.h/; + + my ($dp, $dh) = Parse::Pidl::Ethereal::NDR::Parser::Parse($ndr, $basename, $eparser); + FileSave($eparser, $dp); + FileSave($eheader, $dh); } my $tdr_parser = ($opt_tdr_parser or "$outputdir/tdr_$basename.c"); |