X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Fconnection.c;h=3e039004975e4276395df29e4fe58fdaa826dd43;hb=4f05d992f2146921dbc13d3477de9918f20172b9;hp=12dbb7c1fbbd99d0f47ed566aab8a8a4e8c35f99;hpb=13f52646b26e3afbb16e78c2487f19f7854a9180;p=openldap diff --git a/servers/slapd/connection.c b/servers/slapd/connection.c index 12dbb7c1fb..3e03900497 100644 --- a/servers/slapd/connection.c +++ b/servers/slapd/connection.c @@ -1,7 +1,7 @@ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * - * 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 @@ -154,9 +154,7 @@ int connections_destroy(void) 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, @@ -209,19 +207,15 @@ int connections_shutdown(void) 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 ) { @@ -236,23 +230,35 @@ int connections_timeout_idle(time_t now) 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; @@ -382,6 +388,7 @@ Connection * connection_init( 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( ); @@ -395,9 +402,7 @@ Connection * connection_init( /* 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 ) { @@ -427,6 +432,7 @@ Connection * connection_init( 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); @@ -546,9 +552,14 @@ Connection * connection_init( 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; } @@ -749,10 +760,7 @@ connection_wake_writers( Connection *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 ) { @@ -840,6 +848,17 @@ unsigned long connections_nextid(void) 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 ); @@ -856,6 +875,7 @@ Connection* connection_first( ber_socket_t *index ) return connection_next(NULL, index); } +/* Next connection in loop, see connection_first() */ Connection* connection_next( Connection *c, ber_socket_t *index ) { assert( connections != NULL ); @@ -904,6 +924,7 @@ Connection* connection_next( Connection *c, ber_socket_t *index ) return c; } +/* End connection loop, see connection_first() */ void connection_done( Connection *c ) { assert( connections != NULL ); @@ -1267,11 +1288,6 @@ int connection_read_activate( ber_socket_t s ) 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 ); @@ -1344,6 +1360,7 @@ connection_read( ber_socket_t s, conn_readinfo *cri ) } else if ( rc == 0 ) { void *ssl; struct berval authid = BER_BVNULL; + char msgbuf[32]; c->c_needs_tls_accept = 0; @@ -1361,11 +1378,19 @@ connection_read( ber_socket_t s, conn_readinfo *cri ) "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 ); @@ -1474,14 +1499,53 @@ connection_input( Connection *conn , conn_readinfo *cri ) #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 ); @@ -1526,8 +1590,8 @@ connection_input( Connection *conn , conn_readinfo *cri ) #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 ); @@ -1857,11 +1921,10 @@ int connection_write(ber_socket_t s) { 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, @@ -1870,6 +1933,8 @@ int connection_write(ber_socket_t s) return -1; } + slapd_clr_write( s, 0 ); + #ifdef HAVE_TLS if ( c->c_is_tls && c->c_needs_tls_accept ) { connection_return( c ); @@ -1883,14 +1948,13 @@ int connection_write(ber_socket_t s) 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 ); }