autofs-5.0.5 - auto adjust ldap page size
From: Ian Kent <raven@themaw.net>
When doing a paged LDAP request, if an LDAP server is configured with
request size limits less than the size autofs requests the query fails
with an LDAP_ADMINLIMIT_EXCEEDED. To fix this, when the error is returned
halve the request size and try again until we get down to a ridiculously
small size.
---
CHANGELOG | 1 +
modules/lookup_ldap.c | 32 ++++++++++++++++++++++++--------
2 files changed, 25 insertions(+), 8 deletions(-)
--- autofs-5.0.5.orig/CHANGELOG
+++ autofs-5.0.5/CHANGELOG
@@ -56,6 +56,7 @@
- add option to dump configured automount maps.
- use weight only for server selection.
- fix isspace() wild card substition.
+- auto adjust ldap page size.
03/09/2009 autofs-5.0.5
-----------------------
--- autofs-5.0.5.orig/modules/lookup_ldap.c
+++ autofs-5.0.5/modules/lookup_ldap.c
@@ -55,6 +55,7 @@ struct ldap_search_params {
LDAP *ldap;
char *query, **attrs;
struct berval *cookie;
+ ber_int_t pageSize;
int morePages;
ber_int_t totalCount;
LDAPMessage *result;
@@ -1946,7 +1947,6 @@ static int do_paged_query(struct ldap_se
struct autofs_point *ap = sp->ap;
LDAPControl *pageControl=NULL, *controls[2] = { NULL, NULL };
LDAPControl **returnedControls = NULL;
- static ber_int_t pageSize = 1000;
static char pagingCriticality = 'T';
int rv, scope = LDAP_SCOPE_SUBTREE;
@@ -1959,7 +1959,8 @@ static int do_paged_query(struct ldap_se
* Check for Size Limit exceeded and force run through loop
* and requery using page control.
*/
- if (rv == LDAP_SIZELIMIT_EXCEEDED)
+ if (rv == LDAP_SIZELIMIT_EXCEEDED ||
+ rv == LDAP_ADMINLIMIT_EXCEEDED)
sp->morePages = TRUE;
else {
debug(ap->logopt,
@@ -1974,7 +1975,7 @@ do_paged:
/* we need to use page controls so requery LDAP */
debug(ap->logopt, MODPREFIX "geting page of results");
- rv = ldap_create_page_control(sp->ldap, pageSize, sp->cookie,
+ rv = ldap_create_page_control(sp->ldap, sp->pageSize, sp->cookie,
pagingCriticality, &pageControl);
if (rv != LDAP_SUCCESS) {
warn(ap->logopt, MODPREFIX "failed to create page control");
@@ -1989,10 +1990,11 @@ do_paged:
ctxt->qdn, scope, sp->query, sp->attrs,
0, controls, NULL, NULL, 0, &sp->result);
if ((rv != LDAP_SUCCESS) && (rv != LDAP_PARTIAL_RESULTS)) {
- debug(ap->logopt,
- MODPREFIX "query failed for %s: %s",
- sp->query, ldap_err2string(rv));
ldap_control_free(pageControl);
+ if (rv != LDAP_ADMINLIMIT_EXCEEDED)
+ debug(ap->logopt,
+ MODPREFIX "query failed for %s: %s",
+ sp->query, ldap_err2string(rv));
return rv;
}
@@ -2347,18 +2349,32 @@ static int read_one_map(struct autofs_po
MODPREFIX "searching for \"%s\" under \"%s\"", sp.query, ctxt->qdn);
sp.cookie = NULL;
+ sp.pageSize = 1000;
sp.morePages = FALSE;
sp.totalCount = 0;
sp.result = NULL;
do {
rv = do_paged_query(&sp, ctxt);
- if (rv == LDAP_SIZELIMIT_EXCEEDED)
- {
+ if (rv == LDAP_SIZELIMIT_EXCEEDED) {
debug(ap->logopt, MODPREFIX "result size exceed");
if (sp.result)
ldap_msgfree(sp.result);
+ continue;
+ }
+ if (rv == LDAP_ADMINLIMIT_EXCEEDED) {
+ if (sp.result)
+ ldap_msgfree(sp.result);
+ sp.pageSize = sp.pageSize / 2;
+ if (sp.pageSize < 5) {
+ debug(ap->logopt, MODPREFIX
+ "administrative result size too small");
+ unbind_ldap_connection(ap->logopt, sp.ldap, ctxt);
+ *result_ldap = rv;
+ free(sp.query);
+ return NSS_STATUS_UNAVAIL;
+ }
continue;
}