Read the source Luke – part 1

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[21622]: l0M7JEYx016921: SYSERR(root): Error in ldap_search using 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:

First I downloaded and uncpaked the latest sendmail (8.13.8) and openldap (2.3.32) sources. Now where do I start? The error message points where:

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:


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() .
./libsm/ldap.c:sm_ldap_search(lmap, key)

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.

So there:

Unknown error 325 means that your sendmail cannot talk to your LDAP server because sendmail thinks that slapd is down.

Or not?


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s