Example #1
0
/*
  initialise a nbt_dgram_socket. The event_ctx is optional, if provided
  then operations will use that event context
*/
struct nbt_dgram_socket *nbt_dgram_socket_init(TALLOC_CTX *mem_ctx, 
					      struct tevent_context *event_ctx)
{
	struct nbt_dgram_socket *dgmsock;
	NTSTATUS status;

	dgmsock = talloc(mem_ctx, struct nbt_dgram_socket);
	if (dgmsock == NULL) goto failed;

	dgmsock->event_ctx = event_ctx;
	if (dgmsock->event_ctx == NULL) goto failed;

	status = socket_create("ip", SOCKET_TYPE_DGRAM, &dgmsock->sock, 0);
	if (!NT_STATUS_IS_OK(status)) goto failed;

	socket_set_option(dgmsock->sock, "SO_BROADCAST", "1");

	talloc_steal(dgmsock, dgmsock->sock);

	dgmsock->fde = tevent_add_fd(dgmsock->event_ctx, dgmsock,
				    socket_get_fd(dgmsock->sock), 0,
				    dgm_socket_handler, dgmsock);

	dgmsock->send_queue = NULL;
	dgmsock->incoming.handler = NULL;
	dgmsock->mailslot_handlers = NULL;
	
	return dgmsock;

failed:
	talloc_free(dgmsock);
	return NULL;
}
Example #2
0
static void setup_handlers(struct tevent_context *ev, int from_parent_fd) {
	struct tevent_fd *fde = NULL;
	struct tevent_signal *se = NULL;

	fde = tevent_add_fd(ev, ev, from_parent_fd, TEVENT_FD_READ,
		      prefork_pipe_handler, NULL);
	if (fde == NULL) {
		smb_panic("Failed to add fd handler after fork");
	}

	se = tevent_add_signal(ev,
			       ev,
			       SIGHUP,
			       0,
			       sighup_signal_handler,
			       NULL);
	if (se == NULL) {
		smb_panic("Failed to add SIGHUP handler after fork");
	}

	se = tevent_add_signal(ev,
			       ev,
			       SIGTERM,
			       0,
			       sigterm_signal_handler,
			       NULL);
	if (se == NULL) {
		smb_panic("Failed to add SIGTERM handler after fork");
	}
}
Example #3
0
/*
  setup the inotify handle - called the first time a watch is added on
  this context
*/
static NTSTATUS inotify_setup(struct sys_notify_context *ctx)
{
    struct inotify_private *in;

    if (!lp_parm_bool(-1, "notify", "inotify", True)) {
        return NT_STATUS_INVALID_SYSTEM_SERVICE;
    }

    in = talloc(ctx, struct inotify_private);
    NT_STATUS_HAVE_NO_MEMORY(in);
    in->fd = inotify_init();
    if (in->fd == -1) {
        DEBUG(0,("Failed to init inotify - %s\n", strerror(errno)));
        talloc_free(in);
        return map_nt_error_from_unix(errno);
    }
    in->ctx = ctx;
    in->watches = NULL;

    ctx->private_data = in;
    talloc_set_destructor(in, inotify_destructor);

    /* add a event waiting for the inotify fd to be readable */
    tevent_add_fd(ctx->ev, in, in->fd, TEVENT_FD_READ, inotify_handler, in);

    return NT_STATUS_OK;
}
Example #4
0
static void
mock_server_child(void *data)
{
    struct mock_server *mock = data;
    struct tevent_context *loop;
    struct sbus_connection *server;
    bool stop_server = false;
    TALLOC_CTX *ctx;

    ctx = talloc_new(NULL);
    loop = tevent_context_init(ctx);

    verify_eq (sbus_new_server(ctx, loop, mock->dbus_address, false,
                               &server, on_accept_connection, mock), EOK);

    tevent_add_fd(loop, ctx, mock->sync_fds[1], TEVENT_FD_READ,
                  on_sync_fd_written, &stop_server);

    /* Synchronization point: test_dbus_setup_mock() should connect */
    verify_eq (write(mock->sync_fds[1], "X", 1), 1);

    /* Do the loop */
    while(!stop_server) {
        verify_eq (tevent_loop_once(loop), 0);
    }

    /* TODO: sbus doesn't support cleanup of a server */

    talloc_free(ctx);
}
Example #5
0
static bool init_aio_threadpool(struct vfs_handle_struct *handle)
{
	struct fd_event *sock_event = NULL;
	int ret = 0;
	int num_threads;

	if (pool) {
		return true;
	}

	num_threads = aio_get_num_threads(handle);
	ret = pthreadpool_init(num_threads, &pool);
	if (ret) {
		errno = ret;
		return false;
	}
	sock_event = tevent_add_fd(server_event_context(),
				NULL,
				pthreadpool_signal_fd(pool),
				TEVENT_FD_READ,
				aio_pthread_handle_completion,
				NULL);
	if (sock_event == NULL) {
		pthreadpool_destroy(pool);
		pool = NULL;
		return false;
	}

	DEBUG(10,("init_aio_threadpool: initialized with up to %d threads\n",
			num_threads));

	return true;
}
Example #6
0
static PyObject *py_tevent_context_add_fd(TeventContext_Object *self, PyObject *args)
{
	int fd, flags;
	PyObject *handler;
	struct tevent_fd *tfd;
	TeventFd_Object *ret;

	if (!PyArg_ParseTuple(args, "iiO", &fd, &flags, &handler))
		return NULL;

	tfd = tevent_add_fd(self->ev, NULL, fd, flags, py_fd_handler, handler);
	if (tfd == NULL) {
		PyErr_SetNone(PyExc_RuntimeError);
		return NULL;
	}

	ret = PyObject_New(TeventFd_Object, &TeventFd_Type);
	if (ret == NULL) {
		talloc_free(tfd);
		return NULL;
	}
	ret->fd = tfd;

	return (PyObject *)ret;
}
Example #7
0
static bool init_aio_linux(struct vfs_handle_struct *handle)
{
	struct tevent_timer *te = NULL;

	if (event_fd != -1) {
		/* Already initialized. */
		return true;
	}

	/* Schedule a shutdown event for 30 seconds from now. */
	te = tevent_add_timer(handle->conn->sconn->ev_ctx,
				NULL,
				timeval_current_ofs(30, 0),
				aio_linux_housekeeping,
				NULL);

	if (te == NULL) {
		goto fail;
	}

	event_fd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
	if (event_fd == -1) {
		goto fail;
	}

	aio_read_event = tevent_add_fd(server_event_context(),
				NULL,
				event_fd,
				TEVENT_FD_READ,
				aio_linux_done,
				NULL);
	if (aio_read_event == NULL) {
		goto fail;
	}

	if (io_queue_init(lp_aio_max_threads(), &io_ctx)) {
		goto fail;
	}

	DEBUG(10,("init_aio_linux: initialized with up to %d events\n",
		  (int)lp_aio_max_threads()));

	return true;

  fail:

	DEBUG(10,("init_aio_linux: initialization failed\n"));

	TALLOC_FREE(te);
	TALLOC_FREE(aio_read_event);
	if (event_fd != -1) {
		close(event_fd);
		event_fd = -1;
	}
	memset(&io_ctx, '\0', sizeof(io_ctx));
	return false;
}
Example #8
0
static bool py_cli_state_setup_ev(struct py_cli_state *self)
{
	struct py_cli_thread *t = NULL;
	int ret;

	self->ev = tevent_context_init_byname(NULL, "poll_mt");
	if (self->ev == NULL) {
		goto fail;
	}
	samba_tevent_set_debug(self->ev, "pylibsmb_tevent_mt");
	tevent_set_trace_callback(self->ev, py_cli_state_trace_callback, self);

	self->thread_state = talloc_zero(NULL, struct py_cli_thread);
	if (self->thread_state == NULL) {
		goto fail;
	}
	t = self->thread_state;

	ret = pipe(t->shutdown_pipe);
	if (ret == -1) {
		goto fail;
	}
	t->shutdown_fde = tevent_add_fd(
		self->ev, self->ev, t->shutdown_pipe[0], TEVENT_FD_READ,
		py_cli_state_shutdown_handler, self);
	if (t->shutdown_fde == NULL) {
		goto fail;
	}

	PyEval_InitThreads();

	ret = pthread_create(&t->id, NULL, py_cli_state_poll_thread, self);
	if (ret != 0) {
		goto fail;
	}
	talloc_set_destructor(self->thread_state, py_cli_thread_destructor);
	return true;

fail:
	if (t != NULL) {
		TALLOC_FREE(t->shutdown_fde);

		if (t->shutdown_pipe[0] != -1) {
			close(t->shutdown_pipe[0]);
			t->shutdown_pipe[0] = -1;
		}
		if (t->shutdown_pipe[1] != -1) {
			close(t->shutdown_pipe[1]);
			t->shutdown_pipe[1] = -1;
		}
	}

	TALLOC_FREE(self->thread_state);
	TALLOC_FREE(self->ev);
	return false;
}
Example #9
0
/*
  called to create a new server task
*/
static void standard_new_task(struct tevent_context *ev, 
			      struct loadparm_context *lp_ctx,
			      const char *service_name,
			      void (*new_task)(struct tevent_context *, struct loadparm_context *lp_ctx, struct server_id , void *), 
			      void *private_data)
{
	pid_t pid;
	struct tevent_context *ev2;

	pid = fork();

	if (pid != 0) {
		/* parent or error code ... go back to the event loop */
		return;
	}

	pid = getpid();

	/* This is now the child code. We need a completely new event_context to work with */
	ev2 = s4_event_context_init(NULL);

	/* setup this as the default context */
	s4_event_context_set_default(ev2);

	/* the service has given us a private pointer that
	   encapsulates the context it needs for this new connection -
	   everything else will be freed */
	talloc_steal(ev2, private_data);

	/* this will free all the listening sockets and all state that
	   is not associated with this new connection */
	talloc_free(ev);

	/* ldb/tdb need special fork handling */
	ldb_wrap_fork_hook();

	tevent_add_fd(ev2, ev2, child_pipe[0], TEVENT_FD_READ,
		      standard_pipe_handler, NULL);
	close(child_pipe[1]);

	/* Ensure that the forked children do not expose identical random streams */
	set_need_random_reseed();

	setproctitle("task %s server_id[%d]", service_name, pid);

	/* setup this new task.  Cluster ID is PID based for this process modal */
	new_task(ev2, lp_ctx, cluster_id(pid, 0), private_data);

	/* we can't return to the top level here, as that event context is gone,
	   so we now process events in the new event context until there are no
	   more to process */	   
	event_loop_wait(ev2);

	talloc_free(ev2);
	exit(0);
}
Example #10
0
bool setup_named_pipe_socket(const char *pipe_name,
			     struct tevent_context *ev_ctx,
			     struct messaging_context *msg_ctx)
{
	struct dcerpc_ncacn_listen_state *state;
	struct tevent_fd *fde;
	int rc;

