1/* $NetBSD: slapd-read.c,v 1.1.1.3 2010/12/12 15:24:16 adam Exp $ */ 2 3/* OpenLDAP: pkg/ldap/tests/progs/slapd-read.c,v 1.37.2.10 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 Kurt Spanier for inclusion 19 * 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 "ldap_pvt.h" 39 40#include "slapd-common.h" 41 42#define LOOPS 100 43#define RETRIES 0 44 45static void 46do_read( char *uri, char *manager, struct berval *passwd, 47 char *entry, LDAP **ld, 48 char **attrs, int noattrs, int nobind, int maxloop, 49 int maxretries, int delay, int force, int chaserefs ); 50 51static void 52do_random( char *uri, char *manager, struct berval *passwd, 53 char *sbase, char *filter, char **attrs, int noattrs, int nobind, 54 int innerloop, int maxretries, int delay, int force, int chaserefs ); 55 56static void 57usage( char *name ) 58{ 59 fprintf( stderr, 60 "usage: %s " 61 "-H <uri> | ([-h <host>] -p <port>) " 62 "-D <manager> " 63 "-w <passwd> " 64 "-e <entry> " 65 "[-A] " 66 "[-C] " 67 "[-F] " 68 "[-N] " 69 "[-f filter] " 70 "[-i <ignore>] " 71 "[-l <loops>] " 72 "[-L <outerloops>] " 73 "[-r <maxretries>] " 74 "[-t <delay>] " 75 "[-T <attrs>] " 76 "[<attrs>] " 77 "\n", 78 name ); 79 exit( EXIT_FAILURE ); 80} 81 82int 83main( int argc, char **argv ) 84{ 85 int i; 86 char *uri = NULL; 87 char *host = "localhost"; 88 int port = -1; 89 char *manager = NULL; 90 struct berval passwd = { 0, NULL }; 91 char *entry = NULL; 92 char *filter = NULL; 93 int loops = LOOPS; 94 int outerloops = 1; 95 int retries = RETRIES; 96 int delay = 0; 97 int force = 0; 98 int chaserefs = 0; 99 char *srchattrs[] = { "1.1", NULL }; 100 char **attrs = srchattrs; 101 int noattrs = 0; 102 int nobind = 0; 103 104 tester_init( "slapd-read", TESTER_READ ); 105 106 /* by default, tolerate referrals and no such object */ 107 tester_ignore_str2errlist( "REFERRAL,NO_SUCH_OBJECT" ); 108 109 while ( (i = getopt( argc, argv, "ACD:e:Ff:H:h:i:L:l:p:r:t:T:w:" )) != EOF ) { 110 switch ( i ) { 111 case 'A': 112 noattrs++; 113 break; 114 115 case 'C': 116 chaserefs++; 117 break; 118 119 case 'H': /* the server uri */ 120 uri = strdup( optarg ); 121 break; 122 123 case 'h': /* the servers host */ 124 host = strdup( optarg ); 125 break; 126 127 case 'i': 128 tester_ignore_str2errlist( optarg ); 129 break; 130 131 case 'N': 132 nobind++; 133 break; 134 135 case 'p': /* the servers port */ 136 if ( lutil_atoi( &port, optarg ) != 0 ) { 137 usage( argv[0] ); 138 } 139 break; 140 141 case 'D': /* the servers manager */ 142 manager = strdup( optarg ); 143 break; 144 145 case 'w': /* the server managers password */ 146 passwd.bv_val = strdup( optarg ); 147 passwd.bv_len = strlen( optarg ); 148 memset( optarg, '*', passwd.bv_len ); 149 break; 150 151 case 'e': /* DN to search for */ 152 entry = strdup( optarg ); 153 break; 154 155 case 'f': /* the search request */ 156 filter = strdup( optarg ); 157 break; 158 159 case 'F': 160 force++; 161 break; 162 163 case 'l': /* the number of loops */ 164 if ( lutil_atoi( &loops, optarg ) != 0 ) { 165 usage( argv[0] ); 166 } 167 break; 168 169 case 'L': /* the number of outerloops */ 170 if ( lutil_atoi( &outerloops, optarg ) != 0 ) { 171 usage( argv[0] ); 172 } 173 break; 174 175 case 'r': /* the number of retries */ 176 if ( lutil_atoi( &retries, optarg ) != 0 ) { 177 usage( argv[0] ); 178 } 179 break; 180 181 case 't': /* delay in seconds */ 182 if ( lutil_atoi( &delay, optarg ) != 0 ) { 183 usage( argv[0] ); 184 } 185 break; 186 187 case 'T': 188 attrs = ldap_str2charray( optarg, "," ); 189 if ( attrs == NULL ) { 190 usage( argv[0] ); 191 } 192 break; 193 194 default: 195 usage( argv[0] ); 196 break; 197 } 198 } 199 200 if (( entry == NULL ) || ( port == -1 && uri == NULL )) 201 usage( argv[0] ); 202 203 if ( *entry == '\0' ) { 204 fprintf( stderr, "%s: invalid EMPTY entry DN.\n", 205 argv[0] ); 206 exit( EXIT_FAILURE ); 207 } 208 209 if ( argv[optind] != NULL ) { 210 attrs = &argv[optind]; 211 } 212 213 uri = tester_uri( uri, host, port ); 214 215 for ( i = 0; i < outerloops; i++ ) { 216 if ( filter != NULL ) { 217 do_random( uri, manager, &passwd, entry, filter, attrs, 218 noattrs, nobind, loops, retries, delay, force, 219 chaserefs ); 220 221 } else { 222 do_read( uri, manager, &passwd, entry, NULL, attrs, 223 noattrs, nobind, loops, retries, delay, force, 224 chaserefs ); 225 } 226 } 227 228 exit( EXIT_SUCCESS ); 229} 230 231static void 232do_random( char *uri, char *manager, struct berval *passwd, 233 char *sbase, char *filter, char **srchattrs, int noattrs, int nobind, 234 int innerloop, int maxretries, int delay, int force, int chaserefs ) 235{ 236 LDAP *ld = NULL; 237 int i = 0, do_retry = maxretries; 238 char *attrs[ 2 ]; 239 int rc = LDAP_SUCCESS; 240 int version = LDAP_VERSION3; 241 int nvalues = 0; 242 char **values = NULL; 243 LDAPMessage *res = NULL, *e = NULL; 244 245 attrs[ 0 ] = LDAP_NO_ATTRS; 246 attrs[ 1 ] = NULL; 247 248 ldap_initialize( &ld, uri ); 249 if ( ld == NULL ) { 250 tester_perror( "ldap_initialize", NULL ); 251 exit( EXIT_FAILURE ); 252 } 253 254 (void) ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version ); 255 (void) ldap_set_option( ld, LDAP_OPT_REFERRALS, 256 chaserefs ? LDAP_OPT_ON : LDAP_OPT_OFF ); 257 258 if ( do_retry == maxretries ) { 259 fprintf( stderr, "PID=%ld - Read(%d): base=\"%s\", filter=\"%s\".\n", 260 (long) pid, innerloop, sbase, filter ); 261 } 262 263 if ( nobind == 0 ) { 264 rc = ldap_sasl_bind_s( ld, manager, LDAP_SASL_SIMPLE, passwd, NULL, NULL, NULL ); 265 if ( rc != LDAP_SUCCESS ) { 266 tester_ldap_error( ld, "ldap_sasl_bind_s", NULL ); 267 switch ( rc ) { 268 case LDAP_BUSY: 269 case LDAP_UNAVAILABLE: 270 /* fallthru */ 271 default: 272 break; 273 } 274 exit( EXIT_FAILURE ); 275 } 276 } 277 278 rc = ldap_search_ext_s( ld, sbase, LDAP_SCOPE_SUBTREE, 279 filter, attrs, 0, NULL, NULL, NULL, LDAP_NO_LIMIT, &res ); 280 switch ( rc ) { 281 case LDAP_SIZELIMIT_EXCEEDED: 282 case LDAP_TIMELIMIT_EXCEEDED: 283 case LDAP_SUCCESS: 284 nvalues = ldap_count_entries( ld, res ); 285 if ( nvalues == 0 ) { 286 if ( rc ) { 287 tester_ldap_error( ld, "ldap_search_ext_s", NULL ); 288 } 289 break; 290 } 291 292 values = malloc( ( nvalues + 1 ) * sizeof( char * ) ); 293 for ( i = 0, e = ldap_first_entry( ld, res ); e != NULL; i++, e = ldap_next_entry( ld, e ) ) 294 { 295 values[ i ] = ldap_get_dn( ld, e ); 296 } 297 values[ i ] = NULL; 298 299 ldap_msgfree( res ); 300 301 if ( do_retry == maxretries ) { 302 fprintf( stderr, " PID=%ld - Read base=\"%s\" filter=\"%s\" got %d values.\n", 303 (long) pid, sbase, filter, nvalues ); 304 } 305 306 for ( i = 0; i < innerloop; i++ ) { 307#if 0 /* use high-order bits for better randomness (Numerical Recipes in "C") */ 308 int r = rand() % nvalues; 309#endif 310 int r = ((double)nvalues)*rand()/(RAND_MAX + 1.0); 311 312 do_read( uri, manager, passwd, values[ r ], &ld, 313 srchattrs, noattrs, nobind, 1, maxretries, 314 delay, force, chaserefs ); 315 } 316 free( values ); 317 break; 318 319 default: 320 tester_ldap_error( ld, "ldap_search_ext_s", NULL ); 321 break; 322 } 323 324 fprintf( stderr, " PID=%ld - Search done (%d).\n", (long) pid, rc ); 325 326 if ( ld != NULL ) { 327 ldap_unbind_ext( ld, NULL, NULL ); 328 } 329} 330 331static void 332do_read( char *uri, char *manager, struct berval *passwd, char *entry, 333 LDAP **ldp, char **attrs, int noattrs, int nobind, int maxloop, 334 int maxretries, int delay, int force, int chaserefs ) 335{ 336 LDAP *ld = ldp ? *ldp : NULL; 337 int i = 0, do_retry = maxretries; 338 int rc = LDAP_SUCCESS; 339 int version = LDAP_VERSION3; 340 341retry:; 342 if ( ld == NULL ) { 343 ldap_initialize( &ld, uri ); 344 if ( ld == NULL ) { 345 tester_perror( "ldap_initialize", NULL ); 346 exit( EXIT_FAILURE ); 347 } 348 349 (void) ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version ); 350 (void) ldap_set_option( ld, LDAP_OPT_REFERRALS, 351 chaserefs ? LDAP_OPT_ON : LDAP_OPT_OFF ); 352 353 if ( do_retry == maxretries ) { 354 fprintf( stderr, "PID=%ld - Read(%d): entry=\"%s\".\n", 355 (long) pid, maxloop, entry ); 356 } 357 358 if ( nobind == 0 ) { 359 rc = ldap_sasl_bind_s( ld, manager, LDAP_SASL_SIMPLE, passwd, NULL, NULL, NULL ); 360 if ( rc != LDAP_SUCCESS ) { 361 tester_ldap_error( ld, "ldap_sasl_bind_s", NULL ); 362 switch ( rc ) { 363 case LDAP_BUSY: 364 case LDAP_UNAVAILABLE: 365 if ( do_retry > 0 ) { 366 ldap_unbind_ext( ld, NULL, NULL ); 367 ld = NULL; 368 do_retry--; 369 if ( delay != 0 ) { 370 sleep( delay ); 371 } 372 goto retry; 373 } 374 /* fallthru */ 375 default: 376 break; 377 } 378 exit( EXIT_FAILURE ); 379 } 380 } 381 } 382 383 for ( ; i < maxloop; i++ ) { 384 LDAPMessage *res = NULL; 385 386 rc = ldap_search_ext_s( ld, entry, LDAP_SCOPE_BASE, 387 NULL, attrs, noattrs, NULL, NULL, NULL, 388 LDAP_NO_LIMIT, &res ); 389 if ( res != NULL ) { 390 ldap_msgfree( res ); 391 } 392 393 if ( rc ) { 394 int first = tester_ignore_err( rc ); 395 char buf[ BUFSIZ ]; 396 397 snprintf( buf, sizeof( buf ), "ldap_search_ext_s(%s)", entry ); 398 399 /* if ignore.. */ 400 if ( first ) { 401 /* only log if first occurrence */ 402 if ( ( force < 2 && first > 0 ) || abs(first) == 1 ) { 403 tester_ldap_error( ld, buf, NULL ); 404 } 405 continue; 406 } 407 408 /* busy needs special handling */ 409 tester_ldap_error( ld, buf, NULL ); 410 if ( rc == LDAP_BUSY && do_retry > 0 ) { 411 ldap_unbind_ext( ld, NULL, NULL ); 412 ld = NULL; 413 do_retry--; 414 goto retry; 415 } 416 break; 417 } 418 } 419 420 if ( ldp != NULL ) { 421 *ldp = ld; 422 423 } else { 424 fprintf( stderr, " PID=%ld - Read done (%d).\n", (long) pid, rc ); 425 426 if ( ld != NULL ) { 427 ldap_unbind_ext( ld, NULL, NULL ); 428 } 429 } 430} 431 432