Arthur de Jong

Open Source / Free Software developer

summaryrefslogtreecommitdiffstats
path: root/nslcd
diff options
context:
space:
mode:
Diffstat (limited to 'nslcd')
-rw-r--r--nslcd/cfg.c19
-rw-r--r--nslcd/cfg.h13
-rw-r--r--nslcd/myldap.c96
3 files changed, 86 insertions, 42 deletions
diff --git a/nslcd/cfg.c b/nslcd/cfg.c
index 21b8d56..7f6dbad 100644
--- a/nslcd/cfg.c
+++ b/nslcd/cfg.c
@@ -63,7 +63,11 @@ static void cfg_defaults(struct ldap_config *cfg)
int i;
memset(cfg,0,sizeof(struct ldap_config));
for (i=0;i<(NSS_LDAP_CONFIG_URI_MAX+1);i++)
- cfg->ldc_uris[i]=NULL;
+ {
+ cfg->ldc_uris[i].uri=NULL;
+ cfg->ldc_uris[i].lastok=0;
+ cfg->ldc_uris[i].lastfail=0;
+ }
#ifdef LDAP_VERSION3
cfg->ldc_version=LDAP_VERSION3;
#else /* LDAP_VERSION3 */
@@ -81,7 +85,6 @@ static void cfg_defaults(struct ldap_config *cfg)
cfg->ldc_bind_timelimit=30;
cfg->ldc_timelimit=LDAP_NO_LIMIT;
cfg->ldc_idle_timelimit=0;
- cfg->ldc_reconnect_tries=4;
cfg->ldc_reconnect_sleeptime=1;
cfg->ldc_reconnect_maxsleeptime=30;
cfg->ldc_ssl_on=SSL_OFF;
@@ -123,7 +126,7 @@ static void add_uri(const char *filename,int lnr,
int i;
log_log(LOG_DEBUG,"add_uri(%s)",uri);
/* find the place where to insert the URI */
- for (i=0;cfg->ldc_uris[i]!=NULL;i++)
+ for (i=0;cfg->ldc_uris[i].uri!=NULL;i++)
;
/* check for room */
if (i>=NSS_LDAP_CONFIG_URI_MAX)
@@ -132,8 +135,7 @@ static void add_uri(const char *filename,int lnr,
exit(EXIT_FAILURE);
}
/* append URI to list */
- cfg->ldc_uris[i]=xstrdup(uri);
- cfg->ldc_uris[i+1]=NULL;
+ cfg->ldc_uris[i].uri=xstrdup(uri);
}
#ifndef HOST_NAME_MAX
@@ -698,10 +700,7 @@ static void cfg_read(const char *filename,struct ldap_config *cfg)
get_eol(filename,lnr,keyword,&line);
}
else if (strcasecmp(keyword,"reconnect_tries")==0)
- {
- get_int(filename,lnr,keyword,&line,&cfg->ldc_reconnect_tries);
- get_eol(filename,lnr,keyword,&line);
- }
+ log_log(LOG_WARNING,"%s:%d: option %s has been removed and will be ignored",filename,lnr,keyword);
else if (!strcasecmp(keyword,"reconnect_sleeptime"))
{
get_int(filename,lnr,keyword,&line,&cfg->ldc_reconnect_sleeptime);
@@ -820,7 +819,7 @@ void cfg_init(const char *fname)
/* read configfile */
cfg_read(fname,nslcd_cfg);
/* do some sanity checks */
- if (nslcd_cfg->ldc_uris[0]==NULL)
+ if (nslcd_cfg->ldc_uris[0].uri==NULL)
{
log_log(LOG_ERR,"no URIs defined in config");
exit(EXIT_FAILURE);
diff --git a/nslcd/cfg.h b/nslcd/cfg.h
index 25fa9db..3867348 100644
--- a/nslcd/cfg.h
+++ b/nslcd/cfg.h
@@ -55,10 +55,19 @@ enum ldap_map_selector
LM_NONE
};
+struct myldap_uri
+{
+ char *uri;
+ /* timestamp of last ok search */
+ time_t lastok;
+ /* timestamp of last ok search */
+ time_t lastfail;
+};
+
struct ldap_config
{
/* NULL terminated list of URIs */
- char *ldc_uris[NSS_LDAP_CONFIG_URI_MAX+1];
+ struct myldap_uri ldc_uris[NSS_LDAP_CONFIG_URI_MAX+1];
/* protocol version */
int ldc_version;
/* bind DN */
@@ -85,8 +94,6 @@ struct ldap_config
int ldc_timelimit;
/* idle timeout */
int ldc_idle_timelimit;
- /* number of sleeping reconnect attempts */
- int ldc_reconnect_tries;
/* seconds to sleep; doubled until max */
int ldc_reconnect_sleeptime;
/* maximum seconds to sleep */
diff --git a/nslcd/myldap.c b/nslcd/myldap.c
index ef3da7b..7c1f516 100644
--- a/nslcd/myldap.c
+++ b/nslcd/myldap.c
@@ -66,6 +66,7 @@
#include <sasl.h>
#endif
#include <ctype.h>
+#include <pthread.h>
#include "myldap.h"
#include "compat/pagectrl.h"
@@ -591,11 +592,11 @@ static int do_open(MYLDAP_SESSION *session)
session->ld=NULL;
session->lastactivity=0;
/* open the connection */
- rc=ldap_initialize(&(session->ld),nslcd_cfg->ldc_uris[session->current_uri]);
+ rc=ldap_initialize(&(session->ld),nslcd_cfg->ldc_uris[session->current_uri].uri);
if (rc!=LDAP_SUCCESS)
{
log_log(LOG_WARNING,"ldap_initialize(%s) failed: %s: %s",
- nslcd_cfg->ldc_uris[session->current_uri],
+ nslcd_cfg->ldc_uris[session->current_uri].uri,
ldap_err2string(rc),strerror(errno));
if (session->ld!=NULL)
{
@@ -622,12 +623,12 @@ static int do_open(MYLDAP_SESSION *session)
return rc;
}
/* bind to the server */
- rc=do_bind(session,nslcd_cfg->ldc_uris[session->current_uri]);
+ rc=do_bind(session,nslcd_cfg->ldc_uris[session->current_uri].uri);
if (rc!=LDAP_SUCCESS)
{
/* log actual LDAP error code */
log_log(LOG_WARNING,"failed to bind to LDAP server %s: %s: %s",
- nslcd_cfg->ldc_uris[session->current_uri],
+ nslcd_cfg->ldc_uris[session->current_uri].uri,
ldap_err2string(rc),strerror(errno));
rc2=ldap_unbind(session->ld);
session->ld=NULL;
@@ -644,7 +645,7 @@ static int do_open(MYLDAP_SESSION *session)
/* update last activity and finish off state */
time(&(session->lastactivity));
log_log(LOG_INFO,"connected to LDAP server %s",
- nslcd_cfg->ldc_uris[session->current_uri]);
+ nslcd_cfg->ldc_uris[session->current_uri].uri);
return LDAP_SUCCESS;
}
@@ -762,14 +763,19 @@ void myldap_session_close(MYLDAP_SESSION *session)
free(session);
}
+/* mutex for updating the times in the uri */
+pthread_mutex_t uris_mutex = PTHREAD_MUTEX_INITIALIZER;
+
MYLDAP_SEARCH *myldap_search(
MYLDAP_SESSION *session,
const char *base,int scope,const char *filter,const char **attrs)
{
MYLDAP_SEARCH *search;
int sleeptime=0;
- int try;
int start_uri;
+ time_t endtime;
+ time_t nexttry;
+ time_t t;
/* check parameters */
if (!is_valid_session(session)||(base==NULL)||(filter==NULL)||(attrs==NULL))
{
@@ -780,40 +786,72 @@ MYLDAP_SEARCH *myldap_search(
/* log the call */
log_log(LOG_DEBUG,"myldap_search(base=\"%s\", filter=\"%s\")",
base,filter);
- /* keep trying a number of times */
- for (try=0;try<(nslcd_cfg->ldc_reconnect_tries);try++)
+ /* keep trying until we time out */
+ endtime=time(NULL)+nslcd_cfg->ldc_reconnect_maxsleeptime;
+ nexttry=endtime;
+ while (1)
{
- /* sleep between tries */
- if (try>0)
- {
- if (sleeptime==0)
- sleeptime=nslcd_cfg->ldc_reconnect_sleeptime;
- else
- sleeptime*=2;
- if (sleeptime>(nslcd_cfg->ldc_reconnect_maxsleeptime))
- sleeptime=nslcd_cfg->ldc_reconnect_maxsleeptime;
- log_log(LOG_WARNING,"no available LDAP server found, sleeping %d seconds",sleeptime);
- (void)sleep(sleeptime);
- }
/* try each configured URL once */
+ pthread_mutex_lock(&uris_mutex);
start_uri=session->current_uri;
do
{
- /* try to start the search */
- search=do_try_search(session,base,scope,filter,attrs);
- if (search!=NULL)
- return search;
- /* close the current connection */
- do_close(session);
+ /* only try if we haven't just had an error and it was a long tme
+ since the last ok */
+ if ( ( ( nslcd_cfg->ldc_uris[session->current_uri].lastfail -
+ nslcd_cfg->ldc_uris[session->current_uri].lastok ) < nslcd_cfg->ldc_reconnect_maxsleeptime) ||
+ ( time(NULL) >= (nslcd_cfg->ldc_uris[session->current_uri].lastfail+nslcd_cfg->ldc_reconnect_maxsleeptime) ) )
+ {
+ pthread_mutex_unlock(&uris_mutex);
+ /* try to start the search */
+ search=do_try_search(session,base,scope,filter,attrs);
+ if (search!=NULL)
+ {
+ /* update ok time and return search handle */
+ pthread_mutex_lock(&uris_mutex);
+ nslcd_cfg->ldc_uris[session->current_uri].lastok=time(NULL);
+ pthread_mutex_unlock(&uris_mutex);
+ return search;
+ }
+ /* close the current connection */
+ do_close(session);
+ /* update time of failure and figure out when we should retry */
+ pthread_mutex_lock(&uris_mutex);
+ t=time(NULL);
+ nslcd_cfg->ldc_uris[session->current_uri].lastfail=t;
+ t+=nslcd_cfg->ldc_reconnect_sleeptime;
+ if (t<nexttry)
+ nexttry=t;
+ }
+ else if (nslcd_cfg->ldc_uris[session->current_uri].lastfail>0)
+ {
+ /* we are in a hard fail state, figure out when we can retry */
+ t=(nslcd_cfg->ldc_uris[session->current_uri].lastfail+nslcd_cfg->ldc_reconnect_maxsleeptime);
+ if (t<nexttry)
+ nexttry=t;
+ }
/* try the next URI (with wrap-around) */
session->current_uri++;
- if (nslcd_cfg->ldc_uris[session->current_uri]==NULL)
+ if (nslcd_cfg->ldc_uris[session->current_uri].uri==NULL)
session->current_uri=0;
}
while (session->current_uri!=start_uri);
+ pthread_mutex_unlock(&uris_mutex);
+ /* see if it is any use sleeping */
+ if (nexttry>=endtime)
+ {
+ log_log(LOG_ERR,"no available LDAP server found");
+ return NULL;
+ }
+ /* sleep between tries */
+ sleeptime=nexttry-time(NULL);
+ if (sleeptime>0)
+ {
+ log_log(LOG_WARNING,"no available LDAP server found, sleeping %d seconds",sleeptime);
+ (void)sleep(sleeptime);
+ }
+ nexttry=time(NULL)+nslcd_cfg->ldc_reconnect_maxsleeptime;
}
- log_log(LOG_ERR,"no available LDAP server found");
- return NULL;
}
void myldap_search_close(MYLDAP_SEARCH *search)