	state = talloc(ev_ctx, struct dcerpc_ncacn_listen_state);
	if (!state) {
		DEBUG(0, ("Out of memory\n"));
		return false;
	}
	state->ep.name = talloc_strdup(state, pipe_name);
	if (state->ep.name == NULL) {
		DEBUG(0, ("Out of memory\n"));
		goto out;
	}
	state->fd = create_named_pipe_socket(pipe_name);
	if (state->fd == -1) {
		goto out;
	}

	rc = listen(state->fd, 5);
	if (rc < 0) {
		DEBUG(0, ("Failed to listen on pipe socket %s: %s\n",
			  pipe_name, strerror(errno)));
		goto out;
	}

	state->ev_ctx = ev_ctx;
	state->msg_ctx = msg_ctx;

	DEBUG(10, ("Openened pipe socket fd %d for %s\n",
		   state->fd, pipe_name));

	fde = tevent_add_fd(ev_ctx,
			    state, state->fd, TEVENT_FD_READ,
			    named_pipe_listener, state);
	if (!fde) {
		DEBUG(0, ("Failed to add event handler!\n"));
		goto out;
	}

	tevent_fd_set_auto_close(fde);
	return true;

out:
	if (state->fd != -1) {
		close(state->fd);
	}
	TALLOC_FREE(state);
	return false;
}
Example #11
0
File: nmbd.c Project: sprymak/samba
static bool nmbd_setup_stdin_handler(struct messaging_context *msg, bool foreground)
{
	if (foreground) {
		/* if we are running in the foreground then look for
		   EOF on stdin, and exit if it happens. This allows
		   us to die if the parent process dies
		*/
		tevent_add_fd(nmbd_event_context(), nmbd_event_context(), 0, TEVENT_FD_READ, nmbd_stdin_handler, msg);
	}

	return true;
}
Example #12
0
static bool test_event_context_threaded(struct torture_context *test,
					const void *test_data)
{
	struct tevent_context *ev;
	struct tevent_timer *te;
	struct tevent_fd *fde;
	pthread_t poll_thread;
	int fds[2];
	int ret;
	char c = 0;

	ev = tevent_context_init_byname(test, "poll_mt");
	torture_assert(test, ev != NULL, "poll_mt not supported");

	tevent_set_trace_callback(ev, test_event_threaded_trace, NULL);

	te = tevent_add_timer(ev, ev, timeval_current_ofs(5, 0),
			      test_event_threaded_timer, NULL);
	torture_assert(test, te != NULL, "Could not add timer");

	ret = pthread_create(&poll_thread, NULL, test_event_poll_thread, ev);
	torture_assert(test, ret == 0, "Could not create poll thread");

	ret = pipe(fds);
	torture_assert(test, ret == 0, "Could not create pipe");

	poll(NULL, 0, 100);

	test_event_threaded_lock();

	fde = tevent_add_fd(ev, ev, fds[0], TEVENT_FD_READ,
			    test_event_threaded_read_handler, &fds[0]);
	torture_assert(test, fde != NULL, "Could not add fd event");

	test_event_threaded_unlock();

	poll(NULL, 0, 100);

	write(fds[1], &c, 1);

	poll(NULL, 0, 100);

	test_event_threaded_lock();
	do_shutdown = true;
	test_event_threaded_unlock();

	write(fds[1], &c, 1);

	ret = pthread_join(poll_thread, NULL);
	torture_assert(test, ret == 0, "pthread_join failed");

	return true;
}
Example #13
0
/*
  called to create a new server task
*/
static void standard_new_task(struct tevent_context *ev, 
			      struct loadparm_context *lp_ctx,
			      const char *service_name,
			      void (*new_task)(struct tevent_context *, struct loadparm_context *lp_ctx, struct server_id , void *),
			      void *private_data)
{
	pid_t pid;

	pid = fork();

	if (pid != 0) {
		/* parent or error code ... go back to the event loop */
		return;
	}

	pid = getpid();

	/* this will free all the listening sockets and all state that
	   is not associated with this new connection */
	if (tevent_re_initialise(ev) != 0) {
		smb_panic("Failed to re-initialise tevent after fork");
	}

	/* ldb/tdb need special fork handling */
	ldb_wrap_fork_hook();

	tevent_add_fd(ev, ev, child_pipe[0], TEVENT_FD_READ,
		      standard_pipe_handler, NULL);
	close(child_pipe[1]);

	/* Ensure that the forked children do not expose identical random streams */
	set_need_random_reseed();

	setproctitle("task %s server_id[%d]", service_name, (int)pid);

	/* setup this new task.  Cluster ID is PID based for this process modal */
	new_task(ev, lp_ctx, cluster_id(pid, 0), private_data);

	/* we can't return to the top level here, as that event context is gone,
	   so we now process events in the new event context until there are no
	   more to process */	   
	event_loop_wait(ev);

	talloc_free(ev);
	exit(0);
}
Example #14
0
struct kernel_oplocks *irix_init_kernel_oplocks(struct smbd_server_connection *sconn)
{
    struct kernel_oplocks *_ctx;
    struct irix_oplocks_context *ctx;
    int pfd[2];

    if (!irix_oplocks_available())
        return NULL;

    _ctx = talloc_zero(sconn, struct kernel_oplocks);
    if (!_ctx) {
        return NULL;
    }

    ctx = talloc_zero(_ctx, struct irix_oplocks_context);
    if (!ctx) {
        talloc_free(_ctx);
        return NULL;
    }
    _ctx->ops = &irix_koplocks;
    _ctx->private_data = ctx;
    ctx->ctx = _ctx;
    ctx->sconn = sconn;

    if(pipe(pfd) != 0) {
        talloc_free(_ctx);
        DEBUG(0,("setup_kernel_oplock_pipe: Unable to create pipe. "
                 "Error was %s\n", strerror(errno) ));
        return False;
    }

    ctx->read_fd = pfd[0];
    ctx->write_fd = pfd[1];

    ctx->read_fde = tevent_add_fd(sconn->ev_ctx,
                                  ctx,
                                  ctx->read_fd,
                                  TEVENT_FD_READ,
                                  irix_oplocks_read_fde_handler,
                                  ctx);
    return _ctx;
}
Example #15
0
/*
  setup the fd used by the queue
 */
