From 5cefbfef26bf2d5f470f1d8c52d75e9756c0f738 Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Fri, 16 Jul 2010 14:52:42 +0200 Subject: s3-rpc_server: Added callbacks for init and shutdown of a rpc service. This adds two callback function for each rpc service. One is for initialisation and the other for shutdown. rpc__unregister() needs to be called to execute the shutdown function. --- pidl/lib/Parse/Pidl/Samba3/ServerNDR.pm | 15 ++++++++--- source3/include/proto.h | 20 ++++++++++++--- source3/m4/aclocal.m4 | 10 +++++++- source3/rpc_server/srv_pipe_register.c | 45 ++++++++++++++++++++++++++++++++- source3/winbindd/winbindd.c | 4 +-- source3/wscript | 20 ++++++++++----- 6 files changed, 97 insertions(+), 17 deletions(-) diff --git a/pidl/lib/Parse/Pidl/Samba3/ServerNDR.pm b/pidl/lib/Parse/Pidl/Samba3/ServerNDR.pm index 0ea43e48ad..04475d26c9 100644 --- a/pidl/lib/Parse/Pidl/Samba3/ServerNDR.pm +++ b/pidl/lib/Parse/Pidl/Samba3/ServerNDR.pm @@ -257,10 +257,19 @@ sub ParseInterface($) pidl ""; if (not has_property($if, "no_srv_register")) { - pidl_hdr "NTSTATUS rpc_$if->{NAME}_init(void);"; - pidl "NTSTATUS rpc_$if->{NAME}_init(void)"; + pidl_hdr "struct rpc_srv_callbacks;"; + pidl_hdr "NTSTATUS rpc_$if->{NAME}_init(const struct rpc_srv_callbacks *rpc_srv_cb);"; + pidl "NTSTATUS rpc_$if->{NAME}_init(const struct rpc_srv_callbacks *rpc_srv_cb)"; pidl "{"; - pidl "\treturn rpc_srv_register(SMB_RPC_INTERFACE_VERSION, \"$if->{NAME}\", \"$if->{NAME}\", \&ndr_table_$if->{NAME}, api_$if->{NAME}_cmds, sizeof(api_$if->{NAME}_cmds) / sizeof(struct api_struct));"; + pidl "\treturn rpc_srv_register(SMB_RPC_INTERFACE_VERSION, \"$if->{NAME}\", \"$if->{NAME}\", \&ndr_table_$if->{NAME}, api_$if->{NAME}_cmds, sizeof(api_$if->{NAME}_cmds) / sizeof(struct api_struct), rpc_srv_cb);"; + pidl "}"; + + pidl ""; + + pidl_hdr "NTSTATUS rpc_$if->{NAME}_shutdown(void);"; + pidl "NTSTATUS rpc_$if->{NAME}_shutdown(void)"; + pidl "{"; + pidl "\treturn rpc_srv_unregister(\&ndr_table_$if->{NAME});"; pidl "}"; } pidl_hdr "#endif /* __SRV_$uif\__ */"; diff --git a/source3/include/proto.h b/source3/include/proto.h index a5b98cdc4d..d9f9ab96d4 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -5047,6 +5047,22 @@ void *_policy_handle_find(struct pipes_struct *p, (_access_granted), #_type, __location__, (_pstatus)) +/* The following definitions come from rpc_server/srv_rpc_register.c */ + +struct rpc_srv_callbacks { + bool (*init)(void *private_data); + bool (*shutdown)(void *private_data); + void *private_data; +}; + +NTSTATUS rpc_srv_register(int version, const char *clnt, + const char *srv, + const struct ndr_interface_table *iface, + const struct api_struct *cmds, int size, + const struct rpc_srv_callbacks *rpc_srv_cb); + +NTSTATUS rpc_srv_unregister(const struct ndr_interface_table *iface); + /* The following definitions come from rpc_server/srv_pipe.c */ bool create_next_pdu(pipes_struct *p); @@ -5056,10 +5072,6 @@ NTSTATUS rpc_pipe_register_commands(int version, const char *clnt, const char *srv, const struct ndr_syntax_id *interface, const struct api_struct *cmds, int size); -NTSTATUS rpc_srv_register(int version, const char *clnt, - const char *srv, - const struct ndr_interface_table *iface, - const struct api_struct *cmds, int size); bool is_known_pipename(const char *cli_filename, struct ndr_syntax_id *syntax); bool api_pipe_bind_req(pipes_struct *p, struct ncacn_packet *pkt); bool api_pipe_alter_context(pipes_struct *p, struct ncacn_packet *pkt); diff --git a/source3/m4/aclocal.m4 b/source3/m4/aclocal.m4 index f7f3497a23..3ca44bd496 100644 --- a/source3/m4/aclocal.m4 +++ b/source3/m4/aclocal.m4 @@ -30,9 +30,17 @@ AC_DEFUN(SMB_MODULE, AC_MSG_RESULT([shared]) [$6] string_shared_modules="$string_shared_modules $1" + elif test x"$DEST" = xSTATIC && test x"$4" = xRPC; then + [init_static_modules_]translit([$4], [A-Z], [a-z])="$[init_static_modules_]translit([$4], [A-Z], [a-z]) $1_init(NULL);" + [decl_static_modules_]translit([$4], [A-Z], [a-z])="$[decl_static_modules_]translit([$4], [A-Z], [a-z]) extern NTSTATUS $1_init(const struct rpc_srv_callbacks *rpc_srv_cb);" + string_static_modules="$string_static_modules $1" + $4_STATIC="$$4_STATIC $2" + AC_SUBST($4_STATIC) + [$5] + AC_MSG_RESULT([static]) elif test x"$DEST" = xSTATIC; then [init_static_modules_]translit([$4], [A-Z], [a-z])="$[init_static_modules_]translit([$4], [A-Z], [a-z]) $1_init();" - [decl_static_modules_]translit([$4], [A-Z], [a-z])="$[decl_static_modules_]translit([$4], [A-Z], [a-z]) extern NTSTATUS $1_init(void);" + [decl_static_modules_]translit([$4], [A-Z], [a-z])="$[decl_static_modules_]translit([$4], [A-Z], [a-z]) extern NTSTATUS $1_init(void);" string_static_modules="$string_static_modules $1" $4_STATIC="$$4_STATIC $2" AC_SUBST($4_STATIC) diff --git a/source3/rpc_server/srv_pipe_register.c b/source3/rpc_server/srv_pipe_register.c index c97edb15b5..3753596a2b 100644 --- a/source3/rpc_server/srv_pipe_register.c +++ b/source3/rpc_server/srv_pipe_register.c @@ -31,11 +31,26 @@ struct rpc_table { struct ndr_syntax_id rpc_interface; const struct api_struct *cmds; uint32_t n_cmds; + bool (*shutdown_fn)(void *private_data); + void *shutdown_data; }; static struct rpc_table *rpc_lookup; static uint32_t rpc_lookup_size; +static struct rpc_table *rpc_srv_get_pipe_by_id(const struct ndr_syntax_id *id) +{ + uint32_t i; + + for (i = 0; i < rpc_lookup_size; i++) { + if (ndr_syntax_id_equal(&rpc_lookup[i].rpc_interface, id)) { + return &rpc_lookup[i]; + } + } + + return NULL; +} + bool rpc_srv_pipe_exists_by_id(const struct ndr_syntax_id *id) { uint32_t i; @@ -150,7 +165,8 @@ bool rpc_srv_get_pipe_interface_by_cli_name(const char *cli_name, NTSTATUS rpc_srv_register(int version, const char *clnt, const char *srv, const struct ndr_interface_table *iface, - const struct api_struct *cmds, int size) + const struct api_struct *cmds, int size, + const struct rpc_srv_callbacks *rpc_srv_cb) { struct rpc_table *rpc_entry; @@ -194,5 +210,32 @@ NTSTATUS rpc_srv_register(int version, const char *clnt, const char *srv, rpc_entry->cmds = cmds; rpc_entry->n_cmds = size; + if (rpc_srv_cb != NULL) { + rpc_entry->shutdown_fn = rpc_srv_cb->shutdown; + rpc_entry->shutdown_data = rpc_srv_cb->private_data; + + if (rpc_srv_cb->init != NULL && + !rpc_srv_cb->init(rpc_srv_cb->private_data)) { + DEBUG(0, ("rpc_srv_register: Failed to call the %s " + "init function!\n", srv)); + return NT_STATUS_UNSUCCESSFUL; + } + } + + return NT_STATUS_OK; +} + +NTSTATUS rpc_srv_unregister(const struct ndr_interface_table *iface) +{ + struct rpc_table *rpc_entry = rpc_srv_get_pipe_by_id(&iface->syntax_id); + + if (rpc_entry != NULL && rpc_entry->shutdown_fn != NULL) { + if (!rpc_entry->shutdown_fn(rpc_entry->shutdown_data)) { + DEBUG(0, ("rpc_srv_unregister: Failed to call the %s " + "init function!\n", rpc_entry->pipe.srv)); + return NT_STATUS_UNSUCCESSFUL; + } + } + return NT_STATUS_OK; } diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c index 7e1eb3e714..9efa8ed984 100644 --- a/source3/winbindd/winbindd.c +++ b/source3/winbindd/winbindd.c @@ -1291,8 +1291,8 @@ int main(int argc, char **argv, char **envp) winbindd_register_handlers(); - rpc_lsarpc_init(); - rpc_samr_init(); + rpc_lsarpc_init(NULL); + rpc_samr_init(NULL); if (!init_system_info()) { DEBUG(0,("ERROR: failed to setup system user info.\n")); diff --git a/source3/wscript b/source3/wscript index 0b31563343..66bddcf858 100644 --- a/source3/wscript +++ b/source3/wscript @@ -321,12 +321,20 @@ utimensat vsyslog _write __write __xstat conf.env[shared_env] = [] if p in static_list: decl_list="" - for entry in static_list[p]: - decl_list += "extern NTSTATUS %s_init(void); " % entry - conf.env[static_env].append('%s' % entry.upper()) - decl_list = decl_list.rstrip() - conf.DEFINE('static_decl_%s' % p, decl_list) - conf.DEFINE('static_init_%s' % p, '{ %s_init(); }' % '_init(); '.join(static_list[p])) + if p == "rpc": + for entry in static_list[p]: + decl_list += "extern NTSTATUS %s_init(const struct rpc_srv_callbacks *rpc_srv_cb); " % entry + conf.env[static_env].append('%s' % entry.upper()) + decl_list = decl_list.rstrip() + conf.DEFINE('static_decl_%s' % p, decl_list) + conf.DEFINE('static_init_%s' % p, '{ %s_init(NULL); }' % '_init(NULL); '.join(static_list[p])) + else: + for entry in static_list[p]: + decl_list += "extern NTSTATUS %s_init(void); " % entry + conf.env[static_env].append('%s' % entry.upper()) + decl_list = decl_list.rstrip() + conf.DEFINE('static_decl_%s' % p, decl_list) + conf.DEFINE('static_init_%s' % p, '{ %s_init(); }' % '_init(); '.join(static_list[p])) else: conf.DEFINE('static_decl_%s' % p, '') conf.DEFINE('static_init_%s' % p, '{}') -- cgit