slapd-addel.c revision 1.1 1 1.1 lukem /* $OpenLDAP: pkg/ldap/tests/progs/slapd-addel.c,v 1.41.2.6 2008/04/14 21:43:13 quanah Exp $ */
2 1.1 lukem /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3 1.1 lukem *
4 1.1 lukem * Copyright 1999-2008 The OpenLDAP Foundation.
5 1.1 lukem * All rights reserved.
6 1.1 lukem *
7 1.1 lukem * Redistribution and use in source and binary forms, with or without
8 1.1 lukem * modification, are permitted only as authorized by the OpenLDAP
9 1.1 lukem * Public License.
10 1.1 lukem *
11 1.1 lukem * A copy of this license is available in file LICENSE in the
12 1.1 lukem * top-level directory of the distribution or, alternatively, at
13 1.1 lukem * <http://www.OpenLDAP.org/license.html>.
14 1.1 lukem */
15 1.1 lukem /* ACKNOWLEDGEMENTS:
16 1.1 lukem * This work was initially developed by Kurt Spanier for inclusion
17 1.1 lukem * in OpenLDAP Software.
18 1.1 lukem */
19 1.1 lukem
20 1.1 lukem #include "portable.h"
21 1.1 lukem
22 1.1 lukem #include <stdio.h>
23 1.1 lukem
24 1.1 lukem #include "ac/stdlib.h"
25 1.1 lukem
26 1.1 lukem #include "ac/ctype.h"
27 1.1 lukem #include "ac/param.h"
28 1.1 lukem #include "ac/socket.h"
29 1.1 lukem #include "ac/string.h"
30 1.1 lukem #include "ac/unistd.h"
31 1.1 lukem #include "ac/wait.h"
32 1.1 lukem
33 1.1 lukem #include "ldap.h"
34 1.1 lukem #include "lutil.h"
35 1.1 lukem
36 1.1 lukem #include "slapd-common.h"
37 1.1 lukem
38 1.1 lukem #define LOOPS 100
39 1.1 lukem #define RETRIES 0
40 1.1 lukem
41 1.1 lukem static char *
42 1.1 lukem get_add_entry( char *filename, LDAPMod ***mods );
43 1.1 lukem
44 1.1 lukem static void
45 1.1 lukem do_addel( char *uri, char *manager, struct berval *passwd,
46 1.1 lukem char *dn, LDAPMod **attrs, int maxloop, int maxretries, int delay,
47 1.1 lukem int friendly, int chaserefs );
48 1.1 lukem
49 1.1 lukem static void
50 1.1 lukem usage( char *name )
51 1.1 lukem {
52 1.1 lukem fprintf( stderr,
53 1.1 lukem "usage: %s "
54 1.1 lukem "-H <uri> | ([-h <host>] -p <port>) "
55 1.1 lukem "-D <manager> "
56 1.1 lukem "-w <passwd> "
57 1.1 lukem "-f <addfile> "
58 1.1 lukem "[-i <ignore>] "
59 1.1 lukem "[-l <loops>] "
60 1.1 lukem "[-L <outerloops>] "
61 1.1 lukem "[-r <maxretries>] "
62 1.1 lukem "[-t <delay>] "
63 1.1 lukem "[-F] "
64 1.1 lukem "[-C]\n",
65 1.1 lukem name );
66 1.1 lukem exit( EXIT_FAILURE );
67 1.1 lukem }
68 1.1 lukem
69 1.1 lukem int
70 1.1 lukem main( int argc, char **argv )
71 1.1 lukem {
72 1.1 lukem int i;
73 1.1 lukem char *host = "localhost";
74 1.1 lukem char *uri = NULL;
75 1.1 lukem int port = -1;
76 1.1 lukem char *manager = NULL;
77 1.1 lukem struct berval passwd = { 0, NULL };
78 1.1 lukem char *filename = NULL;
79 1.1 lukem char *entry = NULL;
80 1.1 lukem int loops = LOOPS;
81 1.1 lukem int outerloops = 1;
82 1.1 lukem int retries = RETRIES;
83 1.1 lukem int delay = 0;
84 1.1 lukem int friendly = 0;
85 1.1 lukem int chaserefs = 0;
86 1.1 lukem LDAPMod **attrs = NULL;
87 1.1 lukem
88 1.1 lukem tester_init( "slapd-addel", TESTER_ADDEL );
89 1.1 lukem
90 1.1 lukem while ( ( i = getopt( argc, argv, "CD:Ff:H:h:i:L:l:p:r:t:w:" ) ) != EOF )
91 1.1 lukem {
92 1.1 lukem switch ( i ) {
93 1.1 lukem case 'C':
94 1.1 lukem chaserefs++;
95 1.1 lukem break;
96 1.1 lukem
97 1.1 lukem case 'F':
98 1.1 lukem friendly++;
99 1.1 lukem break;
100 1.1 lukem
101 1.1 lukem case 'H': /* the server's URI */
102 1.1 lukem uri = strdup( optarg );
103 1.1 lukem break;
104 1.1 lukem
105 1.1 lukem case 'h': /* the servers host */
106 1.1 lukem host = strdup( optarg );
107 1.1 lukem break;
108 1.1 lukem
109 1.1 lukem case 'i':
110 1.1 lukem /* ignored (!) by now */
111 1.1 lukem break;
112 1.1 lukem
113 1.1 lukem case 'p': /* the servers port */
114 1.1 lukem if ( lutil_atoi( &port, optarg ) != 0 ) {
115 1.1 lukem usage( argv[0] );
116 1.1 lukem }
117 1.1 lukem break;
118 1.1 lukem
119 1.1 lukem case 'D': /* the servers manager */
120 1.1 lukem manager = strdup( optarg );
121 1.1 lukem break;
122 1.1 lukem
123 1.1 lukem case 'w': /* the server managers password */
124 1.1 lukem passwd.bv_val = strdup( optarg );
125 1.1 lukem passwd.bv_len = strlen( optarg );
126 1.1 lukem memset( optarg, '*', passwd.bv_len );
127 1.1 lukem break;
128 1.1 lukem
129 1.1 lukem case 'f': /* file with entry search request */
130 1.1 lukem filename = strdup( optarg );
131 1.1 lukem break;
132 1.1 lukem
133 1.1 lukem case 'l': /* the number of loops */
134 1.1 lukem if ( lutil_atoi( &loops, optarg ) != 0 ) {
135 1.1 lukem usage( argv[0] );
136 1.1 lukem }
137 1.1 lukem break;
138 1.1 lukem
139 1.1 lukem case 'L': /* the number of outerloops */
140 1.1 lukem if ( lutil_atoi( &outerloops, optarg ) != 0 ) {
141 1.1 lukem usage( argv[0] );
142 1.1 lukem }
143 1.1 lukem break;
144 1.1 lukem
145 1.1 lukem case 'r': /* number of retries */
146 1.1 lukem if ( lutil_atoi( &retries, optarg ) != 0 ) {
147 1.1 lukem usage( argv[0] );
148 1.1 lukem }
149 1.1 lukem break;
150 1.1 lukem
151 1.1 lukem case 't': /* delay in seconds */
152 1.1 lukem if ( lutil_atoi( &delay, optarg ) != 0 ) {
153 1.1 lukem usage( argv[0] );
154 1.1 lukem }
155 1.1 lukem break;
156 1.1 lukem
157 1.1 lukem default:
158 1.1 lukem usage( argv[0] );
159 1.1 lukem break;
160 1.1 lukem }
161 1.1 lukem }
162 1.1 lukem
163 1.1 lukem if (( filename == NULL ) || ( port == -1 && uri == NULL ) ||
164 1.1 lukem ( manager == NULL ) || ( passwd.bv_val == NULL ))
165 1.1 lukem usage( argv[0] );
166 1.1 lukem
167 1.1 lukem entry = get_add_entry( filename, &attrs );
168 1.1 lukem if (( entry == NULL ) || ( *entry == '\0' )) {
169 1.1 lukem
170 1.1 lukem fprintf( stderr, "%s: invalid entry DN in file \"%s\".\n",
171 1.1 lukem argv[0], filename );
172 1.1 lukem exit( EXIT_FAILURE );
173 1.1 lukem
174 1.1 lukem }
175 1.1 lukem
176 1.1 lukem if (( attrs == NULL ) || ( *attrs == '\0' )) {
177 1.1 lukem
178 1.1 lukem fprintf( stderr, "%s: invalid attrs in file \"%s\".\n",
179 1.1 lukem argv[0], filename );
180 1.1 lukem exit( EXIT_FAILURE );
181 1.1 lukem
182 1.1 lukem }
183 1.1 lukem
184 1.1 lukem uri = tester_uri( uri, host, port );
185 1.1 lukem
186 1.1 lukem for ( i = 0; i < outerloops; i++ ) {
187 1.1 lukem do_addel( uri, manager, &passwd, entry, attrs,
188 1.1 lukem loops, retries, delay, friendly, chaserefs );
189 1.1 lukem }
190 1.1 lukem
191 1.1 lukem exit( EXIT_SUCCESS );
192 1.1 lukem }
193 1.1 lukem
194 1.1 lukem
195 1.1 lukem static void
196 1.1 lukem addmodifyop( LDAPMod ***pmodsp, int modop, char *attr, char *value, int vlen )
197 1.1 lukem {
198 1.1 lukem LDAPMod **pmods;
199 1.1 lukem int i, j;
200 1.1 lukem struct berval *bvp;
201 1.1 lukem
202 1.1 lukem pmods = *pmodsp;
203 1.1 lukem modop |= LDAP_MOD_BVALUES;
204 1.1 lukem
205 1.1 lukem i = 0;
206 1.1 lukem if ( pmods != NULL ) {
207 1.1 lukem for ( ; pmods[ i ] != NULL; ++i ) {
208 1.1 lukem if ( strcasecmp( pmods[ i ]->mod_type, attr ) == 0 &&
209 1.1 lukem pmods[ i ]->mod_op == modop ) {
210 1.1 lukem break;
211 1.1 lukem }
212 1.1 lukem }
213 1.1 lukem }
214 1.1 lukem
215 1.1 lukem if ( pmods == NULL || pmods[ i ] == NULL ) {
216 1.1 lukem if (( pmods = (LDAPMod **)realloc( pmods, (i + 2) *
217 1.1 lukem sizeof( LDAPMod * ))) == NULL ) {
218 1.1 lukem tester_perror( "realloc", NULL );
219 1.1 lukem exit( EXIT_FAILURE );
220 1.1 lukem }
221 1.1 lukem *pmodsp = pmods;
222 1.1 lukem pmods[ i + 1 ] = NULL;
223 1.1 lukem if (( pmods[ i ] = (LDAPMod *)calloc( 1, sizeof( LDAPMod )))
224 1.1 lukem == NULL ) {
225 1.1 lukem tester_perror( "calloc", NULL );
226 1.1 lukem exit( EXIT_FAILURE );
227 1.1 lukem }
228 1.1 lukem pmods[ i ]->mod_op = modop;
229 1.1 lukem if (( pmods[ i ]->mod_type = strdup( attr )) == NULL ) {
230 1.1 lukem tester_perror( "strdup", NULL );
231 1.1 lukem exit( EXIT_FAILURE );
232 1.1 lukem }
233 1.1 lukem }
234 1.1 lukem
235 1.1 lukem if ( value != NULL ) {
236 1.1 lukem j = 0;
237 1.1 lukem if ( pmods[ i ]->mod_bvalues != NULL ) {
238 1.1 lukem for ( ; pmods[ i ]->mod_bvalues[ j ] != NULL; ++j ) {
239 1.1 lukem ;
240 1.1 lukem }
241 1.1 lukem }
242 1.1 lukem if (( pmods[ i ]->mod_bvalues =
243 1.1 lukem (struct berval **)ber_memrealloc( pmods[ i ]->mod_bvalues,
244 1.1 lukem (j + 2) * sizeof( struct berval * ))) == NULL ) {
245 1.1 lukem tester_perror( "ber_memrealloc", NULL );
246 1.1 lukem exit( EXIT_FAILURE );
247 1.1 lukem }
248 1.1 lukem pmods[ i ]->mod_bvalues[ j + 1 ] = NULL;
249 1.1 lukem if (( bvp = (struct berval *)ber_memalloc( sizeof( struct berval )))
250 1.1 lukem == NULL ) {
251 1.1 lukem tester_perror( "ber_memalloc", NULL );
252 1.1 lukem exit( EXIT_FAILURE );
253 1.1 lukem }
254 1.1 lukem pmods[ i ]->mod_bvalues[ j ] = bvp;
255 1.1 lukem
256 1.1 lukem bvp->bv_len = vlen;
257 1.1 lukem if (( bvp->bv_val = (char *)malloc( vlen + 1 )) == NULL ) {
258 1.1 lukem tester_perror( "malloc", NULL );
259 1.1 lukem exit( EXIT_FAILURE );
260 1.1 lukem }
261 1.1 lukem AC_MEMCPY( bvp->bv_val, value, vlen );
262 1.1 lukem bvp->bv_val[ vlen ] = '\0';
263 1.1 lukem }
264 1.1 lukem }
265 1.1 lukem
266 1.1 lukem
267 1.1 lukem static char *
268 1.1 lukem get_add_entry( char *filename, LDAPMod ***mods )
269 1.1 lukem {
270 1.1 lukem FILE *fp;
271 1.1 lukem char *entry = NULL;
272 1.1 lukem
273 1.1 lukem if ( (fp = fopen( filename, "r" )) != NULL ) {
274 1.1 lukem char line[BUFSIZ];
275 1.1 lukem
276 1.1 lukem if ( fgets( line, BUFSIZ, fp )) {
277 1.1 lukem char *nl;
278 1.1 lukem
279 1.1 lukem if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' )))
280 1.1 lukem *nl = '\0';
281 1.1 lukem nl = line;
282 1.1 lukem if ( !strncasecmp( nl, "dn: ", 4 ))
283 1.1 lukem nl += 4;
284 1.1 lukem entry = strdup( nl );
285 1.1 lukem
286 1.1 lukem }
287 1.1 lukem
288 1.1 lukem while ( fgets( line, BUFSIZ, fp )) {
289 1.1 lukem char *nl;
290 1.1 lukem char *value;
291 1.1 lukem
292 1.1 lukem if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' )))
293 1.1 lukem *nl = '\0';
294 1.1 lukem
295 1.1 lukem if ( *line == '\0' ) break;
296 1.1 lukem if ( !( value = strchr( line, ':' ))) break;
297 1.1 lukem
298 1.1 lukem *value++ = '\0';
299 1.1 lukem while ( *value && isspace( (unsigned char) *value ))
300 1.1 lukem value++;
301 1.1 lukem
302 1.1 lukem addmodifyop( mods, LDAP_MOD_ADD, line, value, strlen( value ));
303 1.1 lukem
304 1.1 lukem }
305 1.1 lukem fclose( fp );
306 1.1 lukem }
307 1.1 lukem
308 1.1 lukem return( entry );
309 1.1 lukem }
310 1.1 lukem
311 1.1 lukem
312 1.1 lukem static void
313 1.1 lukem do_addel(
314 1.1 lukem char *uri,
315 1.1 lukem char *manager,
316 1.1 lukem struct berval *passwd,
317 1.1 lukem char *entry,
318 1.1 lukem LDAPMod **attrs,
319 1.1 lukem int maxloop,
320 1.1 lukem int maxretries,
321 1.1 lukem int delay,
322 1.1 lukem int friendly,
323 1.1 lukem int chaserefs )
324 1.1 lukem {
325 1.1 lukem LDAP *ld = NULL;
326 1.1 lukem int i = 0, do_retry = maxretries;
327 1.1 lukem int rc = LDAP_SUCCESS;
328 1.1 lukem int version = LDAP_VERSION3;
329 1.1 lukem
330 1.1 lukem retry:;
331 1.1 lukem ldap_initialize( &ld, uri );
332 1.1 lukem if ( ld == NULL ) {
333 1.1 lukem tester_perror( "ldap_initialize", NULL );
334 1.1 lukem exit( EXIT_FAILURE );
335 1.1 lukem }
336 1.1 lukem
337 1.1 lukem (void) ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version );
338 1.1 lukem (void) ldap_set_option( ld, LDAP_OPT_REFERRALS,
339 1.1 lukem chaserefs ? LDAP_OPT_ON : LDAP_OPT_OFF );
340 1.1 lukem
341 1.1 lukem if ( do_retry == maxretries ) {
342 1.1 lukem fprintf( stderr, "PID=%ld - Add/Delete(%d): entry=\"%s\".\n",
343 1.1 lukem (long) pid, maxloop, entry );
344 1.1 lukem }
345 1.1 lukem
346 1.1 lukem rc = ldap_sasl_bind_s( ld, manager, LDAP_SASL_SIMPLE, passwd, NULL, NULL, NULL );
347 1.1 lukem if ( rc != LDAP_SUCCESS ) {
348 1.1 lukem tester_ldap_error( ld, "ldap_sasl_bind_s", NULL );
349 1.1 lukem switch ( rc ) {
350 1.1 lukem case LDAP_BUSY:
351 1.1 lukem case LDAP_UNAVAILABLE:
352 1.1 lukem if ( do_retry > 0 ) {
353 1.1 lukem do_retry--;
354 1.1 lukem if ( delay != 0 ) {
355 1.1 lukem sleep( delay );
356 1.1 lukem }
357 1.1 lukem goto retry;
358 1.1 lukem }
359 1.1 lukem /* fallthru */
360 1.1 lukem default:
361 1.1 lukem break;
362 1.1 lukem }
363 1.1 lukem exit( EXIT_FAILURE );
364 1.1 lukem }
365 1.1 lukem
366 1.1 lukem for ( ; i < maxloop; i++ ) {
367 1.1 lukem
368 1.1 lukem /* add the entry */
369 1.1 lukem rc = ldap_add_ext_s( ld, entry, attrs, NULL, NULL );
370 1.1 lukem if ( rc != LDAP_SUCCESS ) {
371 1.1 lukem tester_ldap_error( ld, "ldap_add_ext_s", NULL );
372 1.1 lukem switch ( rc ) {
373 1.1 lukem case LDAP_ALREADY_EXISTS:
374 1.1 lukem /* NOTE: this likely means
375 1.1 lukem * the delete failed
376 1.1 lukem * during the previous round... */
377 1.1 lukem if ( !friendly ) {
378 1.1 lukem goto done;
379 1.1 lukem }
380 1.1 lukem break;
381 1.1 lukem
382 1.1 lukem case LDAP_BUSY:
383 1.1 lukem case LDAP_UNAVAILABLE:
384 1.1 lukem if ( do_retry > 0 ) {
385 1.1 lukem do_retry--;
386 1.1 lukem goto retry;
387 1.1 lukem }
388 1.1 lukem /* fall thru */
389 1.1 lukem
390 1.1 lukem default:
391 1.1 lukem goto done;
392 1.1 lukem }
393 1.1 lukem }
394 1.1 lukem
395 1.1 lukem #if 0
396 1.1 lukem /* wait a second for the add to really complete */
397 1.1 lukem /* This masks some race conditions though. */
398 1.1 lukem sleep( 1 );
399 1.1 lukem #endif
400 1.1 lukem
401 1.1 lukem /* now delete the entry again */
402 1.1 lukem rc = ldap_delete_ext_s( ld, entry, NULL, NULL );
403 1.1 lukem if ( rc != LDAP_SUCCESS ) {
404 1.1 lukem tester_ldap_error( ld, "ldap_delete_ext_s", NULL );
405 1.1 lukem switch ( rc ) {
406 1.1 lukem case LDAP_NO_SUCH_OBJECT:
407 1.1 lukem /* NOTE: this likely means
408 1.1 lukem * the add failed
409 1.1 lukem * during the previous round... */
410 1.1 lukem if ( !friendly ) {
411 1.1 lukem goto done;
412 1.1 lukem }
413 1.1 lukem break;
414 1.1 lukem
415 1.1 lukem case LDAP_BUSY:
416 1.1 lukem case LDAP_UNAVAILABLE:
417 1.1 lukem if ( do_retry > 0 ) {
418 1.1 lukem do_retry--;
419 1.1 lukem goto retry;
420 1.1 lukem }
421 1.1 lukem /* fall thru */
422 1.1 lukem
423 1.1 lukem default:
424 1.1 lukem goto done;
425 1.1 lukem }
426 1.1 lukem }
427 1.1 lukem }
428 1.1 lukem
429 1.1 lukem done:;
430 1.1 lukem fprintf( stderr, " PID=%ld - Add/Delete done (%d).\n", (long) pid, rc );
431 1.1 lukem
432 1.1 lukem ldap_unbind_ext( ld, NULL, NULL );
433 1.1 lukem }
434 1.1 lukem
435 1.1 lukem
436