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