slapd-search.c 8.85 KB
Newer Older
Kurt Zeilenga's avatar
Kurt Zeilenga committed
1
/* $OpenLDAP$ */
Kurt Zeilenga's avatar
Kurt Zeilenga committed
2
3
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
 *
Kurt Zeilenga's avatar
Kurt Zeilenga committed
4
 * Copyright 1999-2006 The OpenLDAP Foundation.
Kurt Zeilenga's avatar
Kurt Zeilenga committed
5
6
7
8
9
10
11
12
13
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted only as authorized by the OpenLDAP
 * Public License.
 *
 * A copy of this license is available in file LICENSE in the
 * top-level directory of the distribution or, alternatively, at
 * <http://www.OpenLDAP.org/license.html>.
14
 */
Kurt Zeilenga's avatar
Kurt Zeilenga committed
15
16
17
18
19
/* ACKNOWLEDGEMENTS:
 * This work was initially developed by Kurt Spanier for inclusion
 * in OpenLDAP Software.
 */

20
21
22
#include "portable.h"

#include <stdio.h>
Kurt Zeilenga's avatar
Kurt Zeilenga committed
23
24

#include <ac/stdlib.h>
25
26

#include <ac/ctype.h>
27
#include <ac/param.h>
28
#include <ac/socket.h>
29
#include <ac/string.h>
30
31
32
#include <ac/unistd.h>
#include <ac/wait.h>

Kurt Zeilenga's avatar
Kurt Zeilenga committed
33
#include <ldap.h>
34
#include <lutil.h>
35

36
37
#include "slapd-common.h"

38
#define LOOPS	100
39
#define RETRIES	0
40
41

static void
42
do_search( char *uri, char *manager, struct berval *passwd,
43
	char *sbase, char *filter, LDAP **ldp, int noattrs,
44
	int innerloop, int maxretries, int delay, int force, int chaserefs );
45
46
47

static void
do_random( char *uri, char *manager, struct berval *passwd,
48
	char *sbase, char *filter, char *attr, int noattrs, int innerloop,
49
	int maxretries, int delay, int force, int chaserefs );
50
51
52
53

static void
usage( char *name )
{
54
55
56
57
58
59
60
        fprintf( stderr,
		"usage: %s "
		"-H <uri> | ([-h <host>] -p <port>) "
		"-D <manager> "
		"-w <passwd> "
		"-b <searchbase> "
		"-f <searchfilter> "
61
		"[-a <attr>] "
62
		"[-A] "
63
		"[-C] "
64
		"[-F] "
65
		"[-l <loops>] "
66
		"[-L <outerloops>] "
67
68
		"[-r <maxretries>] "
		"[-t <delay>]\n",
69
			name );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
70
	exit( EXIT_FAILURE );
71
72
73
74
75
}

int
main( int argc, char **argv )
{
Hallvard Furuseth's avatar
Hallvard Furuseth committed
76
	int		i;
77
	char		*uri = NULL;
78
79
	char		*host = "localhost";
	int		port = -1;
80
	char		*manager = NULL;
81
	struct berval	passwd = { 0, NULL };
82
	char		*sbase = NULL;
83
	char		*filter  = NULL;
84
	char		*attr = NULL;
85
	int		loops = LOOPS;
86
	int		outerloops = 1;
87
	int		retries = RETRIES;
88
	int		delay = 0;
89
	int		force = 0;
90
	int		chaserefs = 0;
91
	int		noattrs = 0;
92

93
94
	tester_init( "slapd-search" );

95
	while ( (i = getopt( argc, argv, "Aa:b:CD:f:FH:h:l:L:p:w:r:t:" )) != EOF ) {
96
		switch( i ) {
97
98
99
100
		case 'A':
			noattrs++;
			break;

101
102
103
104
		case 'C':
			chaserefs++;
			break;

105
106
		case 'H':		/* the server uri */
			uri = strdup( optarg );
107
			break;
108
109
110
111
112
113

		case 'h':		/* the servers host */
			host = strdup( optarg );
			break;

		case 'p':		/* the servers port */
114
115
116
			if ( lutil_atoi( &port, optarg ) != 0 ) {
				usage( argv[0] );
			}
117
118
			break;

119
120
121
		case 'D':		/* the servers manager */
			manager = strdup( optarg );
			break;
122

123
		case 'w':		/* the server managers password */
124
125
			passwd.bv_val = strdup( optarg );
			passwd.bv_len = strlen( optarg );
126
127
			break;

128
129
130
131
		case 'a':
			attr = strdup( optarg );
			break;

132
133
		case 'b':		/* file with search base */
			sbase = strdup( optarg );
134
135
			break;

136
137
		case 'f':		/* the search request */
			filter = strdup( optarg );
138
139
			break;

140
141
142
143
		case 'F':
			force++;
			break;

144
		case 'l':		/* number of loops */
145
146
147
			if ( lutil_atoi( &loops, optarg ) != 0 ) {
				usage( argv[0] );
			}
148
			break;
149

150
151
152
153
154
155
		case 'L':		/* number of loops */
			if ( lutil_atoi( &outerloops, optarg ) != 0 ) {
				usage( argv[0] );
			}
			break;

156
		case 'r':		/* number of retries */
157
158
159
			if ( lutil_atoi( &retries, optarg ) != 0 ) {
				usage( argv[0] );
			}
160
			break;
161

162
		case 't':		/* delay in seconds */
163
164
165
			if ( lutil_atoi( &delay, optarg ) != 0 ) {
				usage( argv[0] );
			}
166
167
			break;

168
169
170
		default:
			usage( argv[0] );
			break;
171
172
173
		}
	}

174
	if (( sbase == NULL ) || ( filter == NULL ) || ( port == -1 && uri == NULL ))
175
176
177
178
179
180
		usage( argv[0] );

	if ( *filter == '\0' ) {

		fprintf( stderr, "%s: invalid EMPTY search filter.\n",
				argv[0] );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
181
		exit( EXIT_FAILURE );
182
183
184

	}

185
186
	uri = tester_uri( uri, host, port );

187
	for ( i = 0; i < outerloops; i++ ) {
188
189
		if ( attr != NULL ) {
			do_random( uri, manager, &passwd, sbase, filter, attr,
190
				noattrs, loops, retries, delay, force, chaserefs );
191
192
193

		} else {
			do_search( uri, manager, &passwd, sbase, filter, NULL,
194
				noattrs, loops, retries, delay, force, chaserefs );
195
		}
196
197
	}

Kurt Zeilenga's avatar
Kurt Zeilenga committed
198
	exit( EXIT_SUCCESS );
199
200
201
202
}


