mirror of
https://github.com/samba-team/samba.git
synced 2025-12-09 00:23:50 +03:00
1357 lines
31 KiB
Perl
1357 lines
31 KiB
Perl
##################################################
|
|
# 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 EthParser;
|
|
|
|
use strict;
|
|
use pidl::typelist;
|
|
use 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 (util::has_property($t, "public")) {
|
|
$needed->{"pull_$t->{NAME}"} = not util::has_property($t, "nopull");
|
|
$needed->{"decl_$t->{NAME}"} = not util::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 = util::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 util::has_property($e->{DATA}, "bitmap16bit");
|
|
return "8", if util::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);
|
|
}
|
|
|
|
####################################################################
|
|
# work out the name of a size_is() variable
|
|
sub ParseExpr($$)
|
|
{
|
|
my($orig_expr) = shift;
|
|
my $varlist = shift;
|
|
|
|
die("Undefined value in ParseExpr") if not defined($orig_expr);
|
|
|
|
my $expr = $orig_expr;
|
|
|
|
return $expr if (util::is_constant($expr));
|
|
|
|
my $prefix = "";
|
|
my $postfix = "";
|
|
|
|
if ($expr =~ /\*(.*)/) {
|
|
$expr = $1;
|
|
$prefix = "*";
|
|
}
|
|
|
|
if ($expr =~ /^(.*)([\&\|\/+])(.*)$/) {
|
|
$postfix = $2.$3;
|
|
$expr = $1;
|
|
}
|
|
|
|
if (defined($varlist->{$expr})) {
|
|
return $prefix.$varlist->{$expr}.$postfix;
|
|
}
|
|
|
|
return $prefix.$expr.$postfix;
|
|
}
|
|
|
|
#####################################################################
|
|
# 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 (util::has_property($fn, "public"));
|
|
return "static ";
|
|
}
|
|
|
|
###################################################################
|
|
# setup any special flags for an element or structure
|
|
sub start_flags($)
|
|
{
|
|
my $e = shift;
|
|
my $flags = util::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 = util::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 = util::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 = util::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 (util::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;
|