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