static void
203
do_random( char *uri, char *manager, struct berval *passwd,
204
	char *sbase, char *filter, char *attr, int noattrs,
205
	int innerloop, int maxretries, int delay, int force, int chaserefs )
206
{
207
	LDAP	*ld = NULL;
208
	int  	i = 0, do_retry = maxretries;
209
	char	*attrs[ 2 ];
210
	pid_t	pid = getpid();
211
	int     rc = LDAP_SUCCESS;
212
	int	version = LDAP_VERSION3;
213
214
	int	nvalues = 0;
	char	**values = NULL;
215
	LDAPMessage *res = NULL, *e = NULL;
216
217
218

	attrs[ 0 ] = attr;
	attrs[ 1 ] = NULL;
219

220
	ldap_initialize( &ld, uri );
221
	if ( ld == NULL ) {
222
		tester_perror( "ldap_initialize" );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
223
		exit( EXIT_FAILURE );
224
225
	}

226
	(void) ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version ); 
227
228
	(void) ldap_set_option( ld, LDAP_OPT_REFERRALS,
		chaserefs ? LDAP_OPT_ON : LDAP_OPT_OFF );
229

230
	if ( do_retry == maxretries ) {
231
232
		fprintf( stderr, "PID=%ld - Search(%d): base=\"%s\", filter=\"%s\" attr=\"%s\".\n",
				(long) pid, innerloop, sbase, filter, attr );
233
234
	}

235
	rc = ldap_sasl_bind_s( ld, manager, LDAP_SASL_SIMPLE, passwd, NULL, NULL, NULL );
236
	if ( rc != LDAP_SUCCESS ) {
237
		tester_ldap_error( ld, "ldap_sasl_bind_s" );
238
239
240
241
242
243
244
		switch ( rc ) {
		case LDAP_BUSY:
		case LDAP_UNAVAILABLE:
		/* fallthru */
		default:
			break;
		}
245
246
		exit( EXIT_FAILURE );
	}
247

248
249
	rc = ldap_search_ext_s( ld, sbase, LDAP_SCOPE_SUBTREE,
		filter, attrs, 0, NULL, NULL, NULL, LDAP_NO_LIMIT, &res );
