xref: /netbsd-src/external/bsd/openldap/dist/tests/progs/slapd-modify.c (revision b1c86f5f087524e68db12794ee9c3e3da1ab17a0)
1 /*	$NetBSD: slapd-modify.c,v 1.1.1.2 2010/03/08 02:14:20 lukem Exp $	*/
2 
3 /* OpenLDAP: pkg/ldap/tests/progs/slapd-modify.c,v 1.19.2.7 2009/01/22 00:01:17 kurt Exp */
4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5  *
6  * Copyright 1999-2009 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 
18 #include "portable.h"
19 
20 #include <stdio.h>
21 
22 #include "ac/stdlib.h"
23 
24 #include "ac/ctype.h"
25 #include "ac/param.h"
26 #include "ac/socket.h"
27 #include "ac/string.h"
28 #include "ac/unistd.h"
29 #include "ac/wait.h"
30 
31 #include "ldap.h"
32 #include "lutil.h"
33 
34 #include "slapd-common.h"
35 
36 #define LOOPS	100
37 #define RETRIES 0
38 
39 static void
40 do_modify( char *uri, char *manager, struct berval *passwd,
41 		char *entry, char *attr, char *value, int maxloop,
42 		int maxretries, int delay, int friendly, int chaserefs );
43 
44 
45 static void
46 usage( char *name )
47 {
48         fprintf( stderr,
49 		"usage: %s "
50 		"-H <uri> | ([-h <host>] -p <port>) "
51 		"-D <manager> "
52 		"-w <passwd> "
53 		"-e <entry> "
54 		"[-i <ignore>] "
55 		"[-l <loops>] "
56 		"[-L <outerloops>] "
57 		"[-r <maxretries>] "
58 		"[-t <delay>] "
59 		"[-F] "
60 		"[-C]\n",
61 			name );
62 	exit( EXIT_FAILURE );
63 }
64 
65 int
66 main( int argc, char **argv )
67 {
68 	int		i;
69 	char		*uri = NULL;
70 	char		*host = "localhost";
71 	int		port = -1;
72 	char		*manager = NULL;
73 	struct berval	passwd = { 0, NULL };
74 	char		*entry = NULL;
75 	char		*ava = NULL;
76 	char		*value = NULL;
77 	int		loops = LOOPS;
78 	int		outerloops = 1;
79 	int		retries = RETRIES;
80 	int		delay = 0;
81 	int		friendly = 0;
82 	int		chaserefs = 0;
83 
84 	tester_init( "slapd-modify", TESTER_MODIFY );
85 
86 	while ( ( i = getopt( argc, argv, "a:CD:e:FH:h:i:L:l:p:r:t:w:" ) ) != EOF )
87 	{
88 		switch ( i ) {
89 		case 'C':
90 			chaserefs++;
91 			break;
92 
93 		case 'F':
94 			friendly++;
95 			break;
96 
97 		case 'H':		/* the server uri */
98 			uri = strdup( optarg );
99 			break;
100 
101 		case 'h':		/* the servers host */
102 			host = strdup( optarg );
103 			break;
104 
105 		case 'i':
106 			/* ignored (!) by now */
107 			break;
108 
109 		case 'p':		/* the servers port */
110 			if ( lutil_atoi( &port, optarg ) != 0 ) {
111 				usage( argv[0] );
112 			}
113 			break;
114 
115 		case 'D':		/* the servers manager */
116 			manager = strdup( optarg );
117 			break;
118 
119 		case 'w':		/* the server managers password */
120 			passwd.bv_val = strdup( optarg );
121 			passwd.bv_len = strlen( optarg );
122 			memset( optarg, '*', passwd.bv_len );
123 			break;
124 
125 		case 'e':		/* entry to modify */
126 			entry = strdup( optarg );
127 			break;
128 
129 		case 'a':
130 			ava = 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 (( entry == NULL ) || ( ava == NULL ) || ( port == -1 && uri == NULL ))
164 		usage( argv[0] );
165 
166 	if ( *entry == '\0' ) {
167 
168 		fprintf( stderr, "%s: invalid EMPTY entry DN.\n",
169 				argv[0] );
170 		exit( EXIT_FAILURE );
171 
172 	}
173 	if ( *ava  == '\0' ) {
174 		fprintf( stderr, "%s: invalid EMPTY AVA.\n",
175 				argv[0] );
176 		exit( EXIT_FAILURE );
177 	}
178 
179 	if ( !( value = strchr( ava, ':' ))) {
180 		fprintf( stderr, "%s: invalid AVA.\n",
181 				argv[0] );
182 		exit( EXIT_FAILURE );
183 	}
184 	*value++ = '\0';
185 	while ( *value && isspace( (unsigned char) *value ))
186 		value++;
187 
188 	uri = tester_uri( uri, host, port );
189 
190 	for ( i = 0; i < outerloops; i++ ) {
191 		do_modify( uri, manager, &passwd, entry, ava, value,
192 				loops, retries, delay, friendly, chaserefs );
193 	}
194 
195 	exit( EXIT_SUCCESS );
196 }
197 
198 
199 static void
200 do_modify( char *uri, char *manager,
201 	struct berval *passwd, char *entry, char* attr, char* value,
202 	int maxloop, int maxretries, int delay, int friendly, int chaserefs )
203 {
204 	LDAP	*ld = NULL;
205 	int  	i = 0, do_retry = maxretries;
206 	int     rc = LDAP_SUCCESS;
207 
208 	struct ldapmod mod;
209 	struct ldapmod *mods[2];
210 	char *values[2];
211 	int version = LDAP_VERSION3;
212 
213 	values[0] = value;
214 	values[1] = NULL;
215 	mod.mod_op = LDAP_MOD_ADD;
216 	mod.mod_type = attr;
217 	mod.mod_values = values;
218 	mods[0] = &mod;
219 	mods[1] = NULL;
220 
221 retry:;
222 	ldap_initialize( &ld, uri );
223 	if ( ld == NULL ) {
224 		tester_perror( "ldap_initialize", NULL );
225 		exit( EXIT_FAILURE );
226 	}
227 
228 	(void) ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version );
229 	(void) ldap_set_option( ld, LDAP_OPT_REFERRALS,
230 		chaserefs ? LDAP_OPT_ON : LDAP_OPT_OFF );
231 
232 	if ( do_retry == maxretries ) {
233 		fprintf( stderr, "PID=%ld - Modify(%d): entry=\"%s\".\n",
234 			(long) pid, maxloop, entry );
235 	}
236 
237 	rc = ldap_sasl_bind_s( ld, manager, LDAP_SASL_SIMPLE, passwd, NULL, NULL, NULL );
238 	if ( rc != LDAP_SUCCESS ) {
239 		tester_ldap_error( ld, "ldap_sasl_bind_s", NULL );
240 		switch ( rc ) {
241 		case LDAP_BUSY:
242 		case LDAP_UNAVAILABLE:
243 			if ( do_retry > 0 ) {
244 				do_retry--;
245 				if ( delay > 0 ) {
246 				    sleep( delay );
247 				}
248 				goto retry;
249 			}
250 		/* fallthru */
251 		default:
252 			break;
253 		}
254 		exit( EXIT_FAILURE );
255 	}
256 
257 	for ( ; i < maxloop; i++ ) {
258 		mod.mod_op = LDAP_MOD_ADD;
259 		rc = ldap_modify_ext_s( ld, entry, mods, NULL, NULL );
260 		if ( rc != LDAP_SUCCESS ) {
261 			tester_ldap_error( ld, "ldap_modify_ext_s", NULL );
262 			switch ( rc ) {
263 			case LDAP_TYPE_OR_VALUE_EXISTS:
264 				/* NOTE: this likely means
265 				 * the second modify failed
266 				 * during the previous round... */
267 				if ( !friendly ) {
268 					goto done;
269 				}
270 				break;
271 
272 			case LDAP_BUSY:
273 			case LDAP_UNAVAILABLE:
274 				if ( do_retry > 0 ) {
275 					do_retry--;
276 					goto retry;
277 				}
278 				/* fall thru */
279 
280 			default:
281 				goto done;
282 			}
283 		}
284 
285 		mod.mod_op = LDAP_MOD_DELETE;
286 		rc = ldap_modify_ext_s( ld, entry, mods, NULL, NULL );
287 		if ( rc != LDAP_SUCCESS ) {
288 			tester_ldap_error( ld, "ldap_modify_ext_s", NULL );
289 			switch ( rc ) {
290 			case LDAP_NO_SUCH_ATTRIBUTE:
291 				/* NOTE: this likely means
292 				 * the first modify failed
293 				 * during the previous round... */
294 				if ( !friendly ) {
295 					goto done;
296 				}
297 				break;
298 
299 			case LDAP_BUSY:
300 			case LDAP_UNAVAILABLE:
301 				if ( do_retry > 0 ) {
302 					do_retry--;
303 					goto retry;
304 				}
305 				/* fall thru */
306 
307 			default:
308 				goto done;
309 			}
310 		}
311 
312 	}
313 
314 done:;
315 	fprintf( stderr, "  PID=%ld - Modify done (%d).\n", (long) pid, rc );
316 
317 	ldap_unbind_ext( ld, NULL, NULL );
318 }
319 
320 
321