process incoming connections and fork a samba3 in inetd mode
authorStefan Metzmacher <metze@samba.org>
Mon, 22 Sep 2008 01:57:31 +0000 (03:57 +0200)
committerVolker Lendecke <vl@samba.org>
Mon, 22 Sep 2008 02:38:06 +0000 (04:38 +0200)
source4/smb_server/config.mk
source4/smb_server/smb_samba3.c [new file with mode: 0644]
source4/smbd/server.c

index e11968a1004a28456b33e09bd48c79887842ca04..d1ec6d49e8b73416c8bcf24d88540b0de1636972 100644 (file)
@@ -9,6 +9,14 @@ SERVICE_SMB_OBJ_FILES = $(smb_serversrcdir)/smb_server.o
 
 $(eval $(call proto_header_template,$(smb_serversrcdir)/service_smb_proto.h,$(SERVICE_SMB_OBJ_FILES:.o=.c)))
 
+# samba3 SMB server subsystem
+#
+[MODULE::SERVICE_SAMBA3_SMB]
+INIT_FUNCTION = server_service_samba3_smb_init
+SUBSYSTEM = smbd
+
+SERVICE_SAMBA3_SMB_OBJ_FILES = $(smb_serversrcdir)/smb_samba3.o
+
 #######################
 # Start SUBSYSTEM SMB
 [SUBSYSTEM::SMB_SERVER]
diff --git a/source4/smb_server/smb_samba3.c b/source4/smb_server/smb_samba3.c
new file mode 100644 (file)
index 0000000..7b32298
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+   Unix SMB/CIFS implementation.
+
+   process incoming connections and fork a samba3 in inetd mode
+
+   Copyright (C) Stefan Metzmacher     2008
+
+   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 "smbd/service_task.h"
+#include "smbd/service_stream.h"
+#include "smbd/service.h"
+#include "lib/messaging/irpc.h"
+#include "lib/stream/packet.h"
+#include "lib/socket/socket.h"
+#include "libcli/smb2/smb2.h"
+#include "smb_server/smb2/smb2_server.h"
+#include "system/network.h"
+#include "lib/socket/netif.h"
+#include "param/share.h"
+#include "dsdb/samdb/samdb.h"
+#include "param/param.h"
+#include "dynconfig/dynconfig.h"
+#include "smbd/process_model.h"
+
+/*
+  initialise a server_context from a open socket and register a event handler
+  for reading from that socket
+*/
+static void samba3_smb_accept(struct stream_connection *conn)
+{
+       int i;
+       int fd = socket_get_fd(conn->socket);
+       const char *prog;
+       char *argv[2];
+       char *reason;
+
+       close(0);
+       close(1);
+       dup2(fd, 0);
+       dup2(fd, 1);
+       for (i=2;i<256;i++) {
+               close(i);
+       }
+
+       prog = lp_parm_string(conn->lp_ctx, NULL, "samba3", "smbd");
+
+       if (prog == NULL) {
+               argv[0] = talloc_asprintf(conn, "%s/%s", dyn_BINDIR, "smbd3");
+       }
+       else {
+               argv[0] = talloc_strdup(conn, prog);
+       }
+
+       if (argv[0] == NULL) {
+               stream_terminate_connection(conn, "out of memory");
+               return;
+       }
+       argv[1] = NULL;
+
+       execve(argv[0], argv, environ);
+
+       /*
+        * Should never get here
+        */
+       reason = talloc_asprintf(conn, "Could not execute %s", argv[0]);
+       if (reason == NULL) {
+               stream_terminate_connection(conn, "out of memory");
+               return;
+       }
+       stream_terminate_connection(conn, reason);
+       talloc_free(reason);
+}
+
+static const struct stream_server_ops samba3_smb_stream_ops = {
+       .name                   = "samba3",
+       .accept_connection      = samba3_smb_accept,
+};
+
+/*
+  setup a listening socket on all the SMB ports for a particular address
+*/
+static NTSTATUS samba3_add_socket(struct event_context *event_context,
+                                 struct loadparm_context *lp_ctx,
+                                 const struct model_ops *model_ops,
+                                 const char *address)
+{
+       const char **ports = lp_smb_ports(lp_ctx);
+       int i;
+       NTSTATUS status;
+
+       for (i=0;ports[i];i++) {
+               uint16_t port = atoi(ports[i]);
+               if (port == 0) continue;
+               status = stream_setup_socket(event_context, lp_ctx,
+                                            model_ops, &samba3_smb_stream_ops,
+                                            "ip", address, &port,
+                                            lp_socket_options(lp_ctx),
+                                            NULL);
+               NT_STATUS_NOT_OK_RETURN(status);
+       }
+
+       return NT_STATUS_OK;
+}
+
+
+/*
+  open the smb server sockets
+*/
+static void samba3_smb_task_init(struct task_server *task)
+{
+       NTSTATUS status;
+       const struct model_ops *model_ops;
+
+       model_ops = process_model_startup(task->event_ctx, "standard");
+
+       if (model_ops == NULL) {
+               goto failed;
+       }
+
+       task_server_set_title(task, "task[samba3_smb]");
+
+       if (lp_interfaces(task->lp_ctx)
+           && lp_bind_interfaces_only(task->lp_ctx)) {
+               int num_interfaces;
+               int i;
+               struct interface *ifaces;
+
+               load_interfaces(task, lp_interfaces(task->lp_ctx), &ifaces);
+
+               num_interfaces = iface_count(ifaces);
+
+               /* 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.
+               */
+               for(i = 0; i < num_interfaces; i++) {
+                       const char *address = iface_n_ip(ifaces, i);
+                       status = samba3_add_socket(task->event_ctx,
+                                                  task->lp_ctx,
+                                                  model_ops, address);
+                       if (!NT_STATUS_IS_OK(status)) goto failed;
+               }
+       } else {
+               /* Just bind to lp_socket_address() (usually 0.0.0.0) */
+               status = samba3_add_socket(task->event_ctx, task->lp_ctx,
+                                          model_ops,
+                                          lp_socket_address(task->lp_ctx));
+               if (!NT_STATUS_IS_OK(status)) goto failed;
+       }
+
+       return;
+failed:
+       task_server_terminate(task, "Failed to startup samba3 smb task");
+}
+
+/* called at smbd startup - register ourselves as a server service */
+NTSTATUS server_service_samba3_smb_init(void)
+{
+       return register_server_service("samba3_smb", samba3_smb_task_init);
+}
index 5bd5568913deac99f4607a4166945d81ef051b54..cf25693fbe7c9789dffa6468f59a3994020b943e 100644 (file)
@@ -199,6 +199,7 @@ static int binary_smbd_main(const char *binary_name, int argc, const char *argv[
        extern NTSTATUS server_service_drepl_init(void);
        extern NTSTATUS server_service_rpc_init(void);
        extern NTSTATUS server_service_ntp_signd_init(void);
+       extern NTSTATUS server_service_samba3_smb_init(void);
        init_module_fn static_init[] = { STATIC_smbd_MODULES };
        init_module_fn *shared_init;
        struct event_context *event_ctx;