From f6eb8342cba87c7c8f17471ed9783b567d36b0ed Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 14 Dec 2003 13:22:12 +0000 Subject: added auto-generation of the server side boilerplate code for each pipe. The server side code gets generated as librpc/gen_ndr/ndr_NAME_s.c and gets included in the pipe module (This used to be commit bd3dcfe5820489a838e19b244266bd9126af5eb4) --- source4/build/pidl/header.pm | 3 +- source4/build/pidl/pidl.pl | 19 +++-- source4/build/pidl/server.pm | 108 +++++++++++++++++++++++++++++ source4/build/pidl/util.pm | 4 +- source4/librpc/idl/echo.idl | 4 +- source4/rpc_server/dcerpc_server.c | 18 ++++- source4/rpc_server/echo/rpc_echo.c | 82 ++-------------------- source4/rpc_server/epmapper/rpc_epmapper.c | 78 +-------------------- source4/script/build_idl.sh | 2 +- source4/torture/rpc/echo.c | 8 +-- source4/torture/torture.c | 11 +++ 11 files changed, 167 insertions(+), 170 deletions(-) create mode 100644 source4/build/pidl/server.pm diff --git a/source4/build/pidl/header.pm b/source4/build/pidl/header.pm index 3277525487..4fa5969d3f 100644 --- a/source4/build/pidl/header.pm +++ b/source4/build/pidl/header.pm @@ -239,7 +239,8 @@ sub HeaderInterface($) $res .= "#define DCERPC_$name\_UUID \"$if_uuid\"\n"; $res .= "#define DCERPC_$name\_VERSION $if_version\n"; $res .= "#define DCERPC_$name\_NAME \"$interface->{NAME}\"\n\n"; - $res .= "extern const struct dcerpc_interface_table dcerpc_table_$interface->{NAME};\n\n"; + $res .= "extern const struct dcerpc_interface_table dcerpc_table_$interface->{NAME};\n"; + $res .= "void rpc_$interface->{NAME}_init(void *);\n\n"; } foreach my $d (@{$data}) { diff --git a/source4/build/pidl/pidl.pl b/source4/build/pidl/pidl.pl index 30dcde929a..ce8250826a 100755 --- a/source4/build/pidl/pidl.pl +++ b/source4/build/pidl/pidl.pl @@ -16,6 +16,7 @@ use File::Basename; use idl; use dump; use header; +use server; use parser; use eparser; use validator; @@ -26,6 +27,7 @@ my($opt_parse) = 0; my($opt_dump) = 0; my($opt_diff) = 0; my($opt_header) = 0; +my($opt_server) = 0; my($opt_parser) = 0; my($opt_eparser) = 0; my($opt_keep) = 0; @@ -61,6 +63,7 @@ sub ShowHelp() --dump dump a pidl file back to idl --header create a C header file --parser create a C parser + --server create server boilterplate --eparser create an ethereal parser --diff run diff on the idl and dumped output --keep keep the .pidl file @@ -75,6 +78,7 @@ GetOptions ( 'parse' => \$opt_parse, 'dump' => \$opt_dump, 'header' => \$opt_header, + 'server' => \$opt_server, 'parser' => \$opt_parser, 'eparser' => \$opt_eparser, 'diff' => \$opt_diff, @@ -100,7 +104,7 @@ sub process_file($) $output = $opt_output . $basename; } - my($pidl_file) = util::ChangeExtension($output, "pidl"); + my($pidl_file) = util::ChangeExtension($output, ".pidl"); print "Compiling $idl_file\n"; @@ -120,22 +124,27 @@ sub process_file($) } if ($opt_header) { - my($header) = util::ChangeExtension($output, "h"); + my($header) = util::ChangeExtension($output, ".h"); util::FileSave($header, IdlHeader::Parse($pidl)); } + + if ($opt_server) { + my($server) = util::ChangeExtension($output, "_s.c"); + util::FileSave($server, IdlServer::Parse($pidl)); + } if ($opt_parser) { - my($parser) = util::ChangeExtension($output, "c"); + my($parser) = util::ChangeExtension($output, ".c"); IdlParser::Parse($pidl, $parser); } if ($opt_eparser) { - my($parser) = util::ChangeExtension($output, "c"); + my($parser) = util::ChangeExtension($output, ".c"); util::FileSave($parser, IdlEParser::Parse($pidl)); } if ($opt_diff) { - my($tempfile) = util::ChangeExtension($output, "tmp"); + my($tempfile) = util::ChangeExtension($output, ".tmp"); util::FileSave($tempfile, IdlDump::Dump($pidl)); system("diff -wu $idl_file $tempfile"); unlink($tempfile); diff --git a/source4/build/pidl/server.pm b/source4/build/pidl/server.pm new file mode 100644 index 0000000000..e6d996b95d --- /dev/null +++ b/source4/build/pidl/server.pm @@ -0,0 +1,108 @@ + + +################################################### +# server boilerplate generator +# Copyright tridge@samba.org 2003 +# released under the GNU GPL + +package IdlServer; + +use strict; +use Data::Dumper; + +my($res); + +sub pidl($) +{ + $res .= shift; +} + +##################################################################### +# produce boilerplate code for a interface +sub Boilerplate($) +{ + my($interface) = shift; + my($data) = $interface->{DATA}; + my $count = 0; + my $name = $interface->{NAME}; + my $uname = uc $name; + + foreach my $d (@{$data}) { + if ($d->{TYPE} eq "FUNCTION") { $count++; } + } + + if ($count == 0) { + return; + } + + pidl "static const dcesrv_dispatch_fn_t dispatch_table[] = {\n"; + foreach my $d (@{$data}) { + if ($d->{TYPE} eq "FUNCTION") { + pidl "\t(dcesrv_dispatch_fn_t)$d->{NAME},\n"; + } + } + pidl "\tNULL};\n\n"; + + pidl " +static BOOL op_query_endpoint(const struct dcesrv_endpoint *ep) +{ + return dcesrv_table_query(&dcerpc_table_$name, ep); +} + +static BOOL op_set_interface(struct dcesrv_state *dce, + const char *uuid, uint32 if_version) +{ + return dcesrv_set_interface(dce, uuid, if_version, + &dcerpc_table_$name, dispatch_table); +} + +static NTSTATUS op_connect(struct dcesrv_state *dce) +{ + return NT_STATUS_OK; +} + +static void op_disconnect(struct dcesrv_state *dce) +{ + /* nothing to do */ +} + +static int op_lookup_endpoints(TALLOC_CTX *mem_ctx, struct dcesrv_ep_iface **e) +{ + return dcesrv_lookup_endpoints(&dcerpc_table_$name, mem_ctx, e); +} + +static const struct dcesrv_endpoint_ops $name\_ops = { + op_query_endpoint, + op_set_interface, + op_connect, + op_disconnect, + op_lookup_endpoints +}; + +void rpc_$name\_init(void *v) +{ + struct dcesrv_context *dce = v; + if (!dcesrv_endpoint_register(dce, &$name\_ops, + &dcerpc_table_$name)) { + DEBUG(1,(\"Failed to register rpcecho endpoint\\n\")); + } +} +"; +} + + +##################################################################### +# parse a parsed IDL structure back into an IDL file +sub Parse($) +{ + my($idl) = shift; + $res = "/* dcerpc server boilerplate generated by pidl */\n\n"; + foreach my $x (@{$idl}) { + ($x->{TYPE} eq "INTERFACE") && + Boilerplate($x); + } + return $res; +} + +1; + diff --git a/source4/build/pidl/util.pm b/source4/build/pidl/util.pm index 57ce80253f..dc6fd35f0c 100644 --- a/source4/build/pidl/util.pm +++ b/source4/build/pidl/util.pm @@ -127,9 +127,9 @@ sub ChangeExtension($$) my($fname) = shift; my($ext) = shift; if ($fname =~ /^(.*)\.(.*?)$/) { - return "$1.$ext"; + return "$1$ext"; } - return "$fname.$ext"; + return "$fname$ext"; } ##################################################################### diff --git a/source4/librpc/idl/echo.idl b/source4/librpc/idl/echo.idl index d747a39f23..e62208ac98 100644 --- a/source4/librpc/idl/echo.idl +++ b/source4/librpc/idl/echo.idl @@ -31,7 +31,7 @@ interface rpcecho /* test strings */ - void TestCall ( + void echo_TestCall ( [in] unistr *s1, [out] unistr *s2 ); @@ -83,7 +83,7 @@ interface rpcecho [case(7)] echo_info7 info7; } echo_Info; - NTSTATUS TestCall2 ( + NTSTATUS echo_TestCall2 ( [in] uint16 level, [out,switch_is(level)] echo_Info *info ); diff --git a/source4/rpc_server/dcerpc_server.c b/source4/rpc_server/dcerpc_server.c index a34c00cd58..cbde3c9532 100644 --- a/source4/rpc_server/dcerpc_server.c +++ b/source4/rpc_server/dcerpc_server.c @@ -792,12 +792,28 @@ int dcesrv_lookup_endpoints(const struct dcerpc_interface_table *table, } +BOOL dcesrv_set_interface(struct dcesrv_state *dce, + const char *uuid, uint32 if_version, + const struct dcerpc_interface_table *table, + const dcesrv_dispatch_fn_t *dispatch_table) +{ + if (strcasecmp(table->uuid, uuid) != 0 || if_version != table->if_version) { + DEBUG(2,("Attempt to use unknown interface %s/%d\n", uuid, if_version)); + return False; + } + + dce->ndr = table; + dce->dispatch = dispatch_table; + return True; +} + + /* initialise the dcerpc server subsystem */ BOOL dcesrv_init(struct dcesrv_context *dce) { - rpc_echo_init(dce); + rpc_rpcecho_init(dce); rpc_epmapper_init(dce); return True; } diff --git a/source4/rpc_server/echo/rpc_echo.c b/source4/rpc_server/echo/rpc_echo.c index d62ebc3d26..1d3846aaff 100644 --- a/source4/rpc_server/echo/rpc_echo.c +++ b/source4/rpc_server/echo/rpc_echo.c @@ -55,14 +55,14 @@ static NTSTATUS echo_SourceData(struct dcesrv_state *dce, TALLOC_CTX *mem_ctx, s return NT_STATUS_OK; } -static NTSTATUS echo_TestCall(struct dcesrv_state *dce, TALLOC_CTX *mem_ctx, struct TestCall *r) +static NTSTATUS echo_TestCall(struct dcesrv_state *dce, TALLOC_CTX *mem_ctx, struct echo_TestCall *r) { r->out.s2 = "this is a test string"; return NT_STATUS_OK; } -static NTSTATUS echo_TestCall2(struct dcesrv_state *dce, TALLOC_CTX *mem_ctx, struct TestCall2 *r) +static NTSTATUS echo_TestCall2(struct dcesrv_state *dce, TALLOC_CTX *mem_ctx, struct echo_TestCall2 *r) { r->out.info = talloc(mem_ctx, sizeof(*r->out.info)); if (!r->out.info) { @@ -109,79 +109,5 @@ static NTSTATUS echo_TestCall2(struct dcesrv_state *dce, TALLOC_CTX *mem_ctx, st } - - -/************************************************************************** - all the code below this point is boilerplate that will be auto-generated -***************************************************************************/ - -static const dcesrv_dispatch_fn_t dispatch_table[] = { - (dcesrv_dispatch_fn_t)echo_AddOne, - (dcesrv_dispatch_fn_t)echo_EchoData, - (dcesrv_dispatch_fn_t)echo_SinkData, - (dcesrv_dispatch_fn_t)echo_SourceData, - (dcesrv_dispatch_fn_t)echo_TestCall, - (dcesrv_dispatch_fn_t)echo_TestCall2 -}; - - -/* - return True if we want to handle the given endpoint -*/ -static BOOL op_query_endpoint(const struct dcesrv_endpoint *ep) -{ - return dcesrv_table_query(&dcerpc_table_rpcecho, ep); -} - -/* - setup for a particular rpc interface -*/ -static BOOL op_set_interface(struct dcesrv_state *dce, const char *uuid, uint32 if_version) -{ - if (strcasecmp(uuid, dcerpc_table_rpcecho.uuid) != 0 || - if_version != dcerpc_table_rpcecho.if_version) { - DEBUG(2,("Attempt to use unknown interface %s/%d\n", uuid, if_version)); - return False; - } - - dce->ndr = &dcerpc_table_rpcecho; - dce->dispatch = dispatch_table; - - return True; -} - - -/* op_connect is called when a connection is made to an endpoint */ -static NTSTATUS op_connect(struct dcesrv_state *dce) -{ - return NT_STATUS_OK; -} - -static void op_disconnect(struct dcesrv_state *dce) -{ - /* nothing to do */ -} - - -static int op_lookup_endpoints(TALLOC_CTX *mem_ctx, struct dcesrv_ep_iface **e) -{ - return dcesrv_lookup_endpoints(&dcerpc_table_rpcecho, mem_ctx, e); -} - -static const struct dcesrv_endpoint_ops rpc_echo_ops = { - op_query_endpoint, - op_set_interface, - op_connect, - op_disconnect, - op_lookup_endpoints -}; - -/* - register with the dcerpc server -*/ -void rpc_echo_init(struct dcesrv_context *dce) -{ - if (!dcesrv_endpoint_register(dce, &rpc_echo_ops, &dcerpc_table_rpcecho)) { - DEBUG(1,("Failed to register rpcecho endpoint\n")); - } -} +/* include the generated boilerplate */ +#include "librpc/gen_ndr/ndr_echo_s.c" diff --git a/source4/rpc_server/epmapper/rpc_epmapper.c b/source4/rpc_server/epmapper/rpc_epmapper.c index 43e4d4514f..f2ecc0faa9 100644 --- a/source4/rpc_server/epmapper/rpc_epmapper.c +++ b/source4/rpc_server/epmapper/rpc_epmapper.c @@ -319,79 +319,5 @@ static NTSTATUS epm_MgmtDelete(struct dcesrv_state *dce, TALLOC_CTX *mem_ctx, } -/************************************************************************** - all the code below this point is boilerplate that will be auto-generated -***************************************************************************/ - -static const dcesrv_dispatch_fn_t dispatch_table[] = { - (dcesrv_dispatch_fn_t)epm_Insert, - (dcesrv_dispatch_fn_t)epm_Delete, - (dcesrv_dispatch_fn_t)epm_Lookup, - (dcesrv_dispatch_fn_t)epm_Map, - (dcesrv_dispatch_fn_t)epm_LookupHandleFree, - (dcesrv_dispatch_fn_t)epm_InqObject, - (dcesrv_dispatch_fn_t)epm_MgmtDelete -}; - - -/* - return True if we want to handle the given endpoint -*/ -static BOOL op_query_endpoint(const struct dcesrv_endpoint *ep) -{ - return dcesrv_table_query(&dcerpc_table_epmapper, ep); -} - -/* - setup for a particular rpc interface -*/ -static BOOL op_set_interface(struct dcesrv_state *dce, const char *uuid, uint32 if_version) -{ - if (strcasecmp(uuid, dcerpc_table_epmapper.uuid) != 0 || - if_version != dcerpc_table_epmapper.if_version) { - DEBUG(2,("Attempt to use unknown interface %s/%d\n", uuid, if_version)); - return False; - } - - dce->ndr = &dcerpc_table_epmapper; - dce->dispatch = dispatch_table; - - return True; -} - - -/* op_connect is called when a connection is made to an endpoint */ -static NTSTATUS op_connect(struct dcesrv_state *dce) -{ - return NT_STATUS_OK; -} - -static void op_disconnect(struct dcesrv_state *dce) -{ - /* nothing to do */ -} - - -static int op_lookup_endpoints(TALLOC_CTX *mem_ctx, struct dcesrv_ep_iface **e) -{ - return dcesrv_lookup_endpoints(&dcerpc_table_epmapper, mem_ctx, e); -} - - -static const struct dcesrv_endpoint_ops rpc_epmapper_ops = { - op_query_endpoint, - op_set_interface, - op_connect, - op_disconnect, - op_lookup_endpoints -}; - -/* - register with the dcerpc server -*/ -void rpc_epmapper_init(struct dcesrv_context *dce) -{ - if (!dcesrv_endpoint_register(dce, &rpc_epmapper_ops, &dcerpc_table_epmapper)) { - DEBUG(1,("Failed to register epmapper endpoint\n")); - } -} +/* include the generated boilerplate */ +#include "librpc/gen_ndr/ndr_epmapper_s.c" diff --git a/source4/script/build_idl.sh b/source4/script/build_idl.sh index 6ca0063184..f39fab3a65 100755 --- a/source4/script/build_idl.sh +++ b/source4/script/build_idl.sh @@ -4,7 +4,7 @@ FULLBUILD=$1 [ -d librpc/gen_ndr ] || mkdir -p librpc/gen_ndr || exit 1 -PIDL="build/pidl/pidl.pl --output librpc/gen_ndr/ndr_ --parse --header --parser" +PIDL="build/pidl/pidl.pl --output librpc/gen_ndr/ndr_ --parse --header --parser --server" TABLES="build/pidl/tables.pl --output librpc/gen_ndr/tables" if [ x$FULLBUILD = xFULL ]; then diff --git a/source4/torture/rpc/echo.c b/source4/torture/rpc/echo.c index 4ac57e7b6e..be70939de1 100644 --- a/source4/torture/rpc/echo.c +++ b/source4/torture/rpc/echo.c @@ -169,12 +169,12 @@ static BOOL test_sinkdata(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx) static BOOL test_testcall(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx) { NTSTATUS status; - struct TestCall r; + struct echo_TestCall r; r.in.s1 = "input string"; printf("\nTesting TestCall\n"); - status = dcerpc_TestCall(p, mem_ctx, &r); + status = dcerpc_echo_TestCall(p, mem_ctx, &r); if (!NT_STATUS_IS_OK(status)) { printf("TestCall failed - %s\n", nt_errstr(status)); return False; @@ -189,7 +189,7 @@ static BOOL test_testcall(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx) static BOOL test_testcall2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx) { NTSTATUS status; - struct TestCall2 r; + struct echo_TestCall2 r; int i; BOOL ret = True; @@ -197,7 +197,7 @@ static BOOL test_testcall2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx) r.in.level = i; printf("\nTesting TestCall2 level %d\n", i); - status = dcerpc_TestCall2(p, mem_ctx, &r); + status = dcerpc_echo_TestCall2(p, mem_ctx, &r); if (!NT_STATUS_IS_OK(status)) { printf("TestCall2 failed - %s\n", nt_errstr(status)); ret = False; diff --git a/source4/torture/torture.c b/source4/torture/torture.c index cc0a83fe80..84734569d0 100644 --- a/source4/torture/torture.c +++ b/source4/torture/torture.c @@ -226,7 +226,18 @@ NTSTATUS torture_rpc_connection(struct dcerpc_pipe **p, cli_tree_close(cli->tree); /* bind to the pipe, using the uuid as the key */ +#if 0 status = dcerpc_bind_auth_none(*p, pipe_uuid, pipe_version); +#else + /* enable signing on tcp connections */ + (*p)->flags |= DCERPC_SIGN; + + /* bind to the pipe, using the uuid as the key */ + status = dcerpc_bind_auth_ntlm(*p, pipe_uuid, pipe_version, + lp_workgroup(), + lp_parm_string(-1, "torture", "username"), + lp_parm_string(-1, "torture", "password")); +#endif if (!NT_STATUS_IS_OK(status)) { dcerpc_pipe_close(*p); return status; -- cgit