ruby-ldap 0.9.18 → 0.9.19

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,310 @@
1
+ /* $OpenLDAP$ */
2
+ /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3
+ *
4
+ * Copyright 1999-2016 The OpenLDAP Foundation.
5
+ * All rights reserved.
6
+ *
7
+ * Redistribution and use in source and binary forms, with or without
8
+ * modification, are permitted only as authorized by the OpenLDAP
9
+ * Public License.
10
+ *
11
+ * A copy of this license is available in file LICENSE in the
12
+ * top-level directory of the distribution or, alternatively, at
13
+ * <http://www.OpenLDAP.org/license.html>.
14
+ */
15
+ /* ACKNOWLEDGEMENTS:
16
+ * This work was initially developed by Howard Chu, based in part
17
+ * on other OpenLDAP test tools, for inclusion in OpenLDAP Software.
18
+ */
19
+
20
+ #include "portable.h"
21
+
22
+ #include <stdio.h>
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
+ #include "ac/unistd.h"
31
+ #include "ac/wait.h"
32
+
33
+ #include "ldap.h"
34
+ #include "lutil.h"
35
+
36
+ #include "slapd-common.h"
37
+
38
+ #define LOOPS 100
39
+ #define RETRIES 0
40
+
41
+ static void
42
+ do_modrdn( char *uri, char *manager, struct berval *passwd,
43
+ char *entry, int maxloop, int maxretries, int delay,
44
+ int friendly, int chaserefs );
45
+
46
+ static void
47
+ usage( char *name )
48
+ {
49
+ fprintf( stderr,
50
+ "usage: %s "
51
+ "-H <uri> | ([-h <host>] -p <port>) "
52
+ "-D <manager> "
53
+ "-w <passwd> "
54
+ "-e <entry> "
55
+ "[-i <ignore>] "
56
+ "[-l <loops>] "
57
+ "[-L <outerloops>] "
58
+ "[-r <maxretries>] "
59
+ "[-t <delay>] "
60
+ "[-F] "
61
+ "[-C]\n",
62
+ name );
63
+ exit( EXIT_FAILURE );
64
+ }
65
+
66
+ int
67
+ main( int argc, char **argv )
68
+ {
69
+ int i;
70
+ char *uri = NULL;
71
+ char *host = "localhost";
72
+ int port = -1;
73
+ char *manager = NULL;
74
+ struct berval passwd = { 0, NULL };
75
+ char *entry = NULL;
76
+ int loops = LOOPS;
77
+ int outerloops = 1;
78
+ int retries = RETRIES;
79
+ int delay = 0;
80
+ int friendly = 0;
81
+ int chaserefs = 0;
82
+
83
+ tester_init( "slapd-modrdn", TESTER_MODRDN );
84
+
85
+ while ( ( i = getopt( argc, argv, "CD:e:FH:h:i:L:l:p:r:t:w:" ) ) != EOF )
86
+ {
87
+ switch ( i ) {
88
+ case 'C':
89
+ chaserefs++;
90
+ break;
91
+
92
+ case 'F':
93
+ friendly++;
94
+ break;
95
+
96
+ case 'H': /* the server uri */
97
+ uri = strdup( optarg );
98
+ break;
99
+
100
+ case 'h': /* the servers host */
101
+ host = strdup( optarg );
102
+ break;
103
+
104
+ case 'i':
105
+ /* ignored (!) by now */
106
+ break;
107
+
108
+ case 'p': /* the servers port */
109
+ if ( lutil_atoi( &port, optarg ) != 0 ) {
110
+ usage( argv[0] );
111
+ }
112
+ break;
113
+
114
+ case 'D': /* the servers manager */
115
+ manager = strdup( optarg );
116
+ break;
117
+
118
+ case 'w': /* the server managers password */
119
+ passwd.bv_val = strdup( optarg );
120
+ passwd.bv_len = strlen( optarg );
121
+ memset( optarg, '*', passwd.bv_len );
122
+ break;
123
+
124
+ case 'e': /* entry to rename */
125
+ entry = strdup( optarg );
126
+ break;
127
+
128
+ case 'l': /* the number of loops */
129
+ if ( lutil_atoi( &loops, optarg ) != 0 ) {
130
+ usage( argv[0] );
131
+ }
132
+ break;
133
+
134
+ case 'L': /* the number of outerloops */
135
+ if ( lutil_atoi( &outerloops, optarg ) != 0 ) {
136
+ usage( argv[0] );
137
+ }
138
+ break;
139
+
140
+ case 'r': /* the number of retries */
141
+ if ( lutil_atoi( &retries, optarg ) != 0 ) {
142
+ usage( argv[0] );
143
+ }
144
+ break;
145
+
146
+ case 't': /* delay in seconds */
147
+ if ( lutil_atoi( &delay, optarg ) != 0 ) {
148
+ usage( argv[0] );
149
+ }
150
+ break;
151
+
152
+ default:
153
+ usage( argv[0] );
154
+ break;
155
+ }
156
+ }
157
+
158
+ if (( entry == NULL ) || ( port == -1 && uri == NULL ))
159
+ usage( argv[0] );
160
+
161
+ if ( *entry == '\0' ) {
162
+
163
+ fprintf( stderr, "%s: invalid EMPTY entry DN.\n",
164
+ argv[0] );
165
+ exit( EXIT_FAILURE );
166
+
167
+ }
168
+
169
+ uri = tester_uri( uri, host, port );
170
+
171
+ for ( i = 0; i < outerloops; i++ ) {
172
+ do_modrdn( uri, manager, &passwd, entry,
173
+ loops, retries, delay, friendly, chaserefs );
174
+ }
175
+
176
+ exit( EXIT_SUCCESS );
177
+ }
178
+
179
+
180
+ static void
181
+ do_modrdn( char *uri, char *manager,
182
+ struct berval *passwd, char *entry, int maxloop, int maxretries,
183
+ int delay, int friendly, int chaserefs )
184
+ {
185
+ LDAP *ld = NULL;
186
+ int i, do_retry = maxretries;
187
+ char *DNs[2];
188
+ char *rdns[2];
189
+ int rc = LDAP_SUCCESS;
190
+ char *p1, *p2;
191
+ int version = LDAP_VERSION3;
192
+
193
+ DNs[0] = entry;
194
+ DNs[1] = strdup( entry );
195
+
196
+ /* reverse the RDN, make new DN */
197
+ p1 = strchr( entry, '=' ) + 1;
198
+ p2 = strchr( p1, ',' );
199
+
200
+ *p2 = '\0';
201
+ rdns[1] = strdup( entry );
202
+ *p2-- = ',';
203
+
204
+ for (i = p1 - entry;p2 >= p1;)
205
+ DNs[1][i++] = *p2--;
206
+
207
+ DNs[1][i] = '\0';
208
+ rdns[0] = strdup( DNs[1] );
209
+ DNs[1][i] = ',';
210
+
211
+ i = 0;
212
+
213
+ retry:;
214
+ ldap_initialize( &ld, uri );
215
+ if ( ld == NULL ) {
216
+ tester_perror( "ldap_initialize", NULL );
217
+ exit( EXIT_FAILURE );
218
+ }
219
+
220
+ (void) ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version );
221
+ (void) ldap_set_option( ld, LDAP_OPT_REFERRALS,
222
+ chaserefs ? LDAP_OPT_ON : LDAP_OPT_OFF );
223
+
224
+ if ( do_retry == maxretries ) {
225
+ fprintf( stderr, "PID=%ld - Modrdn(%d): entry=\"%s\".\n",
226
+ (long) pid, maxloop, entry );
227
+ }
228
+
229
+ rc = ldap_sasl_bind_s( ld, manager, LDAP_SASL_SIMPLE, passwd, NULL, NULL, NULL );
230
+ if ( rc != LDAP_SUCCESS ) {
231
+ tester_ldap_error( ld, "ldap_sasl_bind_s", NULL );
232
+ switch ( rc ) {
233
+ case LDAP_BUSY:
234
+ case LDAP_UNAVAILABLE:
235
+ if ( do_retry > 0 ) {
236
+ do_retry--;
237
+ if ( delay > 0) {
238
+ sleep( delay );
239
+ }
240
+ goto retry;
241
+ }
242
+ /* fallthru */
243
+ default:
244
+ break;
245
+ }
246
+ exit( EXIT_FAILURE );
247
+ }
248
+
249
+ for ( ; i < maxloop; i++ ) {
250
+ rc = ldap_rename_s( ld, DNs[0], rdns[0], NULL, 0, NULL, NULL );
251
+ if ( rc != LDAP_SUCCESS ) {
252
+ tester_ldap_error( ld, "ldap_rename_s", NULL );
253
+ switch ( rc ) {
254
+ case LDAP_NO_SUCH_OBJECT:
255
+ /* NOTE: this likely means
256
+ * the second modrdn failed
257
+ * during the previous round... */
258
+ if ( !friendly ) {
259
+ goto done;
260
+ }
261
+ break;
262
+
263
+ case LDAP_BUSY:
264
+ case LDAP_UNAVAILABLE:
265
+ if ( do_retry > 0 ) {
266
+ do_retry--;
267
+ goto retry;
268
+ }
269
+ /* fall thru */
270
+
271
+ default:
272
+ goto done;
273
+ }
274
+ }
275
+ rc = ldap_rename_s( ld, DNs[1], rdns[1], NULL, 1, NULL, NULL );
276
+ if ( rc != LDAP_SUCCESS ) {
277
+ tester_ldap_error( ld, "ldap_rename_s", NULL );
278
+ switch ( rc ) {
279
+ case LDAP_NO_SUCH_OBJECT:
280
+ /* NOTE: this likely means
281
+ * the first modrdn failed
282
+ * during the previous round... */
283
+ if ( !friendly ) {
284
+ goto done;
285
+ }
286
+ break;
287
+
288
+ case LDAP_BUSY:
289
+ case LDAP_UNAVAILABLE:
290
+ if ( do_retry > 0 ) {
291
+ do_retry--;
292
+ goto retry;
293
+ }
294
+ /* fall thru */
295
+
296
+ default:
297
+ goto done;
298
+ }
299
+ }
300
+ }
301
+
302
+ done:;
303
+ fprintf( stderr, " PID=%ld - Modrdn done (%d).\n", (long) pid, rc );
304
+
305
+ ldap_unbind_ext( ld, NULL, NULL );
306
+
307
+ free( DNs[1] );
308
+ free( rdns[0] );
309
+ free( rdns[1] );
310
+ }
@@ -0,0 +1,837 @@
1
+ /* $OpenLDAP$ */
2
+ /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3
+ *
4
+ * Copyright 1999-2016 The OpenLDAP Foundation.
5
+ * All rights reserved.
6
+ *
7
+ * Redistribution and use in source and binary forms, with or without
8
+ * modification, are permitted only as authorized by the OpenLDAP
9
+ * Public License.
10
+ *
11
+ * A copy of this license is available in file LICENSE in the
12
+ * top-level directory of the distribution or, alternatively, at
13
+ * <http://www.OpenLDAP.org/license.html>.
14
+ */
15
+ /* ACKNOWLEDGEMENTS:
16
+ * This work was initially developed by Kurt Spanier for inclusion
17
+ * in OpenLDAP Software.
18
+ */
19
+
20
+ /*
21
+ * This tool is a MT reader. It behaves like slapd-read however
22
+ * with one or more threads simultaneously using the same connection.
23
+ * If -M is enabled, then M threads will also perform write operations.
24
+ */
25
+
26
+ #include "portable.h"
27
+
28
+ #include <stdio.h>
29
+ #include "ldap_pvt_thread.h"
30
+
31
+ #include "ac/stdlib.h"
32
+
33
+ #include "ac/ctype.h"
34
+ #include "ac/param.h"
35
+ #include "ac/socket.h"
36
+ #include "ac/string.h"
37
+ #include "ac/unistd.h"
38
+ #include "ac/wait.h"
39
+
40
+ #include "ldap.h"
41
+ #include "lutil.h"
42
+
43
+ #include "ldap_pvt.h"
44
+
45
+ #include "slapd-common.h"
46
+
47
+ #define MAXCONN 512
48
+ #define LOOPS 100
49
+ #define RETRIES 0
50
+ #define DEFAULT_BASE "ou=people,dc=example,dc=com"
51
+
52
+ static void
53
+ do_conn( char *uri, char *manager, struct berval *passwd,
54
+ LDAP **ld, int nobind, int maxretries, int conn_num );
55
+
56
+ static void
57
+ do_read( LDAP *ld, char *entry,
58
+ char **attrs, int noattrs, int nobind, int maxloop,
59
+ int maxretries, int delay, int force, int chaserefs, int idx );
60
+
61
+ static void
62
+ do_random( LDAP *ld,
63
+ char *sbase, char *filter, char **attrs, int noattrs, int nobind,
64
+ int innerloop, int maxretries, int delay, int force, int chaserefs,
65
+ int idx );
66
+
67
+ static void
68
+ do_random2( LDAP *ld,
69
+ char *sbase, char *filter, char **attrs, int noattrs, int nobind,
70
+ int innerloop, int maxretries, int delay, int force, int chaserefs,
71
+ int idx );
72
+
73
+ static void *
74
+ do_onethread( void *arg );
75
+
76
+ static void *
77
+ do_onerwthread( void *arg );
78
+
79
+ #define MAX_THREAD 1024
80
+ /* Use same array for readers and writers, offset writers by MAX_THREAD */
81
+ int rt_pass[MAX_THREAD*2];
82
+ int rt_fail[MAX_THREAD*2];
83
+ int *rwt_pass = rt_pass + MAX_THREAD;
84
+ int *rwt_fail = rt_fail + MAX_THREAD;
85
+ ldap_pvt_thread_t rtid[MAX_THREAD*2], *rwtid = rtid + MAX_THREAD;
86
+
87
+ /*
88
+ * Shared globals (command line args)
89
+ */
90
+ LDAP *ld = NULL;
91
+ char *entry = NULL;
92
+ char *filter = NULL;
93
+ int loops = LOOPS;
94
+ int outerloops = 1;
95
+ int retries = RETRIES;
96
+ int delay = 0;
97
+ int force = 0;
98
+ int chaserefs = 0;
99
+ char *srchattrs[] = { "1.1", NULL };
100
+ char **attrs = srchattrs;
101
+ int noattrs = 0;
102
+ int nobind = 0;
103
+ int threads = 1;
104
+ int rwthreads = 0;
105
+ int verbose = 0;
106
+
107
+ int noconns = 1;
108
+ LDAP **lds = NULL;
109
+
110
+ static void
111
+ thread_error(int idx, char *string)
112
+ {
113
+ char thrstr[BUFSIZ];
114
+
115
+ snprintf(thrstr, BUFSIZ, "error on tidx: %d: %s", idx, string);
116
+ tester_error( thrstr );
117
+ }
118
+
119
+ static void
120
+ thread_output(int idx, char *string)
121
+ {
122
+ char thrstr[BUFSIZ];
123
+
124
+ snprintf(thrstr, BUFSIZ, "tidx: %d says: %s", idx, string);
125
+ tester_error( thrstr );
126
+ }
127
+
128
+ static void
129
+ thread_verbose(int idx, char *string)
130
+ {
131
+ char thrstr[BUFSIZ];
132
+
133
+ if (!verbose)
134
+ return;
135
+ snprintf(thrstr, BUFSIZ, "tidx: %d says: %s", idx, string);
136
+ tester_error( thrstr );
137
+ }
138
+
139
+ static void
140
+ usage( char *name )
141
+ {
142
+ fprintf( stderr,
143
+ "usage: %s "
144
+ "-H <uri> | ([-h <host>] -p <port>) "
145
+ "-D <manager> "
146
+ "-w <passwd> "
147
+ "-e <entry> "
148
+ "[-A] "
149
+ "[-C] "
150
+ "[-F] "
151
+ "[-N] "
152
+ "[-v] "
153
+ "[-c connections] "
154
+ "[-f filter] "
155
+ "[-i <ignore>] "
156
+ "[-l <loops>] "
157
+ "[-L <outerloops>] "
158
+ "[-m threads] "
159
+ "[-M threads] "
160
+ "[-r <maxretries>] "
161
+ "[-t <delay>] "
162
+ "[-T <attrs>] "
163
+ "[<attrs>] "
164
+ "\n",
165
+ name );
166
+ exit( EXIT_FAILURE );
167
+ }
168
+
169
+ int
170
+ main( int argc, char **argv )
171
+ {
172
+ int i;
173
+ char *uri = NULL;
174
+ char *host = "localhost";
175
+ int port = -1;
176
+ char *manager = NULL;
177
+ struct berval passwd = { 0, NULL };
178
+ char outstr[BUFSIZ];
179
+ int ptpass;
180
+ int testfail = 0;
181
+
182
+
183
+ tester_init( "slapd-mtread", TESTER_READ );
184
+
185
+ /* by default, tolerate referrals and no such object */
186
+ tester_ignore_str2errlist( "REFERRAL,NO_SUCH_OBJECT" );
187
+
188
+ while ( (i = getopt( argc, argv, "ACc:D:e:Ff:H:h:i:L:l:M:m:Np:r:t:T:w:v" )) != EOF ) {
189
+ switch ( i ) {
190
+ case 'A':
191
+ noattrs++;
192
+ break;
193
+
194
+ case 'C':
195
+ chaserefs++;
196
+ break;
197
+
198
+ case 'H': /* the server uri */
199
+ uri = strdup( optarg );
200
+ break;
201
+
202
+ case 'h': /* the servers host */
203
+ host = strdup( optarg );
204
+ break;
205
+
206
+ case 'i':
207
+ tester_ignore_str2errlist( optarg );
208
+ break;
209
+
210
+ case 'N':
211
+ nobind++;
212
+ break;
213
+
214
+ case 'v':
215
+ verbose++;
216
+ break;
217
+
218
+ case 'p': /* the servers port */
219
+ if ( lutil_atoi( &port, optarg ) != 0 ) {
220
+ usage( argv[0] );
221
+ }
222
+ break;
223
+
224
+ case 'D': /* the servers manager */
225
+ manager = strdup( optarg );
226
+ break;
227
+
228
+ case 'w': /* the server managers password */
229
+ passwd.bv_val = strdup( optarg );
230
+ passwd.bv_len = strlen( optarg );
231
+ memset( optarg, '*', passwd.bv_len );
232
+ break;
233
+
234
+ case 'c': /* the number of connections */
235
+ if ( lutil_atoi( &noconns, optarg ) != 0 ) {
236
+ usage( argv[0] );
237
+ }
238
+ break;
239
+
240
+ case 'e': /* DN to search for */
241
+ entry = strdup( optarg );
242
+ break;
243
+
244
+ case 'f': /* the search request */
245
+ filter = strdup( optarg );
246
+ break;
247
+
248
+ case 'F':
249
+ force++;
250
+ break;
251
+
252
+ case 'l': /* the number of loops */
253
+ if ( lutil_atoi( &loops, optarg ) != 0 ) {
254
+ usage( argv[0] );
255
+ }
256
+ break;
257
+
258
+ case 'L': /* the number of outerloops */
259
+ if ( lutil_atoi( &outerloops, optarg ) != 0 ) {
260
+ usage( argv[0] );
261
+ }
262
+ break;
263
+
264
+ case 'M': /* the number of R/W threads */
265
+ if ( lutil_atoi( &rwthreads, optarg ) != 0 ) {
266
+ usage( argv[0] );
267
+ }
268
+ if (rwthreads > MAX_THREAD)
269
+ rwthreads = MAX_THREAD;
270
+ break;
271
+
272
+ case 'm': /* the number of threads */
273
+ if ( lutil_atoi( &threads, optarg ) != 0 ) {
274
+ usage( argv[0] );
275
+ }
276
+ if (threads > MAX_THREAD)
277
+ threads = MAX_THREAD;
278
+ break;
279
+
280
+ case 'r': /* the number of retries */
281
+ if ( lutil_atoi( &retries, optarg ) != 0 ) {
282
+ usage( argv[0] );
283
+ }
284
+ break;
285
+
286
+ case 't': /* delay in seconds */
287
+ if ( lutil_atoi( &delay, optarg ) != 0 ) {
288
+ usage( argv[0] );
289
+ }
290
+ break;
291
+
292
+ case 'T':
293
+ attrs = ldap_str2charray( optarg, "," );
294
+ if ( attrs == NULL ) {
295
+ usage( argv[0] );
296
+ }
297
+ break;
298
+
299
+ default:
300
+ usage( argv[0] );
301
+ break;
302
+ }
303
+ }
304
+
305
+ if (( entry == NULL ) || ( port == -1 && uri == NULL ))
306
+ usage( argv[0] );
307
+
308
+ if ( *entry == '\0' ) {
309
+ fprintf( stderr, "%s: invalid EMPTY entry DN.\n",
310
+ argv[0] );
311
+ exit( EXIT_FAILURE );
312
+ }
313
+
314
+ if ( argv[optind] != NULL ) {
315
+ attrs = &argv[optind];
316
+ }
317
+
318
+ if (noconns < 1)
319
+ noconns = 1;
320
+ if (noconns > MAXCONN)
321
+ noconns = MAXCONN;
322
+ lds = (LDAP **) calloc( sizeof(LDAP *), noconns);
323
+ if (lds == NULL) {
324
+ fprintf( stderr, "%s: Memory error: calloc noconns.\n",
325
+ argv[0] );
326
+ exit( EXIT_FAILURE );
327
+ }
328
+
329
+ uri = tester_uri( uri, host, port );
330
+ /* One connection and one connection only */
331
+ do_conn( uri, manager, &passwd, &ld, nobind, retries, 0 );
332
+ lds[0] = ld;
333
+ for(i = 1; i < noconns; i++) {
334
+ do_conn( uri, manager, &passwd, &lds[i], nobind, retries, i );
335
+ }
336
+
337
+ ldap_pvt_thread_initialize();
338
+
339
+ snprintf(outstr, BUFSIZ, "MT Test Start: conns: %d (%s)", noconns, uri);
340
+ tester_error(outstr);
341
+ snprintf(outstr, BUFSIZ, "Threads: RO: %d RW: %d", threads, rwthreads);
342
+ tester_error(outstr);
343
+
344
+ /* Set up read only threads */
345
+ for ( i = 0; i < threads; i++ ) {
346
+ ldap_pvt_thread_create( &rtid[i], 0, do_onethread, &rtid[i]);
347
+ snprintf(outstr, BUFSIZ, "Created RO thread %d", i);
348
+ thread_verbose(-1, outstr);
349
+ }
350
+ /* Set up read/write threads */
351
+ for ( i = 0; i < rwthreads; i++ ) {
352
+ ldap_pvt_thread_create( &rwtid[i], 0, do_onerwthread, &rwtid[i]);
353
+ snprintf(outstr, BUFSIZ, "Created RW thread %d", i + MAX_THREAD);
354
+ thread_verbose(-1, outstr);
355
+ }
356
+
357
+ ptpass = outerloops * loops;
358
+
359
+ /* wait for read only threads to complete */
360
+ for ( i = 0; i < threads; i++ )
361
+ ldap_pvt_thread_join(rtid[i], NULL);
362
+ /* wait for read/write threads to complete */
363
+ for ( i = 0; i < rwthreads; i++ )
364
+ ldap_pvt_thread_join(rwtid[i], NULL);
365
+
366
+ for(i = 0; i < noconns; i++) {
367
+ if ( lds[i] != NULL ) {
368
+ ldap_unbind_ext( lds[i], NULL, NULL );
369
+ }
370
+ }
371
+ free( lds );
372
+
373
+ for ( i = 0; i < threads; i++ ) {
374
+ snprintf(outstr, BUFSIZ, "RO thread %d pass=%d fail=%d", i,
375
+ rt_pass[i], rt_fail[i]);
376
+ tester_error(outstr);
377
+ if (rt_fail[i] != 0 || rt_pass[i] != ptpass) {
378
+ snprintf(outstr, BUFSIZ, "FAIL RO thread %d", i);
379
+ tester_error(outstr);
380
+ testfail++;
381
+ }
382
+ }
383
+ for ( i = 0; i < rwthreads; i++ ) {
384
+ snprintf(outstr, BUFSIZ, "RW thread %d pass=%d fail=%d", i + MAX_THREAD,
385
+ rwt_pass[i], rwt_fail[i]);
386
+ tester_error(outstr);
387
+ if (rwt_fail[i] != 0 || rwt_pass[i] != ptpass) {
388
+ snprintf(outstr, BUFSIZ, "FAIL RW thread %d", i);
389
+ tester_error(outstr);
390
+ testfail++;
391
+ }
392
+ }
393
+ snprintf(outstr, BUFSIZ, "MT Test complete" );
394
+ tester_error(outstr);
395
+
396
+ if (testfail)
397
+ exit( EXIT_FAILURE );
398
+ exit( EXIT_SUCCESS );
399
+ }
400
+
401
+ static void *
402
+ do_onethread( void *arg )
403
+ {
404
+ int i, j, thisconn;
405
+ LDAP **mlds;
406
+ char thrstr[BUFSIZ];
407
+ int rc, refcnt = 0;
408
+ int idx = (ldap_pvt_thread_t *)arg - rtid;
409
+
410
+ mlds = (LDAP **) calloc( sizeof(LDAP *), noconns);
411
+ if (mlds == NULL) {
412
+ thread_error( idx, "Memory error: thread calloc for noconns" );
413
+ exit( EXIT_FAILURE );
414
+ }
415
+
416
+ for ( j = 0; j < outerloops; j++ ) {
417
+ for(i = 0; i < noconns; i++) {
418
+ mlds[i] = ldap_dup(lds[i]);
419
+ if (mlds[i] == NULL) {
420
+ thread_error( idx, "ldap_dup error" );
421
+ }
422
+ }
423
+ rc = ldap_get_option(mlds[0], LDAP_OPT_SESSION_REFCNT, &refcnt);
424
+ snprintf(thrstr, BUFSIZ,
425
+ "RO Thread conns: %d refcnt: %d (rc = %d)",
426
+ noconns, refcnt, rc);
427
+ thread_verbose(idx, thrstr);
428
+
429
+ thisconn = (idx + j) % noconns;
430
+ if (thisconn < 0 || thisconn >= noconns)
431
+ thisconn = 0;
432
+ if (mlds[thisconn] == NULL) {
433
+ thread_error( idx, "(failed to dup)");
434
+ tester_perror( "ldap_dup", "(failed to dup)" );
435
+ exit( EXIT_FAILURE );
436
+ }
437
+ snprintf(thrstr, BUFSIZ, "Using conn %d", thisconn);
438
+ thread_verbose(idx, thrstr);
439
+ if ( filter != NULL ) {
440
+ if (strchr(filter, '['))
441
+ do_random2( mlds[thisconn], entry, filter, attrs,
442
+ noattrs, nobind, loops, retries, delay, force,
443
+ chaserefs, idx );
444
+ else
445
+ do_random( mlds[thisconn], entry, filter, attrs,
446
+ noattrs, nobind, loops, retries, delay, force,
447
+ chaserefs, idx );
448
+
449
+ } else {
450
+ do_read( mlds[thisconn], entry, attrs,
451
+ noattrs, nobind, loops, retries, delay, force,
452
+ chaserefs, idx );
453
+ }
454
+ for(i = 0; i < noconns; i++) {
455
+ (void) ldap_destroy(mlds[i]);
456
+ mlds[i] = NULL;
457
+ }
458
+ }
459
+ free( mlds );
460
+ return( NULL );
461
+ }
462
+
463
+ static void *
464
+ do_onerwthread( void *arg )
465
+ {
466
+ int i, j, thisconn;
467
+ LDAP **mlds, *ld;
468
+ char thrstr[BUFSIZ];
469
+ char dn[256], uids[32], cns[32], *base;
470
+ LDAPMod *attrp[5], attrs[4];
471
+ char *oc_vals[] = { "top", "OpenLDAPperson", NULL };
472
+ char *cn_vals[] = { NULL, NULL };
473
+ char *sn_vals[] = { NULL, NULL };
474
+ char *uid_vals[] = { NULL, NULL };
475
+ int ret;
476
+ int adds = 0;
477
+ int dels = 0;
478
+ int rc, refcnt = 0;
479
+ int idx = (ldap_pvt_thread_t *)arg - rtid;
480
+
481
+ mlds = (LDAP **) calloc( sizeof(LDAP *), noconns);
482
+ if (mlds == NULL) {
483
+ thread_error( idx, "Memory error: thread calloc for noconns" );
484
+ exit( EXIT_FAILURE );
485
+ }
486
+
487
+ snprintf(uids, sizeof(uids), "rwtest%04d", idx);
488
+ snprintf(cns, sizeof(cns), "rwtest%04d", idx);
489
+ /* add setup */
490
+ for (i = 0; i < 4; i++) {
491
+ attrp[i] = &attrs[i];
492
+ attrs[i].mod_op = 0;
493
+ }
494
+ attrp[4] = NULL;
495
+ attrs[0].mod_type = "objectClass";
496
+ attrs[0].mod_values = oc_vals;
497
+ attrs[1].mod_type = "cn";
498
+ attrs[1].mod_values = cn_vals;
499
+ cn_vals[0] = &cns[0];
500
+ attrs[2].mod_type = "sn";
501
+ attrs[2].mod_values = sn_vals;
502
+ sn_vals[0] = &cns[0];
503
+ attrs[3].mod_type = "uid";
504
+ attrs[3].mod_values = uid_vals;
505
+ uid_vals[0] = &uids[0];
506
+
507
+ for ( j = 0; j < outerloops; j++ ) {
508
+ for(i = 0; i < noconns; i++) {
509
+ mlds[i] = ldap_dup(lds[i]);
510
+ if (mlds[i] == NULL) {
511
+ thread_error( idx, "ldap_dup error" );
512
+ }
513
+ }
514
+ rc = ldap_get_option(mlds[0], LDAP_OPT_SESSION_REFCNT, &refcnt);
515
+ snprintf(thrstr, BUFSIZ,
516
+ "RW Thread conns: %d refcnt: %d (rc = %d)",
517
+ noconns, refcnt, rc);
518
+ thread_verbose(idx, thrstr);
519
+
520
+ thisconn = (idx + j) % noconns;
521
+ if (thisconn < 0 || thisconn >= noconns)
522
+ thisconn = 0;
523
+ if (mlds[thisconn] == NULL) {
524
+ thread_error( idx, "(failed to dup)");
525
+ tester_perror( "ldap_dup", "(failed to dup)" );
526
+ exit( EXIT_FAILURE );
527
+ }
528
+ snprintf(thrstr, BUFSIZ, "START RW Thread using conn %d", thisconn);
529
+ thread_verbose(idx, thrstr);
530
+
531
+ ld = mlds[thisconn];
532
+ if (entry != NULL)
533
+ base = entry;
534
+ else
535
+ base = DEFAULT_BASE;
536
+ snprintf(dn, 256, "cn=%s,%s", cns, base);
537
+
538
+ adds = 0;
539
+ dels = 0;
540
+ for (i = 0; i < loops; i++) {
541
+ ret = ldap_add_ext_s(ld, dn, &attrp[0], NULL, NULL);
542
+ if (ret == LDAP_SUCCESS) {
543
+ adds++;
544
+ ret = ldap_delete_ext_s(ld, dn, NULL, NULL);
545
+ if (ret == LDAP_SUCCESS) {
546
+ dels++;
547
+ rt_pass[idx]++;
548
+ } else {
549
+ thread_output(idx, ldap_err2string(ret));
550
+ rt_fail[idx]++;
551
+ }
552
+ } else {
553
+ thread_output(idx, ldap_err2string(ret));
554
+ rt_fail[idx]++;
555
+ }
556
+ }
557
+
558
+ snprintf(thrstr, BUFSIZ,
559
+ "INNER STOP RW Thread using conn %d (%d/%d)",
560
+ thisconn, adds, dels);
561
+ thread_verbose(idx, thrstr);
562
+
563
+ for(i = 0; i < noconns; i++) {
564
+ (void) ldap_destroy(mlds[i]);
565
+ mlds[i] = NULL;
566
+ }
567
+ }
568
+
569
+ free( mlds );
570
+ return( NULL );
571
+ }
572
+
573
+ static void
574
+ do_conn( char *uri, char *manager, struct berval *passwd,
575
+ LDAP **ldp, int nobind, int maxretries, int conn_num )
576
+ {
577
+ LDAP *ld = NULL;
578
+ int version = LDAP_VERSION3;
579
+ int i = 0, do_retry = maxretries;
580
+ int rc = LDAP_SUCCESS;
581
+ char thrstr[BUFSIZ];
582
+
583
+ retry:;
584
+ ldap_initialize( &ld, uri );
585
+ if ( ld == NULL ) {
586
+ snprintf( thrstr, BUFSIZ, "connection: %d", conn_num );
587
+ tester_error( thrstr );
588
+ tester_perror( "ldap_initialize", NULL );
589
+ exit( EXIT_FAILURE );
590
+ }
591
+
592
+ (void) ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version );
593
+ (void) ldap_set_option( ld, LDAP_OPT_REFERRALS,
594
+ chaserefs ? LDAP_OPT_ON : LDAP_OPT_OFF );
595
+
596
+ if ( do_retry == maxretries ) {
597
+ snprintf( thrstr, BUFSIZ, "do_conn #%d\n", conn_num );
598
+ thread_verbose( -1, thrstr );
599
+ }
600
+
601
+ if ( nobind == 0 ) {
602
+ rc = ldap_sasl_bind_s( ld, manager, LDAP_SASL_SIMPLE, passwd, NULL, NULL, NULL );
603
+ if ( rc != LDAP_SUCCESS ) {
604
+ snprintf( thrstr, BUFSIZ, "connection: %d", conn_num );
605
+ tester_error( thrstr );
606
+ tester_ldap_error( ld, "ldap_sasl_bind_s", NULL );
607
+ switch ( rc ) {
608
+ case LDAP_BUSY:
609
+ case LDAP_UNAVAILABLE:
610
+ if ( do_retry > 0 ) {
611
+ ldap_unbind_ext( ld, NULL, NULL );
612
+ ld = NULL;
613
+ do_retry--;
614
+ if ( delay != 0 ) {
615
+ sleep( delay );
616
+ }
617
+ goto retry;
618
+ }
619
+ /* fallthru */
620
+ default:
621
+ break;
622
+ }
623
+ exit( EXIT_FAILURE );
624
+ }
625
+ }
626
+ *ldp = ld;
627
+ }
628
+
629
+ static void
630
+ do_random( LDAP *ld,
631
+ char *sbase, char *filter, char **srchattrs, int noattrs, int nobind,
632
+ int innerloop, int maxretries, int delay, int force, int chaserefs,
633
+ int idx )
634
+ {
635
+ int i = 0, do_retry = maxretries;
636
+ char *attrs[ 2 ];
637
+ int rc = LDAP_SUCCESS;
638
+ int nvalues = 0;
639
+ char **values = NULL;
640
+ LDAPMessage *res = NULL, *e = NULL;
641
+ char thrstr[BUFSIZ];
642
+
643
+ attrs[ 0 ] = LDAP_NO_ATTRS;
644
+ attrs[ 1 ] = NULL;
645
+
646
+ snprintf( thrstr, BUFSIZ,
647
+ "Read(%d): base=\"%s\", filter=\"%s\".\n",
648
+ innerloop, sbase, filter );
649
+ thread_verbose( idx, thrstr );
650
+
651
+ rc = ldap_search_ext_s( ld, sbase, LDAP_SCOPE_SUBTREE,
652
+ filter, attrs, 0, NULL, NULL, NULL, LDAP_NO_LIMIT, &res );
653
+ switch ( rc ) {
654
+ case LDAP_SIZELIMIT_EXCEEDED:
655
+ case LDAP_TIMELIMIT_EXCEEDED:
656
+ case LDAP_SUCCESS:
657
+ nvalues = ldap_count_entries( ld, res );
658
+ if ( nvalues == 0 ) {
659
+ if ( rc ) {
660
+ tester_ldap_error( ld, "ldap_search_ext_s", NULL );
661
+ }
662
+ break;
663
+ }
664
+
665
+ values = malloc( ( nvalues + 1 ) * sizeof( char * ) );
666
+ for ( i = 0, e = ldap_first_entry( ld, res ); e != NULL; i++, e = ldap_next_entry( ld, e ) )
667
+ {
668
+ values[ i ] = ldap_get_dn( ld, e );
669
+ }
670
+ values[ i ] = NULL;
671
+
672
+ ldap_msgfree( res );
673
+
674
+ if ( do_retry == maxretries ) {
675
+ snprintf( thrstr, BUFSIZ,
676
+ "Read base=\"%s\" filter=\"%s\" got %d values.\n",
677
+ sbase, filter, nvalues );
678
+ thread_verbose( idx, thrstr );
679
+ }
680
+
681
+ for ( i = 0; i < innerloop; i++ ) {
682
+ int r = ((double)nvalues)*rand()/(RAND_MAX + 1.0);
683
+
684
+ do_read( ld, values[ r ],
685
+ srchattrs, noattrs, nobind, 1, maxretries,
686
+ delay, force, chaserefs, idx );
687
+ }
688
+ for( i = 0; i < nvalues; i++) {
689
+ if (values[i] != NULL)
690
+ ldap_memfree( values[i] );
691
+ }
692
+ free( values );
693
+ break;
694
+
695
+ default:
696
+ tester_ldap_error( ld, "ldap_search_ext_s", NULL );
697
+ break;
698
+ }
699
+
700
+ snprintf( thrstr, BUFSIZ, "Search done (%d).\n", rc );
701
+ thread_verbose( idx, thrstr );
702
+ }
703
+
704
+ /* substitute a generated int into the filter */
705
+ static void
706
+ do_random2( LDAP *ld,
707
+ char *sbase, char *filter, char **srchattrs, int noattrs, int nobind,
708
+ int innerloop, int maxretries, int delay, int force, int chaserefs,
709
+ int idx )
710
+ {
711
+ int i = 0, do_retry = maxretries;
712
+ int rc = LDAP_SUCCESS;
713
+ int lo, hi, range;
714
+ int flen;
715
+ LDAPMessage *res = NULL, *e = NULL;
716
+ char *ptr, *ftail;
717
+ char thrstr[BUFSIZ];
718
+ char fbuf[BUFSIZ];
719
+
720
+ snprintf( thrstr, BUFSIZ,
721
+ "Read(%d): base=\"%s\", filter=\"%s\".\n",
722
+ innerloop, sbase, filter );
723
+ thread_verbose( idx, thrstr );
724
+
725
+ ptr = strchr(filter, '[');
726
+ if (!ptr)
727
+ return;
728
+ ftail = strchr(filter, ']');
729
+ if (!ftail || ftail < ptr)
730
+ return;
731
+
732
+ sscanf(ptr, "[%d-%d]", &lo, &hi);
733
+ range = hi - lo + 1;
734
+
735
+ flen = ptr - filter;
736
+ ftail++;
737
+
738
+ for ( i = 0; i < innerloop; i++ ) {
739
+ int r = ((double)range)*rand()/(RAND_MAX + 1.0);
740
+ sprintf(fbuf, "%.*s%d%s", flen, filter, r, ftail);
741
+
742
+ rc = ldap_search_ext_s( ld, sbase, LDAP_SCOPE_SUBTREE,
743
+ fbuf, srchattrs, noattrs, NULL, NULL, NULL,
744
+ LDAP_NO_LIMIT, &res );
745
+ if ( res != NULL ) {
746
+ ldap_msgfree( res );
747
+ }
748
+ if ( rc == 0 ) {
749
+ rt_pass[idx]++;
750
+ } else {
751
+ int first = tester_ignore_err( rc );
752
+ char buf[ BUFSIZ ];
753
+
754
+ rt_fail[idx]++;
755
+ snprintf( buf, sizeof( buf ), "ldap_search_ext_s(%s)", entry );
756
+
757
+ /* if ignore.. */
758
+ if ( first ) {
759
+ /* only log if first occurrence */
760
+ if ( ( force < 2 && first > 0 ) || abs(first) == 1 ) {
761
+ tester_ldap_error( ld, buf, NULL );
762
+ }
763
+ continue;
764
+ }
765
+
766
+ /* busy needs special handling */
767
+ tester_ldap_error( ld, buf, NULL );
768
+ if ( rc == LDAP_BUSY && do_retry > 0 ) {
769
+ do_retry--;
770
+ continue;
771
+ }
772
+ break;
773
+ }
774
+ }
775
+
776
+ snprintf( thrstr, BUFSIZ, "Search done (%d).\n", rc );
777
+ thread_verbose( idx, thrstr );
778
+ }
779
+
780
+ static void
781
+ do_read( LDAP *ld, char *entry,
782
+ char **attrs, int noattrs, int nobind, int maxloop,
783
+ int maxretries, int delay, int force, int chaserefs, int idx )
784
+ {
785
+ int i = 0, do_retry = maxretries;
786
+ int rc = LDAP_SUCCESS;
787
+ char thrstr[BUFSIZ];
788
+
789
+ retry:;
790
+ if ( do_retry == maxretries ) {
791
+ snprintf( thrstr, BUFSIZ, "Read(%d): entry=\"%s\".\n",
792
+ maxloop, entry );
793
+ thread_verbose( idx, thrstr );
794
+ }
795
+
796
+ snprintf(thrstr, BUFSIZ, "LD %p cnt: %d (retried %d) (%s)", \
797
+ (void *) ld, maxloop, (do_retry - maxretries), entry);
798
+ thread_verbose( idx, thrstr );
799
+
800
+ for ( ; i < maxloop; i++ ) {
801
+ LDAPMessage *res = NULL;
802
+
803
+ rc = ldap_search_ext_s( ld, entry, LDAP_SCOPE_BASE,
804
+ NULL, attrs, noattrs, NULL, NULL, NULL,
805
+ LDAP_NO_LIMIT, &res );
806
+ if ( res != NULL ) {
807
+ ldap_msgfree( res );
808
+ }
809
+
810
+ if ( rc == 0 ) {
811
+ rt_pass[idx]++;
812
+ } else {
813
+ int first = tester_ignore_err( rc );
814
+ char buf[ BUFSIZ ];
815
+
816
+ rt_fail[idx]++;
817
+ snprintf( buf, sizeof( buf ), "ldap_search_ext_s(%s)", entry );
818
+
819
+ /* if ignore.. */
820
+ if ( first ) {
821
+ /* only log if first occurrence */
822
+ if ( ( force < 2 && first > 0 ) || abs(first) == 1 ) {
823
+ tester_ldap_error( ld, buf, NULL );
824
+ }
825
+ continue;
826
+ }
827
+
828
+ /* busy needs special handling */
829
+ tester_ldap_error( ld, buf, NULL );
830
+ if ( rc == LDAP_BUSY && do_retry > 0 ) {
831
+ do_retry--;
832
+ goto retry;
833
+ }
834
+ break;
835
+ }
836
+ }
837
+ }