summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJim McDonough <jmcd@samba.org>2002-03-14 17:48:26 +0000
committerJim McDonough <jmcd@samba.org>2002-03-14 17:48:26 +0000
commit0640a5ceeb974f06dc29669bdbce75fcf7154439 (patch)
tree351ab7a853071bd0b8bce0ef88b9742481cd414b
parentaad2072e07481da2f24ffb91454881c026840500 (diff)
downloadsamba-0640a5ceeb974f06dc29669bdbce75fcf7154439.tar.gz
samba-0640a5ceeb974f06dc29669bdbce75fcf7154439.tar.bz2
samba-0640a5ceeb974f06dc29669bdbce75fcf7154439.zip
This adds the Paged Result Control to ads searching. The new function, ads_do_paged_search, is the same as ads_do_search, but it also contains a count of records returned in this page, and a cookie for resuming, to be passed back. The cookie must start off NULL, and when it returns as NULL, the search is done.
(This used to be commit 9afba67f9a56699e34735e1e425f97b2464f2402)
-rw-r--r--source3/libads/ldap.c79
1 files changed, 79 insertions, 0 deletions
diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c
index e53f6d87db..28970e8fa9 100644
--- a/source3/libads/ldap.c
+++ b/source3/libads/ldap.c
@@ -66,6 +66,83 @@ ADS_STATUS ads_connect(ADS_STRUCT *ads)
return ads_sasl_bind(ads);
}
+/* Do a search with paged results. cookie must be null on the first
+ call, and then returned on each subsequent call. It will be null
+ again when the entire search is complete */
+
+ADS_STATUS ads_do_paged_search(ADS_STRUCT *ads, const char *bind_path,
+ int scope, const char *exp,
+ const char **attrs, void **res,
+ int *count, void **cookie)
+{
+ int rc;
+#define ADS_PAGE_CTL_OID "1.2.840.113556.1.4.319"
+ int version;
+ LDAPControl PagedResults;
+ BerElement *berelem = NULL;
+ struct berval *berval = NULL;
+ LDAPControl *controls[2];
+ LDAPControl **rcontrols, *cur_control;
+
+ *res = NULL;
+
+ ldap_get_option(ads->ld, LDAP_OPT_PROTOCOL_VERSION, &version);
+
+ /* Paged results only available on ldap v3 or later, so check
+ version first before using, since at connect time we're
+ only v2. Not sure exactly why... */
+ if (version < LDAP_VERSION3)
+ return ADS_ERROR(LDAP_NOT_SUPPORTED);
+
+ berelem = ber_alloc_t(LBER_USE_DER);
+ if (cookie && *cookie) {
+ ber_printf(berelem, "{iO}", (ber_int_t) 256, *cookie);
+ ber_bvfree(*cookie); /* don't need it from last time */
+ } else {
+ ber_printf(berelem, "{io}", (ber_int_t) 256, "", 0);
+ }
+ ber_flatten(berelem, &berval);
+ PagedResults.ldctl_oid = ADS_PAGE_CTL_OID;
+ PagedResults.ldctl_iscritical = (char) 1;
+ PagedResults.ldctl_value.bv_len = berval->bv_len;
+ PagedResults.ldctl_value.bv_val = berval->bv_val;
+
+ controls[0] = &PagedResults;
+ controls[1] = NULL;
+
+ *res = NULL;
+
+ rc = ldap_search_ext_s(ads->ld, bind_path, scope, exp,
+ (char **) attrs, 0, controls, NULL,
+ NULL, LDAP_NO_LIMIT,
+ (LDAPMessage **)res);
+ ber_free(berelem, 1);
+ ber_bvfree(berval);
+
+ rc = ldap_parse_result(ads->ld, *res, NULL, NULL, NULL,
+ NULL, &rcontrols, 0);
+
+ for (cur_control=rcontrols[0]; cur_control; cur_control++) {
+ if (strcmp(ADS_PAGE_CTL_OID, cur_control->ldctl_oid) == 0) {
+ berelem = ber_init(&cur_control->ldctl_value);
+ ber_scanf(berelem,"{iO}", (ber_int_t *) count,
+ &berval);
+ /* the berval is the cookie, but must be freed when
+ it is all done */
+ if (berval->bv_len) /* still more to do */
+ *cookie=ber_bvdup(berval);
+ else
+ *cookie=NULL;
+ ber_bvfree(berval);
+ ber_free(berelem, 1);
+ break;
+ }
+ }
+ ldap_controls_free(rcontrols);
+
+ return ADS_ERROR(rc);
+}
+
/*
do a search with a timeout
*/
@@ -84,10 +161,12 @@ ADS_STATUS ads_do_search(ADS_STRUCT *ads, const char *bind_path, int scope,
bind_path, scope,
exp, (char **) attrs, 0, NULL, NULL,
&timeout, LDAP_NO_LIMIT, (LDAPMessage **)res);
+
if (rc == LDAP_SIZELIMIT_EXCEEDED) {
DEBUG(3,("Warning! sizelimit exceeded in ldap. Truncating.\n"));
rc = 0;
}
+
return ADS_ERROR(rc);
}
/*