int ctdb_queue_set_fd(struct ctdb_queue *queue, int fd)
{
	queue->fd = fd;
	talloc_free(queue->fde);
	queue->fde = NULL;

	if (fd != -1) {
		queue->fde = tevent_add_fd(queue->ctdb->ev, queue, fd,
					   TEVENT_FD_READ,
					   queue_io_handler, queue);
		if (queue->fde == NULL) {
			return -1;
		}
		tevent_fd_set_auto_close(queue->fde);

		if (queue->out_queue) {
			TEVENT_FD_WRITEABLE(queue->fde);
		}
	}

	return 0;
}
Example #16
0
static bool init_aio_threadpool(struct event_context *ev_ctx,
				struct pthreadpool **pp_pool,
				void (*completion_fn)(struct event_context *,
						struct fd_event *,
						uint16,
						void *))
{
	struct fd_event *sock_event = NULL;
	int ret = 0;

	if (*pp_pool) {
		return true;
	}

	ret = pthreadpool_init(aio_pending_size, pp_pool);
	if (ret) {
		errno = ret;
		return false;
	}
	sock_event = tevent_add_fd(ev_ctx,
				NULL,
				pthreadpool_signal_fd(*pp_pool),
				TEVENT_FD_READ,
				completion_fn,
				NULL);
	if (sock_event == NULL) {
		pthreadpool_destroy(*pp_pool);
		*pp_pool = NULL;
		return false;
	}

	DEBUG(10,("init_aio_threadpool: initialized with up to %d threads\n",
		  aio_pending_size));

	return true;
}
Example #17
0
static bool nmbd_setup_stdin_handler(struct messaging_context *msg, bool foreground)
{
	if (foreground) {
		/* if we are running in the foreground then look for
		   EOF on stdin, and exit if it happens. This allows
		   us to die if the parent process dies
		   Only do this on a pipe or socket, no other device.
		*/
		struct stat st;
		if (fstat(0, &st) != 0) {
			return false;
		}
		if (S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode)) {
			tevent_add_fd(nmbd_event_context(),
				nmbd_event_context(),
				0,
				TEVENT_FD_READ,
				nmbd_stdin_handler,
				msg);
		}
	}

	return true;
}
Example #18
0
static bool init_aio_threadpool(struct tevent_context *ev_ctx,
				struct pthreadpool_pipe **pp_pool,
				void (*completion_fn)(struct tevent_context *,
						struct tevent_fd *,
						uint16_t,
						void *))
{
	struct tevent_fd *sock_event = NULL;
	int ret = 0;

	if (*pp_pool) {
		return true;
	}

	ret = pthreadpool_pipe_init(lp_aio_max_threads(), pp_pool);
	if (ret) {
		errno = ret;
		return false;
	}
	sock_event = tevent_add_fd(ev_ctx,
				NULL,
				pthreadpool_pipe_signal_fd(*pp_pool),
				TEVENT_FD_READ,
				completion_fn,
				NULL);
	if (sock_event == NULL) {
		pthreadpool_pipe_destroy(*pp_pool);
		*pp_pool = NULL;
		return false;
	}

	DEBUG(10,("init_aio_threadpool: initialized with up to %d threads\n",
		  (int)lp_aio_max_threads()));

	return true;
}
Example #19
0
/*
  run a command as a child process, with a timeout.

  any stdout/stderr from the child will appear in the Samba logs with
  the specified log levels
 */
