1/* $NetBSD$ */ 2 3/* OpenLDAP: pkg/ldap/tests/progs/slapd-modify.c,v 1.19.2.8 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 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 39static void 40do_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 45static void 46usage( 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 65int 66main( 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 199static void 200do_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 221retry:; 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 314done:; 315 fprintf( stderr, " PID=%ld - Modify done (%d).\n", (long) pid, rc ); 316 317 ldap_unbind_ext( ld, NULL, NULL ); 318} 319 320 321