]> git.sur5r.net Git - openldap/blob - tests/progs/slapd-modrdn.c
d2ec0d5be31f385683c567d829eeda8a1aaf4acd
[openldap] / tests / progs / slapd-modrdn.c
1 /* $OpenLDAP$ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3  *
4  * Copyright 1999-2017 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 }