s3fs: rework file_server code to use child daemon
authorAndrew Tridgell <tridge@samba.org>
Tue, 29 Nov 2011 23:06:46 +0000 (10:06 +1100)
committerAndrew Tridgell <tridge@samba.org>
Thu, 9 Feb 2012 04:41:49 +0000 (15:41 +1100)
this makes $SBINDIR/smbd a child daemon of bin/samba, rather than
calling directly into the smbd code

file_server/file_server.c
file_server/wscript_build

index c69872424e65dd5451368453ee78007c61bb8d42..f26580364a7fc6b9e7672bb78c259fdeec912444 100644 (file)
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
-#include "source3/include/includes.h"
-
-/* we use the full source3/source4 prefixes as this code mixes the two
-   sets of header pathsx */
-#include "source3/smbd/globals.h"
-#include "source3/smbd/proto.h"
-#include "source3/include/memcache.h"
-#include "source3/include/passdb.h"
-#include "source3/include/secrets.h"
-#include "source3/locking/proto.h"
-#include "source3/include/messages.h"
-#include "source3/include/serverid.h"
-#include "source3/printing/printer_list.h"
-#include "source3/registry/reg_init_full.h"
-#include "source3/include/printing.h"
-#include "source3/include/auth.h"
-#include "rpc_server/rpc_service_setup.h"
-#include "source4/smbd/service_stream.h"
+#include "includes.h"
+#include "talloc.h"
+#include "tevent.h"
+#include "system/filesys.h"
 #include "lib/param/param.h"
-#include "source4/lib/socket/socket.h"
 #include "source4/smbd/service.h"
 #include "source4/smbd/process_model.h"
-#include "source4/lib/socket/netif.h"
-#include "libcli/auth/schannel.h"
 #include "file_server/file_server.h"
-
+#include "dynconfig.h"
 
 /*
-  this runs through the initialisation that the samba3 file server
-  normally does. It is derived from main() in source3/smbd/server.c
+  generate a smbd config file for the file server
  */
