diff options
Diffstat (limited to 'nslcd')
-rw-r--r-- | nslcd/cfg.c | 19 | ||||
-rw-r--r-- | nslcd/cfg.h | 13 | ||||
-rw-r--r-- | nslcd/myldap.c | 96 |
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) |