1/* $OpenLDAP$ */ 2/* This work is part of OpenLDAP Software <http://www.openldap.org/>. 3 * 4 * Copyright 1999-2011 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 41static void 42do_modrdn( char *uri, char *manager, struct berval *passwd, 43 char *entry, int maxloop, int maxretries, int delay, 44 int friendly, int chaserefs ); 45 46static void 47usage( 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 66int 67main( 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 180static void 181do_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 213retry:; 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 302done:; 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} 311