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
usage(char * name,int opt)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
main(int argc,char ** argv)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
do_modify(struct tester_conn_args * config,char * entry,char * attr,char * value,int friendly)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