struct tevent_req *samba_runcmd_send(TALLOC_CTX *mem_ctx,
				     struct tevent_context *ev,
				     struct timeval endtime,
				     int stdout_log_level,
				     int stderr_log_level,
				     const char * const *argv0, ...)
{
	struct tevent_req *req;
	struct samba_runcmd_state *state;
	int p1[2], p2[2], p3[2];
	char **argv;
	va_list ap;

	if (argv0 == NULL) {
		return NULL;
	}

	req = tevent_req_create(mem_ctx, &state,
				struct samba_runcmd_state);
	if (req == NULL) {
		return NULL;
	}

	state->stdout_log_level = stdout_log_level;
	state->stderr_log_level = stderr_log_level;
	state->fd_stdin = -1;

	state->arg0 = talloc_strdup(state, argv0[0]);
	if (tevent_req_nomem(state->arg0, req)) {
		return tevent_req_post(req, ev);
	}

	if (pipe(p1) != 0) {
		tevent_req_error(req, errno);
		return tevent_req_post(req, ev);
	}
	if (pipe(p2) != 0) {
		close(p1[0]);
		close(p1[1]);
		tevent_req_error(req, errno);
		return tevent_req_post(req, ev);
	}
	if (pipe(p3) != 0) {
		close(p1[0]);
		close(p1[1]);
		close(p2[0]);
		close(p2[1]);
		tevent_req_error(req, errno);
		return tevent_req_post(req, ev);
	}

	state->tfork = tfork_create();
	if (state->tfork == NULL) {
		close(p1[0]);
		close(p1[1]);
		close(p2[0]);
		close(p2[1]);
		close(p3[0]);
		close(p3[1]);
		tevent_req_error(req, errno);
		return tevent_req_post(req, ev);
	}
	state->pid = tfork_child_pid(state->tfork);
	if (state->pid != 0) {
		/* the parent */
		close(p1[1]);
		close(p2[1]);
		close(p3[0]);
		state->fd_stdout = p1[0];
		state->fd_stderr = p2[0];
		state->fd_stdin  = p3[1];
		state->fd_status = tfork_event_fd(state->tfork);

		set_blocking(state->fd_stdout, false);
		set_blocking(state->fd_stderr, false);
		set_blocking(state->fd_stdin,  false);
		set_blocking(state->fd_status, false);

		smb_set_close_on_exec(state->fd_stdin);
		smb_set_close_on_exec(state->fd_stdout);
		smb_set_close_on_exec(state->fd_stderr);
		smb_set_close_on_exec(state->fd_status);

		tevent_req_set_cleanup_fn(req, samba_runcmd_cleanup_fn);

		state->fde_stdout = tevent_add_fd(ev, state,
						  state->fd_stdout,
						  TEVENT_FD_READ,
						  samba_runcmd_io_handler,
						  req);
		if (tevent_req_nomem(state->fde_stdout, req)) {
			close(state->fd_stdout);
			close(state->fd_stderr);
			close(state->fd_status);
			return tevent_req_post(req, ev);
		}
		tevent_fd_set_auto_close(state->fde_stdout);

		state->fde_stderr = tevent_add_fd(ev, state,
						  state->fd_stderr,
						  TEVENT_FD_READ,
						  samba_runcmd_io_handler,
						  req);
		if (tevent_req_nomem(state->fde_stdout, req)) {
			close(state->fd_stdout);
			close(state->fd_stderr);
			close(state->fd_status);
			return tevent_req_post(req, ev);
		}
		tevent_fd_set_auto_close(state->fde_stderr);

		state->fde_status = tevent_add_fd(ev, state,
						  state->fd_status,
						  TEVENT_FD_READ,
						  samba_runcmd_io_handler,
						  req);
		if (tevent_req_nomem(state->fde_stdout, req)) {
			close(state->fd_stdout);
			close(state->fd_stderr);
			close(state->fd_status);
			return tevent_req_post(req, ev);
		}
		tevent_fd_set_auto_close(state->fde_status);

		if (!timeval_is_zero(&endtime)) {
			tevent_req_set_endtime(req, ev, endtime);
		}

		return req;
	}

	/* the child */
	close(p1[0]);
	close(p2[0]);
	close(p3[1]);
	close(0);
	close(1);
	close(2);

	/* we want to ensure that all of the network sockets we had
	   open are closed */
	tevent_re_initialise(ev);

	/* setup for logging to go to the parents debug log */
	dup2(p3[0], 0);
	dup2(p1[1], 1);
	dup2(p2[1], 2);

	close(p1[1]);
	close(p2[1]);
	close(p3[0]);

	argv = str_list_copy(state, discard_const_p(const char *, argv0));
	if (!argv) {
		fprintf(stderr, "Out of memory in child\n");
		_exit(255);
	}

	va_start(ap, argv0);
	while (1) {
		const char **l;
		char *arg = va_arg(ap, char *);
		if (arg == NULL) break;
		l = discard_const_p(const char *, argv);
		l = str_list_add(l, arg);
		if (l == NULL) {
			fprintf(stderr, "Out of memory in child\n");
			_exit(255);
		}
		argv = discard_const_p(char *, l);
	}
	va_end(ap);

	(void)execvp(state->arg0, argv);
	fprintf(stderr, "Failed to exec child - %s\n", strerror(errno));
	_exit(255);
	return NULL;
}
Example #20
0
static bool smbd_open_one_socket(struct smbd_parent_context *parent,
				 struct tevent_context *ev_ctx,
				 struct messaging_context *msg_ctx,
				 const struct sockaddr_storage *ifss,
				 uint16_t port)
{
	struct smbd_open_socket *s;

	s = talloc(parent, struct smbd_open_socket);
	if (!s) {
		return false;
	}

	s->parent = parent;
	s->fd = open_socket_in(SOCK_STREAM,
			       port,
			       parent->sockets == NULL ? 0 : 2,
			       ifss,
			       true);
	if (s->fd == -1) {
		DEBUG(0,("smbd_open_once_socket: open_socket_in: "
			"%s\n", strerror(errno)));
		TALLOC_FREE(s);
		/*
		 * We ignore an error here, as we've done before
		 */
		return true;
	}

	/* ready to listen */
	set_socket_options(s->fd, "SO_KEEPALIVE");
	set_socket_options(s->fd, lp_socket_options());

	/* Set server socket to
	 * non-blocking for the accept. */
	set_blocking(s->fd, False);

	if (listen(s->fd, SMBD_LISTEN_BACKLOG) == -1) {
		DEBUG(0,("open_sockets_smbd: listen: "
			"%s\n", strerror(errno)));
			close(s->fd);
		TALLOC_FREE(s);
		return false;
	}

	s->msg_ctx = msg_ctx;
	s->fde = tevent_add_fd(ev_ctx,
			       s,
			       s->fd, TEVENT_FD_READ,
			       smbd_accept_connection,
			       s);
	if (!s->fde) {
		DEBUG(0,("open_sockets_smbd: "
			 "tevent_add_fd: %s\n",
			 strerror(errno)));
		close(s->fd);
		TALLOC_FREE(s);
		return false;
	}
	tevent_fd_set_close_fn(s->fde, smbd_open_socket_close_fn);

	DLIST_ADD_END(parent->sockets, s, struct smbd_open_socket *);

	return true;
}
static bool fdpass2_parent(pid_t child_pid, int ready_fd)
{
	struct tevent_context *ev = NULL;
	struct messaging_context *msg_ctx = NULL;
	bool retval = false;
	int up_pipe[2];
	int down_pipe[2];
	int pass_fds[2] = { 0 };
	int ret;
	NTSTATUS status;
	struct server_id dst;
	TALLOC_CTX *frame = talloc_stackframe();
	uint8_t c1 = 1, c2, c;
	ssize_t bytes;
	struct iovec iov;
	DATA_BLOB blob;
	struct tevent_fd *child_done_fde;
	struct child_done_state child_state;

	ev = samba_tevent_context_init(frame);
	if (ev == NULL) {
		fprintf(stderr, "parent: tevent_context_init failed\n");
		goto done;
	}

	msg_ctx = messaging_init(ev, ev);
	if (msg_ctx == NULL) {
		fprintf(stderr, "parent: messaging_init failed\n");
		goto done;
	}

	/* wait util the child is ready to receive messages */
	bytes = read(ready_fd, &c, 1);
	if (bytes != 1) {
		perror("parent: read from ready_fd failed");
		goto done;
	}

	ret = pipe(up_pipe);
	if (ret != 0) {
		perror("parent: pipe failed for up_pipe");
		goto done;
	}

	ret = pipe(down_pipe);
	if (ret != 0) {
		perror("parent: pipe failed for down_pipe");
		goto done;
	}

	child_state.fd = ready_fd;
	child_state.done = false;

	child_done_fde = tevent_add_fd(ev, ev, ready_fd, TEVENT_FD_READ,
				       child_done_cb, &child_state);
	if (child_done_fde == NULL) {
		fprintf(stderr,
			"parent: failed tevent_add_fd for child done\n");
		goto done;
	}

	pass_fds[0] = up_pipe[0];
	pass_fds[1] = down_pipe[1];

	dst = messaging_server_id(msg_ctx);
	dst.pid = child_pid;

	/*
	 * Send a certain payload with the fds, to test to test
	 * that fd-passing works when we have fragmentation and
	 * re-assembly of the datagrams.
	 */
	blob = data_blob_talloc_zero(frame, 1000*1000);
	iov.iov_base = blob.data;
	iov.iov_len  = blob.length;

	status = messaging_send_iov(msg_ctx, dst, MSG_TORTURE_FDPASS2, &iov, 1,
				    pass_fds, 2);
	if (!NT_STATUS_IS_OK(status)) {
		fprintf(stderr, "parent: messaging_send_iov failed: %s\n",
			nt_errstr(status));
		goto done;
	}

	printf("parent: waiting for child to confirm\n");

	while (!child_state.done) {
		ret = tevent_loop_once(ev);
		if (ret != 0) {
			fprintf(stderr, "parent: tevent_loop_once failed\n");
			goto done;
		}
	}

	printf("parent: child confirmed\n");

	close(up_pipe[0]);
	close(down_pipe[1]);

	bytes = write(up_pipe[1], &c1, 1);
	if (bytes != 1) {
		perror("parent: write to up pipe failed");
		goto done;
	}

	bytes = read(down_pipe[0], &c2, 1);
	if (bytes != 1) {
		perror("parent: read from down pipe failed");
		goto done;
	}

	if (c1 != c2) {
		fprintf(stderr, "parent: c1[%d] != c2[%d]\n", c1, c2);
		goto done;
	}

	ret = waitpid(child_pid, NULL, 0);
	if (ret == -1) {
		perror("parent: waitpid failed");
		goto done;
	}

	retval = true;

done:
	TALLOC_FREE(frame);
	return retval;
}
Example #22
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)) {
		DEBUG(10, ("scavenger %s already running\n",
			   server_id_str(talloc_tos(),
					 state->scavenger_id)));
		return true;
	}

	if (state->scavenger_id != NULL) {
		DEBUG(10, ("scavenger zombie %s, cleaning up\n",
			   server_id_str(talloc_tos(),
					 state->scavenger_id)));
		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]);

		am_parent = NULL;

		set_my_unique_id(unique_id);

		status = 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;
}
Example #23
0
/*
 main server.
*/
static int binary_smbd_main(const char *binary_name, int argc, const char *argv[])
{
	bool opt_daemon = false;
	bool opt_interactive = false;
	int opt;
	poptContext pc;
#define _MODULE_PROTO(init) extern NTSTATUS init(void);
	STATIC_service_MODULES_PROTO;
	init_module_fn static_init[] = { STATIC_service_MODULES };
	init_module_fn *shared_init;
	struct tevent_context *event_ctx;
	uint16_t stdin_event_flags;
	NTSTATUS status;
	const char *model = "standard";
	int max_runtime = 0;
	enum {
		OPT_DAEMON = 1000,
		OPT_INTERACTIVE,
		OPT_PROCESS_MODEL,
		OPT_SHOW_BUILD
	};
	struct poptOption long_options[] = {
		POPT_AUTOHELP
		{"daemon", 'D', POPT_ARG_NONE, NULL, OPT_DAEMON,
		 "Become a daemon (default)", NULL },
		{"interactive",	'i', POPT_ARG_NONE, NULL, OPT_INTERACTIVE,
		 "Run interactive (not a daemon)", NULL},
		{"model", 'M', POPT_ARG_STRING,	NULL, OPT_PROCESS_MODEL, 
		 "Select process model", "MODEL"},
		{"maximum-runtime",0, POPT_ARG_INT, &max_runtime, 0, 
		 "set maximum runtime of the server process, till autotermination", "seconds"},
		{"show-build", 'b', POPT_ARG_NONE, NULL, OPT_SHOW_BUILD, "show build info", NULL },
		POPT_COMMON_SAMBA
		POPT_COMMON_VERSION
		{ NULL }
	};

	pc = poptGetContext(binary_name, argc, argv, long_options, 0);
	while((opt = poptGetNextOpt(pc)) != -1) {
		switch(opt) {
		case OPT_DAEMON:
			opt_daemon = true;
			break;
		case OPT_INTERACTIVE:
			opt_interactive = true;
			break;
		case OPT_PROCESS_MODEL:
			model = poptGetOptArg(pc);
			break;
		case OPT_SHOW_BUILD:
			show_build();
			break;
		default:
			fprintf(stderr, "\nInvalid option %s: %s\n\n",
				  poptBadOption(pc, 0), poptStrerror(opt));
			poptPrintUsage(pc, stderr, 0);
			return 1;
		}
	}

	if (opt_daemon && opt_interactive) {
		fprintf(stderr,"\nERROR: "
			  "Option -i|--interactive is not allowed together with -D|--daemon\n\n");
		poptPrintUsage(pc, stderr, 0);
		return 1;
	} else if (!opt_interactive) {
		/* default is --daemon */
		opt_daemon = true;
	}

	poptFreeContext(pc);

	setup_logging(binary_name, opt_interactive?DEBUG_STDOUT:DEBUG_FILE);
	setup_signals();

	/* we want total control over the permissions on created files,
	   so set our umask to 0 */
	umask(0);

	DEBUG(0,("%s version %s started.\n", binary_name, SAMBA_VERSION_STRING));
	DEBUGADD(0,("Copyright Andrew Tridgell and the Samba Team 1992-2011\n"));

	if (sizeof(uint16_t) < 2 || sizeof(uint32_t) < 4 || sizeof(uint64_t) < 8) {
		DEBUG(0,("ERROR: Samba is not configured correctly for the word size on your machine\n"));
		DEBUGADD(0,("sizeof(uint16_t) = %u, sizeof(uint32_t) %u, sizeof(uint64_t) = %u\n",
			    (unsigned int)sizeof(uint16_t), (unsigned int)sizeof(uint32_t), (unsigned int)sizeof(uint64_t)));
		return 1;
	}

	if (opt_daemon) {
		DEBUG(3,("Becoming a daemon.\n"));
		become_daemon(true, false, false);
	}

	cleanup_tmp_files(cmdline_lp_ctx);

	if (!directory_exist(lpcfg_lockdir(cmdline_lp_ctx))) {
		mkdir(lpcfg_lockdir(cmdline_lp_ctx), 0755);
	}

	pidfile_create(lpcfg_piddir(cmdline_lp_ctx), binary_name);

	/* Set up a database to hold a random seed, in case we don't
	 * have /dev/urandom */
	if (!randseed_init(talloc_autofree_context(), cmdline_lp_ctx)) {
		return 1;
	}

	if (lpcfg_server_role(cmdline_lp_ctx) == ROLE_DOMAIN_CONTROLLER) {
		if (!open_schannel_session_store(talloc_autofree_context(), lpcfg_private_dir(cmdline_lp_ctx))) {
			DEBUG(0,("ERROR: Samba cannot open schannel store for secured NETLOGON operations.\n"));
			exit(1);
		}
	}

	gensec_init(); /* FIXME: */

	ntptr_init();	/* FIXME: maybe run this in the initialization function 
						of the spoolss RPC server instead? */

	ntvfs_init(cmdline_lp_ctx); 	/* FIXME: maybe run this in the initialization functions 
						of the SMB[,2] server instead? */

	process_model_init(cmdline_lp_ctx); 

	shared_init = load_samba_modules(NULL, "service");

	run_init_functions(static_init);
	run_init_functions(shared_init);

	talloc_free(shared_init);
	
	/* the event context is the top level structure in smbd. Everything else
	   should hang off that */
	event_ctx = s4_event_context_init(talloc_autofree_context());

	if (event_ctx == NULL) {
		DEBUG(0,("Initializing event context failed\n"));
		return 1;
	}

	if (opt_interactive) {
		/* terminate when stdin goes away */
		stdin_event_flags = TEVENT_FD_READ;
	} else {
		/* stay alive forever */
		stdin_event_flags = 0;
	}

	/* catch EOF on stdin */
#ifdef SIGTTIN
	signal(SIGTTIN, SIG_IGN);
#endif
	tevent_add_fd(event_ctx, event_ctx, 0, stdin_event_flags,
		      server_stdin_handler,
		      discard_const(binary_name));

	if (max_runtime) {
		DEBUG(0,("Called with maxruntime %d - current ts %llu\n",
		      max_runtime, (unsigned long long) time(NULL)));
		tevent_add_timer(event_ctx, event_ctx,
				 timeval_current_ofs(max_runtime, 0),
				 max_runtime_handler,
				 discard_const(binary_name));
	}

	prime_ldb_databases(event_ctx);

	status = setup_parent_messaging(event_ctx, cmdline_lp_ctx);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0,("Failed to setup parent messaging - %s\n", nt_errstr(status)));
		return 1;
	}

	DEBUG(0,("%s: using '%s' process model\n", binary_name, model));

	status = server_service_startup(event_ctx, cmdline_lp_ctx, model, 
					lpcfg_server_services(cmdline_lp_ctx));
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0,("Starting Services failed - %s\n", nt_errstr(status)));
		return 1;
	}

	/* wait for events - this is where smbd sits for most of its
	   life */
	tevent_loop_wait(event_ctx);

	/* as everything hangs off this event context, freeing it
	   should initiate a clean shutdown of all services */
	talloc_free(event_ctx);

	return 0;
}
Example #24
0
 int main(int argc,const char *argv[])
{
	/* shall I run as a daemon */
	bool is_daemon = false;
	bool interactive = false;
	bool Fork = true;
	bool no_process_group = false;
	bool log_stdout = false;
	char *ports = NULL;
	char *profile_level = NULL;
	int opt;
	poptContext pc;
	bool print_build_options = False;
        enum {
		OPT_DAEMON = 1000,
		OPT_INTERACTIVE,
		OPT_FORK,
		OPT_NO_PROCESS_GROUP,
		OPT_LOG_STDOUT
	};
	struct poptOption long_options[] = {
	POPT_AUTOHELP
	{"daemon", 'D', POPT_ARG_NONE, NULL, OPT_DAEMON, "Become a daemon (default)" },
	{"interactive", 'i', POPT_ARG_NONE, NULL, OPT_INTERACTIVE, "Run interactive (not a daemon)"},
	{"foreground", 'F', POPT_ARG_NONE, NULL, OPT_FORK, "Run daemon in foreground (for daemontools, etc.)" },
	{"no-process-group", '\0', POPT_ARG_NONE, NULL, OPT_NO_PROCESS_GROUP, "Don't create a new process group" },
	{"log-stdout", 'S', POPT_ARG_NONE, NULL, OPT_LOG_STDOUT, "Log to stdout" },
	{"build-options", 'b', POPT_ARG_NONE, NULL, 'b', "Print build options" },
	{"port", 'p', POPT_ARG_STRING, &ports, 0, "Listen on the specified ports"},
	{"profiling-level", 'P', POPT_ARG_STRING, &profile_level, 0, "Set profiling level","PROFILE_LEVEL"},
	POPT_COMMON_SAMBA
	POPT_TABLEEND
	};
	struct smbd_parent_context *parent = NULL;
	TALLOC_CTX *frame;
	NTSTATUS status;
	struct tevent_context *ev_ctx;
	struct messaging_context *msg_ctx;
	struct server_id server_id;
	struct tevent_signal *se;
	int profiling_level;
	char *np_dir = NULL;
	static const struct smbd_shim smbd_shim_fns =
	{
		.cancel_pending_lock_requests_by_fid = smbd_cancel_pending_lock_requests_by_fid,
		.send_stat_cache_delete_message = smbd_send_stat_cache_delete_message,
		.change_to_root_user = smbd_change_to_root_user,
		.become_authenticated_pipe_user = smbd_become_authenticated_pipe_user,
		.unbecome_authenticated_pipe_user = smbd_unbecome_authenticated_pipe_user,

		.contend_level2_oplocks_begin = smbd_contend_level2_oplocks_begin,
		.contend_level2_oplocks_end = smbd_contend_level2_oplocks_end,

		.become_root = smbd_become_root,
		.unbecome_root = smbd_unbecome_root,

		.exit_server = smbd_exit_server,
		.exit_server_cleanly = smbd_exit_server_cleanly,
	};

	/*
	 * Do this before any other talloc operation
	 */
	talloc_enable_null_tracking();
	frame = talloc_stackframe();

	setup_logging(argv[0], DEBUG_DEFAULT_STDOUT);

	smb_init_locale();

	set_smbd_shim(&smbd_shim_fns);

	smbd_init_globals();

	TimeInit();

#ifdef HAVE_SET_AUTH_PARAMETERS
	set_auth_parameters(argc,argv);
#endif

	pc = poptGetContext("smbd", argc, argv, long_options, 0);
	while((opt = poptGetNextOpt(pc)) != -1) {
		switch (opt)  {
		case OPT_DAEMON:
			is_daemon = true;
			break;
		case OPT_INTERACTIVE:
			interactive = true;
			break;
		case OPT_FORK:
			Fork = false;
			break;
		case OPT_NO_PROCESS_GROUP:
			no_process_group = true;
			break;
		case OPT_LOG_STDOUT:
			log_stdout = true;
			break;
		case 'b':
			print_build_options = True;
			break;
		default:
			d_fprintf(stderr, "\nInvalid option %s: %s\n\n",
				  poptBadOption(pc, 0), poptStrerror(opt));
			poptPrintUsage(pc, stderr, 0);
			exit(1);
		}
	}
	poptFreeContext(pc);

	if (interactive) {
		Fork = False;
		log_stdout = True;
	}

	if (log_stdout) {
		setup_logging(argv[0], DEBUG_STDOUT);
	} else {
		setup_logging(argv[0], DEBUG_FILE);
	}

	if (print_build_options) {
		build_options(True); /* Display output to screen as well as debug */
		exit(0);
	}

#ifdef HAVE_SETLUID
	/* needed for SecureWare on SCO */
	setluid(0);
#endif

	set_remote_machine_name("smbd", False);

	if (interactive && (DEBUGLEVEL >= 9)) {
		talloc_enable_leak_report();
	}

	if (log_stdout && Fork) {
		DEBUG(0,("ERROR: Can't log to stdout (-S) unless daemon is in foreground (-F) or interactive (-i)\n"));
		exit(1);
	}

	/* we want to re-seed early to prevent time delays causing
           client problems at a later date. (tridge) */
	generate_random_buffer(NULL, 0);

	/* get initial effective uid and gid */
	sec_init();

	/* make absolutely sure we run as root - to handle cases where people
	   are crazy enough to have it setuid */
	gain_root_privilege();
	gain_root_group_privilege();

	fault_setup();
	dump_core_setup("smbd", lp_logfile(talloc_tos()));

	/* we are never interested in SIGPIPE */
	BlockSignals(True,SIGPIPE);

#if defined(SIGFPE)
	/* we are never interested in SIGFPE */
	BlockSignals(True,SIGFPE);
#endif

#if defined(SIGUSR2)
	/* We are no longer interested in USR2 */
	BlockSignals(True,SIGUSR2);
#endif

	/* POSIX demands that signals are inherited. If the invoking process has
	 * these signals masked, we will have problems, as we won't recieve them. */
	BlockSignals(False, SIGHUP);
	BlockSignals(False, SIGUSR1);
	BlockSignals(False, SIGTERM);

	/* Ensure we leave no zombies until we
	 * correctly set up child handling below. */

	CatchChild();

	/* we want total control over the permissions on created files,
	   so set our umask to 0 */
	umask(0);

	reopen_logs();

	DEBUG(0,("smbd version %s started.\n", samba_version_string()));
	DEBUGADD(0,("%s\n", COPYRIGHT_STARTUP_MESSAGE));

	DEBUG(2,("uid=%d gid=%d euid=%d egid=%d\n",
		 (int)getuid(),(int)getgid(),(int)geteuid(),(int)getegid()));

	/* Output the build options to the debug log */ 
	build_options(False);

	if (sizeof(uint16_t) < 2 || sizeof(uint32_t) < 4) {
		DEBUG(0,("ERROR: Samba is not configured correctly for the word size on your machine\n"));
		exit(1);
	}

	if (!lp_load_initial_only(get_dyn_CONFIGFILE())) {
		DEBUG(0, ("error opening config file '%s'\n", get_dyn_CONFIGFILE()));
		exit(1);
	}

	if (!cluster_probe_ok()) {
		exit(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) {
		exit(1);
	}

	/*
	 * Init the messaging context
	 * FIXME: This should only call messaging_init()
	 */
	msg_ctx = server_messaging_context();
	if (msg_ctx == NULL) {
		exit(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, NULL, false)) {
		exit(1);
	}

	if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC
	    && !lp_parm_bool(-1, "server role check", "inhibit", false)) {
		DEBUG(0, ("server role = 'active directory domain controller' not compatible with running smbd standalone. \n"));
		DEBUGADD(0, ("You should start 'samba' instead, and it will control starting smbd if required\n"));
		exit(1);
	}

	/* ...NOTE... Log files are working from this point! */

	DEBUG(3,("loaded services\n"));

	init_structs();

	if (!profile_setup(msg_ctx, False)) {
		DEBUG(0,("ERROR: failed to setup profiling\n"));
		return -1;
	}

	if (profile_level != NULL) {
		profiling_level = atoi(profile_level);
	} else {
		profiling_level = lp_smbd_profiling_level();
	}
	set_profile_level(profiling_level, messaging_server_id(msg_ctx));

	if (!is_daemon && !is_a_socket(0)) {
		if (!interactive) {
			DEBUG(3, ("Standard input is not a socket, "
				  "assuming -D option\n"));
		}

		/*
		 * Setting is_daemon here prevents us from eventually calling
		 * the open_sockets_inetd()
		 */

		is_daemon = True;
	}

	if (is_daemon && !interactive) {
		DEBUG(3, ("Becoming a daemon.\n"));
		become_daemon(Fork, no_process_group, log_stdout);
	}

#if HAVE_SETPGID
	/*
	 * If we're interactive we want to set our own process group for
	 * signal management.
	 */
	if (interactive && !no_process_group)
		setpgid( (pid_t)0, (pid_t)0);
#endif

	if (!directory_exist(lp_lock_directory()))
		mkdir(lp_lock_directory(), 0755);

	if (!directory_exist(lp_pid_directory()))
		mkdir(lp_pid_directory(), 0755);

	if (is_daemon)
		pidfile_create(lp_pid_directory(), "smbd");

	status = reinit_after_fork(msg_ctx, ev_ctx, false, NULL);
	if (!NT_STATUS_IS_OK(status)) {
		exit_daemon("reinit_after_fork() failed", map_errno_from_nt_status(status));
	}

	if (!interactive) {
		/*
		 * Do not initialize the parent-child-pipe before becoming a
		 * daemon: this is used to detect a died parent in the child
		 * process.
		 */
		status = init_before_fork();
		if (!NT_STATUS_IS_OK(status)) {
			exit_daemon(nt_errstr(status), map_errno_from_nt_status(status));
		}
	}

	parent = talloc_zero(ev_ctx, struct smbd_parent_context);
	if (!parent) {
		exit_server("talloc(struct smbd_parent_context) failed");
	}
	parent->interactive = interactive;
	parent->ev_ctx = ev_ctx;
	parent->msg_ctx = msg_ctx;
	am_parent = parent;

	se = tevent_add_signal(parent->ev_ctx,
			       parent,
			       SIGTERM, 0,
			       smbd_parent_sig_term_handler,
			       parent);
	if (!se) {
		exit_server("failed to setup SIGTERM handler");
	}
	se = tevent_add_signal(parent->ev_ctx,
			       parent,
			       SIGHUP, 0,
			       smbd_parent_sig_hup_handler,
			       parent);
	if (!se) {
		exit_server("failed to setup SIGHUP handler");
	}

	/* Setup all the TDB's - including CLEAR_IF_FIRST tdb's. */

	if (smbd_memcache() == NULL) {
		exit_daemon("no memcache available", EACCES);
	}

	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))
		exit(1);

	if (!secrets_init()) {
		exit_daemon("smbd can not open secrets.tdb", EACCES);
	}

	if (lp_server_role() == ROLE_DOMAIN_BDC || lp_server_role() == ROLE_DOMAIN_PDC) {
		struct loadparm_context *lp_ctx = loadparm_init_s3(NULL, loadparm_s3_helpers());
		if (!open_schannel_session_store(NULL, lp_ctx)) {
			exit_daemon("ERROR: Samba cannot open schannel store for secured NETLOGON operations.", EACCES);
		}
		TALLOC_FREE(lp_ctx);
	}

	if(!get_global_sam_sid()) {
		exit_daemon("Samba cannot create a SAM SID", EACCES);
	}

	server_id = messaging_server_id(msg_ctx);
	status = smbXsrv_version_global_init(&server_id);
	if (!NT_STATUS_IS_OK(status)) {
		exit_daemon("Samba cannot init server context", EACCES);
	}

	status = smbXsrv_session_global_init();
	if (!NT_STATUS_IS_OK(status)) {
		exit_daemon("Samba cannot init session context", EACCES);
	}

	status = smbXsrv_tcon_global_init();
	if (!NT_STATUS_IS_OK(status)) {
		exit_daemon("Samba cannot init tcon context", EACCES);
	}

	if (!locking_init())
		exit_daemon("Samba cannot init locking", EACCES);

	if (!leases_db_init(false)) {
		exit_daemon("Samba cannot init leases", EACCES);
	}

	if (!smbd_notifyd_init(msg_ctx, interactive)) {
		exit_daemon("Samba cannot init notification", EACCES);
	}

	if (!messaging_parent_dgm_cleanup_init(msg_ctx)) {
		exit(1);
	}

	if (!smbd_scavenger_init(NULL, msg_ctx, ev_ctx)) {
		exit_daemon("Samba cannot init scavenging", EACCES);
	}

	if (!serverid_parent_init(ev_ctx)) {
		exit_daemon("Samba cannot init server id", EACCES);
	}

	if (!W_ERROR_IS_OK(registry_init_full()))
		exit_daemon("Samba cannot init registry", EACCES);

	/* 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()) {
		exit_daemon("ERROR: failed to load share info db.", EACCES);
	}

	status = init_system_session_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_global()) {
		DEBUG(0, ("ERROR: file_init_global() failed\n"));
		return -1;
	}
	status = smbXsrv_open_global_init();
	if (!NT_STATUS_IS_OK(status)) {
		exit_daemon("Samba cannot init global open", map_errno_from_nt_status(status));
	}

	/* This MUST be done before start_epmd() because otherwise
	 * start_epmd() forks and races against dcesrv_ep_setup() to
	 * call directory_create_or_exist() */
	if (!directory_create_or_exist(lp_ncalrpc_dir(), 0755)) {
		DEBUG(0, ("Failed to create pipe directory %s - %s\n",
			  lp_ncalrpc_dir(), strerror(errno)));
		return -1;
	}

	np_dir = talloc_asprintf(talloc_tos(), "%s/np", lp_ncalrpc_dir());
	if (!np_dir) {
		DEBUG(0, ("%s: Out of memory\n", __location__));
		return -1;
	}

	if (!directory_create_or_exist_strict(np_dir, geteuid(), 0700)) {
		DEBUG(0, ("Failed to create pipe directory %s - %s\n",
			  np_dir, strerror(errno)));
		return -1;
	}

	if (is_daemon && !interactive) {
		if (rpc_epmapper_daemon() == RPC_DAEMON_FORK) {
			start_epmd(ev_ctx, msg_ctx);
		}
	}

	if (!dcesrv_ep_setup(ev_ctx, msg_ctx)) {
		exit_daemon("Samba cannot setup ep pipe", EACCES);
	}

	if (is_daemon && !interactive) {
		daemon_ready("smbd");
	}

	/* only start other daemons if we are running as a daemon
	 * -- bad things will happen if smbd is launched via inetd
	 *  and we fork a copy of ourselves here */
	if (is_daemon && !interactive) {

		if (rpc_lsasd_daemon() == RPC_DAEMON_FORK) {
			start_lsasd(ev_ctx, msg_ctx);
		}

		if (rpc_fss_daemon() == RPC_DAEMON_FORK) {
			start_fssd(ev_ctx, msg_ctx);
		}

		if (!lp__disable_spoolss() &&
		    (rpc_spoolss_daemon() != RPC_DAEMON_DISABLED)) {
			bool bgq = lp_parm_bool(-1, "smbd", "backgroundqueue", true);

			if (!printing_subsystem_init(ev_ctx, msg_ctx, true, bgq)) {
				exit_daemon("Samba failed to init printing subsystem", EACCES);
			}
		}

#ifdef WITH_SPOTLIGHT
		if ((rpc_mdssvc_mode() == RPC_SERVICE_MODE_EXTERNAL) &&
		    (rpc_mdssd_daemon() == RPC_DAEMON_FORK)) {
			start_mdssd(ev_ctx, msg_ctx);
		}
#endif
	} else if (!lp__disable_spoolss() &&
		   (rpc_spoolss_daemon() != RPC_DAEMON_DISABLED)) {
		if (!printing_subsystem_init(ev_ctx, msg_ctx, false, false)) {
			exit(1);
		}
	}

	if (!is_daemon) {
		int sock;

		/* inetd mode */
		TALLOC_FREE(frame);

		/* Started from inetd. fd 0 is the socket. */
		/* We will abort gracefully when the client or remote system
		   goes away */
		sock = dup(0);

		/* close stdin, stdout (if not logging to it), but not stderr */
		close_low_fds(true, !debug_get_output_is_stdout(), false);

#ifdef HAVE_ATEXIT
		atexit(killkids);
#endif

	        /* Stop zombies */
		smbd_setup_sig_chld_handler(parent);

		smbd_process(ev_ctx, msg_ctx, sock, true);

		exit_server_cleanly(NULL);
		return(0);
	}

	if (!open_sockets_smbd(parent, ev_ctx, msg_ctx, ports))
		exit_server("open_sockets_smbd() failed");

	/* do a printer update now that all messaging has been set up,
	 * before we allow clients to start connecting */
	if (!lp__disable_spoolss() &&
	    (rpc_spoolss_daemon() != RPC_DAEMON_DISABLED)) {
		printing_subsystem_update(ev_ctx, msg_ctx, false);
	}

	TALLOC_FREE(frame);
	/* make sure we always have a valid stackframe */
	frame = talloc_stackframe();

	if (!Fork) {
		/* if we are running in the foreground then look for
		   EOF on stdin, and exit if it happens. This allows
		   us to die if the parent process dies
		   Only do this on a pipe or socket, no other device.
		*/
		struct stat st;
		if (fstat(0, &st) != 0) {
			return false;
		}
		if (S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode)) {
			tevent_add_fd(ev_ctx,
					parent,
					0,
					TEVENT_FD_READ,
					smbd_stdin_handler,
					NULL);
		}
	}

	smbd_parent_loop(ev_ctx, parent);

	exit_server_cleanly(NULL);
	TALLOC_FREE(frame);
	return(0);
}
Example #25
0
static int ibw_setup_cq_qp(struct ibw_conn *conn)
{
	struct ibw_ctx_priv *pctx = talloc_get_type(conn->ctx->internal, struct ibw_ctx_priv);
	struct ibw_conn_priv *pconn = talloc_get_type(conn->internal, struct ibw_conn_priv);
	struct ibv_qp_init_attr init_attr;
	struct ibv_qp_attr attr;
	int rc;

	DEBUG(DEBUG_DEBUG, ("ibw_setup_cq_qp(cmid: %p)\n", pconn->cm_id));

	/* init verbs */
	pconn->verbs_channel = ibv_create_comp_channel(pconn->cm_id->verbs);
	if (!pconn->verbs_channel) {
		sprintf(ibw_lasterr, "ibv_create_comp_channel failed %d\n", errno);
		return -1;
	}
	DEBUG(DEBUG_DEBUG, ("created channel %p\n", pconn->verbs_channel));

	pconn->verbs_channel_event = tevent_add_fd(pctx->ectx, NULL, /* not pconn or conn */
		pconn->verbs_channel->fd, TEVENT_FD_READ, ibw_event_handler_verbs, conn);

	pconn->pd = ibv_alloc_pd(pconn->cm_id->verbs);
	if (!pconn->pd) {
		sprintf(ibw_lasterr, "ibv_alloc_pd failed %d\n", errno);
		return -1;
	}
	DEBUG(DEBUG_DEBUG, ("created pd %p\n", pconn->pd));

	/* init mr */
	if (ibw_init_memory(conn))
		return -1;

	/* init cq */
	pconn->cq = ibv_create_cq(pconn->cm_id->verbs,
		pctx->opts.max_recv_wr + pctx->opts.max_send_wr,
		conn, pconn->verbs_channel, 0);
	if (pconn->cq==NULL) {
		sprintf(ibw_lasterr, "ibv_create_cq failed\n");
		return -1;
	}

	rc = ibv_req_notify_cq(pconn->cq, 0);
	if (rc) {
		sprintf(ibw_lasterr, "ibv_req_notify_cq failed with %d\n", rc);
		return rc;
	}

	/* init qp */
	memset(&init_attr, 0, sizeof(init_attr));
	init_attr.cap.max_send_wr = pctx->opts.max_send_wr;
	init_attr.cap.max_recv_wr = pctx->opts.max_recv_wr;
	init_attr.cap.max_recv_sge = 1;
	init_attr.cap.max_send_sge = 1;
	init_attr.qp_type = IBV_QPT_RC;
	init_attr.send_cq = pconn->cq;
	init_attr.recv_cq = pconn->cq;

	rc = rdma_create_qp(pconn->cm_id, pconn->pd, &init_attr);
	if (rc) {
		sprintf(ibw_lasterr, "rdma_create_qp failed with %d\n", rc);
		return rc;
	}
	/* elase result is in pconn->cm_id->qp */

	rc = ibv_query_qp(pconn->cm_id->qp, &attr, IBV_QP_PATH_MTU, &init_attr);
	if (rc) {
		sprintf(ibw_lasterr, "ibv_query_qp failed with %d\n", rc);
		return rc;
	}

	return ibw_fill_cq(conn);
}
Example #26
0
/*
  called when a listening socket becomes readable. 
*/
static void standard_accept_connection(struct tevent_context *ev, 
				       struct loadparm_context *lp_ctx,
				       struct socket_context *sock, 
				       void (*new_conn)(struct tevent_context *,
							struct loadparm_context *, struct socket_context *, 
							struct server_id , void *), 
				       void *private_data)
{
	NTSTATUS status;
	struct socket_context *sock2;
	pid_t pid;
	struct socket_address *c, *s;
	struct standard_child_state *state;
	struct tevent_fd *fde = NULL;
	struct tevent_signal *se = NULL;

	state = setup_standard_child_pipe(ev, NULL);
	if (state == NULL) {
		return;
	}

	/* accept an incoming connection. */
	status = socket_accept(sock, &sock2);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0,("standard_accept_connection: accept: %s\n",
			 nt_errstr(status)));
		/* this looks strange, but is correct. We need to throttle things until
		   the system clears enough resources to handle this new socket */
		sleep(1);
		close(state->to_parent_fd);
		state->to_parent_fd = -1;
		TALLOC_FREE(state);
		return;
	}

	pid = fork();

	if (pid != 0) {
		close(state->to_parent_fd);
		state->to_parent_fd = -1;

		if (pid > 0) {
			state->pid = pid;
		} else {
			TALLOC_FREE(state);
		}

		/* parent or error code ... */
		talloc_free(sock2);
		/* go back to the event loop */
		return;
	}

	/* this leaves state->to_parent_fd open */
	TALLOC_FREE(state);

	pid = getpid();

	/* This is now the child code. We need a completely new event_context to work with */

	if (tevent_re_initialise(ev) != 0) {
		smb_panic("Failed to re-initialise tevent after fork");
	}

	/* this will free all the listening sockets and all state that
	   is not associated with this new connection */
	talloc_free(sock);

	/* we don't care if the dup fails, as its only a select()
	   speed optimisation */
	socket_dup(sock2);
			
	/* tdb needs special fork handling */
	ldb_wrap_fork_hook();

	/* Must be done after a fork() to reset messaging contexts. */
	status = imessaging_reinit_all();
	if (!NT_STATUS_IS_OK(status)) {
		smb_panic("Failed to re-initialise imessaging after fork");
	}

	fde = tevent_add_fd(ev, ev, child_pipe[0], TEVENT_FD_READ,
		      standard_pipe_handler, NULL);
	if (fde == NULL) {
		smb_panic("Failed to add fd handler after fork");
	}

	if (child_pipe[1] != -1) {
		close(child_pipe[1]);
		child_pipe[1] = -1;
	}

	se = tevent_add_signal(ev,
				ev,
				SIGHUP,
				0,
				sighup_signal_handler,
				NULL);
	if (se == NULL) {
		smb_panic("Failed to add SIGHUP handler after fork");
	}

	se = tevent_add_signal(ev,
				ev,
				SIGTERM,
				0,
				sigterm_signal_handler,
				NULL);
	if (se == NULL) {
		smb_panic("Failed to add SIGTERM handler after fork");
	}

	/* setup the process title */
	c = socket_get_peer_addr(sock2, ev);
	s = socket_get_my_addr(sock2, ev);
	if (s && c) {
		setproctitle("conn c[%s:%u] s[%s:%u] server_id[%d]",
			     c->addr, c->port, s->addr, s->port, (int)pid);
	}
	talloc_free(c);
	talloc_free(s);

	/* setup this new connection.  Cluster ID is PID based for this process model */
	new_conn(ev, lp_ctx, sock2, cluster_id(pid, 0), private_data);

	/* we can't return to the top level here, as that event context is gone,
	   so we now process events in the new event context until there are no
	   more to process */	   
	tevent_loop_wait(ev);

	talloc_free(ev);
	exit(0);
}
Example #27
0
int setup_watchdog(struct tevent_context *ev, int interval)
{
    struct sigevent sev;
    struct itimerspec its;
    struct tevent_fd *tfd;
    int signum = SIGRTMIN;
    int ret;

    memset(&sev, 0, sizeof(sev));
    CatchSignal(signum, watchdog_handler);

    sev.sigev_notify = SIGEV_SIGNAL;
    sev.sigev_signo = signum;
    sev.sigev_value.sival_ptr = &watchdog_ctx.timerid;
    errno = 0;
    ret = timer_create(CLOCK_MONOTONIC, &sev, &watchdog_ctx.timerid);
    if (ret == -1) {
        ret = errno;
        DEBUG(SSSDBG_FATAL_FAILURE,
              "Failed to create watchdog timer (%d) [%s]\n",
              ret, strerror(ret));
        return ret;
    }

    if (interval == 0) {
        interval = WATCHDOG_DEF_INTERVAL;
    }
    watchdog_ctx.interval.tv_sec = interval;
    watchdog_ctx.interval.tv_usec = 0;

    watchdog_ctx.ev = ev;
    watchdog_ctx.input_interval = interval;
    watchdog_ctx.timestamp = time(NULL);

    ret = pipe(watchdog_ctx.pipefd);
    if (ret == -1) {
        ret = errno;
        DEBUG(SSSDBG_FATAL_FAILURE,
              "pipe failed [%d] [%s].\n", ret, strerror(ret));
        return ret;
    }

    sss_fd_nonblocking(watchdog_ctx.pipefd[0]);
    sss_fd_nonblocking(watchdog_ctx.pipefd[1]);

    tfd = tevent_add_fd(ev, (TALLOC_CTX *)ev, watchdog_ctx.pipefd[0],
                        TEVENT_FD_READ, watchdog_fd_read_handler, NULL);
    watchdog_ctx.tfd = tfd;

    /* Start the timer */
    /* we give 1 second head start to the watchdog event */
    its.it_value.tv_sec = interval + 1;
    its.it_value.tv_nsec = 0;
    its.it_interval.tv_sec = interval;
    its.it_interval.tv_nsec = 0;
    errno = 0;
    ret = timer_settime(watchdog_ctx.timerid, 0, &its, NULL);
    if (ret == -1) {
        ret = errno;
        DEBUG(SSSDBG_FATAL_FAILURE,
              "Failed to create watchdog timer (%d) [%s]\n",
              ret, strerror(ret));
        return ret;
    }

    /* Add the watchdog event and make it fire as fast as the timer */
    watchdog_event_handler(ev, NULL, tevent_timeval_zero(), NULL);

    return EOK;
}
Example #28
0
/*
  called to create a new server task
*/
static void standard_new_task(struct tevent_context *ev, 
			      struct loadparm_context *lp_ctx,
			      const char *service_name,
			      void (*new_task)(struct tevent_context *, struct loadparm_context *lp_ctx, struct server_id , void *),
			      void *private_data)
{
	pid_t pid;
	NTSTATUS status;
	struct standard_child_state *state;
	struct tevent_fd *fde = NULL;
	struct tevent_signal *se = NULL;

	state = setup_standard_child_pipe(ev, service_name);
	if (state == NULL) {
		return;
	}

	pid = fork();

	if (pid != 0) {
		close(state->to_parent_fd);
		state->to_parent_fd = -1;

		if (pid > 0) {
			state->pid = pid;
		} else {
			TALLOC_FREE(state);
		}

		/* parent or error code ... go back to the event loop */
		return;
	}

	/* this leaves state->to_parent_fd open */
	TALLOC_FREE(state);

	pid = getpid();

	/* this will free all the listening sockets and all state that
	   is not associated with this new connection */
	if (tevent_re_initialise(ev) != 0) {
		smb_panic("Failed to re-initialise tevent after fork");
	}

	/* ldb/tdb need special fork handling */
	ldb_wrap_fork_hook();

	/* Must be done after a fork() to reset messaging contexts. */
	status = imessaging_reinit_all();
	if (!NT_STATUS_IS_OK(status)) {
		smb_panic("Failed to re-initialise imessaging after fork");
	}

	fde = tevent_add_fd(ev, ev, child_pipe[0], TEVENT_FD_READ,
		      standard_pipe_handler, NULL);
	if (fde == NULL) {
		smb_panic("Failed to add fd handler after fork");
	}
	if (child_pipe[1] != -1) {
		close(child_pipe[1]);
		child_pipe[1] = -1;
	}

	se = tevent_add_signal(ev,
				ev,
				SIGHUP,
				0,
				sighup_signal_handler,
				NULL);
	if (se == NULL) {
		smb_panic("Failed to add SIGHUP handler after fork");
	}

	se = tevent_add_signal(ev,
				ev,
				SIGTERM,
				0,
				sigterm_signal_handler,
				NULL);
	if (se == NULL) {
		smb_panic("Failed to add SIGTERM handler after fork");
	}

	setproctitle("task %s server_id[%d]", service_name, (int)pid);

	/* setup this new task.  Cluster ID is PID based for this process model */
	new_task(ev, lp_ctx, cluster_id(pid, 0), private_data);

	/* we can't return to the top level here, as that event context is gone,
	   so we now process events in the new event context until there are no
	   more to process */	   
	tevent_loop_wait(ev);

	talloc_free(ev);
	exit(0);
}
Example #29
0
struct ibw_ctx *ibw_init(struct ibw_initattr *attr, int nattr,
	void *ctx_userdata,
	ibw_connstate_fn_t ibw_connstate,
	ibw_receive_fn_t ibw_receive,
	struct tevent_context *ectx)
{
	struct ibw_ctx *ctx = talloc_zero(NULL, struct ibw_ctx);
	struct ibw_ctx_priv *pctx;
	int	rc;

