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