|
|
dc8c34 |
From 43c715dfb8a72bd61e8cf2fd43324b7d3b1b5143 Mon Sep 17 00:00:00 2001
|
|
|
dc8c34 |
From: Rich Megginson <rmeggins@redhat.com>
|
|
|
dc8c34 |
Date: Fri, 10 May 2013 15:11:13 -0600
|
|
|
dc8c34 |
Subject: [PATCH 62/99] Ticket #47359 - new ldap connections can block ldaps
|
|
|
dc8c34 |
and ldapi connections
|
|
|
dc8c34 |
|
|
|
dc8c34 |
https://fedorahosted.org/389/ticket/47359
|
|
|
dc8c34 |
Reviewed by: lkrispen, nhosoi (Thanks!)
|
|
|
dc8c34 |
Branch: 389-ds-base-1.2.11
|
|
|
dc8c34 |
Fix Description: description
|
|
|
dc8c34 |
In the polling thread, first process all of the new connection requests from
|
|
|
dc8c34 |
the listening sockets, then process any new operation read requests
|
|
|
dc8c34 |
The listener_idxs keeps track of the index of the active listeners in the
|
|
|
dc8c34 |
poll fd array, and keeps a pointer to the listenfd object for that
|
|
|
dc8c34 |
listener. This allows us to very quickly scan through the poll fd array
|
|
|
dc8c34 |
and find the ready listeners. The work of scanning through the array
|
|
|
dc8c34 |
and handling the new connection requests has been moved to a new function
|
|
|
dc8c34 |
handle_listeners().
|
|
|
dc8c34 |
Platforms tested: RHEL6 x86_64
|
|
|
dc8c34 |
Flag Day: no
|
|
|
dc8c34 |
Doc impact: no
|
|
|
dc8c34 |
(cherry picked from commit 115ab1d9a3f026e8523b91bf62245a25454a3e8a)
|
|
|
dc8c34 |
(cherry picked from commit 24b751cc724468a7bce5f86848a82e4b03e24a3c)
|
|
|
dc8c34 |
(cherry picked from commit 5226ed9f2e585dc3d561f9286555efc7e3eea6b6)
|
|
|
dc8c34 |
(cherry picked from commit e0328aba6ed9254cf537f85927c55cbbb82cae77)
|
|
|
dc8c34 |
(cherry picked from commit 8a1fd0711e060aca3943ca346005bb43eddf82c4)
|
|
|
dc8c34 |
---
|
|
|
dc8c34 |
ldap/servers/slapd/daemon.c | 115 ++++++++++++++++++++++++--------------------
|
|
|
dc8c34 |
1 file changed, 62 insertions(+), 53 deletions(-)
|
|
|
dc8c34 |
|
|
|
dc8c34 |
diff --git a/ldap/servers/slapd/daemon.c b/ldap/servers/slapd/daemon.c
|
|
|
dc8c34 |
index 75a83c0..93ebe4a 100644
|
|
|
dc8c34 |
--- a/ldap/servers/slapd/daemon.c
|
|
|
dc8c34 |
+++ b/ldap/servers/slapd/daemon.c
|
|
|
dc8c34 |
@@ -136,6 +136,15 @@ void disk_monitoring_stop();
|
|
|
dc8c34 |
|
|
|
dc8c34 |
#define FDS_SIGNAL_PIPE 0
|
|
|
dc8c34 |
|
|
|
dc8c34 |
+typedef struct listener_info {
|
|
|
dc8c34 |
+ int idx; /* index of this listener in the ct->fd array */
|
|
|
dc8c34 |
+ PRFileDesc *listenfd; /* the listener fd */
|
|
|
dc8c34 |
+ int secure;
|
|
|
dc8c34 |
+ int local;
|
|
|
dc8c34 |
+} listener_info;
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+#define SLAPD_POLL_LISTEN_READY(xxflagsxx) (xxflagsxx & PR_POLL_READ)
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
static int get_configured_connection_table_size();
|
|
|
dc8c34 |
#ifdef RESOLVER_NEEDS_LOW_FILE_DESCRIPTORS
|
|
|
dc8c34 |
static void get_loopback_by_addr( void );
|
|
|
dc8c34 |
@@ -149,7 +158,7 @@ static PRFileDesc **createprlistensockets(unsigned short port,
|
|
|
dc8c34 |
static const char *netaddr2string(const PRNetAddr *addr, char *addrbuf,
|
|
|
dc8c34 |
size_t addrbuflen);
|
|
|
dc8c34 |
static void set_shutdown (int);
|
|
|
dc8c34 |
-static void setup_pr_read_pds(Connection_Table *ct, PRFileDesc **n_tcps, PRFileDesc **s_tcps, PRFileDesc **i_unix, PRIntn *num_to_read);
|
|
|
dc8c34 |
+static void setup_pr_read_pds(Connection_Table *ct, PRFileDesc **n_tcps, PRFileDesc **s_tcps, PRFileDesc **i_unix, PRIntn *num_to_read, listener_info *listener_idxs, int max_listeners);
|
|
|
dc8c34 |
|
|
|
dc8c34 |
#ifdef HPUX10
|
|
|
dc8c34 |
static void* catch_signals();
|
|
|
dc8c34 |
@@ -913,6 +922,30 @@ disk_monitoring_thread(void *nothing)
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
+static void
|
|
|
dc8c34 |
+handle_listeners(Connection_Table *ct, listener_info *listener_idxs, int n_listeners)
|
|
|
dc8c34 |
+{
|
|
|
dc8c34 |
+ int idx;
|
|
|
dc8c34 |
+ for (idx = 0; idx < n_listeners; ++idx) {
|
|
|
dc8c34 |
+ int fdidx = listener_idxs[idx].idx;
|
|
|
dc8c34 |
+ PRFileDesc *listenfd = listener_idxs[idx].listenfd;
|
|
|
dc8c34 |
+ int secure = listener_idxs[idx].secure;
|
|
|
dc8c34 |
+ int local = listener_idxs[idx].local;
|
|
|
dc8c34 |
+ if (fdidx && listenfd) {
|
|
|
dc8c34 |
+ if (SLAPD_POLL_LISTEN_READY(ct->fd[fdidx].out_flags)) {
|
|
|
dc8c34 |
+ /* accept() the new connection, put it on the active list for handle_pr_read_ready */
|
|
|
dc8c34 |
+ int rc = handle_new_connection(ct, SLAPD_INVALID_SOCKET, listenfd, secure, local);
|
|
|
dc8c34 |
+ if (rc) {
|
|
|
dc8c34 |
+ LDAPDebug1Arg(LDAP_DEBUG_CONNS, "Error accepting new connection listenfd=%d\n",
|
|
|
dc8c34 |
+ PR_FileDesc2NativeHandle(listenfd));
|
|
|
dc8c34 |
+ continue;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ return;
|
|
|
dc8c34 |
+}
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
void slapd_daemon( daemon_ports_t *ports )
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
/* We are passed some ports---one for regular connections, one
|
|
|
dc8c34 |
@@ -929,7 +962,6 @@ void slapd_daemon( daemon_ports_t *ports )
|
|
|
dc8c34 |
int s_tcps_native = 0;
|
|
|
dc8c34 |
PRFileDesc *s_tcps = NULL;
|
|
|
dc8c34 |
#else
|
|
|
dc8c34 |
- PRFileDesc *tcps = 0;
|
|
|
dc8c34 |
PRFileDesc **n_tcps = NULL;
|
|
|
dc8c34 |
PRFileDesc **s_tcps = NULL;
|
|
|
dc8c34 |
PRFileDesc **i_unix = NULL;
|
|
|
dc8c34 |
@@ -940,6 +972,8 @@ void slapd_daemon( daemon_ports_t *ports )
|
|
|
dc8c34 |
PRThread *time_thread_p;
|
|
|
dc8c34 |
int threads;
|
|
|
dc8c34 |
int in_referral_mode = config_check_referral_mode();
|
|
|
dc8c34 |
+ int n_listeners = 0; /* number of listener sockets */
|
|
|
dc8c34 |
+ listener_info *listener_idxs = NULL; /* array of indexes of listener sockets in the ct->fd array */
|
|
|
dc8c34 |
|
|
|
dc8c34 |
int connection_table_size = get_configured_connection_table_size();
|
|
|
dc8c34 |
the_connection_table= connection_table_new(connection_table_size);
|
|
|
dc8c34 |
@@ -1054,6 +1088,7 @@ void slapd_daemon( daemon_ports_t *ports )
|
|
|
dc8c34 |
netaddr2string(&ports->n_listenaddr, addrbuf, sizeof(addrbuf)),
|
|
|
dc8c34 |
ports->n_port, oserr, slapd_system_strerror( oserr ) );
|
|
|
dc8c34 |
g_set_shutdown( SLAPI_SHUTDOWN_EXIT );
|
|
|
dc8c34 |
+ n_listeners++;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
#else
|
|
|
dc8c34 |
if ( n_tcps != NULL ) {
|
|
|
dc8c34 |
@@ -1071,6 +1106,7 @@ void slapd_daemon( daemon_ports_t *ports )
|
|
|
dc8c34 |
slapd_pr_strerror( prerr ));
|
|
|
dc8c34 |
g_set_shutdown( SLAPI_SHUTDOWN_EXIT );
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
+ n_listeners++;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
#endif
|
|
|
dc8c34 |
@@ -1090,6 +1126,7 @@ void slapd_daemon( daemon_ports_t *ports )
|
|
|
dc8c34 |
slapd_pr_strerror( prerr ));
|
|
|
dc8c34 |
g_set_shutdown( SLAPI_SHUTDOWN_EXIT );
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
+ n_listeners++;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
@@ -1108,11 +1145,13 @@ void slapd_daemon( daemon_ports_t *ports )
|
|
|
dc8c34 |
slapd_pr_strerror( prerr ));
|
|
|
dc8c34 |
g_set_shutdown( SLAPI_SHUTDOWN_EXIT );
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
+ n_listeners++;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
#endif /* ENABLE_LDAPI */
|
|
|
dc8c34 |
#endif
|
|
|
dc8c34 |
|
|
|
dc8c34 |
+ listener_idxs = (listener_info *)slapi_ch_calloc(n_listeners, sizeof(*listener_idxs));
|
|
|
dc8c34 |
/* Now we write the pid file, indicating that the server is finally and listening for connections */
|
|
|
dc8c34 |
write_pid_file();
|
|
|
dc8c34 |
|
|
|
dc8c34 |
@@ -1125,9 +1164,6 @@ void slapd_daemon( daemon_ports_t *ports )
|
|
|
dc8c34 |
int oserr;
|
|
|
dc8c34 |
#endif
|
|
|
dc8c34 |
int select_return = 0;
|
|
|
dc8c34 |
- int secure = 0; /* is a new connection an SSL one ? */
|
|
|
dc8c34 |
- int local = 0; /* is new connection an ldapi one? */
|
|
|
dc8c34 |
- int i;
|
|
|
dc8c34 |
|
|
|
dc8c34 |
#ifndef _WIN32
|
|
|
dc8c34 |
PRErrorCode prerr;
|
|
|
dc8c34 |
@@ -1139,7 +1175,7 @@ void slapd_daemon( daemon_ports_t *ports )
|
|
|
dc8c34 |
/* This select needs to timeout to give the server a chance to test for shutdown */
|
|
|
dc8c34 |
select_return = select(connection_table_size, &readfds, NULL, 0, &wakeup_timer);
|
|
|
dc8c34 |
#else
|
|
|
dc8c34 |
- setup_pr_read_pds(the_connection_table,n_tcps,s_tcps,i_unix,&num_poll);
|
|
|
dc8c34 |
+ setup_pr_read_pds(the_connection_table,n_tcps,s_tcps,i_unix,&num_poll,listener_idxs,n_listeners);
|
|
|
dc8c34 |
select_return = POLL_FN(the_connection_table->fd, num_poll, pr_timeout);
|
|
|
dc8c34 |
#endif
|
|
|
dc8c34 |
switch (select_return) {
|
|
|
dc8c34 |
@@ -1175,52 +1211,8 @@ void slapd_daemon( daemon_ports_t *ports )
|
|
|
dc8c34 |
handle_read_ready(the_connection_table,&readfds);
|
|
|
dc8c34 |
clear_signal(&readfds);
|
|
|
dc8c34 |
#else
|
|
|
dc8c34 |
- tcps = NULL;
|
|
|
dc8c34 |
- /* info for n_tcps is always in fd[n_tcps ~ n_tcpe] */
|
|
|
dc8c34 |
- if( NULL != n_tcps ) {
|
|
|
dc8c34 |
- for (i = the_connection_table->n_tcps;
|
|
|
dc8c34 |
- i < the_connection_table->n_tcpe; i++) {
|
|
|
dc8c34 |
- if (the_connection_table->fd[i].out_flags &
|
|
|
dc8c34 |
- SLAPD_POLL_FLAGS ) {
|
|
|
dc8c34 |
- /* tcps = n_tcps[i - the_connection_table->n_tcps]; */
|
|
|
dc8c34 |
- tcps = the_connection_table->fd[i].fd;
|
|
|
dc8c34 |
- break;
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
- /* info for s_tcps is always in fd[s_tcps ~ s_tcpe] */
|
|
|
dc8c34 |
- if ( NULL == tcps && NULL != s_tcps ) {
|
|
|
dc8c34 |
- for (i = the_connection_table->s_tcps;
|
|
|
dc8c34 |
- i < the_connection_table->s_tcpe; i++) {
|
|
|
dc8c34 |
- if (the_connection_table->fd[i].out_flags &
|
|
|
dc8c34 |
- SLAPD_POLL_FLAGS ) {
|
|
|
dc8c34 |
- /* tcps = s_tcps[i - the_connection_table->s_tcps]; */
|
|
|
dc8c34 |
- tcps = the_connection_table->fd[i].fd;
|
|
|
dc8c34 |
- secure = 1;
|
|
|
dc8c34 |
- break;
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
-#if defined(ENABLE_LDAPI)
|
|
|
dc8c34 |
- /* info for i_unix is always in fd[i_unixs ~ i_unixe] */
|
|
|
dc8c34 |
- if ( NULL == tcps && NULL != i_unix ) {
|
|
|
dc8c34 |
- for (i = the_connection_table->i_unixs;
|
|
|
dc8c34 |
- i < the_connection_table->i_unixe; i++) {
|
|
|
dc8c34 |
- if (the_connection_table->fd[i].out_flags &
|
|
|
dc8c34 |
- SLAPD_POLL_FLAGS ) {
|
|
|
dc8c34 |
- /* tcps = i_unix[i - the_connection_table->i_unixs]; */
|
|
|
dc8c34 |
- tcps = the_connection_table->fd[i].fd;
|
|
|
dc8c34 |
- local = 1;
|
|
|
dc8c34 |
- break;
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
-#endif /* ENABLE_LDAPI */
|
|
|
dc8c34 |
-
|
|
|
dc8c34 |
- /* If so, then handle a new connection */
|
|
|
dc8c34 |
- if ( tcps != NULL ) {
|
|
|
dc8c34 |
- handle_new_connection(the_connection_table,SLAPD_INVALID_SOCKET,tcps,secure,local);
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
+ /* handle new connections from the listeners */
|
|
|
dc8c34 |
+ handle_listeners(the_connection_table, listener_idxs, n_listeners);
|
|
|
dc8c34 |
/* handle new data ready */
|
|
|
dc8c34 |
handle_pr_read_ready(the_connection_table, connection_table_size);
|
|
|
dc8c34 |
clear_signal(the_connection_table->fd);
|
|
|
dc8c34 |
@@ -1548,7 +1540,7 @@ static void setup_read_fds(Connection_Table *ct, fd_set *readfds, int n_tcps, in
|
|
|
dc8c34 |
static int first_time_setup_pr_read_pds = 1;
|
|
|
dc8c34 |
static int listen_addr_count = 0;
|
|
|
dc8c34 |
static void
|
|
|
dc8c34 |
-setup_pr_read_pds(Connection_Table *ct, PRFileDesc **n_tcps, PRFileDesc **s_tcps, PRFileDesc **i_unix, PRIntn *num_to_read)
|
|
|
dc8c34 |
+setup_pr_read_pds(Connection_Table *ct, PRFileDesc **n_tcps, PRFileDesc **s_tcps, PRFileDesc **i_unix, PRIntn *num_to_read, listener_info *listener_idxs, int max_listeners)
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
Connection *c= NULL;
|
|
|
dc8c34 |
Connection *next= NULL;
|
|
|
dc8c34 |
@@ -1558,6 +1550,7 @@ setup_pr_read_pds(Connection_Table *ct, PRFileDesc **n_tcps, PRFileDesc **s_tcps
|
|
|
dc8c34 |
PRIntn count = 0;
|
|
|
dc8c34 |
slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
|
|
|
dc8c34 |
int max_threads_per_conn = config_get_maxthreadsperconn();
|
|
|
dc8c34 |
+ int n_listeners = 0;
|
|
|
dc8c34 |
|
|
|
dc8c34 |
accept_new_connections = ((ct->size - g_get_current_conn_count())
|
|
|
dc8c34 |
> slapdFrontendConfig->reservedescriptors);
|
|
|
dc8c34 |
@@ -1609,6 +1602,9 @@ setup_pr_read_pds(Connection_Table *ct, PRFileDesc **n_tcps, PRFileDesc **s_tcps
|
|
|
dc8c34 |
ct->fd[count].fd = *fdesc;
|
|
|
dc8c34 |
ct->fd[count].in_flags = SLAPD_POLL_FLAGS;
|
|
|
dc8c34 |
ct->fd[count].out_flags = 0;
|
|
|
dc8c34 |
+ listener_idxs[n_listeners].listenfd = *fdesc;
|
|
|
dc8c34 |
+ listener_idxs[n_listeners].idx = count;
|
|
|
dc8c34 |
+ n_listeners++;
|
|
|
dc8c34 |
LDAPDebug( LDAP_DEBUG_HOUSE,
|
|
|
dc8c34 |
"listening for connections on %d\n", socketdesc, 0, 0 );
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
@@ -1627,6 +1623,10 @@ setup_pr_read_pds(Connection_Table *ct, PRFileDesc **n_tcps, PRFileDesc **s_tcps
|
|
|
dc8c34 |
ct->fd[count].fd = *fdesc;
|
|
|
dc8c34 |
ct->fd[count].in_flags = SLAPD_POLL_FLAGS;
|
|
|
dc8c34 |
ct->fd[count].out_flags = 0;
|
|
|
dc8c34 |
+ listener_idxs[n_listeners].listenfd = *fdesc;
|
|
|
dc8c34 |
+ listener_idxs[n_listeners].idx = count;
|
|
|
dc8c34 |
+ listener_idxs[n_listeners].secure = 1;
|
|
|
dc8c34 |
+ n_listeners++;
|
|
|
dc8c34 |
LDAPDebug( LDAP_DEBUG_HOUSE,
|
|
|
dc8c34 |
"listening for SSL connections on %d\n", socketdesc, 0, 0 );
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
@@ -1648,6 +1648,10 @@ setup_pr_read_pds(Connection_Table *ct, PRFileDesc **n_tcps, PRFileDesc **s_tcps
|
|
|
dc8c34 |
ct->fd[count].fd = *fdesc;
|
|
|
dc8c34 |
ct->fd[count].in_flags = SLAPD_POLL_FLAGS;
|
|
|
dc8c34 |
ct->fd[count].out_flags = 0;
|
|
|
dc8c34 |
+ listener_idxs[n_listeners].listenfd = *fdesc;
|
|
|
dc8c34 |
+ listener_idxs[n_listeners].idx = count;
|
|
|
dc8c34 |
+ listener_idxs[n_listeners].local = 1;
|
|
|
dc8c34 |
+ n_listeners++;
|
|
|
dc8c34 |
LDAPDebug( LDAP_DEBUG_HOUSE,
|
|
|
dc8c34 |
"listening for LDAPI connections on %d\n", socketdesc, 0, 0 );
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
@@ -1661,6 +1665,11 @@ setup_pr_read_pds(Connection_Table *ct, PRFileDesc **n_tcps, PRFileDesc **s_tcps
|
|
|
dc8c34 |
|
|
|
dc8c34 |
first_time_setup_pr_read_pds = 0;
|
|
|
dc8c34 |
listen_addr_count = count;
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ if (n_listeners < max_listeners) {
|
|
|
dc8c34 |
+ listener_idxs[n_listeners].idx = 0;
|
|
|
dc8c34 |
+ listener_idxs[n_listeners].listenfd = NULL;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
/* count is the number of entries we've place in the fds array.
|
|
|
dc8c34 |
--
|
|
|
dc8c34 |
1.8.1.4
|
|
|
dc8c34 |
|