	DEBUG(DEBUG_DEBUG, ("ibw_init(ctx_userdata: %p, ectx: %p)\n", ctx_userdata, ectx));

	/* initialize basic data structures */
	memset(ibw_lasterr, 0, IBW_LASTERR_BUFSIZE);

	assert(ctx!=NULL);
	ibw_lasterr[0] = '\0';
	talloc_set_destructor(ctx, ibw_ctx_destruct);
	ctx->ctx_userdata = ctx_userdata;

	pctx = talloc_zero(ctx, struct ibw_ctx_priv);
	talloc_set_destructor(pctx, ibw_ctx_priv_destruct);
	ctx->internal = (void *)pctx;
	assert(pctx!=NULL);

	pctx->connstate_func = ibw_connstate;
	pctx->receive_func = ibw_receive;

	pctx->ectx = ectx;

	/* process attributes */
	if (ibw_process_init_attrs(attr, nattr, &pctx->opts))
		goto cleanup;

	/* init cm */
	pctx->cm_channel = rdma_create_event_channel();
	if (!pctx->cm_channel) {
		sprintf(ibw_lasterr, "rdma_create_event_channel error %d\n", errno);
		goto cleanup;
	}

	pctx->cm_channel_event = tevent_add_fd(pctx->ectx, pctx,
		pctx->cm_channel->fd, TEVENT_FD_READ, ibw_event_handler_cm, ctx);

#if RDMA_USER_CM_MAX_ABI_VERSION >= 2
	rc = rdma_create_id(pctx->cm_channel, &pctx->cm_id, ctx, RDMA_PS_TCP);
#else
	rc = rdma_create_id(pctx->cm_channel, &pctx->cm_id, ctx);
#endif
	if (rc) {
		rc = errno;
		sprintf(ibw_lasterr, "rdma_create_id error %d\n", rc);
		goto cleanup;
	}
	DEBUG(DEBUG_DEBUG, ("created cm_id %p\n", pctx->cm_id));

