#include "lib/util/sys_rw.h"
#include "cleanupdb.h"
#include "g_lock.h"
+#include "libcli/smb/smb_direct.h"
#ifdef CLUSTER_SUPPORT
#include "ctdb_protocol.h"
struct server_id cleanupd;
struct server_id notifyd;
+ pid_t smb_direct_daemon_pid;
struct tevent_timer *cleanup_te;
};
}
}
+static void smb_direct_daemon_stopped(struct tevent_req *req);
+
+static bool smb_direct_daemon_init(struct tevent_context *ev,
+ struct messaging_context *msg,
+ bool interactive,
+ pid_t *ppid)
+{
+ struct tevent_req *req;
+ pid_t pid;
+ NTSTATUS status;
+ ssize_t rwret;
+ int ret;
+ bool ok;
+ char c;
+ int up_pipe[2];
+
+ sec_init();
+
+
+ if (interactive) {
+ req = smb_direct_daemon_send(ev, ev);
+ *ppid = getpid();
+ return (req != NULL);
+ }
+
+ ret = pipe(up_pipe);
+ if (ret == -1) {
+ DBG_WARNING("pipe failed: %s\n", strerror(errno));
+ return false;
+ }
+
+ pid = fork();
+ if (pid == -1) {
+ DBG_WARNING("fork failed: %s\n", strerror(errno));
+ close(up_pipe[0]);
+ close(up_pipe[1]);
+ return false;
+ }
+
+ if (pid != 0) {
+
+ close(up_pipe[1]);
+ rwret = sys_read(up_pipe[0], &c, 1);
+ close(up_pipe[0]);
+
+ if (rwret == -1) {
+ DBG_WARNING("sys_read failed: %s\n", strerror(errno));
+ return false;
+ }
+ if (rwret == 0) {
+ DBG_WARNING("smb_direct_daemon could not start\n");
+ return false;
+ }
+ if (c != 0) {
+ DBG_WARNING("smb_direct_daemon returned %d\n", (int)c);
+ return false;
+ }
+
+ DBG_DEBUG("Started smb_direct_daemon pid=%d\n", (int)pid);
+
+ if (am_parent != NULL) {
+ add_child_pid(am_parent, pid);
+ }
+
+ *ppid = pid;
+ return true;
+ }
+
+ close(up_pipe[0]);
+
+ status = smbd_reinit_after_fork(msg, ev, true, "smb_direct_daemon");
+ if (!NT_STATUS_IS_OK(status)) {
+ DBG_WARNING("reinit_after_fork failed: %s\n",
+ nt_errstr(status));
+ c = 1;
+ sys_write(up_pipe[1], &c, 1);
+
+ exit(1);
+ }
+
+ req = smb_direct_daemon_send(ev, ev);
+ if (req == NULL) {
+ DBG_WARNING("smb_direct_daemon_send failed\n");
+ c = 2;
+ sys_write(up_pipe[1], &c, 1);
+
+ exit(1);
+ }
+
+ tevent_req_set_callback(req, smb_direct_daemon_stopped, msg);
+
+ c = 0;
+ rwret = sys_write(up_pipe[1], &c, 1);
+ close(up_pipe[1]);
+
+ if (rwret == -1) {
+ DBG_WARNING("sys_write failed: %s\n", strerror(errno));
+ exit(1);
+ }
+ if (rwret != 1) {
+ DBG_WARNING("sys_write could not write result\n");
+ exit(1);
+ }
+
+ ok = tevent_req_poll(req, ev);
+ if (!ok) {
+ DBG_WARNING("tevent_req_poll returned %s\n", strerror(errno));
+ }
+
+ ret = smb_direct_daemon_recv(req);
+ TALLOC_FREE(req);
+
+ if (ret != 0) {
+ DBG_WARNING("smb_direct_daemon_recv returned [%s]\n",
+ strerror(ret));
+ }
+
+ exit(ret);
+}
+
+static void smb_direct_daemon_stopped(struct tevent_req *req)
+{
+ int ret;
+
+ ret = smb_direct_daemon_recv(req);
+ DBG_WARNING("smb_direct_daemon stopped: [%s/%d]\n",
+ strerror(ret), ret);
+}
+
+static void smb_direct_daemon_init_trigger(struct tevent_req *req);
+
+struct smb_direct_daemon_init_state {
+ bool ok;
+ struct tevent_context *ev;
+ struct messaging_context *msg;
+ pid_t *smb_direct_daemon_pid;
+};
+
+static struct tevent_req *smb_direct_daemon_init_send(
+ TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct messaging_context *msg,
+ pid_t *smb_direct_daemon_pid)
+{
+ struct tevent_req *req = NULL;
+ struct tevent_req *subreq = NULL;
+ struct smb_direct_daemon_init_state *state = NULL;
+
+ req = tevent_req_create(mem_ctx, &state, struct smb_direct_daemon_init_state);
+ if (req == NULL) {
+ return NULL;
+ }
+
+ *state = (struct smb_direct_daemon_init_state) {
+ .ev = ev,
+ .msg = msg,
+ .smb_direct_daemon_pid = smb_direct_daemon_pid
+ };
+
+ subreq = tevent_wakeup_send(state, ev, tevent_timeval_current_ofs(0, 0));
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
+
+ tevent_req_set_callback(subreq, smb_direct_daemon_init_trigger, req);
+ return req;
+}
+
+static void smb_direct_daemon_init_trigger(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct smb_direct_daemon_init_state *state = tevent_req_data(
+ req, struct smb_direct_daemon_init_state);
+ bool ok;
+
+ DBG_NOTICE("Triggering smb_direct_daemon startup\n");
+
+ ok = tevent_wakeup_recv(subreq);
+ TALLOC_FREE(subreq);
+ if (!ok) {
+ tevent_req_error(req, ENOMEM);
+ return;
+ }
+
+ state->ok = smb_direct_daemon_init(state->ev, state->msg,
+ false, state->smb_direct_daemon_pid);
+ if (state->ok) {
+ DBG_WARNING("smb_direct_daemon restarted\n");
+ tevent_req_done(req);
+ return;
+ }
+
+ DBG_NOTICE("smb_direct_daemon startup failed, rescheduling\n");
+
+ subreq = tevent_wakeup_send(state, state->ev,
+ tevent_timeval_current_ofs(1, 0));
+ if (tevent_req_nomem(subreq, req)) {
+ DBG_ERR("smb_direct_daemon restart failed, giving up\n");
+ return;
+ }
+
+ tevent_req_set_callback(subreq, smb_direct_daemon_init_trigger, req);
+ return;
+}
+
+static bool smb_direct_daemon_init_recv(struct tevent_req *req)
+{
+ struct smb_direct_daemon_init_state *state = tevent_req_data(
+ req, struct smb_direct_daemon_init_state);
+ bool ok = state->ok;
+
+ tevent_req_received(req);
+
+ return ok;
+}
+
+static void smb_direct_daemon_started(struct tevent_req *req)
+{
+ bool ok;
+
+ ok = smb_direct_daemon_init_recv(req);
+ TALLOC_FREE(req);
+ if (!ok) {
+ DBG_ERR("Failed to restart smb_direct_daemon, giving up\n");
+ return;
+ }
+}
+
static void remove_child_pid(struct smbd_parent_context *parent,
pid_t pid,
bool unclean_shutdown)
return;
}
+ if (pid == parent->smb_direct_daemon_pid) {
+ struct tevent_req *req;
+ struct tevent_context *ev = messaging_tevent_context(
+ parent->msg_ctx);
+
+ DBG_WARNING("Restarting smb_direct_daemon\n");
+
+ req = smb_direct_daemon_init_send(
+ ev, ev, parent->msg_ctx, &parent->smb_direct_daemon_pid);
+ if (req == NULL) {
+ DBG_ERR("Failed to restart smb_direct_daemon\n");
+ return;
+ }
+ tevent_req_set_callback(req, smb_direct_daemon_started, parent);
+ return;
+
+ }
+
ok = cleanupdb_store_child(pid, unclean_shutdown);
if (!ok) {
DBG_ERR("cleanupdb_store_child failed\n");
exit_daemon("Samba cannot init the cleanupd", EACCES);
}
+ if (!smb_direct_daemon_init(ev_ctx, msg_ctx, interactive,
+ &parent->smb_direct_daemon_pid))
+ {
+ exit_daemon("Samba cannot init the smb_direct_daemon", EACCES);
+ }
+
if (!messaging_parent_dgm_cleanup_init(msg_ctx)) {
exit(1);
}