s3:rpc_server: allow building RPC services as shared modules
authorRalph Boehme <slow@samba.org>
Sat, 24 Oct 2015 08:50:43 +0000 (10:50 +0200)
committerRalph Boehme <slow@samba.org>
Sun, 21 Feb 2016 18:21:17 +0000 (19:21 +0100)
This is the general RPC subsystem change, existing modules must be
tweaked to support being loaded as a module.

The next commit shows how to do this for the Spotlight RPC service.

The general syntax is: --with-shared-modules=rpc_NAME_module

Signed-off-by: Ralph Boehme <slow@samba.org>
Reviewed-by: Guenther Deschner <gd@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
source3/rpc_server/rpc_modules.c [new file with mode: 0644]
source3/rpc_server/rpc_modules.h [new file with mode: 0644]
source3/rpc_server/rpc_service_setup.c
source3/rpc_server/rpc_service_setup.h
source3/rpc_server/wscript_build
source3/wscript

diff --git a/source3/rpc_server/rpc_modules.c b/source3/rpc_server/rpc_modules.c
new file mode 100644 (file)
index 0000000..69b5d03
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ *  Unix SMB/CIFS implementation.
+ *
+ *  SMBD RPC modules
+ *
+ *  Copyright (c) 2015 Ralph Boehme <slow@samba.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "includes.h"
+#include "rpc_server/rpc_modules.h"
+
+static struct rpc_module *rpc_modules;
+
+struct rpc_module {
+       struct rpc_module *prev, *next;
+       char *name;
+       struct rpc_module_fns *fns;
+};
+
+static struct rpc_module *find_rpc_module(const char *name)
+{
+       struct rpc_module *module = NULL;
+
+       for (module = rpc_modules; module != NULL; module = module->next) {
+               if (strequal(module->name, name)) {
+                       return module;
+               }
+       }
+
+       return NULL;
+}
+
+NTSTATUS register_rpc_module(struct rpc_module_fns *fns,
+                            const char *name)
+{
+       struct rpc_module *module = find_rpc_module(name);
+
+       if (module != NULL) {
+               DBG_ERR("RPC module %s already loaded!\n", name);
+               return NT_STATUS_OBJECT_NAME_COLLISION;
+       }
+
+       module = SMB_XMALLOC_P(struct rpc_module);
+       module->name = smb_xstrdup(name);
+       module->fns = fns;
+
+       DLIST_ADD(rpc_modules, module);
+       DBG_NOTICE("Successfully added RPC module '%s'\n", name);
+
+       return NT_STATUS_OK;
+}
+
+bool setup_rpc_module(struct tevent_context *ev_ctx,
+                     struct messaging_context *msg_ctx,
+                     const char *name)
+{
+       bool ok;
+       struct rpc_module *module = find_rpc_module(name);
+
+       if (module == NULL) {
+               return false;
+       }
+
+       ok = module->fns->setup(ev_ctx, msg_ctx);
+       if (!ok) {
+               DBG_ERR("calling setup for %s failed\n", name);
+       }
+
+       return true;
+}
+
+bool setup_rpc_modules(struct tevent_context *ev_ctx,
+                      struct messaging_context *msg_ctx)
+{
+       bool ok;
+       struct rpc_module *module = rpc_modules;
+
+       for (module = rpc_modules; module; module = module->next) {
+               ok = module->fns->setup(ev_ctx, msg_ctx);
+               if (!ok) {
+                       DBG_ERR("calling setup for %s failed\n", module->name);
+               }
+       }
+
+       return true;
+}
+
+bool init_rpc_module(const char *name,
+                    const struct rpc_srv_callbacks *rpc_srv_cb)
+{
+       struct rpc_module *module = find_rpc_module(name);
+       NTSTATUS status;
+
+       if (module == NULL) {
+               return false;
+       }
+
+       status = module->fns->init(rpc_srv_cb);
+       if (!NT_STATUS_IS_OK(status)) {
+               DBG_ERR("calling init for %s failed %s\n",
+                       name, nt_errstr(status));
+               return false;
+       }
+
+       return true;
+}
+
+bool shutdown_rpc_module(const char *name)
+{
+       struct rpc_module *module = find_rpc_module(name);
+       NTSTATUS status;
+
+       if (module == NULL) {
+               return false;
+       }
+
+       status = module->fns->shutdown();
+       if (!NT_STATUS_IS_OK(status)) {
+               DBG_ERR("calling shutdown for %s failed %s\n",
+                       name, nt_errstr(status));
+               return false;
+       }
+
+       return true;
+}
diff --git a/source3/rpc_server/rpc_modules.h b/source3/rpc_server/rpc_modules.h
new file mode 100644 (file)
index 0000000..afac1d9
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ *  Unix SMB/CIFS implementation.
+ *
+ *  SMBD RPC modules
+ *
+ *  Copyright (c) 2015 Ralph Boehme <slow@samba.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _RPC_MODULES_H
+#define _RPC_MODULES_H
+
+struct rpc_srv_callbacks;
+
+struct rpc_module_fns {
+       bool (*setup)(struct tevent_context *ev_ctx, struct messaging_context *msg_ctx);
+       NTSTATUS (*init)(const struct rpc_srv_callbacks *rpc_srv_cb);
+       NTSTATUS (*shutdown)(void);
+};
+
+NTSTATUS register_rpc_module(struct rpc_module_fns *fns,
+                            const char *name);
+
+bool setup_rpc_modules(struct tevent_context *ev_ctx,
+                      struct messaging_context *msg_ctx);
+
+bool setup_rpc_module(struct tevent_context *ev_ctx,
+                     struct messaging_context *msg_ctx,
+                     const char *name);
+
+bool init_rpc_module(const char *name,
+                    const struct rpc_srv_callbacks *rpc_srv_cb);
+
+bool shutdown_rpc_module(const char *name);
+#endif
index ee995a805d161e9e1c73283f00ca49746b15564a..3a4c0b08844e8c9b3cf5b56970cc44f4f52520db 100644 (file)
 #include "rpc_server/rpc_ep_register.h"
 #include "rpc_server/rpc_server.h"
 #include "rpc_server/rpc_config.h"
