summaryrefslogtreecommitdiff
path: root/source3/nsswitch/winbindd.c
diff options
context:
space:
mode:
authorGerald Carter <jerry@samba.org>2005-06-08 22:10:34 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 10:57:08 -0500
commitfed660877c16562265327c6093ea645cf4176b5c (patch)
treee92ae1356542ba095d806bbe1093fa56fbc8ddcc /source3/nsswitch/winbindd.c
parent66bb4f03c3466205488f72e4878e8801c5bbb295 (diff)
downloadsamba-fed660877c16562265327c6093ea645cf4176b5c.tar.gz
samba-fed660877c16562265327c6093ea645cf4176b5c.tar.bz2
samba-fed660877c16562265327c6093ea645cf4176b5c.zip
r7415: * big change -- volker's new async winbindd from trunk
(This used to be commit a0ac9a8ffd4af31a0ebc423b4acbb2f043d865b8)
Diffstat (limited to 'source3/nsswitch/winbindd.c')
-rw-r--r--source3/nsswitch/winbindd.c733
1 files changed, 421 insertions, 312 deletions
diff --git a/source3/nsswitch/winbindd.c b/source3/nsswitch/winbindd.c
index 81dbf327fc..f083dfe44a 100644
--- a/source3/nsswitch/winbindd.c
+++ b/source3/nsswitch/winbindd.c
@@ -6,6 +6,7 @@
Copyright (C) by Tim Potter 2000-2002
Copyright (C) Andrew Tridgell 2002
Copyright (C) Jelmer Vernooij 2003
+ Copyright (C) Volker Lendecke 2004
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -27,6 +28,7 @@
BOOL opt_nocache = False;
BOOL opt_dual_daemon = True;
+static BOOL interactive = False;
extern BOOL override_logfile;
@@ -131,7 +133,6 @@ static void winbindd_status(void)
static void print_winbindd_status(void)
{
winbindd_status();
- winbindd_cm_status();
}
/* Flush client cache */
@@ -163,6 +164,17 @@ static void terminate(void)
pstr_sprintf(path, "%s/%s",
WINBINDD_SOCKET_DIR, WINBINDD_SOCKET_NAME);
unlink(path);
+
+#if 0
+ if (interactive) {
+ TALLOC_CTX *mem_ctx = talloc_init("end_description");
+ char *description = talloc_describe_all(mem_ctx);
+
+ DEBUG(3, ("tallocs left:\n%s\n", description));
+ talloc_destroy(mem_ctx);
+ }
+#endif
+
exit(0);
}
@@ -190,14 +202,11 @@ static void sighup_handler(int signum)
sys_select_signal();
}
+static BOOL do_sigchld;
+
static void sigchld_handler(int signum)
{
- pid_t pid;
- int status;
-
- while ((pid = wait(&status)) != -1 || errno == EINTR) {
- continue; /* Reap children */
- }
+ do_sigchld = True;
sys_select_signal();
}
@@ -215,13 +224,7 @@ static void msg_shutdown(int msg_type, pid_t src, void *buf, size_t len)
terminate();
}
-struct dispatch_table {
- enum winbindd_cmd cmd;
- enum winbindd_result (*fn)(struct winbindd_cli_state *state);
- const char *winbindd_cmd_name;
-};
-
-static struct dispatch_table dispatch_table[] = {
+static struct winbindd_dispatch_table dispatch_table[] = {
/* User functions */
@@ -234,6 +237,8 @@ static struct dispatch_table dispatch_table[] = {
{ WINBINDD_GETGROUPS, winbindd_getgroups, "GETGROUPS" },
{ WINBINDD_GETUSERSIDS, winbindd_getusersids, "GETUSERSIDS" },
+ { WINBINDD_GETUSERDOMGROUPS, winbindd_getuserdomgroups,
+ "GETUSERDOMGROUPS" },
/* Group functions */
@@ -247,14 +252,15 @@ static struct dispatch_table dispatch_table[] = {
/* PAM auth functions */
{ WINBINDD_PAM_AUTH, winbindd_pam_auth, "PAM_AUTH" },
- { WINBINDD_PAM_AUTH_CRAP, winbindd_pam_auth_crap, "AUTH_CRAP" },
+ { WINBINDD_PAM_AUTH_CRAP, winbindd_crap_auth, "AUTH_CRAP" },
{ WINBINDD_PAM_CHAUTHTOK, winbindd_pam_chauthtok, "CHAUTHTOK" },
/* Enumeration functions */
{ WINBINDD_LIST_USERS, winbindd_list_users, "LIST_USERS" },
{ WINBINDD_LIST_GROUPS, winbindd_list_groups, "LIST_GROUPS" },
- { WINBINDD_LIST_TRUSTDOM, winbindd_list_trusted_domains, "LIST_TRUSTDOM" },
+ { WINBINDD_LIST_TRUSTDOM, winbindd_list_trusted_domains,
+ "LIST_TRUSTDOM" },
{ WINBINDD_SHOW_SEQUENCE, winbindd_show_sequence, "SHOW_SEQUENCE" },
/* SID related functions */
@@ -266,20 +272,25 @@ static struct dispatch_table dispatch_table[] = {
{ WINBINDD_SID_TO_UID, winbindd_sid_to_uid, "SID_TO_UID" },
{ WINBINDD_SID_TO_GID, winbindd_sid_to_gid, "SID_TO_GID" },
- { WINBINDD_GID_TO_SID, winbindd_gid_to_sid, "GID_TO_SID" },
{ WINBINDD_UID_TO_SID, winbindd_uid_to_sid, "UID_TO_SID" },
+ { WINBINDD_GID_TO_SID, winbindd_gid_to_sid, "GID_TO_SID" },
{ WINBINDD_ALLOCATE_RID, winbindd_allocate_rid, "ALLOCATE_RID" },
+ { WINBINDD_ALLOCATE_RID_AND_GID, winbindd_allocate_rid_and_gid,
+ "ALLOCATE_RID_AND_GID" },
/* Miscellaneous */
{ WINBINDD_CHECK_MACHACC, winbindd_check_machine_acct, "CHECK_MACHACC" },
{ WINBINDD_PING, winbindd_ping, "PING" },
{ WINBINDD_INFO, winbindd_info, "INFO" },
- { WINBINDD_INTERFACE_VERSION, winbindd_interface_version, "INTERFACE_VERSION" },
+ { WINBINDD_INTERFACE_VERSION, winbindd_interface_version,
+ "INTERFACE_VERSION" },
{ WINBINDD_DOMAIN_NAME, winbindd_domain_name, "DOMAIN_NAME" },
{ WINBINDD_DOMAIN_INFO, winbindd_domain_info, "DOMAIN_INFO" },
{ WINBINDD_NETBIOS_NAME, winbindd_netbios_name, "NETBIOS_NAME" },
- { WINBINDD_PRIV_PIPE_DIR, winbindd_priv_pipe_dir, "WINBINDD_PRIV_PIPE_DIR" },
+ { WINBINDD_PRIV_PIPE_DIR, winbindd_priv_pipe_dir,
+ "WINBINDD_PRIV_PIPE_DIR" },
+ { WINBINDD_GETDCNAME, winbindd_getdcname, "GETDCNAME" },
/* WINS functions */
@@ -293,7 +304,7 @@ static struct dispatch_table dispatch_table[] = {
static void process_request(struct winbindd_cli_state *state)
{
- struct dispatch_table *table = dispatch_table;
+ struct winbindd_dispatch_table *table = dispatch_table;
/* Free response data - we may be interrupted and receive another
command before being able to send this data off. */
@@ -302,26 +313,255 @@ static void process_request(struct winbindd_cli_state *state)
ZERO_STRUCT(state->response);
- state->response.result = WINBINDD_ERROR;
+ state->response.result = WINBINDD_PENDING;
state->response.length = sizeof(struct winbindd_response);
+ state->mem_ctx = talloc_init("winbind request");
+ if (state->mem_ctx == NULL)
+ return;
+
/* Process command */
for (table = dispatch_table; table->fn; table++) {
if (state->request.cmd == table->cmd) {
- DEBUG(10,("process_request: request fn %s\n", table->winbindd_cmd_name ));
+ DEBUG(10,("process_request: request fn %s\n",
+ table->winbindd_cmd_name ));
state->response.result = table->fn(state);
break;
}
}
- if (!table->fn)
- DEBUG(10,("process_request: unknown request fn number %d\n", (int)state->request.cmd ));
+ if (!table->fn) {
+ DEBUG(10,("process_request: unknown request fn number %d\n",
+ (int)state->request.cmd ));
+ state->response.result = WINBINDD_ERROR;
+ }
+}
+
+/*
+ * A list of file descriptors being monitored by select in the main processing
+ * loop. fd_event->handler is called whenever the socket is readable/writable.
+ */
+
+static struct fd_event *fd_events = NULL;
+
+void add_fd_event(struct fd_event *ev)
+{
+ struct fd_event *match;
+
+ /* only add unique fd_event structs */
+
+ for (match=fd_events; match; match=match->next ) {
+#ifdef DEVELOPER
+ SMB_ASSERT( match != ev );
+#else
+ if ( match == ev )
+ return;
+#endif
+ }
+
+ DLIST_ADD(fd_events, ev);
+}
+
+void remove_fd_event(struct fd_event *ev)
+{
+ DLIST_REMOVE(fd_events, ev);
+}
+
+/*
+ * Handler for fd_events to complete a read/write request, set up by
+ * setup_async_read/setup_async_write.
+ */
+
+static void rw_callback(struct fd_event *event, int flags)
+{
+ size_t todo;
+ ssize_t done = 0;
+
+ todo = event->length - event->done;
+
+ if (event->flags & EVENT_FD_WRITE) {
+ SMB_ASSERT(flags == EVENT_FD_WRITE);
+ done = sys_write(event->fd,
+ &((char *)event->data)[event->done],
+ todo);
+
+ if (done <= 0) {
+ event->flags = 0;
+ event->finished(event->private, False);
+ return;
+ }
+ }
+
+ if (event->flags & EVENT_FD_READ) {
+ SMB_ASSERT(flags == EVENT_FD_READ);
+ done = sys_read(event->fd, &((char *)event->data)[event->done],
+ todo);
- /* In case extra data pointer is NULL */
+ if (done <= 0) {
+ event->flags = 0;
+ event->finished(event->private, False);
+ return;
+ }
+ }
+
+ event->done += done;
+
+ if (event->done == event->length) {
+ event->flags = 0;
+ event->finished(event->private, True);
+ }
+}
+
+/*
+ * Request an async read/write on a fd_event structure. (*finished) is called
+ * when the request is completed or an error had occurred.
+ */
+
+void setup_async_read(struct fd_event *event, void *data, size_t length,
+ void (*finished)(void *private, BOOL success),
+ void *private)
+{
+ SMB_ASSERT(event->flags == 0);
+ event->data = data;
+ event->length = length;
+ event->done = 0;
+ event->handler = rw_callback;
+ event->finished = finished;
+ event->private = private;
+ event->flags = EVENT_FD_READ;
+}
+
+void setup_async_write(struct fd_event *event, void *data, size_t length,
+ void (*finished)(void *private, BOOL success),
+ void *private)
+{
+ SMB_ASSERT(event->flags == 0);
+ event->data = data;
+ event->length = length;
+ event->done = 0;
+ event->handler = rw_callback;
+ event->finished = finished;
+ event->private = private;
+ event->flags = EVENT_FD_WRITE;
+}
+
+/*
+ * This is the main event loop of winbind requests. It goes through a
+ * state-machine of 3 read/write requests, 4 if you have extra data to send.
+ *
+ * An idle winbind client has a read request of 4 bytes outstanding,
+ * finalizing function is request_len_recv, checking the length. request_recv
+ * then processes the packet. The processing function then at some point has
+ * to call request_finished which schedules sending the response.
+ */
+
+static void request_len_recv(void *private, BOOL success);
+static void request_recv(void *private, BOOL success);
+void request_finished(struct winbindd_cli_state *state);
+void request_finished_cont(void *private, BOOL success);
+static void response_main_sent(void *private, BOOL success);
+static void response_extra_sent(void *private, BOOL success);
+
+static void response_extra_sent(void *private, BOOL success)
+{
+ struct winbindd_cli_state *state =
+ talloc_get_type_abort(private, struct winbindd_cli_state);
+
+ if (state->mem_ctx != NULL) {
+ talloc_destroy(state->mem_ctx);
+ state->mem_ctx = NULL;
+ }
+
+ if (!success) {
+ state->finished = True;
+ return;
+ }
+
+ SAFE_FREE(state->response.extra_data);
+
+ setup_async_read(&state->fd_event, &state->request, sizeof(uint32),
+ request_len_recv, state);
+}
+
+static void response_main_sent(void *private, BOOL success)
+{
+ struct winbindd_cli_state *state =
+ talloc_get_type_abort(private, struct winbindd_cli_state);
+
+ if (!success) {
+ state->finished = True;
+ return;
+ }
+
+ if (state->response.length == sizeof(state->response)) {
+ if (state->mem_ctx != NULL) {
+ talloc_destroy(state->mem_ctx);
+ state->mem_ctx = NULL;
+ }
+
+ setup_async_read(&state->fd_event, &state->request,
+ sizeof(uint32), request_len_recv, state);
+ return;
+ }
+
+ setup_async_write(&state->fd_event, state->response.extra_data,
+ state->response.length - sizeof(state->response),
+ response_extra_sent, state);
+}
+
+void request_finished(struct winbindd_cli_state *state)
+{
+ setup_async_write(&state->fd_event, &state->response,
+ sizeof(state->response), response_main_sent, state);
+}
+
+void request_finished_cont(void *private, BOOL success)
+{
+ struct winbindd_cli_state *state =
+ talloc_get_type_abort(private, struct winbindd_cli_state);
+
+ if (!success)
+ state->response.result = WINBINDD_ERROR;
+ request_finished(state);
+}
+
+static void request_recv(void *private, BOOL success)
+{
+ struct winbindd_cli_state *state =
+ talloc_get_type_abort(private, struct winbindd_cli_state);
+
+ if (!success) {
+ state->finished = True;
+ return;
+ }
+
+ process_request(state);
+
+ if (state->response.result != WINBINDD_PENDING)
+ request_finished(state);
+}
+
+static void request_len_recv(void *private, BOOL success)
+{
+ struct winbindd_cli_state *state =
+ talloc_get_type_abort(private, struct winbindd_cli_state);
+
+ if (!success) {
+ state->finished = True;
+ return;
+ }
+
+ if (*(uint32 *)(&state->request) != sizeof(state->request)) {
+ DEBUG(0,("process_loop: Invalid request size received: %d\n",
+ *(uint32 *)(&state->request)));
+ state->finished = True;
+ return;
+ }
- if (!state->response.extra_data)
- state->response.length = sizeof(struct winbindd_response);
+ setup_async_read(&state->fd_event, (uint32 *)(&state->request)+1,
+ sizeof(state->request) - sizeof(uint32),
+ request_recv, state);
}
/* Process a new connection by adding it to the client connection list */
@@ -348,16 +588,22 @@ static void new_connection(int listen_sock, BOOL privileged)
/* Create new connection structure */
- if ((state = SMB_MALLOC_P(struct winbindd_cli_state)) == NULL)
+ if ((state = TALLOC_ZERO_P(NULL, struct winbindd_cli_state)) == NULL)
return;
- ZERO_STRUCTP(state);
state->sock = sock;
state->last_access = time(NULL);
state->privileged = privileged;
+ state->fd_event.fd = state->sock;
+ state->fd_event.flags = 0;
+ add_fd_event(&state->fd_event);
+
+ setup_async_read(&state->fd_event, &state->request, sizeof(uint32),
+ request_len_recv, state);
+
/* Add to connection list */
winbindd_add_client(state);
@@ -384,11 +630,18 @@ static void remove_client(struct winbindd_cli_state *state)
client was killed unexpectedly */
SAFE_FREE(state->response.extra_data);
+
+ if (state->mem_ctx != NULL) {
+ talloc_destroy(state->mem_ctx);
+ state->mem_ctx = NULL;
+ }
+
+ remove_fd_event(&state->fd_event);
/* Remove from list and free */
winbindd_remove_client(state);
- SAFE_FREE(state);
+ talloc_free(state);
}
}
@@ -403,7 +656,8 @@ static BOOL remove_idle_client(void)
for (state = winbindd_client_list(); state; state = state->next) {
if (state->read_buf_len == 0 && state->write_buf_len == 0 &&
- !state->getpwent_state && !state->getgrent_state) {
+ state->response.result != WINBINDD_PENDING &&
+ !state->getpwent_state && !state->getgrent_state) {
nidle++;
if (!last_access || state->last_access < last_access) {
last_access = state->last_access;
@@ -432,7 +686,7 @@ void winbind_process_packet(struct winbindd_cli_state *state)
state->request.null_term = '\0';
state->pid = state->request.pid;
-
+
process_request(state);
/* Update client state */
@@ -446,124 +700,6 @@ void winbind_process_packet(struct winbindd_cli_state *state)
}
}
-/* Read some data from a client connection */
-
-void winbind_client_read(struct winbindd_cli_state *state)
-{
- int n;
-
- /* Read data */
-
- n = sys_read(state->sock, state->read_buf_len +
- (char *)&state->request,
- sizeof(state->request) - state->read_buf_len);
-
- DEBUG(10,("client_read: read %d bytes. Need %ld more for a full request.\n", n, (unsigned long)(sizeof(state->request) - n - state->read_buf_len) ));
-
- /* Read failed, kill client */
-
- if (n == -1 || n == 0) {
- DEBUG(5,("read failed on sock %d, pid %lu: %s\n",
- state->sock, (unsigned long)state->pid,
- (n == -1) ? strerror(errno) : "EOF"));
-
- state->finished = True;
- return;
- }
-
- /* Update client state */
-
- state->read_buf_len += n;
- state->last_access = time(NULL);
-}
-
-/* Write some data to a client connection */
-
-static void client_write(struct winbindd_cli_state *state)
-{
- char *data;
- int num_written;
-
- /* Write some data */
- /*
- * The fancy calculation of data below allows us to handle the
- * case where write (sys_write) does not write all the data we
- * gave it. In that case, we will come back through here again
- * because of the loop above us, and we want to pick up where
- * we left off.
- */
-
- if (!state->write_extra_data) {
-
- /* Write response structure */
-
- data = (char *)&state->response + sizeof(state->response) -
- state->write_buf_len;
-
- } else {
-
- /* Write extra data */
-
- data = (char *)state->response.extra_data +
- state->response.length -
- sizeof(struct winbindd_response) -
- state->write_buf_len;
- }
-
- num_written = sys_write(state->sock, data, state->write_buf_len);
-
- DEBUG(10,("client_write: wrote %d bytes.\n", num_written ));
-
- /* Write failed, kill cilent */
-
- if (num_written == -1 || num_written == 0) {
-
- DEBUG(3,("write failed on sock %d, pid %lu: %s\n",
- state->sock, (unsigned long)state->pid,
- (num_written == -1) ? strerror(errno) : "EOF"));
-
- state->finished = True;
-
- SAFE_FREE(state->response.extra_data);
-
- return;
- }
-
- /* Update client state */
-
- state->write_buf_len -= num_written;
- state->last_access = time(NULL);
-
- /* Have we written all data? */
-
- if (state->write_buf_len == 0) {
-
- /* Take care of extra data */
-
- if (state->write_extra_data) {
-
- SAFE_FREE(state->response.extra_data);
-
- state->write_extra_data = False;
-
- DEBUG(10,("client_write: client_write: complete response written.\n"));
-
- } else if (state->response.length >
- sizeof(struct winbindd_response)) {
-
- /* Start writing extra data */
-
- state->write_buf_len =
- state->response.length -
- sizeof(struct winbindd_response);
-
- DEBUG(10,("client_write: need to write %d extra data bytes.\n", (int)state->write_buf_len));
-
- state->write_extra_data = True;
- }
- }
-}
-
/* Process incoming clients on listen_sock. We use a tricky non-blocking,
non-forking, non-threaded model which allows us to handle many
simultaneous connections while remaining impervious to many denial of
@@ -571,211 +707,182 @@ static void client_write(struct winbindd_cli_state *state)
static void process_loop(void)
{
- /* We'll be doing this a lot */
+ struct winbindd_cli_state *state;
+ struct fd_event *ev;
+ fd_set r_fds, w_fds;
+ int maxfd, listen_sock, listen_priv_sock, selret;
+ struct timeval timeout;
- while (1) {
- struct winbindd_cli_state *state;
- fd_set r_fds, w_fds;
- int maxfd, listen_sock, listen_priv_sock, selret;
- struct timeval timeout;
+ /* We'll be doing this a lot */
- again:
- /* Handle messages */
+ /* Handle messages */
- message_dispatch();
+ message_dispatch();
- /* refresh the trusted domain cache */
+ /* refresh the trusted domain cache */
- rescan_trusted_domains();
-
- /* Free up temporary memory */
+ rescan_trusted_domains();
- lp_talloc_free();
- main_loop_talloc_free();
+ /* Free up temporary memory */
- /* Initialise fd lists for select() */
+ lp_talloc_free();
+ main_loop_talloc_free();
- listen_sock = open_winbindd_socket();
- listen_priv_sock = open_winbindd_priv_socket();
-
- if (listen_sock == -1 || listen_priv_sock == -1) {
- perror("open_winbind_socket");
- exit(1);
- }
+ /* Initialise fd lists for select() */
- maxfd = MAX(listen_sock, listen_priv_sock);
+ listen_sock = open_winbindd_socket();
+ listen_priv_sock = open_winbindd_priv_socket();
- FD_ZERO(&r_fds);
- FD_ZERO(&w_fds);
- FD_SET(listen_sock, &r_fds);
- FD_SET(listen_priv_sock, &r_fds);
-
- timeout.tv_sec = WINBINDD_ESTABLISH_LOOP;
- timeout.tv_usec = 0;
-
- if (opt_dual_daemon) {
- maxfd = dual_select_setup(&w_fds, maxfd);
- }
-
- /* Set up client readers and writers */
+ if (listen_sock == -1 || listen_priv_sock == -1) {
+ perror("open_winbind_socket");
+ exit(1);
+ }
- state = winbindd_client_list();
+ maxfd = MAX(listen_sock, listen_priv_sock);
- while (state) {
+ FD_ZERO(&r_fds);
+ FD_ZERO(&w_fds);
+ FD_SET(listen_sock, &r_fds);
+ FD_SET(listen_priv_sock, &r_fds);
- /* Dispose of client connection if it is marked as
- finished */
+ timeout.tv_sec = WINBINDD_ESTABLISH_LOOP;
+ timeout.tv_usec = 0;
- if (state->finished) {
- struct winbindd_cli_state *next = state->next;
+ if (opt_dual_daemon) {
+ maxfd = dual_select_setup(&w_fds, maxfd);
+ }
- remove_client(state);
- state = next;
- continue;
- }
+ /* Set up client readers and writers */
- /* Select requires we know the highest fd used */
+ state = winbindd_client_list();
- if (state->sock > maxfd)
- maxfd = state->sock;
+ while (state) {
- /* Add fd for reading */
+ struct winbindd_cli_state *next = state->next;
- if (state->read_buf_len != sizeof(state->request))
- FD_SET(state->sock, &r_fds);
+ /* Dispose of client connection if it is marked as
+ finished */
- /* Add fd for writing */
+ if (state->finished)
+ remove_client(state);
- if (state->write_buf_len)
- FD_SET(state->sock, &w_fds);
+ state = next;
+ }
- state = state->next;
+ for (ev = fd_events; ev; ev = ev->next) {
+ if (ev->flags & EVENT_FD_READ) {
+ FD_SET(ev->fd, &r_fds);
+ maxfd = MAX(ev->fd, maxfd);
+ }
+ if (ev->flags & EVENT_FD_WRITE) {
+ FD_SET(ev->fd, &w_fds);
+ maxfd = MAX(ev->fd, maxfd);
}
+ }
- /* Call select */
+ /* Call select */
- selret = sys_select(maxfd + 1, &r_fds, &w_fds, NULL, &timeout);
+ selret = sys_select(maxfd + 1, &r_fds, &w_fds, NULL, &timeout);
- if (selret == 0)
- continue;
+ if (selret == 0)
+ goto no_fds_ready;
- if ((selret == -1 && errno != EINTR) || selret == 0) {
+ if ((selret == -1 && errno != EINTR) || selret == 0) {
- /* Select error, something is badly wrong */
+ /* Select error, something is badly wrong */
- perror("select");
- exit(1);
- }
+ perror("select");
+ exit(1);
+ }
- /* Create a new connection if listen_sock readable */
+ /* Create a new connection if listen_sock readable */
- if (selret > 0) {
+ if (opt_dual_daemon) {
+ dual_select(&w_fds);
+ }
- if (opt_dual_daemon) {
- dual_select(&w_fds);
- }
+ ev = fd_events;
+ while (ev != NULL) {
+ struct fd_event *next = ev->next;
+ int flags = 0;
+ if (FD_ISSET(ev->fd, &r_fds))
+ flags |= EVENT_FD_READ;
+ if (FD_ISSET(ev->fd, &w_fds))
+ flags |= EVENT_FD_WRITE;
+ if (flags)
+ ev->handler(ev, flags);
+ ev = next;
+ }
- if (FD_ISSET(listen_sock, &r_fds)) {
- while (winbindd_num_clients() > WINBINDD_MAX_SIMULTANEOUS_CLIENTS - 1) {
- DEBUG(5,("winbindd: Exceeding %d client connections, removing idle connection.\n",
- WINBINDD_MAX_SIMULTANEOUS_CLIENTS));
- if (!remove_idle_client()) {
- DEBUG(0,("winbindd: Exceeding %d client connections, no idle connection found\n",
- WINBINDD_MAX_SIMULTANEOUS_CLIENTS));
- break;
- }
- }
- /* new, non-privileged connection */
- new_connection(listen_sock, False);
+ if (FD_ISSET(listen_sock, &r_fds)) {
+ while (winbindd_num_clients() >
+ WINBINDD_MAX_SIMULTANEOUS_CLIENTS - 1) {
+ DEBUG(5,("winbindd: Exceeding %d client "
+ "connections, removing idle "
+ "connection.\n",
+ WINBINDD_MAX_SIMULTANEOUS_CLIENTS));
+ if (!remove_idle_client()) {
+ DEBUG(0,("winbindd: Exceeding %d "
+ "client connections, no idle "
+ "connection found\n",
+ WINBINDD_MAX_SIMULTANEOUS_CLIENTS));
+ break;
}
+ }
+ /* new, non-privileged connection */
+ new_connection(listen_sock, False);
+ }
- if (FD_ISSET(listen_priv_sock, &r_fds)) {
- while (winbindd_num_clients() > WINBINDD_MAX_SIMULTANEOUS_CLIENTS - 1) {
- DEBUG(5,("winbindd: Exceeding %d client connections, removing idle connection.\n",
- WINBINDD_MAX_SIMULTANEOUS_CLIENTS));
- if (!remove_idle_client()) {
- DEBUG(0,("winbindd: Exceeding %d client connections, no idle connection found\n",
- WINBINDD_MAX_SIMULTANEOUS_CLIENTS));
- break;
- }
- }
- /* new, privileged connection */
- new_connection(listen_priv_sock, True);
- }
-
- /* Process activity on client connections */
-
- for (state = winbindd_client_list(); state;
- state = state->next) {
-
- /* Data available for writing */
-
- if (FD_ISSET(state->sock, &w_fds))
- client_write(state);
- }
-
- for (state = winbindd_client_list(); state;
- state = state->next) {
-
- /* Data available for reading */
-
- if (FD_ISSET(state->sock, &r_fds)) {
-
- /* Read data */
-
- winbind_client_read(state);
-
- /*
- * If we have the start of a
- * packet, then check the
- * length field to make sure
- * the client's not talking
- * Mock Swedish.
- */
-
- if (state->read_buf_len >= sizeof(uint32)
- && *(uint32 *) &state->request != sizeof(state->request)) {
- DEBUG(0,("process_loop: Invalid request size from pid %lu: %d bytes sent, should be %ld\n",
- (unsigned long)state->request.pid, *(uint32 *) &state->request, (unsigned long)sizeof(state->request)));
- DEBUGADD(0, ("This usually means that you are running old wbinfo, pam_winbind or libnss_winbind clients\n"));
-
- remove_client(state);
- break;
- }
-
- /* A request packet might be
- complete */
-
- if (state->read_buf_len ==
- sizeof(state->request)) {
- winbind_process_packet(state);
- winbindd_demote_client(state);
- goto again;
- }
- }
+ if (FD_ISSET(listen_priv_sock, &r_fds)) {
+ while (winbindd_num_clients() >
+ WINBINDD_MAX_SIMULTANEOUS_CLIENTS - 1) {
+ DEBUG(5,("winbindd: Exceeding %d client "
+ "connections, removing idle "
+ "connection.\n",
+ WINBINDD_MAX_SIMULTANEOUS_CLIENTS));
+ if (!remove_idle_client()) {
+ DEBUG(0,("winbindd: Exceeding %d "
+ "client connections, no idle "
+ "connection found\n",
+ WINBINDD_MAX_SIMULTANEOUS_CLIENTS));
+ break;
}
}
+ /* new, privileged connection */
+ new_connection(listen_priv_sock, True);
+ }
+
+ no_fds_ready:
#if 0
- winbindd_check_cache_size(time(NULL));
+ winbindd_check_cache_size(time(NULL));
#endif
- /* Check signal handling things */
+ /* Check signal handling things */
- if (do_sigterm)
- terminate();
+ if (do_sigterm)
+ terminate();
- if (do_sighup) {
+ if (do_sighup) {
- DEBUG(3, ("got SIGHUP\n"));
+ DEBUG(3, ("got SIGHUP\n"));
- msg_reload_services(MSG_SMB_CONF_UPDATED, (pid_t) 0, NULL, 0);
- do_sighup = False;
- }
+ msg_reload_services(MSG_SMB_CONF_UPDATED, (pid_t) 0, NULL, 0);
+ do_sighup = False;
+ }
+
+ if (do_sigusr2) {
+ print_winbindd_status();
+ do_sigusr2 = False;
+ }
- if (do_sigusr2) {
- print_winbindd_status();
- do_sigusr2 = False;
+ if (do_sigchld) {
+ pid_t pid;
+
+ do_sigchld = False;
+
+ while ((pid = sys_waitpid(-1, NULL, WNOHANG)) > 0) {
+ winbind_child_died(pid);
}
}
}
@@ -787,7 +894,6 @@ struct winbindd_state server_state; /* Server state information */
int main(int argc, char **argv)
{
pstring logfile;
- static BOOL interactive = False;
static BOOL Fork = True;
static BOOL log_stdout = False;
struct poptOption long_options[] = {
@@ -886,7 +992,7 @@ int main(int argc, char **argv)
if ( (!winbindd_param_init()) || (!winbindd_upgrade_idmap()) ||
(!idmap_init(lp_idmap_backend())) ) {
DEBUG(1, ("Could not init idmap -- netlogon proxy only\n"));
- idmap_proxyonly();
+ idmap_set_proxyonly();
}
/* Unblock all signals we are interested in as they may have been
@@ -948,9 +1054,12 @@ int main(int argc, char **argv)
init_domain_list();
+ init_idmap_child();
+
/* Loop waiting for requests */
- process_loop();
+ while (1)
+ process_loop();
trustdom_cache_shutdown();