Esempio n. 1
0
void start_fssd(struct tevent_context *ev_ctx,
		struct messaging_context *msg_ctx)
{
	struct rpc_srv_callbacks fss_cb;
	NTSTATUS status;
	pid_t pid;
	bool ok;
	int rc;

	fss_cb.init = fss_init_cb;
	fss_cb.shutdown = fss_shutdown_cb;
	fss_cb.private_data = msg_ctx;

	DEBUG(1, ("Forking File Server Shadow-copy Daemon\n"));

	pid = fork();

	if (pid == -1) {
		DEBUG(0, ("failed to fork file server shadow-copy daemon [%s], "
			  "aborting ...\n", strerror(errno)));
		exit(1);
	}

	if (pid) {
		/* parent */
		return;
	}

	/* child */
	status = smbd_reinit_after_fork(msg_ctx, ev_ctx, true);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0,("reinit_after_fork() failed\n"));
		smb_panic("reinit_after_fork() failed");
	}

	fssd_reopen_logs();

	fssd_setup_sig_term_handler(ev_ctx);
	fssd_setup_sig_hup_handler(ev_ctx, msg_ctx);

	ok = serverid_register(procid_self(),
			       FLAG_MSG_GENERAL |
			       FLAG_MSG_PRINT_GENERAL);
	if (!ok) {
		DEBUG(0, ("Failed to register serverid in fssd!\n"));
		exit(1);
	}

	messaging_register(msg_ctx,
			   ev_ctx,
			   MSG_SMB_CONF_UPDATED,
			   fssd_smb_conf_updated);

	status = rpc_FileServerVssAgent_init(&fss_cb);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0, ("Failed to register fssd rpc inteface! (%s)\n",
			  nt_errstr(status)));
		exit(1);
	}

	/* case is normalized by smbd on connection */
	ok = setup_named_pipe_socket("fssagentrpc", ev_ctx, msg_ctx);
	if (!ok) {
		DEBUG(0, ("Failed to open fssd named pipe!\n"));
		exit(1);
	}

	DEBUG(1, ("File Server Shadow-copy Daemon Started (%d)\n",
		  (int)getpid()));

	/* loop forever */
	rc = tevent_loop_wait(ev_ctx);

	/* should not be reached */
	DEBUG(0,("tevent_loop_wait() exited with %d - %s\n",
		 rc, (rc == 0) ? "out of events" : strerror(errno)));

	exit(1);
}
Esempio n. 2
0
void start_epmd(struct tevent_context *ev_ctx,
		struct messaging_context *msg_ctx)
{
	struct rpc_srv_callbacks epmapper_cb;
	NTSTATUS status;
	pid_t pid;
	bool ok;
	int rc;

	epmapper_cb.init = NULL;
	epmapper_cb.shutdown = epmapper_shutdown_cb;
	epmapper_cb.private_data = NULL;

	DEBUG(1, ("Forking Endpoint Mapper Daemon\n"));

	pid = fork();

	if (pid == -1) {
		DEBUG(0, ("Failed to fork Endpoint Mapper [%s], aborting ...\n",
			  strerror(errno)));
		exit(1);
	}

	if (pid) {
		/* parent */
		return;
	}