	pctx->pagesize = sysconf(_SC_PAGESIZE);

	return ctx;
	/* don't put code here */
cleanup:
	DEBUG(DEBUG_ERR, (ibw_lasterr));

	if (ctx)
		talloc_free(ctx);

	return NULL;
}
Example #30
0
static struct standard_child_state *setup_standard_child_pipe(struct tevent_context *ev,
							      const char *name)
{
	struct standard_child_state *state;
	int parent_child_pipe[2];
	int ret;

	/*
	 * Prepare a pipe to allow us to know when the child exits,
	 * because it will trigger a read event on this private
	 * pipe.
	 *
	 * We do all this before the accept and fork(), so we can
	 * clean up if it fails.
	 */
	state = talloc_zero(ev, struct standard_child_state);
	if (state == NULL) {
		return NULL;
	}

	if (name == NULL) {
		name = "";
	}

	state->name = talloc_strdup(state, name);
	if (state->name == NULL) {
		TALLOC_FREE(state);
		return NULL;
	}

	ret = pipe(parent_child_pipe);
	if (ret == -1) {
		DEBUG(0, ("Failed to create parent-child pipe to handle "
			  "SIGCHLD to track new process for socket\n"));
		TALLOC_FREE(state);
		return NULL;
	}

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

	state->from_child_fd = parent_child_pipe[0];
	state->to_parent_fd = parent_child_pipe[1];

	/*
	 * The basic purpose of calling this handler is to ensure we
	 * call waitpid() and so avoid zombies (now that we no longer
	 * user SIGIGN on for SIGCHLD), but it also allows us to clean
	 * up other resources in the future.
	 */
	state->from_child_fde = tevent_add_fd(ev, state,
					      state->from_child_fd,
					      TEVENT_FD_READ,
					      standard_child_pipe_handler,
					      state);
	if (state->from_child_fde == NULL) {
		TALLOC_FREE(state);
		return NULL;
	}
	tevent_fd_set_auto_close(state->from_child_fde);

	return state;
}