From 5725d5d6e965933c86ec692ac5a274bc09a8c223 Mon Sep 17 00:00:00 2001 From: Ralf Haferkamp Date: Wed, 6 May 2009 13:14:36 +0000 Subject: [PATCH] Introduce options to configure tcp-keepalive settings per connection. These settings only work on Linux and are ignore when not supported (see discussion on -devel) --- include/ldap.h | 7 +++++ libraries/libldap/init.c | 3 +++ libraries/libldap/ldap-int.h | 8 ++++++ libraries/libldap/options.c | 25 ++++++++++++++++++ libraries/libldap/os-ip.c | 51 ++++++++++++++++++++++++++++++++++++ 5 files changed, 94 insertions(+) diff --git a/include/ldap.h b/include/ldap.h index 695996c1a8..16b62dc0a8 100644 --- a/include/ldap.h +++ b/include/ldap.h @@ -191,6 +191,13 @@ LDAP_BEGIN_DECL #define LDAP_OPT_X_GSSAPI_DO_NOT_FREE_CONTEXT 0x6200 #define LDAP_OPT_X_GSSAPI_ALLOW_REMOTE_PRINCIPAL 0x6201 +/* + * OpenLDAP per connection tcp-keepalive settings + * (Linux only, ignored where unsupported) + */ +#define LDAP_OPT_X_KEEPALIVE_IDLE 0x6300 +#define LDAP_OPT_X_KEEPALIVE_PROBES 0x6301 +#define LDAP_OPT_X_KEEPALIVE_INTERVAL 0x6302 /* Private API Extensions -- reserved for application use */ #define LDAP_OPT_PRIVATE_EXTENSION_BASE 0x7000 /* Private API inclusive */ diff --git a/libraries/libldap/init.c b/libraries/libldap/init.c index 4f88dc672a..7349e113ae 100644 --- a/libraries/libldap/init.c +++ b/libraries/libldap/init.c @@ -545,6 +545,9 @@ void ldap_int_initialize_global_options( struct ldapoptions *gopts, int *dbglvl gopts->ldo_tls_connect_arg = NULL; gopts->ldo_tls_require_cert = LDAP_OPT_X_TLS_DEMAND; #endif + gopts->ldo_keepalive_probes = 0; + gopts->ldo_keepalive_interval = 0; + gopts->ldo_keepalive_idle = 0; gopts->ldo_valid = LDAP_INITIALIZED; return; diff --git a/libraries/libldap/ldap-int.h b/libraries/libldap/ldap-int.h index 48b6ccd298..6708503069 100644 --- a/libraries/libldap/ldap-int.h +++ b/libraries/libldap/ldap-int.h @@ -244,6 +244,14 @@ struct ldapoptions { unsigned ldo_gssapi_options; #endif + /* + * Per connection tcp-keepalive settings (Linux only, + * ignored where unsupported) + */ + ber_int_t ldo_keepalive_idle; + ber_int_t ldo_keepalive_probes; + ber_int_t ldo_keepalive_interval; + int ldo_refhoplimit; /* limit on referral nesting */ /* LDAPv3 server and client controls */ diff --git a/libraries/libldap/options.c b/libraries/libldap/options.c index 0b25aa6946..e9ae6d4da2 100644 --- a/libraries/libldap/options.c +++ b/libraries/libldap/options.c @@ -342,6 +342,18 @@ ldap_get_option( case LDAP_OPT_DEBUG_LEVEL: * (int *) outvalue = lo->ldo_debug; return LDAP_OPT_SUCCESS; + + case LDAP_OPT_X_KEEPALIVE_IDLE: + * (int *) outvalue = lo->ldo_keepalive_idle; + return LDAP_OPT_SUCCESS; + + case LDAP_OPT_X_KEEPALIVE_PROBES: + * (int *) outvalue = lo->ldo_keepalive_probes; + return LDAP_OPT_SUCCESS; + + case LDAP_OPT_X_KEEPALIVE_INTERVAL: + * (int *) outvalue = lo->ldo_keepalive_interval; + return LDAP_OPT_SUCCESS; default: #ifdef HAVE_TLS @@ -681,6 +693,9 @@ ldap_set_option( case LDAP_OPT_TIMEOUT: case LDAP_OPT_NETWORK_TIMEOUT: case LDAP_OPT_CONNECT_CB: + case LDAP_OPT_X_KEEPALIVE_IDLE: + case LDAP_OPT_X_KEEPALIVE_PROBES : + case LDAP_OPT_X_KEEPALIVE_INTERVAL : if(invalue == NULL) { /* no place to set from */ return LDAP_OPT_ERROR; @@ -770,6 +785,16 @@ ldap_set_option( lo->ldo_conn_cbs = ll; } return LDAP_OPT_SUCCESS; + case LDAP_OPT_X_KEEPALIVE_IDLE: + lo->ldo_keepalive_idle = * (const int *) invalue; + return LDAP_OPT_SUCCESS; + case LDAP_OPT_X_KEEPALIVE_PROBES : + lo->ldo_keepalive_probes = * (const int *) invalue; + return LDAP_OPT_SUCCESS; + case LDAP_OPT_X_KEEPALIVE_INTERVAL : + lo->ldo_keepalive_interval = * (const int *) invalue; + return LDAP_OPT_SUCCESS; + } return LDAP_OPT_ERROR; } diff --git a/libraries/libldap/os-ip.c b/libraries/libldap/os-ip.c index a3a3306f93..d2d0fac434 100644 --- a/libraries/libldap/os-ip.c +++ b/libraries/libldap/os-ip.c @@ -142,6 +142,57 @@ ldap_int_prepare_socket(LDAP *ld, int s, int proto ) "setsockopt(%d, SO_KEEPALIVE) failed (ignored).\n", s, 0, 0 ); } + if ( ld->ld_options.ldo_keepalive_idle > 0 ) + { +#ifdef TCP_KEEPIDLE + if ( setsockopt( s, SOL_TCP, TCP_KEEPIDLE, + (void*) &ld->ld_options.ldo_keepalive_idle, + sizeof(ld->ld_options.ldo_keepalive_idle) ) == AC_SOCKET_ERROR ) + { + osip_debug( ld, "ldap_prepare_socket: " + "setsockopt(%d, TCP_KEEPIDLE) failed (ignored).\n", + s, 0, 0 ); + } +#else + osip_debug( ld, "ldap_prepare_socket: " + "sockopt TCP_KEEPIDLE not supported on this system.\n", + 0, 0, 0 ); +#endif /* TCP_KEEPIDLE */ + } + if ( ld->ld_options.ldo_keepalive_probes > 0 ) + { +#ifdef TCP_KEEPCNT + if ( setsockopt( s, SOL_TCP, TCP_KEEPCNT, + (void*) &ld->ld_options.ldo_keepalive_probes, + sizeof(ld->ld_options.ldo_keepalive_probes) ) == AC_SOCKET_ERROR ) + { + osip_debug( ld, "ldap_prepare_socket: " + "setsockopt(%d, TCP_KEEPCNT) failed (ignored).\n", + s, 0, 0 ); + } +#else + osip_debug( ld, "ldap_prepare_socket: " + "sockopt TCP_KEEPCNT not supported on this system.\n", + 0, 0, 0 ); +#endif /* TCP_KEEPCNT */ + } + if ( ld->ld_options.ldo_keepalive_interval > 0 ) + { +#ifdef TCP_KEEPINTVL + if ( setsockopt( s, SOL_TCP, TCP_KEEPINTVL, + (void*) &ld->ld_options.ldo_keepalive_interval, + sizeof(ld->ld_options.ldo_keepalive_interval) ) == AC_SOCKET_ERROR ) + { + osip_debug( ld, "ldap_prepare_socket: " + "setsockopt(%d, TCP_KEEPINTVL) failed (ignored).\n", + s, 0, 0 ); + } +#else + osip_debug( ld, "ldap_prepare_socket: " + "sockopt TCP_KEEPINTVL not supported on this system.\n", + 0, 0, 0 ); +#endif /* TCP_KEEPINTVL */ + } #endif /* SO_KEEPALIVE */ #ifdef TCP_NODELAY if ( setsockopt( s, IPPROTO_TCP, TCP_NODELAY, -- 2.39.5