/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
- * Copyright 1998-2010 The OpenLDAP Foundation.
+ * Copyright 1998-2011 The OpenLDAP Foundation.
* Portions Copyright 2007 by Howard Chu, Symas Corporation.
* All rights reserved.
*
#endif /* LDAP_TCP_BUFFER */
Listener **slap_listeners = NULL;
+static volatile sig_atomic_t listening = 1; /* 0 when slap_listeners closed */
#ifndef SLAPD_LISTEN_BACKLOG
#define SLAPD_LISTEN_BACKLOG 1024
# define SLAP_EVENT_WAIT(t, tvp, nsp) do { \
int i; \
- *(nsp) = select( SLAP_EVENT_MAX, &readfds, \
+ *(nsp) = select( SLAP_EVENT_MAX(t), &readfds, \
nwriters > 0 ? &writefds : NULL, NULL, (tvp) ); \
for ( i=0; i<readfds.fd_count; i++) { \
int fd = slapd_sock2fd(readfds.fd_array[i]); \
slap_daemon[t].sd_flags = (char *)(slapd_ws_sockets + dtblsize); \
slap_daemon[t].sd_rflags = slap_daemon[t].sd_flags + dtblsize; \
memset( slap_daemon[t].sd_flags, 0, dtblsize ); \
- slapd_ws_sockets[0] = wake_sds[t][0]; \
- slapd_ws_sockets[1] = wake_sds[t][1]; \
- wake_sds[0] = 0; \
- wake_sds[1] = 1; \
- slap_daemon[t].sd_nfds = 2; \
+ slapd_ws_sockets[t*2] = wake_sds[t][0]; \
+ slapd_ws_sockets[t*2+1] = wake_sds[t][1]; \
+ wake_sds[t][0] = t*2; \
+ wake_sds[t][1] = t*2+1; \
+ slap_daemon[t].sd_nfds = t*2 + 2; \
} while ( 0 )
# define SLAP_SOCK_DESTROY(t) do { \
# define SLAP_EVENT_CLR_WRITE(fd) FD_CLR((fd), &writefds)
# define SLAP_EVENT_WAIT(t, tvp, nsp) do { \
- *(nsp) = select( SLAP_EVENT_MAX, &readfds, \
+ *(nsp) = select( SLAP_EVENT_MAX(t), &readfds, \
nwriters > 0 ? &writefds : NULL, NULL, (tvp) ); \
} while (0)
# endif /* !HAVE_WINSOCK */
* the select() loop. Now that we're removing a session from our
* control, we can try to resume a dropped listener to use.
*/
- if ( emfile ) {
+ if ( emfile && listening ) {
int i;
for ( i = 0; slap_listeners[i] != NULL; i++ ) {
Listener *lr = slap_listeners[i];
switch ( (*sal)->sa_family ) {
#ifdef LDAP_PF_LOCAL
case AF_LOCAL: {
- char *addr = ((struct sockaddr_un *)*sal)->sun_path;
- l.sl_name.bv_len = strlen(addr) + sizeof("PATH=") - 1;
+ char *path = ((struct sockaddr_un *)*sal)->sun_path;
+ l.sl_name.bv_len = strlen(path) + STRLENOF("PATH=");
l.sl_name.bv_val = ber_memalloc( l.sl_name.bv_len + 1 );
snprintf( l.sl_name.bv_val, l.sl_name.bv_len + 1,
- "PATH=%s", addr );
+ "PATH=%s", path );
} break;
#endif /* LDAP_PF_LOCAL */
case AF_INET: {
- char *s;
-#if defined( HAVE_GETADDRINFO ) && defined( HAVE_INET_NTOP )
char addr[INET_ADDRSTRLEN];
- inet_ntop( AF_INET, &((struct sockaddr_in *)*sal)->sin_addr,
+ const char *s;
+#if defined( HAVE_GETADDRINFO ) && defined( HAVE_INET_NTOP )
+ s = inet_ntop( AF_INET, &((struct sockaddr_in *)*sal)->sin_addr,
addr, sizeof(addr) );
- s = addr;
#else /* ! HAVE_GETADDRINFO || ! HAVE_INET_NTOP */
s = inet_ntoa( ((struct sockaddr_in *) *sal)->sin_addr );
#endif /* ! HAVE_GETADDRINFO || ! HAVE_INET_NTOP */
+ if (!s) s = SLAP_STRING_UNKNOWN;
port = ntohs( ((struct sockaddr_in *)*sal) ->sin_port );
l.sl_name.bv_val =
ber_memalloc( sizeof("IP=255.255.255.255:65535") );
snprintf( l.sl_name.bv_val, sizeof("IP=255.255.255.255:65535"),
- "IP=%s:%d",
- s != NULL ? s : SLAP_STRING_UNKNOWN, port );
+ "IP=%s:%d", s, port );
l.sl_name.bv_len = strlen( l.sl_name.bv_val );
} break;
#ifdef LDAP_PF_INET6
case AF_INET6: {
char addr[INET6_ADDRSTRLEN];
- inet_ntop( AF_INET6, &((struct sockaddr_in6 *)*sal)->sin6_addr,
+ const char *s;
+ s = inet_ntop( AF_INET6, &((struct sockaddr_in6 *)*sal)->sin6_addr,
addr, sizeof addr);
+ if (!s) s = SLAP_STRING_UNKNOWN;
port = ntohs( ((struct sockaddr_in6 *)*sal)->sin6_port );
- l.sl_name.bv_len = strlen(addr) + sizeof("IP=[]:65535");
+ l.sl_name.bv_len = strlen(s) + sizeof("IP=[]:65535");
l.sl_name.bv_val = ber_memalloc( l.sl_name.bv_len );
snprintf( l.sl_name.bv_val, l.sl_name.bv_len, "IP=[%s]:%d",
- addr, port );
+ s, port );
l.sl_name.bv_len = strlen( l.sl_name.bv_val );
} break;
#endif /* LDAP_PF_INET6 */
wake_sds[i][1] = AC_SOCKET_INVALID;
}
- for ( i=0; i<MAX_DAEMON_THREADS; i++ )
- ldap_pvt_thread_mutex_init( &slap_daemon[i].sd_mutex );
+ ldap_pvt_thread_mutex_init( &slap_daemon[0].sd_mutex );
#ifdef HAVE_TCPD
ldap_pvt_thread_mutex_init( &sd_tcpd_mutex );
#endif /* TCP Wrappers */
{
int l;
+ if ( !listening )
+ return;
+ listening = 0;
+
for ( l = 0; slap_listeners[l] != NULL; l++ ) {
Listener *lr = slap_listeners[l];
- slap_listeners[l] = NULL;
if ( lr->sl_sd != AC_SOCKET_INVALID ) {
int s = lr->sl_sd;
slapd_close( s );
}
+ }
+}
+static void
+destroy_listeners( void )
+{
+ Listener *lr, **ll = slap_listeners;
+
+ if ( ll == NULL )
+ return;
+
+ while ( (lr = *ll++) != NULL ) {
if ( lr->sl_url.bv_val ) {
ber_memfree( lr->sl_url.bv_val );
}
free( lr );
}
+
+ free( slap_listeners );
+ slap_listeners = NULL;
}
static int
#endif /* SLAPD_RLOOKUPS */
char *dnsname = NULL;
- char *peeraddr = NULL;
+ const char *peeraddr = NULL;
+ /* we assume INET6_ADDRSTRLEN > INET_ADDRSTRLEN */
+ char addr[INET6_ADDRSTRLEN];
#ifdef LDAP_PF_LOCAL
char peername[MAXPATHLEN + sizeof("PATH=")];
#ifdef LDAP_PF_LOCAL_SENDMSG
# ifdef LDAP_PF_INET6
case AF_INET6:
if ( IN6_IS_ADDR_V4MAPPED(&from.sa_in6_addr.sin6_addr) ) {
+#if defined( HAVE_GETADDRINFO ) && defined( HAVE_INET_NTOP )
+ peeraddr = inet_ntop( AF_INET,
+ ((struct in_addr *)&from.sa_in6_addr.sin6_addr.s6_addr[12]),
+ addr, sizeof(addr) );
+#else /* ! HAVE_GETADDRINFO || ! HAVE_INET_NTOP */
peeraddr = inet_ntoa( *((struct in_addr *)
&from.sa_in6_addr.sin6_addr.s6_addr[12]) );
- sprintf( peername, "IP=%s:%d",
- peeraddr != NULL ? peeraddr : SLAP_STRING_UNKNOWN,
+#endif /* ! HAVE_GETADDRINFO || ! HAVE_INET_NTOP */
+ if ( !peeraddr ) peeraddr = SLAP_STRING_UNKNOWN;
+ sprintf( peername, "IP=%s:%d", peeraddr,
(unsigned) ntohs( from.sa_in6_addr.sin6_port ) );
} else {
- char addr[INET6_ADDRSTRLEN];
-
- peeraddr = (char *) inet_ntop( AF_INET6,
+ peeraddr = inet_ntop( AF_INET6,
&from.sa_in6_addr.sin6_addr,
addr, sizeof addr );
- sprintf( peername, "IP=[%s]:%d",
- peeraddr != NULL ? peeraddr : SLAP_STRING_UNKNOWN,
+ if ( !peeraddr ) peeraddr = SLAP_STRING_UNKNOWN;
+ sprintf( peername, "IP=[%s]:%d", peeraddr,
(unsigned) ntohs( from.sa_in6_addr.sin6_port ) );
}
break;
# endif /* LDAP_PF_INET6 */
- case AF_INET:
+ case AF_INET: {
+#if defined( HAVE_GETADDRINFO ) && defined( HAVE_INET_NTOP )
+ peeraddr = inet_ntop( AF_INET, &from.sa_in_addr.sin_addr,
+ addr, sizeof(addr) );
+#else /* ! HAVE_GETADDRINFO || ! HAVE_INET_NTOP */
peeraddr = inet_ntoa( from.sa_in_addr.sin_addr );
- sprintf( peername, "IP=%s:%d",
- peeraddr != NULL ? peeraddr : SLAP_STRING_UNKNOWN,
+#endif /* ! HAVE_GETADDRINFO || ! HAVE_INET_NTOP */
+ if ( !peeraddr ) peeraddr = SLAP_STRING_UNKNOWN;
+ sprintf( peername, "IP=%s:%d", peeraddr,
(unsigned) ntohs( from.sa_in_addr.sin_port ) );
- break;
+ } break;
default:
slapd_close(sfd);
ldap_pvt_thread_mutex_lock( &sd_tcpd_mutex );
rc = hosts_ctl("slapd",
dnsname != NULL ? dnsname : SLAP_STRING_UNKNOWN,
- peeraddr != NULL ? peeraddr : SLAP_STRING_UNKNOWN,
+ peeraddr,
SLAP_STRING_UNKNOWN );
ldap_pvt_thread_mutex_unlock( &sd_tcpd_mutex );
if ( !rc ) {
"fd=%ld DENIED from %s (%s)\n",
(long) sfd,
dnsname != NULL ? dnsname : SLAP_STRING_UNKNOWN,
- peeraddr != NULL ? peeraddr : SLAP_STRING_UNKNOWN,
- 0, 0 );
+ peeraddr, 0, 0 );
slapd_close(sfd);
return 0;
}
Debug( LDAP_DEBUG_TRACE, "slap_listener_activate(%d): %s\n",
sl->sl_sd, sl->sl_busy ? "busy" : "", 0 );
- sl->sl_busy++;
+ sl->sl_busy = 1;
rc = ldap_pvt_thread_pool_submit( &connection_pool,
slap_listener_thread, (void *) sl );
int l;
time_t last_idle_check = 0;
int ebadf = 0;
- int tid = (int)ptr;
+ int tid = *(int *)ptr;
#define SLAPD_IDLE_CHECK_LIMIT 4
nwriters = slap_daemon[tid].sd_nwriters;
+ if ( listening )
for ( l = 0; slap_listeners[l] != NULL; l++ ) {
Listener *lr = slap_listeners[l];
* true for Unix select and poll. We treat Windows select
* like this too, even though it's a kludge.
*/
+ if ( listening )
for ( l = 0; slap_listeners[l] != NULL; l++ ) {
int rc;
0, 0, 0 );
}
- if ( slapd_gentle_shutdown != 2 ) close_listeners ( 0 );
+ close_listeners( 0 );
if ( !slapd_gentle_shutdown ) {
slapd_abrupt_shutdown = 1;
}
ldap_pvt_thread_pool_destroy( &connection_pool, 1 );
- free( slap_listeners );
- slap_listeners = NULL;
-
return NULL;
}
if ( !c ) {
Debug( LDAP_DEBUG_TRACE,
"connectionless_init: failed on %s (%d)\n",
- lr->sl_url, lr->sl_sd, 0 );
+ lr->sl_url.bv_val, lr->sl_sd, 0 );
return -1;
}
lr->sl_is_udp++;
#endif /* LDAP_CONNECTIONLESS */
listener_tid = ch_malloc(slapd_daemon_threads * sizeof(ldap_pvt_thread_t));
- for ( i=0; i<slapd_daemon_threads; i++ )
+
+ /* daemon_init only inits element 0 */
+ for ( i=1; i<slapd_daemon_threads; i++ )
{
- if (i) {
- /* daemon_init only inits element 0 */
- if( (rc = lutil_pair( wake_sds[i] )) < 0 ) {
- Debug( LDAP_DEBUG_ANY,
- "daemon: lutil_pair() failed rc=%d\n", rc, 0, 0 );
- return rc;
- }
- ber_pvt_socket_set_nonblock( wake_sds[i][1], 1 );
+ ldap_pvt_thread_mutex_init( &slap_daemon[i].sd_mutex );
- SLAP_SOCK_INIT(i);
+ if( (rc = lutil_pair( wake_sds[i] )) < 0 ) {
+ Debug( LDAP_DEBUG_ANY,
+ "daemon: lutil_pair() failed rc=%d\n", rc, 0, 0 );
+ return rc;
}
+ ber_pvt_socket_set_nonblock( wake_sds[i][1], 1 );
+
+ SLAP_SOCK_INIT(i);
+ }
+ for ( i=0; i<slapd_daemon_threads; i++ )
+ {
/* listener as a separate THREAD */
rc = ldap_pvt_thread_create( &listener_tid[i],
- 0, slapd_daemon_task, (void *)i );
+ 0, slapd_daemon_task, (void *)&i );
if ( rc != 0 ) {
Debug( LDAP_DEBUG_ANY,
"listener ldap_pvt_thread_create failed (%d)\n", rc, 0, 0 );
return rc;
}
-
}
/* wait for the listener threads to complete */
for ( i=0; i<slapd_daemon_threads; i++ )
ldap_pvt_thread_join( listener_tid[i], (void *)NULL );
+ destroy_listeners();
ch_free( listener_tid );
return 0;
Listener **
slapd_get_listeners( void )
{
+ /* Could return array with no listeners if !listening, but current
+ * callers mostly look at the URLs. E.g. syncrepl uses this to
+ * identify the server, which means it wants the startup arguments.
+ */
return slap_listeners;
}
+/* Reject all incoming requests */
+void
+slap_suspend_listeners( void )
+{
+ int i;
+ for (i=0; slap_listeners[i]; i++) {
+ slap_listeners[i]->sl_mute = 1;
+ listen( slap_listeners[i]->sl_sd, 0 );
+ }
+}
+
+/* Resume after a suspend */
+void
+slap_resume_listeners( void )
+{
+ int i;
+ for (i=0; slap_listeners[i]; i++) {
+ slap_listeners[i]->sl_mute = 0;
+ listen( slap_listeners[i]->sl_sd, SLAPD_LISTEN_BACKLOG );
+ }
+}
+
void
slap_wake_listener()
{