A fellow (and very competent) postmaster of an extremely high traffic ISP (by Greek standards) dropped me a note asking me whether I had seen the following error message:
Jan 25 11:07:43 XXXXXXXXXXX sm-mta: l0M7JEYx016921: SYSERR(root): Error in ldap_search using user@YYYYYYYYYYYY.gr in map ldapmra: Unknown error 325
Being the LDAP hater that I am, I had never encountered it. Googling arround did not result in anything meaningful. So the next step was to read the source code:
Inside the sendmail-8.13.8 directory:
$ grep -r "Error in ldap_search" .
./sendmail/map.c: syserr("Error in ldap_search using %s in map %s",
./sendmail/map.c: syserr("451 4.3.5 Error in ldap_search using %s in map %s",
syserr() is called when sm_ldap_search() fails and errno is set by calling sm_ldap_geterrno():
errno = sm_ldap_geterrno(lmap->ldap_ld) + E_LDAPBASE;
What is E_LDAPBASE? We find it defined in include/sm/errstring.h:
#define E_LDAPBASE (E_PSEUDOBASE + 70)
OK, now what is E_PSEUDOBASE? We find it defined again in include/sm/errstring.h:
# define E_PSEUDOBASE 256
#endif /* ! E_PSEUDOBASE */
Hmm… the valuse of E_LDAPBASE is 256 + 70 = 326? Now does this not look familiar? So what makes sm_ldap_geterrno() return -1?
$ grep -r ^sm_ldap_geterrno .
sm_ldap_geterrno() basically calls:
(void) ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &err);
and returns the value of err.
Now we switch to the openldap-2.3.32 source directory:
$ grep -r ^ldap_get_option .
from which we find out that in our case it returns the following value:
* (int *) outvalue = ld->ld_errno;
So who sets the value of ld->ld_errno to -1? Back in the sendmail sources we see that we followed this branch of the code because of a call to sm_ldap_search():
$ grep -r ^sm_ldap_search() .
sm_ldap_search returns the value of a call to ldap_search(). Switching back to openldap’s sources:
$ grep -r ^ldap_search .
ldap_search() returns the result of ldap_send_initial_request():
$ grep -r ^ldap_send_initial_request
which in turns returns the result of ldap_server_request():
$ grep -r ^ldap_send_server_request .
It sets ld_errno to -1 in two cases. The first is when it sets it to LDAP_SERVER_DOWN (which is #defined as (-1) in ldap.h) and when ldap_int_flush_request() fails returning -1:
$ grep -r ^ldap_int_flush_request .
ldap_int_flush_request() returns -1 when ber_flush() fails and sets ld_errno to LDAP_SERVER_DOWN.
Unknown error 325 means that your sendmail cannot talk to your LDAP server because sendmail thinks that slapd is down.