s3-rpc_server: Created an Endpoint Mapper Daemon.
authorAndreas Schneider <asn@samba.org>
Thu, 24 Feb 2011 09:24:16 +0000 (10:24 +0100)
committerGünther Deschner <gd@samba.org>
Tue, 8 Mar 2011 10:41:29 +0000 (11:41 +0100)
Signed-off-by: Günther Deschner <gd@samba.org>
source3/Makefile.in
source3/rpc_server/epmd.c [new file with mode: 0644]

index 5ec44245d7301e0c929c7ad85217b7634c44f8fc..5b5a93816be8611445588e1b93c6b1e7e3d8d05d 100644 (file)
@@ -885,6 +885,7 @@ SMBD_OBJ_SRV = smbd/server_reload.o \
               smbd/vfs.o smbd/perfcount.o smbd/statcache.o smbd/seal.o \
                smbd/posix_acls.o lib/sysacls.o \
               smbd/process.o smbd/service.o smbd/error.o \
+              rpc_server/epmd.o \
               printing/printspoolss.o \
               lib/sysquotas.o lib/sysquotas_linux.o \
               lib/sysquotas_xfs.o lib/sysquotas_4A.o \
diff --git a/source3/rpc_server/epmd.c b/source3/rpc_server/epmd.c
new file mode 100644 (file)
index 0000000..7bc1ebc
--- /dev/null
@@ -0,0 +1,279 @@
+/*
+ *  Unix SMB/CIFS implementation.
+ *
+ *  SMBD RPC service callbacks
+ *
+ *  Copyright (c) 2011      Andreas Schneider <asn@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 "serverid.h"
+#include "../librpc/gen_ndr/messaging.h"
+#include "../librpc/gen_ndr/srv_epmapper.h"
+#include "rpc_server/rpc_server.h"
+
+#define DAEMON_NAME "epmd"
+
+void start_epmd(struct tevent_context *ev_ctx,
+               struct messaging_context *msg_ctx);
+
+static bool epmd_open_sockets(struct tevent_context *ev_ctx,
+                             struct messaging_context *msg_ctx)
+{
+       uint32_t num_ifs = iface_count();
+       uint16_t port;
+       uint32_t i;
+
+       if (lp_interfaces() && lp_bind_interfaces_only()) {
+               /*
+                * We have been given an interfaces line, and been told to only
+                * bind to those interfaces. Create a socket per interface and
+                * bind to only these.
+                */
+
+               /* Now open a listen socket for each of the interfaces. */
+               for(i = 0; i < num_ifs; i++) {
+                       const struct sockaddr_storage *ifss =
+                                       iface_n_sockaddr_storage(i);
+
+                       port = setup_dcerpc_ncacn_tcpip_socket(ev_ctx,
+                                                              msg_ctx,
+                                                              ndr_table_epmapper.syntax_id,
+                                                              ifss,
+                                                              135);
+                       if (port == 0) {
+                               return false;
+                       }
+               }
+       } else {
+               const char *sock_addr = lp_socket_address();
+               const char *sock_ptr;
+               char *sock_tok;
+
+               for (sock_ptr = sock_addr;
+                    next_token_talloc(talloc_tos(), &sock_ptr, &sock_tok, " \t,");
+                   ) {
+                       struct sockaddr_storage ss;
+
+                       /* open an incoming socket */
+                       if (!interpret_string_addr(&ss,
+                                                  sock_tok,
+                                                  AI_NUMERICHOST|AI_PASSIVE)) {
+                               continue;
+                       }
+
+                       port = setup_dcerpc_ncacn_tcpip_socket(ev_ctx,
+                                                              msg_ctx,
+                                                              ndr_table_epmapper.syntax_id,
+                                                              &ss,
+                                                              135);
+                       if (port == 0) {
+                               return false;
+                       }
+               }
+       }
+
+       return true;
+}
+
+static void epmd_reopen_logs(void)
+{
+       char *lfile = lp_logfile();
+       int rc;
+
+       if (lfile == NULL || lfile[0] == '\0') {
+               rc = asprintf(&lfile, "%s/log.%s", get_dyn_LOGFILEBASE(), DAEMON_NAME);
+               if (rc > 0) {
+                       lp_set_logfile(lfile);
+                       SAFE_FREE(lfile);
+               }
+       } else {
+               if (strstr(lfile, DAEMON_NAME) == NULL) {
+                       rc = asprintf(&lfile, "%s.%s", lp_logfile(), DAEMON_NAME);
+                       if (rc > 0) {
+                               lp_set_logfile(lfile);
+                               SAFE_FREE(lfile);
+                       }
+               }
+       }
+
+       reopen_logs();
+}
+
+static void epmd_smb_conf_updated(struct messaging_context *msg,
+                                 void *private_data,
+                                 uint32_t msg_type,
+                                 struct server_id server_id,
+                                 DATA_BLOB *data)
+{
+       struct tevent_context *ev_ctx =
+               talloc_get_type_abort(private_data, struct tevent_context);
+
+       DEBUG(10, ("Got message saying smb.conf was updated. Reloading.\n"));
+       change_to_root_user();
+       epmd_reopen_logs();
+}
+
+static void epmd_sig_term_handler(struct tevent_context *ev,
+                                 struct tevent_signal *se,
+                                 int signum,
+                                 int count,
+                                 void *siginfo,
+                                 void *private_data)
+{
+       exit_server_cleanly("termination signal");
+}
+
+static void epmd_setup_sig_term_handler(struct tevent_context *ev_ctx)
+{
+       struct tevent_signal *se;
+
+       se = tevent_add_signal(ev_ctx,
+                              ev_ctx,
+                              SIGTERM, 0,
+                              epmd_sig_term_handler,
+                              NULL);
+       if (se == NULL) {
+               exit_server("failed to setup SIGTERM handler");
+       }
+}
+
+static void epmd_sig_hup_handler(struct tevent_context *ev,
+                                   struct tevent_signal *se,
+                                   int signum,
+                                   int count,
+                                   void *siginfo,
+                                   void *private_data)
+{
+       struct messaging_context *msg_ctx = talloc_get_type_abort(private_data,
+                                                                 struct messaging_context);
+
+       change_to_root_user();
+
+       DEBUG(1,("Reloading printers after SIGHUP\n"));
+       epmd_reopen_logs();
+}
+
+static void epmd_setup_sig_hup_handler(struct tevent_context *ev_ctx,
+                                      struct messaging_context *msg_ctx)
+{
+       struct tevent_signal *se;
+
+       se = tevent_add_signal(ev_ctx,
+                              ev_ctx,
+                              SIGHUP, 0,
+                              epmd_sig_hup_handler,
+                              msg_ctx);
+       if (se == NULL) {
+               exit_server("failed to setup SIGHUP handler");
+       }
+}
+
+void start_epmd(struct tevent_context *ev_ctx,
+               struct messaging_context *msg_ctx)
+{
+       NTSTATUS status;
+       pid_t pid;
+       bool ok;
+       int rc;
+
+       DEBUG(1, ("Forking Endpoint Mapper Daemon\n"));
+
+       pid = sys_fork();
+
+       if (pid == -1) {
+               DEBUG(0, ("Failed to fork Endpoint Mapper [%s], aborting ...\n",
+                         strerror(errno)));
+               exit(1);
+       }
+
+       if (pid) {
+               /* parent */
+               return;
+       }
+
+       /* child */
+       close_low_fds(false);
+
+       status = reinit_after_fork(msg_ctx,
+                                  ev_ctx,
+                                  procid_self(),
+                                  true);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0,("reinit_after_fork() failed\n"));
+               smb_panic("reinit_after_fork() failed");
+       }
+
+       epmd_reopen_logs();
+
+       epmd_setup_sig_term_handler(ev_ctx);
+       epmd_setup_sig_hup_handler(ev_ctx, msg_ctx);
+
+       ok = serverid_register(procid_self(),
+                              FLAG_MSG_GENERAL|FLAG_MSG_SMBD
+                              |FLAG_MSG_PRINT_GENERAL);
+       if (!ok) {
+               DEBUG(0, ("Failed to register serverid in epmd!\n"));
+               exit(1);
+       }
+
+       messaging_register(msg_ctx,
+                          ev_ctx,
+                          MSG_SMB_CONF_UPDATED,
+                          epmd_smb_conf_updated);
+
+       status = rpc_epmapper_init(NULL);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0, ("Failed to register epmd rpc inteface! (%s)\n",
+                         nt_errstr(status)));
+               exit(1);
+       }
+
+       ok = setup_dcerpc_ncalrpc_socket(ev_ctx,
+                                        msg_ctx,
+                                        ndr_table_epmapper.syntax_id,
+                                        "EPMAPPER");
+       if (!ok) {
+               DEBUG(0, ("Failed to open epmd ncalrpc pipe!\n"));
+               exit(1);
+       }
+
+       ok = epmd_open_sockets(ev_ctx, msg_ctx);
+       if (!ok) {
+               DEBUG(0, ("Failed to open epmd tcpip sockets!\n"));
+               exit(1);
+       }
+
+       ok = setup_named_pipe_socket("epmapper", ev_ctx);
+       if (!ok) {
+               DEBUG(0, ("Failed to open epmd named pipe!\n"));
+               exit(1);
+       }
+
+       DEBUG(1, ("Endpoint Mapper Daemon Started (%d)\n", getpid()));
+
+       /* loop forever */
+       rc = tevent_loop_wait(ev_ctx);
+
+       /* should not be reached */
+       DEBUG(0,("background_queue: tevent_loop_wait() exited with %d - %s\n",
+                rc, (rc == 0) ? "out of events" : strerror(errno)));
+
+       exit(1);
+}
+
+/* vim: set ts=8 sw=8 noet cindent ft=c.doxygen: */