Back to index

openldap  2.4.31
slapd-addel.c
Go to the documentation of this file.
00001 /* $OpenLDAP$ */
00002 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
00003  *
00004  * Copyright 1999-2012 The OpenLDAP Foundation.
00005  * All rights reserved.
00006  *
00007  * Redistribution and use in source and binary forms, with or without
00008  * modification, are permitted only as authorized by the OpenLDAP
00009  * Public License.
00010  *
00011  * A copy of this license is available in file LICENSE in the
00012  * top-level directory of the distribution or, alternatively, at
00013  * <http://www.OpenLDAP.org/license.html>.
00014  */
00015 /* ACKNOWLEDGEMENTS:
00016  * This work was initially developed by Kurt Spanier for inclusion
00017  * in OpenLDAP Software.
00018  */
00019  
00020 #include "portable.h"
00021 
00022 #include <stdio.h>
00023 
00024 #include "ac/stdlib.h"
00025 
00026 #include "ac/ctype.h"
00027 #include "ac/param.h"
00028 #include "ac/socket.h"
00029 #include "ac/string.h"
00030 #include "ac/unistd.h"
00031 #include "ac/wait.h"
00032 
00033 #include "ldap.h"
00034 #include "lutil.h"
00035 
00036 #include "slapd-common.h"
00037 
00038 #define LOOPS 100
00039 #define RETRIES      0
00040 
00041 static char *
00042 get_add_entry( char *filename, LDAPMod ***mods );
00043 
00044 static void
00045 do_addel( char *uri, char *manager, struct berval *passwd,
00046        char *dn, LDAPMod **attrs, int maxloop, int maxretries, int delay,
00047        int friendly, int chaserefs );
00048 
00049 static void
00050 usage( char *name )
00051 {
00052         fprintf( stderr,
00053               "usage: %s "
00054               "-H <uri> | ([-h <host>] -p <port>) "
00055               "-D <manager> "
00056               "-w <passwd> "
00057               "-f <addfile> "
00058               "[-i <ignore>] "
00059               "[-l <loops>] "
00060               "[-L <outerloops>] "
00061               "[-r <maxretries>] "
00062               "[-t <delay>] "
00063               "[-F] "
00064               "[-C]\n",
00065                      name );
00066        exit( EXIT_FAILURE );
00067 }
00068 
00069 int
00070 main( int argc, char **argv )
00071 {
00072        int           i;
00073        char          *host = "localhost";
00074        char          *uri = NULL;
00075        int           port = -1;
00076        char          *manager = NULL;
00077        struct berval passwd = { 0, NULL };
00078        char          *filename = NULL;
00079        char          *entry = NULL;
00080        int           loops = LOOPS;
00081        int           outerloops = 1;
00082        int           retries = RETRIES;
00083        int           delay = 0;
00084        int           friendly = 0;
00085        int           chaserefs = 0;
00086        LDAPMod              **attrs = NULL;
00087 
00088        tester_init( "slapd-addel", TESTER_ADDEL );
00089 
00090        while ( ( i = getopt( argc, argv, "CD:Ff:H:h:i:L:l:p:r:t:w:" ) ) != EOF )
00091        {
00092               switch ( i ) {
00093               case 'C':
00094                      chaserefs++;
00095                      break;
00096 
00097               case 'F':
00098                      friendly++;
00099                      break;
00100                      
00101               case 'H':            /* the server's URI */
00102                      uri = strdup( optarg );
00103                      break;
00104 
00105               case 'h':            /* the servers host */
00106                      host = strdup( optarg );
00107                      break;
00108 
00109               case 'i':
00110                      /* ignored (!) by now */
00111                      break;
00112 
00113               case 'p':            /* the servers port */
00114                      if ( lutil_atoi( &port, optarg ) != 0 ) {
00115                             usage( argv[0] );
00116                      }
00117                      break;
00118 
00119               case 'D':            /* the servers manager */
00120                      manager = strdup( optarg );
00121                      break;
00122 
00123               case 'w':            /* the server managers password */
00124                      passwd.bv_val = strdup( optarg );
00125                      passwd.bv_len = strlen( optarg );
00126                      memset( optarg, '*', passwd.bv_len );
00127                      break;
00128 
00129               case 'f':            /* file with entry search request */
00130                      filename = strdup( optarg );
00131                      break;
00132 
00133               case 'l':            /* the number of loops */
00134                      if ( lutil_atoi( &loops, optarg ) != 0 ) {
00135                             usage( argv[0] );
00136                      }
00137                      break;
00138 
00139               case 'L':            /* the number of outerloops */
00140                      if ( lutil_atoi( &outerloops, optarg ) != 0 ) {
00141                             usage( argv[0] );
00142                      }
00143                      break;
00144 
00145               case 'r':            /* number of retries */
00146                      if ( lutil_atoi( &retries, optarg ) != 0 ) {
00147                             usage( argv[0] );
00148                      }
00149                      break;
00150 
00151               case 't':            /* delay in seconds */
00152                      if ( lutil_atoi( &delay, optarg ) != 0 ) {
00153                             usage( argv[0] );
00154                      }
00155                      break;
00156 
00157               default:
00158                      usage( argv[0] );
00159                      break;
00160               }
00161        }
00162 
00163        if (( filename == NULL ) || ( port == -1 && uri == NULL ) ||
00164                             ( manager == NULL ) || ( passwd.bv_val == NULL ))
00165               usage( argv[0] );
00166 
00167        entry = get_add_entry( filename, &attrs );
00168        if (( entry == NULL ) || ( *entry == '\0' )) {
00169 
00170               fprintf( stderr, "%s: invalid entry DN in file \"%s\".\n",
00171                             argv[0], filename );
00172               exit( EXIT_FAILURE );
00173 
00174        }
00175 
00176        if (( attrs == NULL ) || ( *attrs == '\0' )) {
00177 
00178               fprintf( stderr, "%s: invalid attrs in file \"%s\".\n",
00179                             argv[0], filename );
00180               exit( EXIT_FAILURE );
00181 
00182        }
00183 
00184        uri = tester_uri( uri, host, port );
00185 
00186        for ( i = 0; i < outerloops; i++ ) {
00187               do_addel( uri, manager, &passwd, entry, attrs,
00188                             loops, retries, delay, friendly, chaserefs );
00189        }
00190 
00191        exit( EXIT_SUCCESS );
00192 }
00193 
00194 
00195 static void
00196 addmodifyop( LDAPMod ***pmodsp, int modop, char *attr, char *value, int vlen )
00197 {
00198     LDAPMod          **pmods;
00199     int                     i, j;
00200     struct berval    *bvp;
00201 
00202     pmods = *pmodsp;
00203     modop |= LDAP_MOD_BVALUES;
00204 
00205     i = 0;
00206     if ( pmods != NULL ) {
00207               for ( ; pmods[ i ] != NULL; ++i ) {
00208               if ( strcasecmp( pmods[ i ]->mod_type, attr ) == 0 &&
00209                      pmods[ i ]->mod_op == modop ) {
00210                             break;
00211               }
00212               }
00213     }
00214 
00215     if ( pmods == NULL || pmods[ i ] == NULL ) {
00216               if (( pmods = (LDAPMod **)realloc( pmods, (i + 2) *
00217                      sizeof( LDAPMod * ))) == NULL ) {
00218                      tester_perror( "realloc", NULL );
00219                      exit( EXIT_FAILURE );
00220               }
00221               *pmodsp = pmods;
00222               pmods[ i + 1 ] = NULL;
00223               if (( pmods[ i ] = (LDAPMod *)calloc( 1, sizeof( LDAPMod )))
00224                      == NULL ) {
00225                      tester_perror( "calloc", NULL );
00226                      exit( EXIT_FAILURE );
00227               }
00228               pmods[ i ]->mod_op = modop;
00229               if (( pmods[ i ]->mod_type = strdup( attr )) == NULL ) {
00230               tester_perror( "strdup", NULL );
00231               exit( EXIT_FAILURE );
00232               }
00233     }
00234 
00235     if ( value != NULL ) {
00236               j = 0;
00237               if ( pmods[ i ]->mod_bvalues != NULL ) {
00238               for ( ; pmods[ i ]->mod_bvalues[ j ] != NULL; ++j ) {
00239                             ;
00240               }
00241               }
00242               if (( pmods[ i ]->mod_bvalues =
00243                      (struct berval **)ber_memrealloc( pmods[ i ]->mod_bvalues,
00244                      (j + 2) * sizeof( struct berval * ))) == NULL ) {
00245                      tester_perror( "ber_memrealloc", NULL );
00246                      exit( EXIT_FAILURE );
00247               }
00248               pmods[ i ]->mod_bvalues[ j + 1 ] = NULL;
00249               if (( bvp = (struct berval *)ber_memalloc( sizeof( struct berval )))
00250                      == NULL ) {
00251                      tester_perror( "ber_memalloc", NULL );
00252                      exit( EXIT_FAILURE );
00253               }
00254               pmods[ i ]->mod_bvalues[ j ] = bvp;
00255 
00256            bvp->bv_len = vlen;
00257            if (( bvp->bv_val = (char *)malloc( vlen + 1 )) == NULL ) {
00258                      tester_perror( "malloc", NULL );
00259                      exit( EXIT_FAILURE );
00260            }
00261            AC_MEMCPY( bvp->bv_val, value, vlen );
00262            bvp->bv_val[ vlen ] = '\0';
00263     }
00264 }
00265 
00266 
00267 static char *
00268 get_add_entry( char *filename, LDAPMod ***mods )
00269 {
00270        FILE    *fp;
00271        char    *entry = NULL;
00272 
00273        if ( (fp = fopen( filename, "r" )) != NULL ) {
00274               char  line[BUFSIZ];
00275 
00276               if ( fgets( line, BUFSIZ, fp )) {
00277                      char *nl;
00278 
00279                      if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' )))
00280                             *nl = '\0';
00281                      nl = line;
00282                      if ( !strncasecmp( nl, "dn: ", 4 ))
00283                             nl += 4;
00284                      entry = strdup( nl );
00285 
00286               }
00287 
00288               while ( fgets( line, BUFSIZ, fp )) {
00289                      char   *nl;
00290                      char   *value;
00291 
00292                      if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' )))
00293                             *nl = '\0';
00294 
00295                      if ( *line == '\0' ) break;
00296                      if ( !( value = strchr( line, ':' ))) break;
00297 
00298                      *value++ = '\0'; 
00299                      while ( *value && isspace( (unsigned char) *value ))
00300                             value++;
00301 
00302                      addmodifyop( mods, LDAP_MOD_ADD, line, value, strlen( value ));
00303 
00304               }
00305               fclose( fp );
00306        }
00307 
00308        return( entry );
00309 }
00310 
00311 
00312 static void
00313 do_addel(
00314        char *uri,
00315        char *manager,
00316        struct berval *passwd,
00317        char *entry,
00318        LDAPMod **attrs,
00319        int maxloop,
00320        int maxretries,
00321        int delay,
00322        int friendly,
00323        int chaserefs )
00324 {
00325        LDAP   *ld = NULL;
00326        int    i = 0, do_retry = maxretries;
00327        int    rc = LDAP_SUCCESS;
00328        int    version = LDAP_VERSION3;
00329 
00330 retry:;
00331        ldap_initialize( &ld, uri );
00332        if ( ld == NULL ) {
00333               tester_perror( "ldap_initialize", NULL );
00334               exit( EXIT_FAILURE );
00335        }
00336 
00337        (void) ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version );
00338        (void) ldap_set_option( ld, LDAP_OPT_REFERRALS,
00339               chaserefs ? LDAP_OPT_ON : LDAP_OPT_OFF );
00340 
00341        if ( do_retry == maxretries ) {
00342               fprintf( stderr, "PID=%ld - Add/Delete(%d): entry=\"%s\".\n",
00343                      (long) pid, maxloop, entry );
00344        }
00345 
00346        rc = ldap_sasl_bind_s( ld, manager, LDAP_SASL_SIMPLE, passwd, NULL, NULL, NULL );
00347        if ( rc != LDAP_SUCCESS ) {
00348               tester_ldap_error( ld, "ldap_sasl_bind_s", NULL );
00349               switch ( rc ) {
00350               case LDAP_BUSY:
00351               case LDAP_UNAVAILABLE:
00352                      if ( do_retry > 0 ) {
00353                             do_retry--;
00354                             if ( delay != 0 ) {
00355                                 sleep( delay );
00356                             }
00357                             goto retry;
00358                      }
00359               /* fallthru */
00360               default:
00361                      break;
00362               }
00363               exit( EXIT_FAILURE );
00364        }
00365 
00366        for ( ; i < maxloop; i++ ) {
00367 
00368               /* add the entry */
00369               rc = ldap_add_ext_s( ld, entry, attrs, NULL, NULL );
00370               if ( rc != LDAP_SUCCESS ) {
00371                      tester_ldap_error( ld, "ldap_add_ext_s", NULL );
00372                      switch ( rc ) {
00373                      case LDAP_ALREADY_EXISTS:
00374                             /* NOTE: this likely means
00375                              * the delete failed
00376                              * during the previous round... */
00377                             if ( !friendly ) {
00378                                    goto done;
00379                             }
00380                             break;
00381 
00382                      case LDAP_BUSY:
00383                      case LDAP_UNAVAILABLE:
00384                             if ( do_retry > 0 ) {
00385                                    do_retry--;
00386                                    goto retry;
00387                             }
00388                             /* fall thru */
00389 
00390                      default:
00391                             goto done;
00392                      }
00393               }
00394 
00395 #if 0
00396               /* wait a second for the add to really complete */
00397               /* This masks some race conditions though. */
00398               sleep( 1 );
00399 #endif
00400 
00401               /* now delete the entry again */
00402               rc = ldap_delete_ext_s( ld, entry, NULL, NULL );
00403               if ( rc != LDAP_SUCCESS ) {
00404                      tester_ldap_error( ld, "ldap_delete_ext_s", NULL );
00405                      switch ( rc ) {
00406                      case LDAP_NO_SUCH_OBJECT:
00407                             /* NOTE: this likely means
00408                              * the add failed
00409                              * during the previous round... */
00410                             if ( !friendly ) {
00411                                    goto done;
00412                             }
00413                             break;
00414 
00415                      case LDAP_BUSY:
00416                      case LDAP_UNAVAILABLE:
00417                             if ( do_retry > 0 ) {
00418                                    do_retry--;
00419                                    goto retry;
00420                             }
00421                             /* fall thru */
00422 
00423                      default:
00424                             goto done;
00425                      }
00426               }
00427        }
00428 
00429 done:;
00430        fprintf( stderr, "  PID=%ld - Add/Delete done (%d).\n", (long) pid, rc );
00431 
00432        ldap_unbind_ext( ld, NULL, NULL );
00433 }
00434 
00435