250
251
252
253
254
	switch ( rc ) {
	case LDAP_SIZELIMIT_EXCEEDED:
	case LDAP_TIMELIMIT_EXCEEDED:
	case LDAP_SUCCESS:
		if ( ldap_count_entries( ld, res ) == 0 ) {
Pierangelo Masarati's avatar
Pierangelo Masarati committed
255
256
257
			if ( rc ) {
				tester_ldap_error( ld, "ldap_search_ext_s" );
			}
258
259
			break;
		}
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280

		for ( e = ldap_first_entry( ld, res ); e != NULL; e = ldap_next_entry( ld, e ) )
		{
			struct berval **v = ldap_get_values_len( ld, e, attr );

			if ( v != NULL ) {
				int n = ldap_count_values_len( v );
				int j;

				values = realloc( values, ( nvalues + n + 1 )*sizeof( char * ) );
				for ( j = 0; j < n; j++ ) {
					values[ nvalues + j ] = strdup( v[ j ]->bv_val );
				}
				values[ nvalues + j ] = NULL;
				nvalues += n;
				ldap_value_free_len( v );
			}
		}

		ldap_msgfree( res );

281
282
283
284
		if ( do_retry == maxretries ) {
			fprintf( stderr, "PID=%ld - got %d values.\n", (long) pid, nvalues );
		}

285
286
287
288
289
		for ( i = 0; i < innerloop; i++ ) {
			char	buf[ BUFSIZ ];

			snprintf( buf, sizeof( buf ), "(%s=%s)", attr, values[ rand() % nvalues ] );

290
			do_search( uri, manager, passwd, sbase, buf, &ld, noattrs,
291
					1, maxretries, delay, force, chaserefs );
292
		}
293
		break;
294
295
296
297

	default:
		tester_ldap_error( ld, "ldap_search_ext_s" );
		break;
298
299
300
301
302
303
304
305
	}

	fprintf( stderr, " PID=%ld - Search done (%d).\n", (long) pid, rc );

	if ( ld != NULL ) {
		ldap_unbind_ext( ld, NULL, NULL );
	}
}
306

307
308
309
static void
do_search( char *uri, char *manager, struct berval *passwd,
		char *sbase, char *filter, LDAP **ldp,
310
		int noattrs, int innerloop, int maxretries, int delay,
311
		int force, int chaserefs )
312
313
314
315
316
317
318
{
	LDAP	*ld = ldp ? *ldp : NULL;
	int  	i = 0, do_retry = maxretries;
	char	*attrs[] = { "cn", "sn", NULL };
	pid_t	pid = getpid();
	int     rc = LDAP_SUCCESS;
	int	version = LDAP_VERSION3;
319
	int	first = 1;
320
321
322
323
324
325
326
327
328
329

retry:;
	if ( ld == NULL ) {
		ldap_initialize( &ld, uri );
		if ( ld == NULL ) {
			tester_perror( "ldap_initialize" );
			exit( EXIT_FAILURE );
		}

		(void) ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version ); 
330
331
		(void) ldap_set_option( ld, LDAP_OPT_REFERRALS,
			chaserefs ? LDAP_OPT_ON : LDAP_OPT_OFF );
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359

		if ( do_retry == maxretries ) {
			fprintf( stderr, "PID=%ld - Search(%d): base=\"%s\", filter=\"%s\".\n",
					(long) pid, innerloop, sbase, filter );
		}

		rc = ldap_sasl_bind_s( ld, manager, LDAP_SASL_SIMPLE, passwd, NULL, NULL, NULL );
		if ( rc != LDAP_SUCCESS ) {
			tester_ldap_error( ld, "ldap_sasl_bind_s" );
			switch ( rc ) {
			case LDAP_BUSY:
			case LDAP_UNAVAILABLE:
				if ( do_retry > 0 ) {
					ldap_unbind_ext( ld, NULL, NULL );
					do_retry--;
					if ( delay != 0 ) {
					    sleep( delay );
					}
					goto retry;
				}
			/* fallthru */
			default:
				break;
			}
			exit( EXIT_FAILURE );
		}
	}

360
	for ( ; i < innerloop; i++ ) {
361
		LDAPMessage *res = NULL;
362

363
		rc = ldap_search_ext_s( ld, sbase, LDAP_SCOPE_SUBTREE,
364
				filter, attrs, noattrs, NULL, NULL,
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
				NULL, LDAP_NO_LIMIT, &res );
		if ( res != NULL ) {
			ldap_msgfree( res );
		}

		switch ( rc ) {
		case LDAP_REFERRAL:
			/* don't log: it's intended */
			if ( force >= 2 ) {
				if ( !first ) {
					break;
				}
				first = 0;
			}
			tester_ldap_error( ld, "ldap_search_ext_s" );
			/* fallthru */

		case LDAP_SUCCESS:
			break;

		default:
386
			tester_ldap_error( ld, "ldap_search_ext_s" );
387
			if ( rc == LDAP_BUSY && do_retry > 0 ) {
Pierangelo Masarati's avatar
Pierangelo Masarati committed
388
				ldap_unbind_ext( ld, NULL, NULL );
389
				do_retry--;
390
391
				goto retry;
			}
392
393
394
395
			if ( rc != LDAP_NO_SUCH_OBJECT ) {
				goto done;
			}
			break;
396
397
398
		}
	}

399
done:;
400
401
402
403
404
405
406
407
408
409
	if ( ldp != NULL ) {
		*ldp = ld;

	} else {
		fprintf( stderr, " PID=%ld - Search done (%d).\n", (long) pid, rc );

		if ( ld != NULL ) {
			ldap_unbind_ext( ld, NULL, NULL );
		}
	}
410
}