1 /* $NetBSD: slapd-modify.c,v 1.3 2021/08/14 16:15:03 christos Exp $ */ 2 3 /* $OpenLDAP$ */ 4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 5 * 6 * Copyright 1999-2021 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 <sys/cdefs.h> 19 __RCSID("$NetBSD: slapd-modify.c,v 1.3 2021/08/14 16:15:03 christos Exp $"); 20 21 #include "portable.h" 22 23 #include <stdio.h> 24 25 #include "ac/stdlib.h" 26 27 #include "ac/ctype.h" 28 #include "ac/param.h" 29 #include "ac/socket.h" 30 #include "ac/string.h" 31 #include "ac/unistd.h" 32 #include "ac/wait.h" 33 34 #include "ldap.h" 35 #include "lutil.h" 36 37 #include "slapd-common.h" 38 39 #define LOOPS 100 40 41 static void 42 do_modify( struct tester_conn_args *config, char *entry, 43 char *attr, char *value, int friendly ); 44 45 46 static void 47 usage( char *name, int opt ) 48 { 49 if ( opt ) { 50 fprintf( stderr, "%s: unable to handle option \'%c\'\n\n", 51 name, opt ); 52 } 53 54 fprintf( stderr, "usage: %s " TESTER_COMMON_HELP 55 "-a <attr:val> " 56 "-e <entry> " 57 "[-F]\n", 58 name ); 59 exit( EXIT_FAILURE ); 60 } 61 62 int 63 main( int argc, char **argv ) 64 { 65 int i; 66 char *entry = NULL; 67 char *ava = NULL; 68 char *value = NULL; 69 int friendly = 0; 70 struct tester_conn_args *config; 71 72 config = tester_init( "slapd-modify", TESTER_MODIFY ); 73 74 while ( ( i = getopt( argc, argv, TESTER_COMMON_OPTS "a:e:F" ) ) != EOF ) 75 { 76 switch ( i ) { 77 case 'F': 78 friendly++; 79 break; 80 81 case 'i': 82 /* ignored (!) by now */ 83 break; 84 85 case 'e': /* entry to modify */ 86 entry = optarg; 87 break; 88 89 case 'a': 90 ava = optarg; 91 break; 92 93 default: 94 if ( tester_config_opt( config, i, optarg ) == LDAP_SUCCESS ) { 95 break; 96 } 97 usage( argv[0], i ); 98 break; 99 } 100 } 101 102 if (( entry == NULL ) || ( ava == NULL )) 103 usage( argv[0], 0 ); 104 105 if ( *entry == '\0' ) { 106 107 fprintf( stderr, "%s: invalid EMPTY entry DN.\n", 108 argv[0] ); 109 exit( EXIT_FAILURE ); 110 111 } 112 if ( *ava == '\0' ) { 113 fprintf( stderr, "%s: invalid EMPTY AVA.\n", 114 argv[0] ); 115 exit( EXIT_FAILURE ); 116 } 117 118 if ( !( value = strchr( ava, ':' ))) { 119 fprintf( stderr, "%s: invalid AVA.\n", 120 argv[0] ); 121 exit( EXIT_FAILURE ); 122 } 123 *value++ = '\0'; 124 while ( *value && isspace( (unsigned char) *value )) 125 value++; 126 127 tester_config_finish( config ); 128 129 for ( i = 0; i < config->outerloops; i++ ) { 130 do_modify( config, entry, ava, value, friendly ); 131 } 132 133 exit( EXIT_SUCCESS ); 134 } 135 136 137 static void 138 do_modify( struct tester_conn_args *config, 139 char *entry, char* attr, char* value, int friendly ) 140 { 141 LDAP *ld = NULL; 142 int i = 0, do_retry = config->retries; 143 int rc = LDAP_SUCCESS; 144 145 struct ldapmod mod; 146 struct ldapmod *mods[2]; 147 char *values[2]; 148 149 values[0] = value; 150 values[1] = NULL; 151 mod.mod_op = LDAP_MOD_ADD; 152 mod.mod_type = attr; 153 mod.mod_values = values; 154 mods[0] = &mod; 155 mods[1] = NULL; 156 157 retry:; 158 if ( ld == NULL ) { 159 tester_init_ld( &ld, config, 0 ); 160 } 161 162 if ( do_retry == config->retries ) { 163 fprintf( stderr, "PID=%ld - Modify(%d): entry=\"%s\".\n", 164 (long) pid, config->loops, entry ); 165 } 166 167 for ( ; i < config->loops; i++ ) { 168 mod.mod_op = LDAP_MOD_ADD; 169 rc = ldap_modify_ext_s( ld, entry, mods, NULL, NULL ); 170 if ( rc != LDAP_SUCCESS ) { 171 tester_ldap_error( ld, "ldap_modify_ext_s", NULL ); 172 switch ( rc ) { 173 case LDAP_TYPE_OR_VALUE_EXISTS: 174 /* NOTE: this likely means 175 * the second modify failed 176 * during the previous round... */ 177 if ( !friendly ) { 178 goto done; 179 } 180 break; 181 182 case LDAP_BUSY: 183 case LDAP_UNAVAILABLE: 184 if ( do_retry > 0 ) { 185 do_retry--; 186 goto retry; 187 } 188 /* fall thru */ 189 190 default: 191 goto done; 192 } 193 } 194 195 mod.mod_op = LDAP_MOD_DELETE; 196 rc = ldap_modify_ext_s( ld, entry, mods, NULL, NULL ); 197 if ( rc != LDAP_SUCCESS ) { 198 tester_ldap_error( ld, "ldap_modify_ext_s", NULL ); 199 switch ( rc ) { 200 case LDAP_NO_SUCH_ATTRIBUTE: 201 /* NOTE: this likely means 202 * the first modify failed 203 * during the previous round... */ 204 if ( !friendly ) { 205 goto done; 206 } 207 break; 208 209 case LDAP_BUSY: 210 case LDAP_UNAVAILABLE: 211 if ( do_retry > 0 ) { 212 do_retry--; 213 goto retry; 214 } 215 /* fall thru */ 216 217 default: 218 goto done; 219 } 220 } 221 222 } 223 224 done:; 225 fprintf( stderr, " PID=%ld - Modify done (%d).\n", (long) pid, rc ); 226 227 ldap_unbind_ext( ld, NULL, NULL ); 228 } 229 230 231