/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
- * Copyright 1998-2010 The OpenLDAP Foundation.
+ * Copyright 1998-2014 The OpenLDAP Foundation.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
ber_sockbuf_free( connections[i].c_sb );
ldap_pvt_thread_mutex_destroy( &connections[i].c_mutex );
ldap_pvt_thread_mutex_destroy( &connections[i].c_write1_mutex );
- ldap_pvt_thread_mutex_destroy( &connections[i].c_write2_mutex );
ldap_pvt_thread_cond_destroy( &connections[i].c_write1_cv );
- ldap_pvt_thread_cond_destroy( &connections[i].c_write2_cv );
#ifdef LDAP_SLAPI
if ( slapi_plugins_used ) {
slapi_int_free_object_extensions( SLAPI_X_EXT_CONNECTION,
int connections_timeout_idle(time_t now)
{
int i = 0, writers = 0;
- int connindex;
+ ber_socket_t connindex;
Connection* c;
- time_t old;
-
- old = slapd_get_writetime();
for( c = connection_first( &connindex );
c != NULL;
c = connection_next( c, &connindex ) )
{
/* Don't timeout a slow-running request or a persistent
- * outbound connection. But if it has a writewaiter, see
- * if the waiter has been there too long.
+ * outbound connection.
*/
if(( c->c_n_ops_executing && !c->c_writewaiter)
|| c->c_conn_state == SLAP_C_CLIENT ) {
i++;
continue;
}
- if ( c->c_writewaiter && global_writetimeout ) {
- writers = 1;
- if( difftime( c->c_activitytime+global_writetimeout, now) < 0 ) {
- /* close it */
- connection_closing( c, "writetimeout" );
- connection_close( c );
- i++;
- }
- }
}
connection_done( c );
- if ( old && !writers )
- slapd_clr_writetime( old );
return i;
}
+/* Drop all client connections */
+void connections_drop()
+{
+ Connection* c;
+ ber_socket_t connindex;
+
+ for( c = connection_first( &connindex );
+ c != NULL;
+ c = connection_next( c, &connindex ) )
+ {
+ /* Don't close a slow-running request or a persistent
+ * outbound connection.
+ */
+ if(( c->c_n_ops_executing && !c->c_writewaiter)
+ || c->c_conn_state == SLAP_C_CLIENT ) {
+ continue;
+ }
+ connection_closing( c, "dropping" );
+ connection_close( c );
+ }
+ connection_done( c );
+}
+
static Connection* connection_get( ber_socket_t s )
{
Connection *c;
c->c_sasl_sockctx = NULL;
c->c_sasl_extra = NULL;
c->c_sasl_bindop = NULL;
+ c->c_sasl_cbind = NULL;
c->c_sb = ber_sockbuf_alloc( );
/* should check status of thread calls */
ldap_pvt_thread_mutex_init( &c->c_mutex );
ldap_pvt_thread_mutex_init( &c->c_write1_mutex );
- ldap_pvt_thread_mutex_init( &c->c_write2_mutex );
ldap_pvt_thread_cond_init( &c->c_write1_cv );
- ldap_pvt_thread_cond_init( &c->c_write2_cv );
#ifdef LDAP_SLAPI
if ( slapi_plugins_used ) {
assert( c->c_sasl_sockctx == NULL );
assert( c->c_sasl_extra == NULL );
assert( c->c_sasl_bindop == NULL );
+ assert( c->c_sasl_cbind == NULL );
assert( c->c_currentber == NULL );
assert( c->c_writewaiter == 0);
assert( c->c_writers == 0);
slap_sasl_external( c, ssf, authid );
slapd_add_internal( s, 1 );
- ldap_pvt_thread_mutex_unlock( &c->c_mutex );
backend_connection_init(c);
+ ldap_pvt_thread_mutex_unlock( &c->c_mutex );
+
+ if ( !(flags & CONN_IS_UDP ))
+ Statslog( LDAP_DEBUG_STATS,
+ "conn=%ld fd=%ld ACCEPT from %s (%s)\n",
+ id, (long) s, peername, listener->sl_name.bv_val, 0 );
return c;
}
ldap_pvt_thread_cond_broadcast( &c->c_write1_cv );
ldap_pvt_thread_mutex_unlock( &c->c_write1_mutex );
if ( c->c_writewaiter ) {
- ldap_pvt_thread_mutex_lock( &c->c_write2_mutex );
- ldap_pvt_thread_cond_signal( &c->c_write2_cv );
- slapd_clr_write( c->c_sd, 1 );
- ldap_pvt_thread_mutex_unlock( &c->c_write2_mutex );
+ slapd_shutsock( c->c_sd );
}
ldap_pvt_thread_mutex_lock( &c->c_write1_mutex );
while ( c->c_writers ) {
return id;
}
+/*
+ * Loop through the connections:
+ *
+ * for (c = connection_first(&i); c; c = connection_next(c, &i)) ...;
+ * connection_done(c);
+ *
+ * 'i' is the cursor, initialized by connection_first().
+ * 'c_mutex' is locked in the returned connection. The functions must
+ * be passed the previous return value so they can unlock it again.
+ */
+
Connection* connection_first( ber_socket_t *index )
{
assert( connections != NULL );
return connection_next(NULL, index);
}
+/* Next connection in loop, see connection_first() */
Connection* connection_next( Connection *c, ber_socket_t *index )
{
assert( connections != NULL );
return c;
}
+/* End connection loop, see connection_first() */
void connection_done( Connection *c )
{
assert( connections != NULL );
if ( rc )
return rc;
- /* Don't let blocked writers block a pause request */
- if ( connections[s].c_writewaiter &&
- ldap_pvt_thread_pool_pausing( &connection_pool ))
- connection_wake_writers( &connections[s] );
-
rc = ldap_pvt_thread_pool_submit( &connection_pool,
connection_read_thread, (void *)(long)s );
} else if ( rc == 0 ) {
void *ssl;
struct berval authid = BER_BVNULL;
+ char msgbuf[32];
c->c_needs_tls_accept = 0;
"unable to get TLS client DN, error=%d id=%lu\n",
s, rc, c->c_connid );
}
+ sprintf(msgbuf, "tls_ssf=%u ssf=%u", c->c_tls_ssf, c->c_ssf);
Statslog( LDAP_DEBUG_STATS,
- "conn=%lu fd=%d TLS established tls_ssf=%u ssf=%u\n",
- c->c_connid, (int) s, c->c_tls_ssf, c->c_ssf, 0 );
+ "conn=%lu fd=%d TLS established %s tls_proto=%s tls_cipher=%s\n",
+ c->c_connid, (int) s,
+ msgbuf, ldap_pvt_tls_get_version( ssl ), ldap_pvt_tls_get_cipher( ssl ));
slap_sasl_external( c, c->c_tls_ssf, &authid );
if ( authid.bv_val ) free( authid.bv_val );
+ {
+ char cbinding[64];
+ struct berval cbv = { sizeof(cbinding), cbinding };
+ if ( ldap_pvt_tls_get_unique( ssl, &cbv, 1 ))
+ slap_sasl_cbinding( c, &cbv );
+ }
} else if ( rc == 1 && ber_sockbuf_ctrl( c->c_sb,
LBER_SB_OPT_NEEDS_WRITE, NULL )) { /* need to retry */
slapd_set_write( s, 1 );
#ifdef LDAP_CONNECTIONLESS
if ( conn->c_is_udp ) {
+#if defined(LDAP_PF_INET6)
+ char peername[sizeof("IP=[ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]:65535")];
+ char addr[INET6_ADDRSTRLEN];
+#else
char peername[sizeof("IP=255.255.255.255:65336")];
-
- len = ber_int_sb_read(conn->c_sb, &peeraddr, sizeof(struct sockaddr));
- if (len != sizeof(struct sockaddr)) return 1;
-
- sprintf( peername, "IP=%s:%d",
- inet_ntoa( peeraddr.sa_in_addr.sin_addr ),
- (unsigned) ntohs( peeraddr.sa_in_addr.sin_port ) );
+ char addr[INET_ADDRSTRLEN];
+#endif
+ const char *peeraddr_string = NULL;
+
+ len = ber_int_sb_read(conn->c_sb, &peeraddr, sizeof(Sockaddr));
+ if (len != sizeof(Sockaddr)) return 1;
+
+#if defined(LDAP_PF_INET6)
+ if (peeraddr.sa_addr.sa_family == AF_INET6) {
+ if ( IN6_IS_ADDR_V4MAPPED(&peeraddr.sa_in6_addr.sin6_addr) ) {
+#if defined( HAVE_GETADDRINFO ) && defined( HAVE_INET_NTOP )
+ peeraddr_string = inet_ntop( AF_INET,
+ ((struct in_addr *)&peeraddr.sa_in6_addr.sin6_addr.s6_addr[12]),
+ addr, sizeof(addr) );
+#else /* ! HAVE_GETADDRINFO || ! HAVE_INET_NTOP */
+ peeraddr_string = inet_ntoa( *((struct in_addr *)
+ &peeraddr.sa_in6_addr.sin6_addr.s6_addr[12]) );
+#endif /* ! HAVE_GETADDRINFO || ! HAVE_INET_NTOP */
+ if ( !peeraddr_string ) peeraddr_string = SLAP_STRING_UNKNOWN;
+ sprintf( peername, "IP=%s:%d", peeraddr_string,
+ (unsigned) ntohs( peeraddr.sa_in6_addr.sin6_port ) );
+ } else {
+ peeraddr_string = inet_ntop( AF_INET6,
+ &peeraddr.sa_in6_addr.sin6_addr,
+ addr, sizeof addr );
+ if ( !peeraddr_string ) peeraddr_string = SLAP_STRING_UNKNOWN;
+ sprintf( peername, "IP=[%s]:%d", peeraddr_string,
+ (unsigned) ntohs( peeraddr.sa_in6_addr.sin6_port ) );
+ }
+ } else
+#endif
+#if defined( HAVE_GETADDRINFO ) && defined( HAVE_INET_NTOP )
+ {
+ peeraddr_string = inet_ntop( AF_INET, &peeraddr.sa_in_addr.sin_addr,
+ addr, sizeof(addr) );
+#else /* ! HAVE_GETADDRINFO || ! HAVE_INET_NTOP */
+ peeraddr_string = inet_ntoa( peeraddr.sa_in_addr.sin_addr );
+#endif /* ! HAVE_GETADDRINFO || ! HAVE_INET_NTOP */
+ sprintf( peername, "IP=%s:%d",
+ peeraddr_string,
+ (unsigned) ntohs( peeraddr.sa_in_addr.sin_port ) );
+ }
Statslog( LDAP_DEBUG_STATS,
"conn=%lu UDP request from %s (%s) accepted.\n",
conn->c_connid, peername, conn->c_sock_name.bv_val, 0, 0 );
#ifdef LDAP_CONNECTIONLESS
if( conn->c_is_udp ) {
if( tag == LBER_OCTETSTRING ) {
- ber_get_stringa( ber, &cdn );
- tag = ber_peek_tag(ber, &len);
+ if ( (tag = ber_get_stringa( ber, &cdn )) != LBER_ERROR )
+ tag = ber_peek_tag( ber, &len );
}
if( tag != LDAP_REQ_ABANDON && tag != LDAP_REQ_SEARCH ) {
Debug( LDAP_DEBUG_ANY, "invalid req for UDP 0x%lx\n", tag, 0, 0 );
{
Connection *c;
Operation *op;
+ int wantwrite;
assert( connections != NULL );
- slapd_clr_write( s, 0 );
-
c = connection_get( s );
if( c == NULL ) {
Debug( LDAP_DEBUG_ANY,
return -1;
}
+ slapd_clr_write( s, 0 );
+
#ifdef HAVE_TLS
if ( c->c_is_tls && c->c_needs_tls_accept ) {
connection_return( c );
Debug( LDAP_DEBUG_TRACE,
"connection_write(%d): waking output for id=%lu\n",
s, c->c_connid, 0 );
- ldap_pvt_thread_mutex_lock( &c->c_write2_mutex );
- ldap_pvt_thread_cond_signal( &c->c_write2_cv );
- ldap_pvt_thread_mutex_unlock( &c->c_write2_mutex );
- if ( ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_NEEDS_READ, NULL ) ) {
- slapd_set_read( s, 1 );
+ wantwrite = ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_NEEDS_WRITE, NULL );
+ if ( ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_NEEDS_READ, NULL )) {
+ /* don't wakeup twice */
+ slapd_set_read( s, !wantwrite );
}
- if ( ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_NEEDS_WRITE, NULL ) ) {
+ if ( wantwrite ) {
slapd_set_write( s, 1 );
}