	status = smbd_reinit_after_fork(msg_ctx, ev_ctx, true, "epmd");
	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(messaging_server_id(msg_ctx),
			       FLAG_MSG_GENERAL |
			       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(&epmapper_cb);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0, ("Failed to register epmd rpc interface! (%s)\n",
			  nt_errstr(status)));
		exit(1);
	}

	status = rpc_setup_tcpip_sockets(ev_ctx,
					 msg_ctx,
					 &ndr_table_epmapper,
					 NULL,
					 135);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0, ("Failed to open epmd tcpip sockets!\n"));
		exit(1);
	}

	ok = setup_dcerpc_ncalrpc_socket(ev_ctx,
					 msg_ctx,
					 "EPMAPPER",
					 srv_epmapper_delete_endpoints);
	if (!ok) {
		DEBUG(0, ("Failed to open epmd ncalrpc pipe!\n"));
		exit(1);
	}

	ok = setup_named_pipe_socket("epmapper", ev_ctx, msg_ctx);
	if (!ok) {
		DEBUG(0, ("Failed to open epmd named pipe!\n"));
		exit(1);
	}

	DEBUG(1, ("Endpoint Mapper Daemon Started (%u)\n", (unsigned int)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);
}
Esempio n. 3
0
static void smbd_accept_connection(struct tevent_context *ev,
				   struct tevent_fd *fde,
				   uint16_t flags,
				   void *private_data)
{
	struct smbd_open_socket *s = talloc_get_type_abort(private_data,
				     struct smbd_open_socket);
	struct messaging_context *msg_ctx = s->parent->msg_ctx;
	struct sockaddr_storage addr;
	socklen_t in_addrlen = sizeof(addr);
	int fd;
	pid_t pid = 0;

	fd = accept(s->fd, (struct sockaddr *)(void *)&addr,&in_addrlen);
	if (fd == -1 && errno == EINTR)
		return;

	if (fd == -1) {
		DEBUG(0,("accept: %s\n",
			 strerror(errno)));
		return;
	}

	if (s->parent->interactive) {
		reinit_after_fork(msg_ctx, ev, true, NULL);
		smbd_process(ev, msg_ctx, fd, true);
		exit_server_cleanly("end of interactive mode");
		return;
	}

	if (!allowable_number_of_smbd_processes(s->parent)) {
		close(fd);
		return;
	}

	pid = fork();
	if (pid == 0) {
		NTSTATUS status = NT_STATUS_OK;

		/*
		 * Can't use TALLOC_FREE here. Nulling out the argument to it
		 * would overwrite memory we've just freed.
		 */
		talloc_free(s->parent);
		s = NULL;

		/* Stop zombies, the parent explicitly handles
		 * them, counting worker smbds. */
		CatchChild();

		status = smbd_reinit_after_fork(msg_ctx, ev, true, NULL);
		if (!NT_STATUS_IS_OK(status)) {
			if (NT_STATUS_EQUAL(status,
					    NT_STATUS_TOO_MANY_OPENED_FILES)) {
				DEBUG(0,("child process cannot initialize "
					 "because too many files are open\n"));
				goto exit;
			}
			if (lp_clustering() &&
			    NT_STATUS_EQUAL(status,
			    NT_STATUS_INTERNAL_DB_ERROR)) {
				DEBUG(1,("child process cannot initialize "
					 "because connection to CTDB "
					 "has failed\n"));
				goto exit;
			}

			DEBUG(0,("reinit_after_fork() failed\n"));
			smb_panic("reinit_after_fork() failed");
		}

		smbd_process(ev, msg_ctx, fd, false);
	 exit:
		exit_server_cleanly("end of child");
		return;
	}

	if (pid < 0) {
		DEBUG(0,("smbd_accept_connection: fork() failed: %s\n",
			 strerror(errno)));
	}

	/* The parent doesn't need this socket */
	close(fd);

	/* Sun May 6 18:56:14 2001 [email protected]:
		Clear the closed fd info out of server_fd --
		and more importantly, out of client_fd in
		util_sock.c, to avoid a possible
		getpeername failure if we reopen the logs
		and use %I in the filename.
	*/

	if (pid != 0) {
		add_child_pid(s->parent, pid);
	}

	/* Force parent to check log size after
	 * spawning child.  Fix from
	 * [email protected].  The
	 * parent smbd will log to logserver.smb.  It
	 * writes only two messages for each child
	 * started/finished. But each child writes,
	 * say, 50 messages also in logserver.smb,
	 * begining with the debug_count of the
	 * parent, before the child opens its own log
	 * file logserver.client. In a worst case
	 * scenario the size of logserver.smb would be
	 * checked after about 50*50=2500 messages
	 * (ca. 100kb).
	 * */
	force_check_log_size();
}
Esempio n. 4
0
static bool smbd_scavenger_start(struct smbd_scavenger_state *state)
{
	struct server_id self = messaging_server_id(state->msg);
	struct tevent_fd *fde = NULL;
	int fds[2];
	int ret;
	uint64_t unique_id;
	bool ok;

	SMB_ASSERT(server_id_equal(&state->parent_id, &self));

	if (smbd_scavenger_running(state)) {
		struct server_id_buf tmp;
		DEBUG(10, ("scavenger %s already running\n",
			   server_id_str_buf(*state->scavenger_id,
					     &tmp)));
		return true;
	}

	if (state->scavenger_id != NULL) {
		struct server_id_buf tmp;
		DEBUG(10, ("scavenger zombie %s, cleaning up\n",
			   server_id_str_buf(*state->scavenger_id,
					     &tmp)));
		TALLOC_FREE(state->scavenger_id);
	}

	state->scavenger_id = talloc_zero(state, struct server_id);
	if (state->scavenger_id == NULL) {
		DEBUG(2, ("Out of memory\n"));
		goto fail;
	}
	talloc_set_destructor(state->scavenger_id,
			      smbd_scavenger_server_id_destructor);

	ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
	if (ret == -1) {
		DEBUG(2, ("socketpair failed: %s", strerror(errno)));
		goto fail;
	}

	smb_set_close_on_exec(fds[0]);
	smb_set_close_on_exec(fds[1]);

	unique_id = serverid_get_random_unique_id();

	ret = fork();
	if (ret == -1) {
		int err = errno;
		close(fds[0]);
		close(fds[1]);
		DEBUG(0, ("fork failed: %s", strerror(err)));
		goto fail;
	}

	if (ret == 0) {
		/* child */

		NTSTATUS status;

		close(fds[0]);

		set_my_unique_id(unique_id);

		status = smbd_reinit_after_fork(state->msg, state->ev, true);
		if (!NT_STATUS_IS_OK(status)) {
			DEBUG(2, ("reinit_after_fork failed: %s\n",
				  nt_errstr(status)));
			exit_server("reinit_after_fork failed");
			return false;
		}

		prctl_set_comment("smbd-scavenger");

		state->am_scavenger = true;
		*state->scavenger_id = messaging_server_id(state->msg);

		scavenger_setup_sig_term_handler(state->ev);

		serverid_register(*state->scavenger_id, FLAG_MSG_GENERAL);

		ok = scavenger_say_hello(fds[1], *state->scavenger_id);
		if (!ok) {
			DEBUG(2, ("scavenger_say_hello failed\n"));
			exit_server("scavenger_say_hello failed");
			return false;
		}

		fde = tevent_add_fd(state->ev, state->scavenger_id,
				    fds[1], TEVENT_FD_READ,
				    smbd_scavenger_parent_dead, state);
		if (fde == NULL) {
			DEBUG(2, ("tevent_add_fd(smbd_scavenger_parent_dead) "
				  "failed\n"));
			exit_server("tevent_add_fd(smbd_scavenger_parent_dead) "
				    "failed");
			return false;
		}
		tevent_fd_set_auto_close(fde);

		ret = smbd_scavenger_main(state);

		DEBUG(10, ("scavenger ended: %d\n", ret));
		exit_server_cleanly("scavenger ended");
		return false;
	}

	/* parent */
	close(fds[1]);

	ok = scavenger_wait_hello(fds[0], state->scavenger_id);
	if (!ok) {
		close(fds[0]);
		goto fail;
	}

	fde = tevent_add_fd(state->ev, state->scavenger_id,
			    fds[0], TEVENT_FD_READ,
			    smbd_scavenger_done, state);
	if (fde == NULL) {
		close(fds[0]);
		goto fail;
	}
	tevent_fd_set_auto_close(fde);

	return true;
fail:
	TALLOC_FREE(state->scavenger_id);
	return false;
}