" -b basedn base dn for search\n"
" -E [!]<ctrl>[=<ctrlparam>] search controls (! indicates criticality)\n"
" [!]mv=<filter> (matched values filter)\n"
+#ifdef LDAP_CONTROL_PAGEDRESULTS
+" [!]pr=<size> (paged results)\n"
+#endif /* LDAP_CONTROL_PAGEDRESULTS */
#ifdef LDAP_CONTROL_SUBENTRIES
" [!]subentries[=true|false] (subentries)\n"
#endif
struct timeval *timeout,
int sizelimit ));
+#ifdef LDAP_CONTROL_PAGEDRESULTS
+static int parse_page_control(
+ LDAP *ld,
+ LDAPMessage *result,
+ struct berval *cookie );
+#endif /* LDAP_CONTROL_PAGEDRESULTS */
+
static char *tmpdir = NULL;
static char *urlpre = NULL;
static char *prog = NULL;
static int use_tls = 0;
static char *sortattr = NULL;
static int verbose, not, includeufn, vals2tmp, ldif;
+#ifdef LDAP_CONTROL_PAGEDRESULTS
+static int pageSize;
+static ber_int_t searchControlSize = 0;
+static ber_int_t morePagedResults = 1;
+static struct berval cookie = { 0, NULL };
+static int npagedresponses;
+static int npagedentries;
+static int npagedreferences;
+static int npagedextended;
+static int npagedpartial;
+#endif /* LDAP_CONTROL_PAGEDRESULTS */
static void
urlize(char *url)
struct berval *bvalp = NULL;
char *vrFilter = NULL, *control = NULL, *cvalue;
char *pw_file = NULL;
+#ifdef LDAP_CONTROL_PAGEDRESULTS
+ BerElement *pageber = NULL;
+ struct berval *bvalptr = NULL;
+ int num = 0, moreEntries, searchControlCrit = 0;
+#endif /* LDAP_CONTROL_PAGEDRESULTS */
infile = NULL;
subentries = valuesReturnFilter =
attrsonly = manageDSAit = noop = ldif = want_bindpw = 0;
+#ifdef LDAP_CONTROL_PAGEDRESULTS
+ npagedresponses = npagedentries = npagedreferences =
+ npagedextended = npagedpartial = 0;
+#endif /* LDAP_CONTROL_PAGEDRESULTS */
+
prog = lutil_progname( "ldapsearch", argc, argv );
lutil_log_initialize(argc, argv);
version = LDAP_VERSION3;
break;
+#ifdef LDAP_CONTROL_PAGEDRESULTS
+ } else if ( strcasecmp( control, "pr" ) == 0 ) {
+ /* PagedResults control */
+ if ( searchControlSize !=0 ) {
+ fprintf( stderr, "PagedResultsControl previously specified" );
+ return EXIT_FAILURE;
+ }
+
+ num = sscanf( cvalue, "%d", &pageSize );
+ if ( num != 1 ) {
+ fprintf( stderr, "Invalid value for PagedResultsControl, %s.\n", cvalue);
+ return EXIT_FAILURE;
+
+ }
+ searchControlSize = (ber_int_t)pageSize;
+ searchControlCrit = crit;
+ break;
+#endif /* LDAP_CONTROL_PAGEDRESULTS */
+
#ifdef LDAP_CONTROL_SUBENTRIES
} else if ( strcasecmp( control, "subentries" ) == 0 ) {
if( subentries ) {
}
}
+#ifdef LDAP_CONTROL_PAGEDRESULTS
+getNextPage:
+ if ( manageDSAit || noop || valuesReturnFilter || searchControlSize ) {
+ int critical = 0;
+#else /* !LDAP_CONTROL_PAGEDRESULTS */
if ( manageDSAit || noop || valuesReturnFilter ) {
+#endif /* !LDAP_CONTROL_PAGEDRESULTS */
int err;
int i=0;
- LDAPControl c1,c2,c3,c4;
- LDAPControl *ctrls[5];
+ LDAPControl c1,c2,c3,c4,c5;
+ LDAPControl *ctrls[6];
if ( manageDSAit ) {
ctrls[i++]=&c1;
c1.ldctl_value.bv_val = NULL;
c1.ldctl_value.bv_len = 0;
c1.ldctl_iscritical = manageDSAit > 1;
+#ifdef LDAP_CONTROL_PAGEDRESULTS
+ if ( c1.ldctl_iscritical ) critical = 1;
+#endif /* LDAP_CONTROL_PAGEDRESULTS */
}
if ( noop ) {
c2.ldctl_value.bv_val = NULL;
c2.ldctl_value.bv_len = 0;
c2.ldctl_iscritical = noop > 1;
+#ifdef LDAP_CONTROL_PAGEDRESULTS
+ if ( c2.ldctl_iscritical ) critical = 1;
+#endif /* LDAP_CONTROL_PAGEDRESULTS */
}
#ifdef LDAP_CONTROL_SUBENTRIES
c3.ldctl_oid = LDAP_CONTROL_SUBENTRIES;
c3.ldctl_iscritical = subentries < 1;
+#ifdef LDAP_CONTROL_PAGEDRESULTS
+ if ( c3.ldctl_iscritical ) critical = 1;
+#endif /* LDAP_CONTROL_PAGEDRESULTS */
if (( ber = ber_alloc_t(LBER_USE_DER)) == NULL ) {
return EXIT_FAILURE;
c4.ldctl_oid = LDAP_CONTROL_VALUESRETURNFILTER;
c4.ldctl_iscritical = valuesReturnFilter > 1;
+#ifdef LDAP_CONTROL_PAGEDRESULTS
+ if ( c4.ldctl_iscritical ) critical = 1;
+#endif /* LDAP_CONTROL_PAGEDRESULTS */
if (( ber = ber_alloc_t(LBER_USE_DER)) == NULL ) {
return EXIT_FAILURE;
c4.ldctl_value=(*bvalp);
}
+#ifdef LDAP_CONTROL_PAGEDRESULTS
+ if ( searchControlSize ) {
+ if (( pageber = ber_alloc_t(LBER_USE_DER)) == NULL ) {
+ return EXIT_FAILURE;
+ }
+
+ ber_printf( pageber, "{iO}", searchControlSize, &cookie );
+ if ( ber_flatten( pageber, &bvalptr ) == LBER_ERROR) {
+ return EXIT_FAILURE;
+ }
+
+ ctrls[i++]=&c5;
+ ctrls[i] = NULL;
+
+ c5.ldctl_oid = LDAP_CONTROL_PAGEDRESULTS;
+ c5.ldctl_value = ( *bvalptr );
+ c5.ldctl_iscritical = searchControlCrit;
+ if ( c5.ldctl_iscritical ) critical = 1;
+ }
+#endif /* LDAP_CONTROL_PAGEDRESULTS */
+
err = ldap_set_option( ld, LDAP_OPT_SERVER_CONTROLS, ctrls );
ber_bvfree(bvalp);
ber_free( ber, 1 );
+#ifdef LDAP_CONTROL_PAGEDRESULTS
+ ber_free( pageber, 1 );
+ ber_bvfree( bvalptr );
+#endif /* LDAP_CONTROL_PAGEDRESULTS */
+#ifdef LDAP_CONTROL_PAGEDRESULTS
+ if( err != LDAP_OPT_SUCCESS ) {
+ if ( critical ) {
+ fprintf( stderr, "Could not set controls\n");
+ return EXIT_FAILURE;
+ } else {
+ fprintf( stderr, "Could not set critical controls\n" );
+ }
+ }
+#else /* !LDAP_CONTROL_PAGEDRESULTS */
if( err != LDAP_OPT_SUCCESS ) {
fprintf( stderr, "Could not set %scontrols\n",
(c1.ldctl_iscritical || c2.ldctl_iscritical)
return EXIT_FAILURE;
}
}
+#endif /* !LDAP_CONTROL_PAGEDRESULTS */
}
if ( verbose ) {
}
}
+#ifdef LDAP_CONTROL_PAGEDRESULTS
+ if ( ( searchControlSize != 0 ) && ( morePagedResults != 0 ) ) {
+ /* Loop to get the next pages when
+ * enter is pressed on the terminal.
+ */
+ printf( "Press Enter for the next %d entries.\n",
+ (int)searchControlSize );
+ moreEntries = getchar();
+ while ( moreEntries != EOF && moreEntries != '\n' ) {
+ moreEntries = getchar();
+ }
+
+ goto getNextPage;
+ }
+#endif /* LDAP_CONTROL_PAGEDRESULTS */
+
ldap_unbind( ld );
return( rc );
}
case LDAP_RES_SEARCH_RESULT:
rc = print_result( ld, msg, 1 );
+#ifdef LDAP_CONTROL_PAGEDRESULTS
+ if ( searchControlSize != 0 ) {
+ rc = parse_page_control( ld, msg, &cookie );
+ }
+#endif /* LDAP_CONTROL_PAGEDRESULTS */
goto done;
}
}
}
done:
+#ifdef LDAP_CONTROL_PAGEDRESULTS
+ if ( searchControlSize == 0 ) {
+ if ( ldif < 2 ) {
+ printf( "\n# numResponses: %d\n", nresponses );
+ if( nentries ) printf( "# numEntries: %d\n", nentries );
+ if( nextended ) printf( "# numExtended: %d\n", nextended );
+ if( npartial ) printf( "# numPartial: %d\n", npartial );
+ if( nreferences ) printf( "# numReferences: %d\n", nreferences );
+ }
+ } else {
+ npagedresponses = npagedresponses + nresponses;
+ npagedentries = npagedentries + nentries;
+ npagedreferences = npagedreferences + nreferences;
+ npagedextended = npagedextended + nextended;
+ npagedpartial = npagedpartial + npartial;
+ if ( ( morePagedResults == 0 ) && ( ldif < 2 ) ) {
+ printf( "\n# numResponses: %d\n", npagedresponses );
+ if( nentries ) printf( "# numEntries: %d\n", npagedentries );
+ if( nextended ) printf( "# numExtended: %d\n", npagedextended );
+ if( npartial ) printf( "# numPartial: %d\n", npagedpartial );
+ if( nreferences ) printf( "# numReferences: %d\n", npagedreferences );
+ }
+ }
+#else /* !LDAP_CONTROL_PAGEDRESULTS */
if ( ldif < 2 ) {
printf( "\n# numResponses: %d\n", nresponses );
if( nentries ) printf( "# numEntries: %d\n", nentries );
if( npartial ) printf( "# numPartial: %d\n", npartial );
if( nreferences ) printf( "# numReferences: %d\n", nreferences );
}
+#endif /* LDAP_CONTROL_PAGEDRESULTS */
return( rc );
}
return( 0 );
}
+
+
+#ifdef LDAP_CONTROL_PAGEDRESULTS
+static int
+parse_page_control(
+ LDAP *ld,
+ LDAPMessage *result,
+ struct berval *cookie )
+{
+ int rc;
+ int err;
+ LDAPControl **ctrl = NULL;
+ LDAPControl *ctrlp = NULL;
+ BerElement *ber;
+ ber_tag_t tag;
+ ber_int_t entriesLeft;
+ struct berval servercookie = { 0, NULL };
+
+
+ rc = ldap_parse_result( ld, result,
+ &err, NULL, NULL, NULL, &ctrl, 0 );
+
+ if( rc != LDAP_SUCCESS ) {
+ ldap_perror(ld, "ldap_parse_result");
+ exit( EXIT_FAILURE );
+ }
+
+ if ( err != LDAP_SUCCESS ) {
+ fprintf( stderr, "%s (%d)\n", ldap_err2string(err), err );
+ }
+
+ if( ctrl ) {
+ /* Parse the control value
+ * searchResult ::= SEQUENCE {
+ * size INTEGER (0..maxInt),
+ * -- result set size estimate from server - unused
+ * cookie OCTET STRING
+ */
+ ctrlp = *ctrl;
+ ber = ber_init( &ctrlp->ldctl_value );
+ if ( ber == NULL ) {
+ fprintf( stderr, "Internal error.\n" );
+ return EXIT_FAILURE;
+ }
+
+ tag = ber_scanf( ber, "{im}", &entriesLeft, &servercookie );
+ ber_dupbv( cookie, &servercookie );
+ (void) ber_free( ber, 1 );
+
+ if( tag == LBER_ERROR ) {
+ fprintf( stderr, "Paged results response control could not be decoded.\n" );
+ return EXIT_FAILURE;
+ }
+
+ if( entriesLeft < 0 ) {
+ fprintf( stderr, "Invalid entries estimate in paged results response.\n" );
+ return EXIT_FAILURE;
+ }
+
+
+ ldap_controls_free( ctrl );
+ } else {
+ morePagedResults = 0;
+ }
+
+ return err;
+}
+#endif /* LDAP_CONTROL_PAGEDRESULTS */
+
int scope,
int deref,
ID *ids );
+#ifdef LDAP_CONTROL_PAGEDRESULTS
+static void send_pagerequest_response(
+ Connection *conn,
+ Operation *op,
+ ID lastid,
+ int nentries );
+#endif /* LDAP_CONTROL_PAGEDRESULTS */
int
bdb_search(
struct berval realbase = { 0, NULL };
int nentries = 0;
int manageDSAit;
+#ifdef LDAP_CONTROL_PAGEDRESULTS
+ int pagedresults;
+ ID lastid = NOID;
+#endif /* LDAP_CONTROL_PAGEDRESULTS */
#ifdef LDAP_CLIENT_UPDATE
Filter lcupf, csnfnot, csnfeq, csnfand, csnfge;
manageDSAit = get_manageDSAit( op );
+#ifdef LDAP_CONTROL_PAGEDRESULTS
+ pagedresults = get_pagedresults( op );
+#endif /* LDAP_CONTROL_PAGEDRESULTS */
+
rc = LOCK_ID (bdb->bi_dbenv, &locker );
switch(rc) {
case 0:
}
}
+#ifdef LDAP_CONTROL_PAGEDRESULTS
+ if ( pagedresults ) {
+ if ( op->o_pagedresults_state.ps_cookie == 0 ) {
+ id = 0;
+ } else {
+ for ( id = bdb_idl_first( candidates, &cursor );
+ id != NOID && id <= (ID)( op->o_pagedresults_state.ps_cookie );
+ id = bdb_idl_next( candidates, &cursor ) );
+ }
+ if ( cursor == NOID ) {
+#ifdef NEW_LOGGING
+ LDAP_LOG ( OPERATION, RESULTS,
+ "bdb_search: no paged results candidates\n",
+ 0, 0, 0 );
+#else
+ Debug( LDAP_DEBUG_TRACE,
+ "bdb_search: no paged results candidates\n",
+ 0, 0, 0 );
+#endif
+ send_pagerequest_response( conn, op, lastid, 0 );
+
+ rc = 1;
+ goto done;
+ }
+ goto loop_begin;
+ }
+#endif /* LDAP_CONTROL_PAGEDRESULTS */
+
#ifdef LDAP_CLIENT_UPDATE
if ( op->o_clientupdate_type & SLAP_LCUP_SYNC ) {
lcupf.f_choice = LDAP_FILTER_AND;
id != NOID;
id = bdb_idl_next( candidates, &cursor ) )
{
+
int scopeok = 0;
+#ifdef LDAP_CONTROL_PAGEDRESULTS
+loop_begin:
+#endif /* LDAP_CONTROL_PAGEDRESULTS */
+
/* check for abandon */
if ( op->o_abandon ) {
rc = 0;
v2refs, NULL, nentries );
goto done;
}
+#ifdef LDAP_CONTROL_PAGEDRESULTS
+ if ( pagedresults ) {
+ if ( nentries >= op->o_pagedresults_size ) {
+ send_pagerequest_response( conn, op, lastid, nentries );
+ goto done;
+ }
+ lastid = id;
+ }
+#endif /* LDAP_CONTROL_PAGEDRESULTS */
if (e) {
int result;
return rc;
}
+#ifdef LDAP_CONTROL_PAGEDRESULTS
+static void
+send_pagerequest_response(
+ Connection *conn,
+ Operation *op,
+ ID lastid,
+ int nentries )
+{
+ LDAPControl ctrl, *ctrls[2];
+ BerElement *ber;
+ struct berval *bvalp, cookie = { 0, NULL };
+ PagedResultsCookie respcookie;
+
+#ifdef NEW_LOGGING
+ LDAP_LOG ( OPERATION, ENTRY,
+ "send_pagerequest_response: lastid: (0x%08lx) "
+ "nentries: (0x%081x)\n",
+ lastid, nentries );
+#else
+ Debug(LDAP_DEBUG_ARGS, "send_pagerequest_response: lastid: (0x%08lx) "
+ "nentries: (0x%081x)\n", lastid, nentries, NULL );
+#endif
+
+ ctrl.ldctl_value.bv_val = NULL;
+ ctrls[0] = &ctrl;
+ ctrls[1] = NULL;
+
+ if (( ber = ber_alloc_t(LBER_USE_DER)) == NULL ) {
+ goto done;
+ }
+
+ respcookie = ( PagedResultsCookie )lastid;
+ conn->c_pagedresults_state.ps_cookie = respcookie;
+ cookie.bv_len = sizeof( respcookie );
+#if 0
+ cookie.bv_val = ber_memalloc( sizeof( respcookie ) );
+ AC_MEMCPY( cookie.bv_val, &respcookie, sizeof( respcookie ) );
+#else
+ cookie.bv_val = (char *)&respcookie;
+#endif
+/*
+ conn->c_pagedresults_state.ps_cookie = cookie.bv_val;
+*/
+
+ ber_printf( ber, "{iO}", 0, &cookie );
+#if 0
+ ber_memfree( cookie.bv_val );
+#endif
+
+ if ( ber_flatten( ber, &bvalp ) == LBER_ERROR ) {
+ goto done;
+ }
+
+ ctrls[0]->ldctl_oid = LDAP_CONTROL_PAGEDRESULTS;
+ ctrls[0]->ldctl_value = ( *bvalp );
+ ctrls[0]->ldctl_iscritical = 0;
+
+ send_search_result( conn, op,
+ LDAP_SUCCESS,
+ NULL, NULL, NULL, ctrls, nentries );
+
+done:
+ if ( ctrls[0]->ldctl_value.bv_val ) {
+ ch_free( ctrls[0]->ldctl_value.bv_val );
+ }
+}
+#endif /* LDAP_CONTROL_PAGEDRESULTS */
+