diff options
-rw-r--r-- | source4/build/pidl/parser.pm | 130 | ||||
-rw-r--r-- | source4/librpc/idl/epmapper.idl | 4 | ||||
-rw-r--r-- | source4/librpc/ndr/libndr.h | 5 | ||||
-rw-r--r-- | source4/librpc/ndr/ndr_basic.c | 12 | ||||
-rw-r--r-- | source4/librpc/rpc/dcerpc_util.c | 52 |
5 files changed, 148 insertions, 55 deletions
diff --git a/source4/build/pidl/parser.pm b/source4/build/pidl/parser.pm index bbebe50cac..7d7ee7a163 100644 --- a/source4/build/pidl/parser.pm +++ b/source4/build/pidl/parser.pm @@ -2,6 +2,7 @@ # Samba4 parser generator for IDL structures # Copyright tridge@samba.org 2000-2003 # Copyright tpot@samba.org 2001 +# Copyright jelmer@samba.org 2004 # released under the GNU GPL package IdlParser; @@ -830,6 +831,65 @@ sub ParseStructPull($) end_flags($struct); } +##################################################################### +# calculate size of ndr struct + +sub ParseStructNdrSize($) +{ + my $t = shift; + my $static = fn_prefix($t); + my $sizevar; + + pidl $static . "size_t ndr_size_$t->{NAME}(int ret, struct $t->{NAME} *r, int flags)\n"; + pidl "{\n"; + + if (util::has_property($t->{DATA}, "flag")) { + + pidl "\tflags = flags | " . $t->{DATA}->{PROPERTIES}->{flag} . ";\n"; + } + + pidl "\tif(!r) return 0;\n"; + + pidl "\tret = NDR_SIZE_ALIGN(ret, " . struct_alignment($t->{DATA}) . ", flags);\n"; + + for my $e (@{$t->{DATA}->{ELEMENTS}}) { + my $switch = ""; + + if (util::has_property($e, "subcontext")) { + pidl "\tret += $e->{PROPERTIES}->{subcontext}; /* Subcontext length */\n"; + } + + if (util::has_property($e, "switch_is")) { + $switch = ", r->$e->{PROPERTIES}->{switch_is}"; + } + + if ($e->{POINTERS} > 0) { + pidl "\tret = ndr_size_ptr(ret, &r->$e->{NAME}, flags); \n"; + } elsif (util::is_inline_array($e)) { + $sizevar = find_size_var($e, util::array_size($e), "r->"); + pidl "\t{\n"; + pidl "\t\tint i;\n"; + pidl "\t\tfor(i = 0; i < $sizevar; i++) {\n"; + pidl "\t\t\tret = ndr_size_$e->{TYPE}(ret, &r->" . $e->{NAME} . "[i], flags);\n"; + pidl "\t\t}\n"; + pidl "\t}\n"; + } else { + pidl "\tret = ndr_size_$e->{TYPE}(ret, &r->$e->{NAME}$switch, flags); \n"; + } + } + + # Add lengths of relative members + for my $e (@{$t->{DATA}->{ELEMENTS}}) { + next unless (util::has_property($e, "relative")); + + pidl "\tif (r->$e->{NAME}) {\n"; + pidl "\t\tret = ndr_size_$e->{TYPE}(ret, r->$e->{NAME}, flags); \n"; + pidl "\t}\n"; + } + + pidl "\treturn ret;\n"; + pidl "}\n\n"; +} ##################################################################### # parse a union - push side @@ -982,6 +1042,43 @@ sub ParseUnionPull($) } ##################################################################### +# calculate size of ndr union + +sub ParseUnionNdrSize($) +{ + my $t = shift; + my $static = fn_prefix($t); + + pidl $static . "size_t ndr_size_$t->{NAME}(int ret, union $t->{NAME} *data, uint16 level, int flags)\n"; + pidl "{\n"; + if (util::has_property($t->{DATA}, "flag")) { + pidl "\tflags = flags | " . $t->{DATA}->{PROPERTIES}->{flag} . ";\n"; + } + pidl "\tif(!data) return 0;\n\n"; + + pidl "\tret = NDR_SIZE_ALIGN(ret, " . union_alignment($t->{DATA}) . ", flags);\n"; + + pidl "\tswitch(level) {\n"; + + for my $e (@{$t->{DATA}->{DATA}}) { + if ($e->{TYPE} eq "UNION_ELEMENT") { + + if ($e->{CASE} eq "default") { + pidl "\t\tdefault:"; + } else { + pidl "\t\tcase $e->{CASE}:"; + } + + pidl " return ndr_size_$e->{DATA}->{TYPE}(ret, &data->$e->{DATA}->{NAME}, flags); \n"; + + } + } + pidl "\t}\n"; + pidl "\treturn ret;\n"; + pidl "}\n\n"; +} + +##################################################################### # parse a type sub ParseTypePush($) { @@ -1107,6 +1204,23 @@ sub ParseTypedefPrint($) } ##################################################################### +## calculate the size of a structure +sub ParseTypedefNdrSize($) +{ + my($t) = shift; + if (! $needed{"ndr_size_$t->{NAME}"}) { + return; + } + + ($t->{DATA}->{TYPE} eq "STRUCT") && + ParseStructNdrSize($t); + + ($t->{DATA}->{TYPE} eq "UNION") && + ParseUnionNdrSize($t); + +} + +##################################################################### # parse a function - print side sub ParseFunctionPrint($) { @@ -1413,7 +1527,10 @@ sub ParseInterface($) } } - + foreach my $d (@{$data}) { + ($d->{TYPE} eq "TYPEDEF") && + ParseTypedefNdrSize($d); + } foreach my $d (@{$data}) { ($d->{TYPE} eq "TYPEDEF") && @@ -1461,7 +1578,12 @@ sub NeededTypedef($) $needed{"pull_$t->{NAME}"} = 1; $needed{"push_$t->{NAME}"} = 1; } + if ($t->{DATA}->{TYPE} eq "STRUCT") { + if (util::has_property($t->{DATA}, "gensize")) { + $needed{"ndr_size_$t->{NAME}"} = 1; + } + for my $e (@{$t->{DATA}->{ELEMENTS}}) { $e->{PARENT} = $t->{DATA}; if ($needed{"pull_$t->{NAME}"}) { @@ -1470,6 +1592,9 @@ sub NeededTypedef($) if ($needed{"push_$t->{NAME}"}) { $needed{"push_$e->{TYPE}"} = 1; } + if ($needed{"ndr_size_$t->{NAME}"}) { + $needed{"ndr_size_$e->{TYPE}"} = 1; + } } } if ($t->{DATA}->{TYPE} eq "UNION") { @@ -1482,6 +1607,9 @@ sub NeededTypedef($) if ($needed{"push_$t->{NAME}"}) { $needed{"push_$e->{DATA}->{TYPE}"} = 1; } + if ($needed{"ndr_size_$t->{NAME}"}) { + $needed{"ndr_size_$e->{DATA}->{TYPE}"} = 1; + } } } } diff --git a/source4/librpc/idl/epmapper.idl b/source4/librpc/idl/epmapper.idl index 7ea58e354f..18bb6bf7d7 100644 --- a/source4/librpc/idl/epmapper.idl +++ b/source4/librpc/idl/epmapper.idl @@ -193,8 +193,8 @@ interface epmapper epm_floor floors[num_floors]; } epm_towers; - typedef struct { - [value(ndr_size_epm_towers(&r->towers))] uint32 tower_length; + typedef [gensize] struct { + [value(ndr_size_epm_towers(0, &r->towers,ndr->flags))] uint32 tower_length; [subcontext(4)] epm_towers towers; } epm_twr_t; diff --git a/source4/librpc/ndr/libndr.h b/source4/librpc/ndr/libndr.h index 59e8b744df..306e480c98 100644 --- a/source4/librpc/ndr/libndr.h +++ b/source4/librpc/ndr/libndr.h @@ -188,6 +188,11 @@ enum ndr_err_code { } \ } while(0) +#define NDR_SIZE_ALIGN(t, n, flags) ((flags & LIBNDR_FLAG_NOALIGN)?(t):(((t) + (n-1)) & ~(n-1))) +#define ndr_size_uint8(t, p, flags) (NDR_SIZE_ALIGN(t, 1, flags) + 1) +#define ndr_size_uint16(t, p, flags) (NDR_SIZE_ALIGN(t, 2, flags) + 2) +#define ndr_size_uint32(t, p, flags) (NDR_SIZE_ALIGN(t, 4, flags) + 4) +#define ndr_size_ptr(t, p, flags) (NDR_SIZE_ALIGN(t, 4, flags) + 4) /* these are used to make the error checking on each element in libndr less tedious, hopefully making the code more readable */ diff --git a/source4/librpc/ndr/ndr_basic.c b/source4/librpc/ndr/ndr_basic.c index edb1590489..5808ae7452 100644 --- a/source4/librpc/ndr/ndr_basic.c +++ b/source4/librpc/ndr/ndr_basic.c @@ -1130,3 +1130,15 @@ NTSTATUS ndr_pull_DATA_BLOB(struct ndr_pull *ndr, DATA_BLOB *blob) ndr->offset += length; return NT_STATUS_OK; } + +uint32 ndr_size_DATA_BLOB(int ret, const DATA_BLOB *data, int flags) +{ + return ret + data->length; +} + +uint32 ndr_size_string(int ret, const char **string, int flags) +{ + /* FIXME: Is this correct for all strings ? */ + if(!(*string)) return ret; + return ret+strlen(*string)+1; +} diff --git a/source4/librpc/rpc/dcerpc_util.c b/source4/librpc/rpc/dcerpc_util.c index fad8417c3f..5f3d911d15 100644 --- a/source4/librpc/rpc/dcerpc_util.c +++ b/source4/librpc/rpc/dcerpc_util.c @@ -23,58 +23,6 @@ #include "includes.h" /* - this ndr_size_* stuff should really be auto-generated .... -*/ - -static size_t ndr_size_epm_floor(struct epm_floor *fl) -{ - size_t ret = 5; - if (fl->lhs.protocol == EPM_PROTOCOL_UUID) { - ret += 18; - } else { - ret += fl->lhs.info.lhs_data.length; - } - switch (fl->lhs.protocol) { - case EPM_PROTOCOL_TCP: - case EPM_PROTOCOL_UDP: - case EPM_PROTOCOL_HTTP: - case EPM_PROTOCOL_UUID: - ret += 2; - break; - case EPM_PROTOCOL_IP: - ret += 4; - break; - case EPM_PROTOCOL_NCADG: - case EPM_PROTOCOL_NCACN: - case EPM_PROTOCOL_NCALRPC: - ret += 2; - break; - - case EPM_PROTOCOL_SMB: - ret += strlen(fl->rhs.smb.unc)+1; - break; - case EPM_PROTOCOL_PIPE: - ret += strlen(fl->rhs.pipe.path)+1; - break; - case EPM_PROTOCOL_NETBIOS: - ret += strlen(fl->rhs.netbios.name)+1; - break; - } - - return ret; -} - -size_t ndr_size_epm_towers(struct epm_towers *towers) -{ - size_t ret = 2; - int i; - for (i=0;i<towers->num_floors;i++) { - ret += ndr_size_epm_floor(&towers->floors[i]); - } - return ret; -} - -/* work out what TCP port to use for a given interface on a given host */ NTSTATUS dcerpc_epm_map_tcp_port(const char *server, |