summaryrefslogtreecommitdiff
path: root/source3/libads
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 /source3/libads
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)
Diffstat (limited to 'source3/libads')
-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);
}
/*