diff options
author | Gerald Carter <jerry@samba.org> | 2005-06-08 22:10:34 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 10:57:08 -0500 |
commit | fed660877c16562265327c6093ea645cf4176b5c (patch) | |
tree | e92ae1356542ba095d806bbe1093fa56fbc8ddcc /source3/nsswitch/winbindd.c | |
parent | 66bb4f03c3466205488f72e4878e8801c5bbb295 (diff) | |
download | samba-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.c | 733 |
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(); |