+#include "rpc_server/rpc_modules.h"
 #include "rpc_server/epmapper/srv_epmapper.h"
 
+static_decl_rpc;
+
 /* Common routine for embedded RPC servers */
-static bool rpc_setup_embedded(struct tevent_context *ev_ctx,
-                              struct messaging_context *msg_ctx,
-                              const struct ndr_interface_table *t,
-                              const char *pipe_name)
+bool rpc_setup_embedded(struct tevent_context *ev_ctx,
+                       struct messaging_context *msg_ctx,
+                       const struct ndr_interface_table *t,
+                       const char *pipe_name)
 {
        struct dcerpc_binding_vector *v;
        enum rpc_service_mode_e epm_mode = rpc_epmapper_mode();
@@ -500,6 +503,7 @@ bool dcesrv_ep_setup(struct tevent_context *ev_ctx,
 {
        TALLOC_CTX *tmp_ctx;
        bool ok;
+       init_module_fn *mod_init_fns = NULL;
 
        tmp_ctx = talloc_stackframe();
        if (tmp_ctx == NULL) {
@@ -585,6 +589,28 @@ bool dcesrv_ep_setup(struct tevent_context *ev_ctx,
        }
 #endif
 
+       /* Initialize static subsystems */
+       static_init_rpc;
+
+       /* Initialize shared modules */
+       mod_init_fns = load_samba_modules(tmp_ctx, "rpc");
+       if (mod_init_fns == NULL) {
+               DBG_ERR("Loading shared RPC modules failed\n");
+               goto done;
+       }
+
+       ok = run_init_functions(mod_init_fns);
+       if (!ok) {
+               DBG_ERR("Initializing shared RPC modules failed\n");
+               goto done;
+       }
+
+       ok = setup_rpc_modules(ev_ctx, msg_ctx);
+       if (!ok) {
+               DBG_ERR("Shared RPC modules setup failed\n");
+               goto done;
+       }
+
 done:
        talloc_free(tmp_ctx);
        return ok;
index 2e27995261d589d162891c5d540ec79614356256..da89cbcbaba6c20f81092c6af9229ef78f24eed8 100644 (file)
@@ -23,6 +23,7 @@
 #define _RPC_EP_SETUP_H
 
 struct ndr_interface_table;
+struct rpc_srv_callbacks;
 
 /**
  * @brief Register an endpoint at the endpoint mapper.
@@ -51,6 +52,11 @@ NTSTATUS rpc_ep_setup_register(struct tevent_context *ev_ctx,
 bool dcesrv_ep_setup(struct tevent_context *ev_ctx,
                     struct messaging_context *msg_ctx);
 
+bool rpc_setup_embedded(struct tevent_context *ev_ctx,
+                       struct messaging_context *msg_ctx,
+                       const struct ndr_interface_table *t,
+                       const char *pipe_name);
+
 #endif /* _RPC_EP_SETUP_H */
 
 /* vim: set ts=8 sw=8 noet cindent ft=c.doxygen: */
index 278e0bd924a3ac290131e6cae71f1b1589d7fdf6..ae4c0613c1f0decba4cccd89a2bc8ce9fd43c29a 100755 (executable)
@@ -146,8 +146,9 @@ bld.SAMBA3_SUBSYSTEM('RPC_SERVER_REGISTER',
                     deps='samba-util')
 
 bld.SAMBA3_SUBSYSTEM('RPC_SERVICE',
-                    source='rpc_service_setup.c',
+                    source='rpc_service_setup.c rpc_modules.c',
                     deps='''
+                    rpc
                     RPC_SERVER
                     RPC_SERVER_REGISTER
                     RPC_SAMR
index c6fdb1bddb9723591ba030aa1a3f8a87949f5a23..b65e3eb0cb7aaa6b2bb6e75daba0cda9b24073a1 100644 (file)
@@ -1725,7 +1725,7 @@ main() {
     static_list = {}
     shared_list = {}
 
-    prefixes = ['vfs', 'pdb', 'auth', 'nss_info', 'charset', 'idmap', 'gpext', 'perfcount']
+    prefixes = ['vfs', 'pdb', 'auth', 'nss_info', 'charset', 'idmap', 'gpext', 'perfcount', 'rpc']
     conf.env['MODULE_PREFIXES'] = prefixes
     for p in prefixes:
         for m in final_static_modules: