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