xref: /netbsd-src/external/bsd/openldap/dist/tests/progs/slapd-modrdn.c (revision 274254cdae52594c1aa480a736aef78313d15c9c)
1 /* $OpenLDAP: pkg/ldap/tests/progs/slapd-modrdn.c,v 1.22.2.5 2008/02/11 23:26:50 kurt Exp $ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3  *
4  * Copyright 1999-2008 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 = 0, 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 retry:;
212 	ldap_initialize( &ld, uri );
213 	if ( ld == NULL ) {
214 		tester_perror( "ldap_initialize", NULL );
215 		exit( EXIT_FAILURE );
216 	}
217 
218 	(void) ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version );
219 	(void) ldap_set_option( ld, LDAP_OPT_REFERRALS,
220 		chaserefs ? LDAP_OPT_ON : LDAP_OPT_OFF );
221 
222 	if ( do_retry == maxretries ) {
223 		fprintf( stderr, "PID=%ld - Modrdn(%d): entry=\"%s\".\n",
224 			(long) pid, maxloop, entry );
225 	}
226 
227 	rc = ldap_sasl_bind_s( ld, manager, LDAP_SASL_SIMPLE, passwd, NULL, NULL, NULL );
228 	if ( rc != LDAP_SUCCESS ) {
229 		tester_ldap_error( ld, "ldap_sasl_bind_s", NULL );
230 		switch ( rc ) {
231 		case LDAP_BUSY:
232 		case LDAP_UNAVAILABLE:
233 			if ( do_retry > 0 ) {
234 				do_retry--;
235 				if ( delay > 0) {
236 				    sleep( delay );
237 				}
238 				goto retry;
239 			}
240 		/* fallthru */
241 		default:
242 			break;
243 		}
244 		exit( EXIT_FAILURE );
245 	}
246 
247 	for ( ; i < maxloop; i++ ) {
248 		rc = ldap_rename_s( ld, DNs[0], rdns[0], NULL, 0, NULL, NULL );
249 		if ( rc != LDAP_SUCCESS ) {
250 			tester_ldap_error( ld, "ldap_rename_s", NULL );
251 			switch ( rc ) {
252 			case LDAP_NO_SUCH_OBJECT:
253 				/* NOTE: this likely means
254 				 * the second modrdn failed
255 				 * during the previous round... */
256 				if ( !friendly ) {
257 					goto done;
258 				}
259 				break;
260 
261 			case LDAP_BUSY:
262 			case LDAP_UNAVAILABLE:
263 				if ( do_retry > 0 ) {
264 					do_retry--;
265 					goto retry;
266 				}
267 				/* fall thru */
268 
269 			default:
270 				goto done;
271 			}
272 		}
273 		rc = ldap_rename_s( ld, DNs[1], rdns[1], NULL, 1, NULL, NULL );
274 		if ( rc != LDAP_SUCCESS ) {
275 			tester_ldap_error( ld, "ldap_rename_s", NULL );
276 			switch ( rc ) {
277 			case LDAP_NO_SUCH_OBJECT:
278 				/* NOTE: this likely means
279 				 * the first modrdn failed
280 				 * during the previous round... */
281 				if ( !friendly ) {
282 					goto done;
283 				}
284 				break;
285 
286 			case LDAP_BUSY:
287 			case LDAP_UNAVAILABLE:
288 				if ( do_retry > 0 ) {
289 					do_retry--;
290 					goto retry;
291 				}
292 				/* fall thru */
293 
294 			default:
295 				goto done;
296 			}
297 		}
298 	}
299 
300 done:;
301 	fprintf( stderr, " PID=%ld - Modrdn done (%d).\n", (long) pid, rc );
302 
303 	ldap_unbind_ext( ld, NULL, NULL );
304 }
305 
306 
307