-static int s3fs_server_init(struct loadparm_context *lp_ctx)
+static const char *generate_smb_conf(struct task_server *task)
 {
-       uint64_t unique_id;
-       NTSTATUS status;
-       struct tevent_context *ev_ctx;
-       struct messaging_context *msg_ctx;
-
-       /* create a stackframe for the file server child */
-       talloc_stackframe();
-
-       smbd_init_globals();
-
-       TimeInit();
-
-       set_remote_machine_name("smbd", False);
-
-       /* get initial effective uid and gid */
-       sec_init();
-
-       lp_set_cmdline("config file", lpcfg_configfile(lp_ctx));
-       lp_set_cmdline("auth methods", "guest samba4");
-       lp_set_cmdline("passdb backend", "samba4");
-        lp_set_cmdline("rpc_server:lsarpc", "external");
-       lp_set_cmdline("rpc_server:netlogon", "external");
-       lp_set_cmdline("rpc_server:samr", "external");
-
-        lp_set_cmdline("rpc_server:epmapper", "disabled");
-       lp_set_cmdline("rpc_server:rpcecho", "disabled");
-        lp_set_cmdline("rpc_server:dssetup", "disabled");
-       lp_set_cmdline("rpc_server:svctl", "disabled");
-       lp_set_cmdline("rpc_server:ntsvcs", "disabled");
-       lp_set_cmdline("rpc_server:eventlog", "disabled");
-       lp_set_cmdline("rpc_server:initshutdown", "disabled");
-
-       lp_set_cmdline("rpc_server:winreg", "embedded");
-       lp_set_cmdline("rpc_server:srvsvc", "embedded");
-       lp_set_cmdline("rpc_server:netdfs", "embedded");
-       lp_set_cmdline("rpc_server:wkssvc", "embedded");
-       lp_set_cmdline("rpc_server:spoolss", "embedded");
-
-       lp_set_cmdline("rpc_daemon:epmd", "disabled");
-       lp_set_cmdline("rpc_daemon:lsasd", "disabled");
-       lp_set_cmdline("rpc_daemon:spoolssd", "disabled");
-
-       lp_set_cmdline("rpc_server:tcpip", "no");
-
-       if (!lp_load_initial_only(lpcfg_configfile(lp_ctx))) {
-               DEBUG(0, ("error opening config file '%s'\n", get_dyn_CONFIGFILE()));
-               return -1;
-       }
-
-       /* Init the security context and global current_user */
-       init_sec_ctx();
-
-       /*
-        * Initialize the event context. The event context needs to be
-        * initialized before the messaging context, cause the messaging
-        * context holds an event context.
-        * FIXME: This should be s3_tevent_context_init()
-        */
-       ev_ctx = server_event_context();
-       if (ev_ctx == NULL) {
-               DEBUG(0, ("Failed to get server event context"));
-               return -1;
-       }
-
-       /*
-        * Init the messaging context
-        * FIXME: This should only call messaging_init()
-        */
-       msg_ctx = server_messaging_context();
-       if (msg_ctx == NULL) {
-               DEBUG(0, ("Failed to get server messaging context"));
-               return -1;
-       }
-
-       /*
-        * Reloading of the printers will not work here as we don't have a
-        * server info and rpc services set up. It will be called later.
-        */
-       if (!reload_services(NULL, -1, False)) {
-               DEBUG(0, ("Failed to reload smb.conf"));
-               return -1;
-       }
-
-       /* ...NOTE... Log files are working from this point! */
-
-        generate_random_buffer((uint8_t *)&unique_id, sizeof(unique_id));
-        set_my_unique_id(unique_id);
-
-       status = reinit_after_fork(msg_ctx,
-                                  ev_ctx,
-                                  procid_self(), false);
-       if (!NT_STATUS_IS_OK(status)) {
-               DEBUG(0,("reinit_after_fork() failed\n"));
-               return -1;
-       }
-
-       smbd_server_conn->msg_ctx = msg_ctx;
-
-       smbd_setup_sig_term_handler();
-       smbd_setup_sig_hup_handler(ev_ctx,
-                                  msg_ctx);
-
-       /* Setup all the TDB's - including CLEAR_IF_FIRST tdb's. */
-
-       if (smbd_memcache() == NULL) {
-               DEBUG(0, ("Failed to init smbd memcache"));
-               return -1;
-       }
-
-       memcache_set_global(smbd_memcache());
-
-       /* Initialise the password backed before the global_sam_sid
-          to ensure that we fetch from ldap before we make a domain sid up */
-
-       if(!initialize_password_db(false, ev_ctx)) {
-               DEBUG(0, ("Failed to init passdb backends"));
-               return -1;
-       }
-
-       if (!secrets_init()) {
-               DEBUG(0, ("ERROR: smbd can not open secrets.tdb\n"));
-               return -1;
-       }
-
-       if (lp_server_role() == ROLE_DOMAIN_BDC || lp_server_role() == ROLE_DOMAIN_PDC) {
-               if (!open_schannel_session_store(NULL, lp_ctx)) {
-                       DEBUG(0,("ERROR: Samba cannot open schannel store for secured NETLOGON operations.\n"));
-                       return -1;
-               }
-       }
-
-       if(!get_global_sam_sid()) {
-               DEBUG(0,("ERROR: Samba cannot create a SAM SID.\n"));
-               return -1;
-       }
-
-       if (!sessionid_init()) {
-               DEBUG(0, ("Failed to init sessionid database"));
-               return -1;
-       }
-
-       if (!connections_init(True)) {
-               DEBUG(0, ("Failed to init connections database"));
-               return -1;
-       }
-
-       if (!locking_init()) {
-               DEBUG(0, ("Failed to init locking database"));
-               return -1;
-       }
-       if (!messaging_tdb_parent_init(ev_ctx)) {
-               DEBUG(0, ("Failed to init messaging tdb as parent task"));
-               return -1;
-       }
-
-       if (!notify_internal_parent_init(ev_ctx)) {
-               DEBUG(0, ("Failed to init notify db as parent task"));
-               return -1;
-       }
-
-       if (!serverid_parent_init(ev_ctx)) {
-               return -1;
-       }
-
-       if (!W_ERROR_IS_OK(registry_init_full())) {
-               DEBUG(0, ("Failed to init registry"));
-               return -1;
-       }
-
-       /* Open the share_info.tdb here, so we don't have to open
-          after the fork on every single connection.  This is a small
-          performance improvment and reduces the total number of system
-          fds used. */
-       if (!share_info_db_init()) {
-               DEBUG(0,("ERROR: failed to load share info db.\n"));
-               return -1;
-       }
-
-       status = init_system_info();
-       if (!NT_STATUS_IS_OK(status)) {
-               DEBUG(1, ("ERROR: failed to setup system user info: %s.\n",
-                         nt_errstr(status)));
-               return -1;
-       }
-
-       if (!init_guest_info()) {
-               DEBUG(0,("ERROR: failed to setup guest info.\n"));
-               return -1;
-       }
-
-       if (!file_init(smbd_server_conn)) {
-               DEBUG(0, ("ERROR: file_init failed\n"));
-               return -1;
-       }
-
-       if (!dcesrv_ep_setup(ev_ctx, msg_ctx)) {
-               DEBUG(0, ("Failed to init dcerpc endpoints"));
-               return -1;
-       }
-
-       init_names();
-
-
-       return 0;
+       int fd;
+       struct loadparm_context *lp_ctx = task->lp_ctx;
+       const char *path = smbd_tmp_path(task, lp_ctx, "fileserver.conf");
+
+       if (path == NULL) {
+               return NULL;
+       }
+
+       fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, 0644);
+       if (fd == -1) {
+               DEBUG(0,("Failed to create %s", path));
+               return NULL;
+       }
+
+       fdprintf(fd, "# auto-generated config for fileserver\n");
+       fdprintf(fd, "auth methods = guest samba4\n");
+       fdprintf(fd, "passdb backend = samba4\n");
+        fdprintf(fd, "rpc_server:lsarpc = external\n");
+       fdprintf(fd, "rpc_server:netlogon = external\n");
+       fdprintf(fd, "rpc_server:samr = external\n");
+       fdprintf(fd, "rpc_server:rpcecho = disabled\n");
+        fdprintf(fd, "rpc_server:dssetup = disabled\n");
+       fdprintf(fd, "rpc_server:svctl = disabled\n");
+       fdprintf(fd, "rpc_server:ntsvcs = disabled\n");
+       fdprintf(fd, "rpc_server:eventlog = disabled\n");
+       fdprintf(fd, "rpc_server:initshutdown = disabled\n");
+       fdprintf(fd, "rpc_server:winreg = embedded\n");
+       fdprintf(fd, "rpc_server:srvsvc = embedded\n");
+       fdprintf(fd, "rpc_server:netdfs = embedded\n");
+       fdprintf(fd, "rpc_server:wkssvc = embedded\n");
+       fdprintf(fd, "rpc_server:spoolss = embedded\n");
+       fdprintf(fd, "rpc_daemon:lsasd = disabled\n");
+       fdprintf(fd, "rpc_daemon:spoolssd = disabled\n");
+       fdprintf(fd, "rpc_server:tcpip = no\n");
+
+       fdprintf(fd, "include = %s\n", lpcfg_configfile(lp_ctx));
+       close(fd);
+       return path;
 }
 
 /*
-  initialise a server_context from a open socket and register a event handler
-  for reading from that socket
-*/
-static void s3fs_smb_accept(struct stream_connection *conn)
+  called if smbd exits
+ */
+static void file_server_smbd_done(struct tevent_req *subreq)
 {
-       if (lpcfg_parm_bool(conn->lp_ctx, NULL, "s3fs", "gdb", false)) {
-               samba_start_debugger();
-               sleep(2);
-       }
-       DEBUG(0,(__location__ ": new s3fs smbd connection\n"));
-
-       if (s3fs_server_init(conn->lp_ctx) != 0) {
-               DEBUG(0,("Failed to initialise s3fs backend\n"));
-               exit(1);
-       }
+       int sys_errno;
+       int ret;
 
-       smbd_server_conn->sock = socket_get_fd(conn->socket);
-
-       if (!serverid_register(procid_self(),
-                              FLAG_MSG_GENERAL|FLAG_MSG_SMBD
-                              |FLAG_MSG_DBWRAP
-                              |FLAG_MSG_PRINT_GENERAL)) {
-               exit_server_cleanly("Could not register myself in "
-                                   "serverid.tdb");
+       ret = samba_runcmd_recv(subreq, &sys_errno);
+       if (ret != 0) {
+               DEBUG(0,("file_server smbd daemon died with exit status %d\n", sys_errno));
+       } else {
+               DEBUG(0,("file_server smbd daemon exited normally\n"));
        }
-
-       smbd_process(server_event_context(), smbd_server_conn);
-       exit(1);
 }
 
-static const struct stream_server_ops s3fs_smb_stream_ops = {
-       .name                   = "s3fs",
-       .accept_connection      = s3fs_smb_accept,
-};
-
-/*
-  setup a listening socket on all the SMB ports for a particular address
-*/
-static NTSTATUS s3fs_add_socket(struct task_server *task,
-                                 struct tevent_context *event_context,
-                                 struct loadparm_context *lp_ctx,
-                                 const struct model_ops *model_ops,
-                                 const char *address)
-{
-       const char **ports = lpcfg_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(task, event_context, lp_ctx,
-                                            model_ops, &s3fs_smb_stream_ops,
-                                            "ip", address, &port,
-                                            lpcfg_socket_options(lp_ctx),
-                                            NULL);
-               NT_STATUS_NOT_OK_RETURN(status);
-       }
-
-       return NT_STATUS_OK;
-}
 
 /*
-  open the s3 smb server sockets
+  startup a copy of smbd as a child daemon
 */
 static void s3fs_task_init(struct task_server *task)
 {
-       NTSTATUS status;
-       const struct model_ops *model_ops;
-
-       model_ops = process_model_startup("standard");
-
-       if (model_ops == NULL) {
-               goto failed;
-       }
+       const char *fileserver_conf;
+       struct tevent_req *req;
+       const char *smbd_path;
+       const char *smbd_cmd[2] = { NULL, NULL };
 
        task_server_set_title(task, "task[s3fs_parent]");
 
-       if (lpcfg_interfaces(task->lp_ctx) && lpcfg_bind_interfaces_only(task->lp_ctx)) {
-               int num_interfaces;
-               int i;
-               struct interface *ifaces;
-
-               load_interface_list(task, task->lp_ctx, &ifaces);
+       /* create a smb.conf for smbd to use */
+       fileserver_conf = generate_smb_conf(task);
 
-               num_interfaces = iface_list_count(ifaces);
+       smbd_path = talloc_asprintf(task, "%s/smbd", dyn_SBINDIR);
+       smbd_cmd[0] = smbd_path;
 
-               /* 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_list_n_ip(ifaces, i);
-                       status = s3fs_add_socket(task, task->event_ctx, task->lp_ctx, model_ops, address);
-                       if (!NT_STATUS_IS_OK(status)) goto failed;
-               }
-       } else {
-               const char **wcard;
-               int i;
-               wcard = iface_list_wildcard(task, task->lp_ctx);
-               if (wcard == NULL) {
-                       DEBUG(0,("No wildcard addresses available\n"));
-                       goto failed;
-               }
-               for (i=0; wcard[i]; i++) {
-                       status = s3fs_add_socket(task, task->event_ctx, task->lp_ctx, model_ops, wcard[i]);
-                       if (!NT_STATUS_IS_OK(status)) goto failed;
-               }
-               talloc_free(wcard);
+       /* start it as a child process */
+       req = samba_runcmd_send(task, task->event_ctx, timeval_zero(), 1, 0,
+                               smbd_cmd,
+                               "--configfile", fileserver_conf,
+                               "--foreground", NULL);
+       if (req == NULL) {
+               DEBUG(0, ("Failed to start smbd as child daemon\n"));
+               goto failed;
        }
 
+       tevent_req_set_callback(req, file_server_smbd_done, task);
+
+       DEBUG(1,("Started file server smbd with config %s\n", fileserver_conf));
        return;
 failed:
        task_server_terminate(task, "Failed to startup s3fs smb task", true);
index 5a0c661ce5ff581a215859547c30b14fef61106b..f76c8470a12999e8bc0af7f152b356a5042ff702 100644 (file)
@@ -1,12 +1,10 @@
 #!/usr/bin/env python
 
-import samba3
-
 bld.SAMBA_MODULE('service_s3fs',
                  source='file_server.c',
                  autoproto='file_server_proto.h',
                  subsystem='service',
                  init_function='server_service_s3fs_init',
-                 deps='netif samba-hostconfig smbd_base service talloc',
+                 deps='samba-hostconfig service talloc UTIL_RUNCMD',
                  internal_module=False
                  )