mirror of
https://github.com/samba-team/samba.git
synced 2025-03-08 04:58:40 +03:00
r753: Big reorganisation of everything - also fixes handling of dissectors
for structures. Instead of trying to parse everything to produce output in the right order, generate parser in two steps: 1) gather information and register names, fields, types etc. 2) generate output using data from step 1. (This used to be commit 03863a2ca88c374e168d579e7e4f78877160215c)
This commit is contained in:
parent
6703be3ef0
commit
8b84f643bd
@ -1,18 +1,129 @@
|
||||
###################################################
|
||||
# parser generator for IDL structures
|
||||
# Copyright tpot@samba.org 2001
|
||||
# Copyright tridge@samba.org 2000
|
||||
# Copyright tpot@samba.org 2004
|
||||
# released under the GNU GPL
|
||||
|
||||
package IdlEParser;
|
||||
|
||||
use strict;
|
||||
use dump;
|
||||
|
||||
my($module);
|
||||
#use Data::Dumper;
|
||||
|
||||
#####################################################################
|
||||
# handlers for parsing ndr argument types
|
||||
# Code for managing hf's
|
||||
|
||||
my %hf_info = ();
|
||||
|
||||
# Convert an idl type to an ethereal FT_* type
|
||||
|
||||
sub type2ft($)
|
||||
{
|
||||
my($t) = shift;
|
||||
|
||||
return "FT_UINT32", if ($t eq "uint32");
|
||||
return "FT_UINT16", if ($t eq "uint16");
|
||||
return "FT_BYTES";
|
||||
}
|
||||
|
||||
# Select an ethereal BASE_* type for an idl type
|
||||
|
||||
sub type2base($)
|
||||
{
|
||||
my($t) = shift;
|
||||
|
||||
return "BASE_DEC", if ($t eq "uint32") or ($t eq "uint16");
|
||||
return "BASE_NONE";
|
||||
}
|
||||
|
||||
# Create a new field. The name of the field is hf_${name}_${type} where
|
||||
# name and type are taken from the IDL definition for the element.
|
||||
|
||||
sub AddField($$)
|
||||
{
|
||||
my($name) = shift;
|
||||
my($type) = shift;
|
||||
|
||||
my $hf_name = "${name}_${type}";
|
||||
return, if defined $hf_info{$hf_name};
|
||||
|
||||
$hf_info{$hf_name} = {
|
||||
'name' => $name, # Field name
|
||||
'type' => $type, # Field type
|
||||
'ft' => type2ft($type), # Ethereal type
|
||||
'base' => type2base($type), # Base of type
|
||||
};
|
||||
}
|
||||
|
||||
# Generate field definitions from %hf_info
|
||||
|
||||
sub EtherealFieldDefinitions()
|
||||
{
|
||||
my($res) = "";
|
||||
|
||||
$res .= << "EOF";
|
||||
static int hf_opnum = -1;
|
||||
static int hf_rc = -1;
|
||||
static int hf_policy_handle = -1;
|
||||
EOF
|
||||
|
||||
foreach my $hf (keys(%hf_info)) {
|
||||
my($hf_name) = "$hf_info{$hf}{name}_$hf_info{$hf}{type}";
|
||||
$res .= "static int hf_$hf_name = -1;\n";
|
||||
}
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
# Generate field initialisers
|
||||
|
||||
sub EtherealFieldInitialisation($)
|
||||
{
|
||||
my($module) = shift;
|
||||
my($res) = "";
|
||||
|
||||
# Fields present in all parsers
|
||||
|
||||
$res .= << "EOF";
|
||||
\t{ &hf_opnum,
|
||||
\t { \"Operation\", \"$module.opnum\", FT_UINT16, BASE_DEC, NULL, 0x0, \"Operation\", HFILL }},
|
||||
\t{ &hf_policy_handle,
|
||||
\t { \"Policy handle\", \"$module.policy\", FT_BYTES, BASE_NONE, NULL, 0x0, \"Policy handle\", HFILL }},
|
||||
\t{ &hf_rc,
|
||||
\t { \"Return code\", \"$module.rc\", FT_UINT32, BASE_HEX, VALS(NT_errors), 0x0, \"Return status code\", HFILL }},
|
||||
EOF
|
||||
|
||||
foreach my $hf (keys(%hf_info)) {
|
||||
$res .= "\t{ &hf_$hf,\n";
|
||||
$res .= "\t { \"$hf_info{$hf}{name}\", \"$hf\", $hf_info{$hf}{ft}, $hf_info{$hf}{base},\n";
|
||||
$res .= "\t NULL, 0, \"$hf\", HFILL }},\n";
|
||||
}
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
#####################################################################
|
||||
# Code for managing subtrees
|
||||
|
||||
sub EtherealSubtreeDefinitions($)
|
||||
{
|
||||
my($module) = shift;
|
||||
my($res) = "";
|
||||
|
||||
$res .= << "EOF";
|
||||
static gint ett_dcerpc_$module = -1;
|
||||
EOF
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
sub EtherealSubtreeInitialisation()
|
||||
{
|
||||
my($res) = "";
|
||||
return $res;
|
||||
}
|
||||
|
||||
#####################################################################
|
||||
# Generate dissection functions for NDR types
|
||||
|
||||
sub ParamSimpleNdrType($)
|
||||
{
|
||||
@ -49,45 +160,52 @@ sub ParamStruct($)
|
||||
my($p) = shift;
|
||||
my($res);
|
||||
|
||||
$res .= "\toffset = dissect_${module}_$p->{TYPE}(tvb, offset, pinfo, tree, drep);\n";
|
||||
$res .= "\toffset = dissect_$p->{TYPE}(tvb, offset, pinfo, tree, drep);\n";
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
# Index of NDR types and functions to generate code to dissect that type
|
||||
|
||||
my %param_handlers = (
|
||||
'uint8' => \&ParamSimpleNdrType,
|
||||
'uint16' => \&ParamSimpleNdrType,
|
||||
'uint32' => \&ParamSimpleNdrType,
|
||||
'uint8' => \&ParamSimpleNdrType,
|
||||
'uint16' => \&ParamSimpleNdrType,
|
||||
'uint32' => \&ParamSimpleNdrType,
|
||||
'policy_handle' => \&ParamPolicyHandle,
|
||||
'string' => \&ParamString,
|
||||
'string' => \&ParamString,
|
||||
);
|
||||
|
||||
my %hf_info = (); # Field info - remember for trailing stuff
|
||||
# Generate a parser for a NDR parameter
|
||||
|
||||
#####################################################################
|
||||
# parse a function
|
||||
sub ParseParameter($)
|
||||
{
|
||||
my($p) = shift;
|
||||
my($res);
|
||||
|
||||
# Call function registered for this type
|
||||
|
||||
if (defined($param_handlers{$p->{TYPE}})) {
|
||||
$res .= &{$param_handlers{$p->{TYPE}}}($p);
|
||||
return $res;
|
||||
}
|
||||
|
||||
# Unknown type - make a note in the protocol tree
|
||||
|
||||
$res .= "\tproto_tree_add_text(tree, tvb, offset, -1, \"Unhandled IDL type '$p->{TYPE}'\");\n";
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
#####################################################################
|
||||
# parse a function
|
||||
sub ParseFunction($)
|
||||
# Generate code fragment for an IDL function
|
||||
|
||||
sub EtherealFunction($)
|
||||
{
|
||||
my($f) = shift;
|
||||
my($res);
|
||||
|
||||
# Comment displaying IDL for this function
|
||||
|
||||
$res .= "/*\n\n";
|
||||
$res .= IdlDump::DumpFunction($f);
|
||||
$res .= "*/\n\n";
|
||||
@ -125,52 +243,38 @@ sub ParseFunction($)
|
||||
}
|
||||
|
||||
#####################################################################
|
||||
# parse a function
|
||||
sub ParseEnum($$)
|
||||
{
|
||||
my($name) = shift;
|
||||
my($enum) = shift;
|
||||
# Generate code fragment for an IDL struct
|
||||
|
||||
return "/* Enum $name */\n\n";
|
||||
}
|
||||
|
||||
#####################################################################
|
||||
# parse a function
|
||||
sub ParseStruct($$)
|
||||
{
|
||||
my($name) = shift;
|
||||
sub EtherealStruct($$)
|
||||
{
|
||||
my($module) = shift;
|
||||
my($struct) = shift;
|
||||
my($res);
|
||||
|
||||
# Add struct name to param handler list
|
||||
|
||||
$param_handlers{$name} = \&ParamStruct;
|
||||
|
||||
# Create parse function
|
||||
my($res) = "";
|
||||
|
||||
$res .= "/*\n\n";
|
||||
$res .= IdlDump::DumpStruct($struct);
|
||||
$res .= IdlDump::DumpStruct($struct->{DATA});
|
||||
$res .= "\n\n*/\n\n";
|
||||
|
||||
$res .= << "EOF";
|
||||
int dissect_${module}_$name(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *parent_tree, guint8 *drep)
|
||||
int dissect_$struct->{NAME}(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *parent_tree, guint8 *drep)
|
||||
{
|
||||
proto_item *item = NULL;
|
||||
proto_tree *tree = NULL;
|
||||
int old_offset = offset;
|
||||
|
||||
if (parent_tree) {
|
||||
item = proto_tree_add_text(parent_tree, tvb, offset, -1, "$name");
|
||||
item = proto_tree_add_text(parent_tree, tvb, offset, -1, "$struct->{NAME}");
|
||||
tree = proto_item_add_subtree(item, ett_dcerpc_$module);
|
||||
}
|
||||
|
||||
EOF
|
||||
|
||||
foreach my $d (@{$struct->{ELEMENTS}}) {
|
||||
# Parse elements
|
||||
|
||||
foreach my $d (@{$struct->{DATA}->{ELEMENTS}}) {
|
||||
$res .= ParseParameter($d);
|
||||
}
|
||||
|
||||
|
||||
$res .= << "EOF";
|
||||
|
||||
proto_item_set_len(item, offset - old_offset);
|
||||
@ -184,55 +288,75 @@ EOF
|
||||
}
|
||||
|
||||
#####################################################################
|
||||
# parse a function
|
||||
sub ParseUnion($$)
|
||||
{
|
||||
my($name) = shift;
|
||||
my($union) = shift;
|
||||
# Generate code fragment for an IDL union
|
||||
|
||||
return "/* Union $name */\n\n";
|
||||
}
|
||||
|
||||
#####################################################################
|
||||
# parse a function
|
||||
sub ParseTypedef($)
|
||||
sub EtherealUnion($$)
|
||||
{
|
||||
my($typedef) = shift;
|
||||
my($data) = $typedef->{DATA};
|
||||
my($module) = shift;
|
||||
my($union) = shift;
|
||||
my($res) = "";
|
||||
|
||||
$res .= ParseEnum($typedef->{NAME}, $data), if $data->{TYPE} eq "ENUM";
|
||||
$res .= ParseStruct($typedef->{NAME}, $data), if $data->{TYPE} eq "STRUCT";
|
||||
$res .= ParseUnion($typedef->{NAME}, $data), if $data->{TYPE} eq "UNION";
|
||||
$res .= "/*\n\n";
|
||||
$res .= IdlDump::DumpUnion($union->{DATA});
|
||||
$res .= "\n\n*/\n\n";
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
#####################################################################
|
||||
# parse the interface definitions
|
||||
sub Pass2Interface($)
|
||||
$res .= << "EOF";
|
||||
int dissect_$union->{NAME}(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *parent_tree, guint8 *drep)
|
||||
{
|
||||
my($interface) = shift;
|
||||
my($data) = $interface->{DATA};
|
||||
my($res) = "";
|
||||
proto_item *item = NULL;
|
||||
proto_tree *tree = NULL;
|
||||
int old_offset = offset;
|
||||
|
||||
foreach my $d (@{$data}) {
|
||||
$res .= ParseFunction($d), if $d->{TYPE} eq "FUNCTION";
|
||||
$res .= ParseTypedef($d), if $d->{TYPE} eq "TYPEDEF";
|
||||
if (parent_tree) {
|
||||
item = proto_tree_add_text(parent_tree, tvb, offset, -1, "$union->{NAME}");
|
||||
tree = proto_item_add_subtree(item, ett_dcerpc_$module);
|
||||
}
|
||||
|
||||
EOF
|
||||
|
||||
# TODO: Parse elements
|
||||
|
||||
$res .= << "EOF";
|
||||
|
||||
proto_item_set_len(item, offset - old_offset);
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
EOF
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
#####################################################################
|
||||
# Pass 1: Stuff required before structs and functions
|
||||
# Generate code fragment for an IDL typedef
|
||||
|
||||
sub Pass1ModuleHeader($)
|
||||
sub EtherealTypedef($$)
|
||||
{
|
||||
my($module) = shift;
|
||||
my($typedef) = shift;
|
||||
|
||||
return EtherealStruct($module, $typedef),
|
||||
if $typedef->{DATA}{TYPE} eq "STRUCT";
|
||||
|
||||
return EtherealUnion($module, $typedef),
|
||||
if $typedef->{DATA}{TYPE} eq "UNION";
|
||||
|
||||
return "/* Unsupported typedef $typedef->{DATA}{TYPE} " .
|
||||
"$typedef->{NAME}*/\n\n";
|
||||
}
|
||||
|
||||
#####################################################################
|
||||
# Generate code fragment for the start of the dissector
|
||||
|
||||
sub EtherealHeader($)
|
||||
{
|
||||
my($d) = shift;
|
||||
my($module) = shift;
|
||||
my($res) = "";
|
||||
|
||||
$res .= << "EOF";
|
||||
/* parser auto-generated by pidl */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
@ -242,211 +366,51 @@ sub Pass1ModuleHeader($)
|
||||
|
||||
extern const value_string NT_errors[];
|
||||
|
||||
EOF
|
||||
|
||||
# UUID
|
||||
|
||||
if ($d->{TYPE} eq "MODULEHEADER" and defined($d->{PROPERTIES}->{uuid})) {
|
||||
my $uuid = $d->{PROPERTIES}->{uuid};
|
||||
$res .= "static e_uuid_t uuid_dcerpc_$module = {\n";
|
||||
$res .= "\t0x" . substr($uuid, 0, 8);
|
||||
$res .= ", 0x" . substr($uuid, 9, 4);
|
||||
$res .= ", 0x" . substr($uuid, 14, 4) . ",\n";
|
||||
$res .= "\t{ 0x" . substr($uuid, 19, 2);
|
||||
$res .= ", 0x" . substr($uuid, 21, 2);
|
||||
$res .= ", 0x" . substr($uuid, 24, 2);
|
||||
$res .= ", 0x" . substr($uuid, 26, 2);
|
||||
$res .= ", 0x" . substr($uuid, 28, 2);
|
||||
$res .= ", 0x" . substr($uuid, 30, 2);
|
||||
$res .= ", 0x" . substr($uuid, 32, 2);
|
||||
$res .= ", 0x" . substr($uuid, 34, 2) . " }\n";
|
||||
$res .= "};\n\n";
|
||||
|
||||
$res .= "static guint16 ver_dcerpc_samr = " .
|
||||
$d->{PROPERTIES}->{version} . ";\n\n";
|
||||
}
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
# Convert an idl type to an ethereal FT_* type
|
||||
|
||||
sub type2ft($)
|
||||
{
|
||||
my($t) = shift;
|
||||
|
||||
return "FT_UINT32", if ($t eq "uint32");
|
||||
return "FT_UINT16", if ($t eq "uint16");
|
||||
|
||||
return "FT_BYTES";
|
||||
}
|
||||
|
||||
# Select an ethereal BASE_* type for an idl type
|
||||
|
||||
sub type2base($)
|
||||
{
|
||||
my($t) = shift;
|
||||
|
||||
return "BASE_DEC", if ($t eq "uint32") or ($t eq "uint16");
|
||||
|
||||
return "BASE_NONE";
|
||||
}
|
||||
|
||||
sub AddField($$)
|
||||
{
|
||||
my($name) = shift;
|
||||
my($type) = shift;
|
||||
my($res) = "";
|
||||
|
||||
my $hf_name = "${name}_${type}";
|
||||
return $res, if defined $hf_info{$hf_name};
|
||||
|
||||
# Make a note about new field
|
||||
|
||||
$res .= "static int hf_$hf_name = -1;\n";
|
||||
$hf_info{$hf_name} = {
|
||||
'ft' => type2ft($type),
|
||||
'base' => type2base($name),
|
||||
'name' => $name
|
||||
};
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
sub ScanFunction($)
|
||||
{
|
||||
my($fn) = shift;
|
||||
my($res) = "";
|
||||
|
||||
foreach my $args ($fn) {
|
||||
foreach my $params (@{$args}) {
|
||||
$res .= AddField($params->{NAME}, $params->{TYPE});
|
||||
}
|
||||
}
|
||||
return $res;
|
||||
}
|
||||
|
||||
sub ScanTypedef($)
|
||||
{
|
||||
my($td) = shift;
|
||||
my($res) = "";
|
||||
|
||||
if ($td->{TYPE} eq "STRUCT") {
|
||||
foreach my $e (@{$td->{ELEMENTS}}) {
|
||||
$res .= AddField($e->{NAME}, $e->{TYPE});
|
||||
}
|
||||
}
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
sub Pass1Interface($)
|
||||
{
|
||||
my($interface) = shift;
|
||||
my($res) = "";
|
||||
|
||||
$res .= << "EOF";
|
||||
static int proto_dcerpc_$module = -1;
|
||||
|
||||
static int hf_opnum = -1;
|
||||
static int hf_rc = -1;
|
||||
static int hf_policy_handle = -1;
|
||||
|
||||
static gint ett_dcerpc_$module = -1;
|
||||
|
||||
EOF
|
||||
|
||||
foreach my $fn (@{$interface->{DATA}}) {
|
||||
$res .= ScanFunction($fn->{DATA}), if $fn->{TYPE} eq "FUNCTION";
|
||||
$res .= ScanTypedef($fn->{DATA}), if $fn->{TYPE} eq "TYPEDEF";
|
||||
}
|
||||
|
||||
$res .= "\n";
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
#####################################################################
|
||||
# Pass 3: trailing stuff
|
||||
|
||||
sub Pass3Interface($)
|
||||
sub EtherealUuidRegistration($$$)
|
||||
{
|
||||
my($interface) = shift;
|
||||
my($module) = shift;
|
||||
my($uuid) = shift;
|
||||
my($uuid_version) = shift;
|
||||
my($res) = "";
|
||||
|
||||
$res .= "static dcerpc_sub_dissector dcerpc_${module}_dissectors[] = {\n";
|
||||
|
||||
my $num = 0;
|
||||
|
||||
foreach my $d (@{$interface->{DATA}}) {
|
||||
if ($d->{TYPE} eq "FUNCTION") {
|
||||
# Strip module name from function name, if present
|
||||
my $n = $d->{NAME};
|
||||
$n = substr($d->{NAME}, length($module) + 1),
|
||||
if $module eq substr($d->{NAME}, 0, length($module));
|
||||
|
||||
$res .= "\t{ $num, \"$n\",\n";
|
||||
$res .= "\t\t$d->{NAME}_rqst,\n";
|
||||
$res .= "\t\t$d->{NAME}_resp },\n";
|
||||
$num++;
|
||||
}
|
||||
}
|
||||
# Various objects for dissector initialisation
|
||||
|
||||
$res .= "static e_uuid_t uuid_dcerpc_$module = {\n";
|
||||
$res .= "\t0x" . substr($uuid, 0, 8);
|
||||
$res .= ", 0x" . substr($uuid, 9, 4);
|
||||
$res .= ", 0x" . substr($uuid, 14, 4) . ",\n";
|
||||
$res .= "\t{ 0x" . substr($uuid, 19, 2);
|
||||
$res .= ", 0x" . substr($uuid, 21, 2);
|
||||
$res .= ", 0x" . substr($uuid, 24, 2);
|
||||
$res .= ", 0x" . substr($uuid, 26, 2);
|
||||
$res .= ", 0x" . substr($uuid, 28, 2);
|
||||
$res .= ", 0x" . substr($uuid, 30, 2);
|
||||
$res .= ", 0x" . substr($uuid, 32, 2);
|
||||
$res .= ", 0x" . substr($uuid, 34, 2) . " }\n";
|
||||
$res .= "};\n\n";
|
||||
|
||||
$res .= "static guint16 ver_dcerpc_$module = " . $uuid_version . ";\n\n";
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
#####################################################################
|
||||
# parse a parsed IDL structure back into an IDL file
|
||||
sub Parse($)
|
||||
# Generate code fragment for the tail of the dissector
|
||||
|
||||
sub EtherealModuleRegistration($$$)
|
||||
{
|
||||
my($idl) = shift;
|
||||
my($res) = "/* parser auto-generated by pidl */\n\n";
|
||||
my($d);
|
||||
my($module) = shift;
|
||||
my($hf_register_info) = shift;
|
||||
my($ett_info) = shift;
|
||||
my($res) = "";
|
||||
|
||||
# Pass 0: set module name
|
||||
|
||||
foreach $d (@{$idl}) {
|
||||
$module = $d->{NAME}, if ($d->{TYPE} eq "INTERFACE");
|
||||
}
|
||||
|
||||
# Pass 1: header stuff
|
||||
|
||||
foreach $d (@{$idl}) {
|
||||
$res .= Pass1ModuleHeader($d), if $d->{TYPE} eq "MODULEHEADER";
|
||||
$res .= Pass1Interface($d), if $d->{TYPE} eq "INTERFACE";
|
||||
}
|
||||
|
||||
# Pass 2: typedefs and functions
|
||||
|
||||
foreach $d (@{$idl}) {
|
||||
$res .= Pass2Interface($d), if $d->{TYPE} eq "INTERFACE";
|
||||
}
|
||||
|
||||
# Pass 3: trailing stuff
|
||||
|
||||
foreach $d (@{$idl}) {
|
||||
$res .= Pass3Interface($d), if $d->{TYPE} eq "INTERFACE";
|
||||
}
|
||||
|
||||
my $hf_register_info = << "EOF";
|
||||
\t{ &hf_opnum,
|
||||
\t { \"Operation\", \"$module.opnum\", FT_UINT16, BASE_DEC, NULL, 0x0, \"Operation\", HFILL }},
|
||||
\t{ &hf_policy_handle,
|
||||
\t { \"Policy handle\", \"$module.policy\", FT_BYTES, BASE_NONE, NULL, 0x0, \"Policy handle\", HFILL }},
|
||||
\t{ &hf_rc,
|
||||
\t { \"Return code\", \"$module.rc\", FT_UINT32, BASE_HEX, VALS(NT_errors), 0x0, \"Return status code\", HFILL }},
|
||||
EOF
|
||||
|
||||
foreach my $hf (keys(%hf_info)) {
|
||||
$hf_register_info .= "\t{ &hf_$hf,\n";
|
||||
$hf_register_info .= "\t { \"$hf_info{$hf}{name}\", \"$hf\", $hf_info{$hf}{ft}, $hf_info{$hf}{base},\n";
|
||||
$hf_register_info .= "\t NULL, 0, \"$hf\", HFILL }},\n";
|
||||
}
|
||||
|
||||
my $ett_info = "/* spotty */";
|
||||
|
||||
$res .= << "EOF";
|
||||
void
|
||||
proto_register_dcerpc_${module}(void)
|
||||
@ -462,7 +426,7 @@ $ett_info
|
||||
|
||||
proto_dcerpc_$module = proto_register_protocol("$module", "$module", "$module");
|
||||
|
||||
proto_register_field_array (proto_dcerpc_$module, hf, array_length (hf));
|
||||
proto_register_field_array(proto_dcerpc_$module, hf, array_length (hf));
|
||||
proto_register_subtree_array(ett, array_length(ett));
|
||||
|
||||
}
|
||||
@ -479,4 +443,134 @@ EOF
|
||||
return $res;
|
||||
}
|
||||
|
||||
#####################################################################
|
||||
# Generate code fragment for DCERPC subdissector registration
|
||||
|
||||
sub EtherealSubdissectorRegistration($$)
|
||||
{
|
||||
my($module) = shift;
|
||||
my($functions) = shift;
|
||||
my($res) = "";
|
||||
|
||||
$res .= "static dcerpc_sub_dissector dcerpc_${module}_dissectors[] = {\n";
|
||||
|
||||
my $num = 0;
|
||||
|
||||
foreach my $name (@$functions) {
|
||||
# Strip module name from function name, if present
|
||||
my($n) = $name;
|
||||
$n = substr($name, length($module) + 1),
|
||||
if $module eq substr($name, 0, length($module));
|
||||
|
||||
$res .= "\t{ $num, \"$n\",\n";
|
||||
$res .= "\t\t${name}_rqst,\n";
|
||||
$res .= "\t\t${name}_resp },\n";
|
||||
$num++;
|
||||
}
|
||||
|
||||
$res .= "};\n\n";
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
#####################################################################
|
||||
# Generate an ethereal dissector from an IDL syntax tree.
|
||||
|
||||
sub Parse($)
|
||||
{
|
||||
my($idl) = shift;
|
||||
my($res) = "";
|
||||
|
||||
#
|
||||
# Phase 1 : Gather information from IDL tree
|
||||
#
|
||||
|
||||
my($module) = "";
|
||||
my($uuid) = "";
|
||||
my($uuid_version) = "";
|
||||
my(@fns) = ();
|
||||
|
||||
foreach my $d (@$idl) {
|
||||
|
||||
# Get data from interface definition
|
||||
|
||||
$module = $d->{NAME}, if $d->{TYPE} eq "INTERFACE";
|
||||
|
||||
if ($d->{TYPE} eq "MODULEHEADER") {
|
||||
$uuid = $d->{PROPERTIES}->{uuid};
|
||||
$uuid_version = $d->{PROPERTIES}->{version};
|
||||
}
|
||||
|
||||
# Iterate over function definitions and register field info
|
||||
|
||||
if ($d->{TYPE} eq "INTERFACE") {
|
||||
|
||||
foreach my $d (@{$d->{DATA}}) {
|
||||
|
||||
if ($d->{TYPE} eq "FUNCTION") {
|
||||
|
||||
# Register function name
|
||||
|
||||
$fns[$#fns + 1] = $d->{NAME};
|
||||
|
||||
# Register function fields (parameter names)
|
||||
|
||||
foreach my $e (@{$d->{DATA}}) {
|
||||
AddField($e->{NAME}, $e->{TYPE});
|
||||
}
|
||||
}
|
||||
|
||||
if ($d->{TYPE} eq "TYPEDEF") {
|
||||
|
||||
# Register structure names
|
||||
|
||||
$param_handlers{$d->{NAME}} = \&ParamStruct;
|
||||
|
||||
# Register typedef fields (element names)
|
||||
|
||||
if ($d->{DATA}->{TYPE} eq "STRUCT") {
|
||||
foreach my $e (@{$d->{DATA}->{ELEMENTS}}) {
|
||||
AddField($e->{NAME}, $e->{TYPE});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#
|
||||
# Phase 2 : Spit out parser from fragments generated above
|
||||
#
|
||||
|
||||
$res .= EtherealHeader($module);
|
||||
$res .= EtherealFieldDefinitions();
|
||||
$res .= EtherealSubtreeDefinitions($module);
|
||||
|
||||
foreach my $d (@$idl) {
|
||||
|
||||
if ($d->{TYPE} eq "INTERFACE") {
|
||||
foreach my $d (@{$d->{DATA}}) {
|
||||
|
||||
# Generate function code fragments
|
||||
|
||||
$res .= EtherealFunction($d), if $d->{TYPE} eq "FUNCTION";
|
||||
|
||||
# Generate structure code fragments
|
||||
|
||||
$res .= EtherealTypedef($module, $d),
|
||||
if $d->{TYPE} eq "TYPEDEF";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$res .= EtherealSubdissectorRegistration($module, \@fns);
|
||||
|
||||
$res .= EtherealUuidRegistration($module, $uuid, $uuid_version);
|
||||
$res .= EtherealModuleRegistration($module,
|
||||
EtherealFieldInitialisation($module),
|
||||
EtherealSubtreeInitialisation());
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
1;
|
||||
|
Loading…
x
Reference in New Issue
Block a user