This is meant to be initialised to the size of the buffer.
[ira/wip.git] / source3 / passdb / pdb_ldap.c
index a0853e21021fda5913a9e5892da14ae4ce67606c..8a2378f91b281fef28896fe2b931489ef009764e 100644 (file)
@@ -74,6 +74,8 @@ struct ldapsam_privates {
 
        char *bind_dn;
        char *bind_secret;
+
+       unsigned int num_failures;
 };
 
 #define LDAPSAM_DONT_PING_TIME 10      /* ping only all 10 seconds */
@@ -166,7 +168,7 @@ static int ldapsam_open_connection (struct ldapsam_privates *ldap_state, LDAP **
        int version;
        BOOL ldap_v3 = False;
 
-#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
+#ifdef HAVE_LDAP_INITIALIZE
        DEBUG(10, ("ldapsam_open_connection: %s\n", ldap_state->uri));
        
        if ((rc = ldap_initialize(ldap_struct, ldap_state->uri)) != LDAP_SUCCESS) {
@@ -409,15 +411,18 @@ static int ldapsam_connect_system(struct ldapsam_privates *ldap_state, LDAP * ld
                char *ld_error = NULL;
                ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
                                &ld_error);
-               DEBUG(0,
+               DEBUG(ldap_state->num_failures ? 2 : 0,
                      ("failed to bind to server with dn= %s Error: %s\n\t%s\n",
                               ldap_dn ? ld_error : "(unknown)", ldap_err2string(rc),
                               ld_error));
                SAFE_FREE(ld_error);
+               ldap_state->num_failures++;
                return rc;
        }
-       
-       DEBUG(2, ("ldap_connect_system: succesful connection to the LDAP server\n"));
+
+       ldap_state->num_failures = 0;
+
+       DEBUG(3, ("ldap_connect_system: succesful connection to the LDAP server\n"));
        return rc;
 }
 
@@ -438,7 +443,7 @@ static int ldapsam_open(struct ldapsam_privates *ldap_state)
 
        if ((ldap_state->ldap_struct != NULL) && ((ldap_state->last_ping + LDAPSAM_DONT_PING_TIME) < time(NULL))) {
                struct sockaddr_un addr;
-               socklen_t len;
+               socklen_t len = sizeof(addr);
                int sd;
                if (ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_DESC, &sd) == 0 &&
                    getpeername(sd, (struct sockaddr *) &addr, &len) < 0) {
@@ -499,13 +504,23 @@ static int ldapsam_retry_open(struct ldapsam_privates *ldap_state, int *attempts
        SMB_ASSERT(ldap_state && attempts);
                
        if (*attempts != 0) {
-               /* we retry after 0.5, 2, 4.5, 8, 12.5, 18, 24.5 seconds */
-               msleep((((*attempts)*(*attempts))/2)*1000);
+               unsigned int sleep_time;
+               uint8 rand_byte = 128; /* a reasonable place to start */
+
+               generate_random_buffer(&rand_byte, 1, False);
+
+               sleep_time = (((*attempts)*(*attempts))/2)*rand_byte*2; 
+               /* we retry after (0.5, 1, 2, 3, 4.5, 6) seconds
+                  on average.  
+                */
+               DEBUG(3, ("Sleeping for %u milliseconds before reconnecting\n", 
+                         sleep_time));
+               msleep(sleep_time);
        }
        (*attempts)++;
 
        if ((rc = ldapsam_open(ldap_state))) {
-               DEBUG(0,("Connection to LDAP Server failed for the %d try!\n",*attempts));
+               DEBUG(1,("Connection to LDAP Server failed for the %d try!\n",*attempts));
                return rc;
        } 
        
@@ -529,7 +544,7 @@ static int ldapsam_search(struct ldapsam_privates *ldap_state,
                        continue;
                
                rc = ldap_search_s(ldap_state->ldap_struct, base, scope, 
-                                  filter, attrs, attrsonly, res);
+                                  filter, (char **)attrs, attrsonly, res);
        }
        
        if (rc == LDAP_SERVER_DOWN) {
@@ -612,6 +627,7 @@ static int ldapsam_delete(struct ldapsam_privates *ldap_state, char *dn)
        return rc;
 }
 
+#ifdef LDAP_EXOP_X_MODIFY_PASSWD
 static int ldapsam_extended_operation(struct ldapsam_privates *ldap_state, LDAP_CONST char *reqoid, struct berval *reqdata, LDAPControl **serverctrls, LDAPControl **clientctrls, char **retoidp, struct berval **retdatap)
 {
        int             rc = LDAP_SERVER_DOWN;
@@ -635,6 +651,7 @@ static int ldapsam_extended_operation(struct ldapsam_privates *ldap_state, LDAP_
                
        return rc;
 }
+#endif
 
 /*******************************************************************
  run the search by name.
@@ -1287,6 +1304,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state,
   * If we are updating the record AND the attribute is CHANGED.
   * If we are adding   the record AND it is SET or CHANGED (ie not default)
 *********************************************************************/
+#ifdef LDAP_EXOP_X_MODIFY_PASSWD
 static BOOL need_ldap_mod(BOOL pdb_add, const SAM_ACCOUNT * sampass, enum pdb_elements element) {
        if (pdb_add) {
                return (!IS_SAM_DEFAULT(sampass, element));
@@ -1294,6 +1312,7 @@ static BOOL need_ldap_mod(BOOL pdb_add, const SAM_ACCOUNT * sampass, enum pdb_el
                return IS_SAM_CHANGED(sampass, element);
        }
 }
+#endif
 
 /**********************************************************************
   Set attribute to newval in LDAP, regardless of what value the