xref: /netbsd-src/external/bsd/openldap/dist/tests/progs/slapd-modrdn.c (revision 6a493d6bc668897c91594964a732d38505b70cbb)
1 /*	$NetBSD: slapd-modrdn.c,v 1.1.1.3 2010/12/12 15:24:16 adam Exp $	*/
2 
3 /* OpenLDAP: pkg/ldap/tests/progs/slapd-modrdn.c,v 1.22.2.9 2010/04/13 20:23:58 kurt Exp */
4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5  *
6  * Copyright 1999-2010 The OpenLDAP Foundation.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted only as authorized by the OpenLDAP
11  * Public License.
12  *
13  * A copy of this license is available in file LICENSE in the
14  * top-level directory of the distribution or, alternatively, at
15  * <http://www.OpenLDAP.org/license.html>.
16  */
17 /* ACKNOWLEDGEMENTS:
18  * This work was initially developed by Howard Chu, based in part
19  * on other OpenLDAP test tools, for inclusion in OpenLDAP Software.
20  */
21 
22 #include "portable.h"
23 
24 #include <stdio.h>
25 
26 #include "ac/stdlib.h"
27 
28 #include "ac/ctype.h"
29 #include "ac/param.h"
30 #include "ac/socket.h"
31 #include "ac/string.h"
32 #include "ac/unistd.h"
33 #include "ac/wait.h"
34 
35 #include "ldap.h"
36 #include "lutil.h"
37 
38 #include "slapd-common.h"
39 
40 #define LOOPS	100
41 #define RETRIES	0
42 
43 static void
44 do_modrdn( char *uri, char *manager, struct berval *passwd,
45 		char *entry, int maxloop, int maxretries, int delay,
46 		int friendly, int chaserefs );
47 
48 static void
49 usage( char *name )
50 {
51         fprintf( stderr,
52 		"usage: %s "
53 		"-H <uri> | ([-h <host>] -p <port>) "
54 		"-D <manager> "
55 		"-w <passwd> "
56 		"-e <entry> "
57 		"[-i <ignore>] "
58 		"[-l <loops>] "
59 		"[-L <outerloops>] "
60 		"[-r <maxretries>] "
61 		"[-t <delay>] "
62 		"[-F] "
63 		"[-C]\n",
64 			name );
65 	exit( EXIT_FAILURE );
66 }
67 
68 int
69 main( int argc, char **argv )
70 {
71 	int		i;
72 	char		*uri = NULL;
73 	char		*host = "localhost";
74 	int		port = -1;
75 	char		*manager = NULL;
76 	struct berval	passwd = { 0, NULL };
77 	char		*entry = NULL;
78 	int		loops = LOOPS;
79 	int		outerloops = 1;
80 	int		retries = RETRIES;
81 	int		delay = 0;
82 	int		friendly = 0;
83 	int		chaserefs = 0;
84 
85 	tester_init( "slapd-modrdn", TESTER_MODRDN );
86 
87 	while ( ( i = getopt( argc, argv, "CD:e:FH:h:i:L:l:p:r:t:w:" ) ) != EOF )
88 	{
89 		switch ( i ) {
90 		case 'C':
91 			chaserefs++;
92 			break;
93 
94 		case 'F':
95 			friendly++;
96 			break;
97 
98 		case 'H':		/* the server uri */
99 			uri = strdup( optarg );
100 			break;
101 
102 		case 'h':		/* the servers host */
103 			host = strdup( optarg );
104 			break;
105 
106 		case 'i':
107 			/* ignored (!) by now */
108 			break;
109 
110 		case 'p':		/* the servers port */
111 			if ( lutil_atoi( &port, optarg ) != 0 ) {
112 				usage( argv[0] );
113 			}
114 			break;
115 
116 		case 'D':		/* the servers manager */
117 			manager = strdup( optarg );
118 			break;
119 
120 		case 'w':		/* the server managers password */
121 			passwd.bv_val = strdup( optarg );
122 			passwd.bv_len = strlen( optarg );
123 			memset( optarg, '*', passwd.bv_len );
124 			break;
125 
126 		case 'e':		/* entry to rename */
127 			entry = strdup( optarg );
128 			break;
129 
130 		case 'l':		/* the number of loops */
131 			if ( lutil_atoi( &loops, optarg ) != 0 ) {
132 				usage( argv[0] );
133 			}
134 			break;
135 
136 		case 'L':		/* the number of outerloops */
137 			if ( lutil_atoi( &outerloops, optarg ) != 0 ) {
138 				usage( argv[0] );
139 			}
140 			break;
141 
142 		case 'r':		/* the number of retries */
143 			if ( lutil_atoi( &retries, optarg ) != 0 ) {
144 				usage( argv[0] );
145 			}
146 			break;
147 
148 		case 't':		/* delay in seconds */
149 			if ( lutil_atoi( &delay, optarg ) != 0 ) {
150 				usage( argv[0] );
151 			}
152 			break;
153 
154 		default:
155 			usage( argv[0] );
156 			break;
157 		}
158 	}
159 
160 	if (( entry == NULL ) || ( port == -1 && uri == NULL ))
161 		usage( argv[0] );
162 
163 	if ( *entry == '\0' ) {
164 
165 		fprintf( stderr, "%s: invalid EMPTY entry DN.\n",
166 				argv[0] );
167 		exit( EXIT_FAILURE );
168 
169 	}
170 
171 	uri = tester_uri( uri, host, port );
172 
173 	for ( i = 0; i < outerloops; i++ ) {
174 		do_modrdn( uri, manager, &passwd, entry,
175 			loops, retries, delay, friendly, chaserefs );
176 	}
177 
178 	exit( EXIT_SUCCESS );
179 }
180 
181 
182 static void
183 do_modrdn( char *uri, char *manager,
184 	struct berval *passwd, char *entry, int maxloop, int maxretries,
185 	int delay, int friendly, int chaserefs )
186 {
187 	LDAP	*ld = NULL;
188 	int  	i, do_retry = maxretries;
189 	char	*DNs[2];
190 	char	*rdns[2];
191 	int	rc = LDAP_SUCCESS;
192 	char	*p1, *p2;
193 	int	version = LDAP_VERSION3;
194 
195 	DNs[0] = entry;
196 	DNs[1] = strdup( entry );
197 
198 	/* reverse the RDN, make new DN */
199 	p1 = strchr( entry, '=' ) + 1;
200 	p2 = strchr( p1, ',' );
201 
202 	*p2 = '\0';
203 	rdns[1] = strdup( entry );
204 	*p2-- = ',';
205 
206 	for (i = p1 - entry;p2 >= p1;)
207 		DNs[1][i++] = *p2--;
208 
209 	DNs[1][i] = '\0';
210 	rdns[0] = strdup( DNs[1] );
211 	DNs[1][i] = ',';
212 
213 	i = 0;
214 
215 retry:;
216 	ldap_initialize( &ld, uri );
217 	if ( ld == NULL ) {
218 		tester_perror( "ldap_initialize", NULL );
219 		exit( EXIT_FAILURE );
220 	}
221 
222 	(void) ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version );
223 	(void) ldap_set_option( ld, LDAP_OPT_REFERRALS,
224 		chaserefs ? LDAP_OPT_ON : LDAP_OPT_OFF );
225 
226 	if ( do_retry == maxretries ) {
227 		fprintf( stderr, "PID=%ld - Modrdn(%d): entry=\"%s\".\n",
228 			(long) pid, maxloop, entry );
229 	}
230 
231 	rc = ldap_sasl_bind_s( ld, manager, LDAP_SASL_SIMPLE, passwd, NULL, NULL, NULL );
232 	if ( rc != LDAP_SUCCESS ) {
233 		tester_ldap_error( ld, "ldap_sasl_bind_s", NULL );
234 		switch ( rc ) {
235 		case LDAP_BUSY:
236 		case LDAP_UNAVAILABLE:
237 			if ( do_retry > 0 ) {
238 				do_retry--;
239 				if ( delay > 0) {
240 				    sleep( delay );
241 				}
242 				goto retry;
243 			}
244 		/* fallthru */
245 		default:
246 			break;
247 		}
248 		exit( EXIT_FAILURE );
249 	}
250 
251 	for ( ; i < maxloop; i++ ) {
252 		rc = ldap_rename_s( ld, DNs[0], rdns[0], NULL, 0, NULL, NULL );
253 		if ( rc != LDAP_SUCCESS ) {
254 			tester_ldap_error( ld, "ldap_rename_s", NULL );
255 			switch ( rc ) {
256 			case LDAP_NO_SUCH_OBJECT:
257 				/* NOTE: this likely means
258 				 * the second modrdn failed
259 				 * during the previous round... */
260 				if ( !friendly ) {
261 					goto done;
262 				}
263 				break;
264 
265 			case LDAP_BUSY:
266 			case LDAP_UNAVAILABLE:
267 				if ( do_retry > 0 ) {
268 					do_retry--;
269 					goto retry;
270 				}
271 				/* fall thru */
272 
273 			default:
274 				goto done;
275 			}
276 		}
277 		rc = ldap_rename_s( ld, DNs[1], rdns[1], NULL, 1, NULL, NULL );
278 		if ( rc != LDAP_SUCCESS ) {
279 			tester_ldap_error( ld, "ldap_rename_s", NULL );
280 			switch ( rc ) {
281 			case LDAP_NO_SUCH_OBJECT:
282 				/* NOTE: this likely means
283 				 * the first modrdn failed
284 				 * during the previous round... */
285 				if ( !friendly ) {
286 					goto done;
287 				}
288 				break;
289 
290 			case LDAP_BUSY:
291 			case LDAP_UNAVAILABLE:
292 				if ( do_retry > 0 ) {
293 					do_retry--;
294 					goto retry;
295 				}
296 				/* fall thru */
297 
298 			default:
299 				goto done;
300 			}
301 		}
302 	}
303 
304 done:;
305 	fprintf( stderr, "  PID=%ld - Modrdn done (%d).\n", (long) pid, rc );
306 
307 	ldap_unbind_ext( ld, NULL, NULL );
308 }
309 
310 
311