From: Nadezhda Ivanova Date: Mon, 15 Mar 2021 13:02:19 +0000 (+0200) Subject: ITS#9502 Implement LDAP_OPT_TCP_USER_TIMEOUT X-Git-Tag: OPENLDAP_REL_ENG_2_6_0~252 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=db389d38ce4334668b1854a9b616360bab871db2;p=thirdparty%2Fopenldap.git ITS#9502 Implement LDAP_OPT_TCP_USER_TIMEOUT --- diff --git a/doc/man/man3/ldap_get_option.3 b/doc/man/man3/ldap_get_option.3 index 9675520ab4..25027ac7f2 100644 --- a/doc/man/man3/ldap_get_option.3 +++ b/doc/man/man3/ldap_get_option.3 @@ -451,6 +451,11 @@ Instructs .BR ldap_result (3) to keep the connection open on read error or if Notice of Disconnection is received. In these cases, the connection should be closed by the caller. This option is OpenLDAP specific. +.TP +.B LDAP_OPT_TCP_USER_TIMEOUT +Allows to configure TCP_USER_TIMEOUT in milliseconds on the connection, overriding the operating system setting. +This option is OpenLDAP specific and supported only on Linux 2.6.37 or higher. + .SH SASL OPTIONS The SASL options are OpenLDAP specific. .TP diff --git a/include/ldap.h b/include/ldap.h index fcea81d9f3..6877d9fd11 100644 --- a/include/ldap.h +++ b/include/ldap.h @@ -133,6 +133,7 @@ LDAP_BEGIN_DECL #define LDAP_OPT_SESSION_REFCNT 0x5012 /* session reference count */ #define LDAP_OPT_KEEPCONN 0x5013 /* keep the connection on read error or NoD */ #define LDAP_OPT_SOCKET_BIND_ADDRESSES 0x5014 /* user configured bind IPs */ +#define LDAP_OPT_TCP_USER_TIMEOUT 0x5015 /* set TCP_USER_TIMEOUT if the OS supports it, ignored otherwise */ /* OpenLDAP TLS options */ #define LDAP_OPT_X_TLS 0x6000 diff --git a/libraries/libldap/init.c b/libraries/libldap/init.c index b247327d57..341a44483f 100644 --- a/libraries/libldap/init.c +++ b/libraries/libldap/init.c @@ -620,6 +620,8 @@ void ldap_int_initialize_global_options( struct ldapoptions *gopts, int *dbglvl gopts->ldo_keepalive_interval = 0; gopts->ldo_keepalive_idle = 0; + gopts->ldo_tcp_user_timeout = 0; + #ifdef LDAP_R_COMPILE ldap_pvt_thread_mutex_init( &gopts->ldo_mutex ); #endif diff --git a/libraries/libldap/ldap-int.h b/libraries/libldap/ldap-int.h index 4dacecbfed..2dae6effdc 100644 --- a/libraries/libldap/ldap-int.h +++ b/libraries/libldap/ldap-int.h @@ -248,6 +248,12 @@ struct ldapoptions { ber_int_t ldo_keepalive_probes; ber_int_t ldo_keepalive_interval; + /* + * Per connection tcp user timeout (Linux >= 2.6.37 only, + * ignored where unsupported) + */ + ber_uint_t ldo_tcp_user_timeout; + int ldo_refhoplimit; /* limit on referral nesting */ /* LDAPv3 server and client controls */ @@ -267,7 +273,7 @@ struct ldapoptions { LDAP_BOOLEANS ldo_booleans; /* boolean options */ -#define LDAP_LDO_NULLARG ,0,0,0,0 ,{0},{0} ,0,0,0,0, 0,0,0,0, 0,0, 0,0,0,0,0,0, 0, 0 +#define LDAP_LDO_NULLARG ,0,0,0,0 ,{0},{0} ,0,0,0,0, 0,0,0,0,0, 0,0, 0,0,0,0,0,0, 0, 0 /* LDAP user configured bind IPs */ struct ldapsourceip ldo_local_ip_addrs; diff --git a/libraries/libldap/options.c b/libraries/libldap/options.c index e07a4ce60b..b51220c57f 100644 --- a/libraries/libldap/options.c +++ b/libraries/libldap/options.c @@ -418,6 +418,11 @@ ldap_get_option( rc = LDAP_OPT_SUCCESS; break; + case LDAP_OPT_TCP_USER_TIMEOUT: + * (unsigned int *) outvalue = lo->ldo_tcp_user_timeout; + rc = LDAP_OPT_SUCCESS; + break; + default: #ifdef HAVE_TLS if ( ldap_pvt_tls_get_option( ld, option, outvalue ) == 0 ) { @@ -842,6 +847,7 @@ ldap_set_option( case LDAP_OPT_X_KEEPALIVE_IDLE: case LDAP_OPT_X_KEEPALIVE_PROBES : case LDAP_OPT_X_KEEPALIVE_INTERVAL : + case LDAP_OPT_TCP_USER_TIMEOUT: if(invalue == NULL) { /* no place to set from */ LDAP_MUTEX_UNLOCK( &lo->ldo_mutex ); @@ -962,6 +968,10 @@ ldap_set_option( lo->ldo_keepalive_interval = * (const int *) invalue; rc = LDAP_OPT_SUCCESS; break; + case LDAP_OPT_TCP_USER_TIMEOUT: + lo->ldo_tcp_user_timeout = * (const unsigned int *) invalue; + rc = LDAP_OPT_SUCCESS; + break; } LDAP_MUTEX_UNLOCK( &lo->ldo_mutex ); diff --git a/libraries/libldap/os-ip.c b/libraries/libldap/os-ip.c index 14899cc007..3e8d86718e 100644 --- a/libraries/libldap/os-ip.c +++ b/libraries/libldap/os-ip.c @@ -118,7 +118,7 @@ ldap_int_prepare_socket(LDAP *ld, int s, int proto ) { Debug1(LDAP_DEBUG_TRACE, "ldap_prepare_socket: %d\n", s ); -#if defined( SO_KEEPALIVE ) || defined( TCP_NODELAY ) +#if defined( SO_KEEPALIVE ) || defined( TCP_NODELAY ) || defined( TCP_USER_TIMEOUT ) if ( proto == LDAP_PROTO_TCP ) { int dummy = 1; #ifdef SO_KEEPALIVE @@ -190,8 +190,25 @@ ldap_int_prepare_socket(LDAP *ld, int s, int proto ) s ); } #endif /* TCP_NODELAY */ + if ( ld->ld_options.ldo_tcp_user_timeout > 0 ) + { +#ifdef TCP_USER_TIMEOUT + if ( setsockopt( s, IPPROTO_TCP, TCP_USER_TIMEOUT, + (void*) &ld->ld_options.ldo_tcp_user_timeout, + sizeof(ld->ld_options.ldo_tcp_user_timeout) ) == AC_SOCKET_ERROR ) + { + Debug1(LDAP_DEBUG_TRACE, + "ldap_prepare_socket: " + "setsockopt(%d, TCP_USER_TIMEOUT) failed (ignored).\n", + s ); + } +#else + Debug0(LDAP_DEBUG_TRACE, "ldap_prepare_socket: " + "sockopt TCP_USER_TIMEOUT not supported on this system.\n" ); +#endif /* TCP_USER_TIMEOUT */ + } } -#endif /* SO_KEEPALIVE || TCP_NODELAY */ +#endif /* SO_KEEPALIVE || TCP_NODELAY || TCP_USER_TIMEOUT */ return 0; }