xref: /netbsd-src/external/bsd/openldap/dist/tests/progs/slapd-addel.c (revision 549b59ed3ccf0d36d3097190a0db27b770f3a839)
1 /*	$NetBSD: slapd-addel.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 /* ACKNOWLEDGEMENTS:
18  * This work was initially developed by Kurt Spanier for inclusion
19  * in OpenLDAP Software.
20  */
21 
22 #include <sys/cdefs.h>
23 __RCSID("$NetBSD: slapd-addel.c,v 1.3 2021/08/14 16:15:03 christos Exp $");
24 
25 #include "portable.h"
26 
27 #include <stdio.h>
28 
29 #include "ac/stdlib.h"
30 
31 #include "ac/ctype.h"
32 #include "ac/param.h"
33 #include "ac/socket.h"
34 #include "ac/string.h"
35 #include "ac/unistd.h"
36 #include "ac/wait.h"
37 
38 #include "ldap.h"
39 #include "lutil.h"
40 #include "ldif.h"
41 
42 #include "slapd-common.h"
43 
44 static LDIFRecord *
45 get_add_entry( char *filename );
46 
47 static void
48 do_addel( struct tester_conn_args *config,
49 	LDIFRecord *record, int friendly );
50 
51 static void
usage(char * name,char opt)52 usage( char *name, char opt )
53 {
54 	if ( opt ) {
55 		fprintf( stderr, "%s: unable to handle option \'%c\'\n\n",
56 			name, opt );
57 	}
58 
59 	fprintf( stderr, "usage: %s " TESTER_COMMON_HELP
60 		"-f <addfile> "
61 		"[-F]\n",
62 		name );
63 	exit( EXIT_FAILURE );
64 }
65 
66 int
main(int argc,char ** argv)67 main( int argc, char **argv )
68 {
69 	int		i;
70 	char *filename = NULL, *buf = NULL;
71 	int		friendly = 0;
72 	struct LDIFFP *fp;
73 	LDIFRecord	record = {};
74 	struct tester_conn_args	*config;
75 	struct berval bv = {};
76 	unsigned long lineno = 0;
77 
78 	config = tester_init( "slapd-addel", TESTER_ADDEL );
79 
80 	while ( ( i = getopt( argc, argv, TESTER_COMMON_OPTS "Ff:" ) ) != EOF )
81 	{
82 		switch ( i ) {
83 		case 'F':
84 			friendly++;
85 			break;
86 
87 		case 'i':
88 			/* ignored (!) by now */
89 			break;
90 
91 		case 'f':		/* file with entry search request */
92 			filename = optarg;
93 			break;
94 
95 		default:
96 			if ( tester_config_opt( config, i, optarg ) == LDAP_SUCCESS ) {
97 				break;
98 			}
99 			usage( argv[0], i );
100 			break;
101 		}
102 	}
103 
104 	if ( filename == NULL )
105 		usage( argv[0], 0 );
106 
107 	if ( (fp = ldif_open( filename, "r" )) == NULL ) {
108 		tester_perror( filename, "while reading ldif file" );
109 		exit( EXIT_FAILURE );
110 	}
111 
112 	i = 0;
113 	if ( ldif_read_record( fp, &lineno, &buf, &i ) < 0 ) {
114 		tester_error( "ldif_read_record failed" );
115 		exit( EXIT_FAILURE );
116 	}
117 	bv.bv_val = buf;
118 	bv.bv_len = i;
119 
120 	if ( ldap_parse_ldif_record( &bv, lineno, &record, "slapd-addel",
121 			LDIF_DEFAULT_ADD | LDIF_ENTRIES_ONLY ) ) {
122 		tester_error( "ldif_read_record failed" );
123 		exit( EXIT_FAILURE );
124 	}
125 	ldif_close( fp );
126 
127 	if ( ( record.lr_op != LDAP_REQ_ADD ) || ( !record.lrop_mods ) ) {
128 
129 		fprintf( stderr, "%s: invalid entry DN in file \"%s\".\n",
130 				argv[0], filename );
131 		exit( EXIT_FAILURE );
132 
133 	}
134 
135 	tester_config_finish( config );
136 
137 	for ( i = 0; i < config->outerloops; i++ ) {
138 		do_addel( config, &record, friendly );
139 	}
140 
141 	free( buf );
142 	exit( EXIT_SUCCESS );
143 }
144 
145 
146 static void
addmodifyop(LDAPMod *** pmodsp,int modop,char * attr,char * value,int vlen)147 addmodifyop( LDAPMod ***pmodsp, int modop, char *attr, char *value, int vlen )
148 {
149     LDAPMod		**pmods;
150     int			i, j;
151     struct berval	*bvp;
152 
153     pmods = *pmodsp;
154     modop |= LDAP_MOD_BVALUES;
155 
156     i = 0;
157     if ( pmods != NULL ) {
158 		for ( ; pmods[ i ] != NULL; ++i ) {
159 	    	if ( strcasecmp( pmods[ i ]->mod_type, attr ) == 0 &&
160 		    	pmods[ i ]->mod_op == modop ) {
161 				break;
162 	    	}
163 		}
164     }
165 
166     if ( pmods == NULL || pmods[ i ] == NULL ) {
167 		if (( pmods = (LDAPMod **)realloc( pmods, (i + 2) *
168 			sizeof( LDAPMod * ))) == NULL ) {
169 	    		tester_perror( "realloc", NULL );
170 	    		exit( EXIT_FAILURE );
171 		}
172 		*pmodsp = pmods;
173 		pmods[ i + 1 ] = NULL;
174 		if (( pmods[ i ] = (LDAPMod *)calloc( 1, sizeof( LDAPMod )))
175 			== NULL ) {
176 	    		tester_perror( "calloc", NULL );
177 	    		exit( EXIT_FAILURE );
178 		}
179 		pmods[ i ]->mod_op = modop;
180 		if (( pmods[ i ]->mod_type = strdup( attr )) == NULL ) {
181 	    	tester_perror( "strdup", NULL );
182 	    	exit( EXIT_FAILURE );
183 		}
184     }
185 
186     if ( value != NULL ) {
187 		j = 0;
188 		if ( pmods[ i ]->mod_bvalues != NULL ) {
189 	    	for ( ; pmods[ i ]->mod_bvalues[ j ] != NULL; ++j ) {
190 				;
191 	    	}
192 		}
193 		if (( pmods[ i ]->mod_bvalues =
194 			(struct berval **)ber_memrealloc( pmods[ i ]->mod_bvalues,
195 			(j + 2) * sizeof( struct berval * ))) == NULL ) {
196 	    		tester_perror( "ber_memrealloc", NULL );
197 	    		exit( EXIT_FAILURE );
198 		}
199 		pmods[ i ]->mod_bvalues[ j + 1 ] = NULL;
200 		if (( bvp = (struct berval *)ber_memalloc( sizeof( struct berval )))
201 			== NULL ) {
202 	    		tester_perror( "ber_memalloc", NULL );
203 	    		exit( EXIT_FAILURE );
204 		}
205 		pmods[ i ]->mod_bvalues[ j ] = bvp;
206 
207 	    bvp->bv_len = vlen;
208 	    if (( bvp->bv_val = (char *)malloc( vlen + 1 )) == NULL ) {
209 			tester_perror( "malloc", NULL );
210 			exit( EXIT_FAILURE );
211 	    }
212 	    AC_MEMCPY( bvp->bv_val, value, vlen );
213 	    bvp->bv_val[ vlen ] = '\0';
214     }
215 }
216 
217 
218 static void
do_addel(struct tester_conn_args * config,LDIFRecord * record,int friendly)219 do_addel(
220 	struct tester_conn_args *config,
221 	LDIFRecord *record,
222 	int friendly )
223 {
224 	LDAP	*ld = NULL;
225 	int  	i = 0, do_retry = config->retries;
226 	int	rc = LDAP_SUCCESS;
227 
228 retry:;
229 	if ( ld == NULL ) {
230 		tester_init_ld( &ld, config, 0 );
231 	}
232 
233 	if ( do_retry == config->retries ) {
234 		fprintf( stderr, "PID=%ld - Add/Delete(%d): entry=\"%s\".\n",
235 			(long) pid, config->loops, record->lr_dn.bv_val );
236 	}
237 
238 	for ( ; i < config->loops; i++ ) {
239 
240 		/* add the entry */
241 		rc = ldap_add_ext_s( ld, record->lr_dn.bv_val, record->lrop_mods, NULL, NULL );
242 		if ( rc != LDAP_SUCCESS ) {
243 			tester_ldap_error( ld, "ldap_add_ext_s", NULL );
244 			switch ( rc ) {
245 			case LDAP_ALREADY_EXISTS:
246 				/* NOTE: this likely means
247 				 * the delete failed
248 				 * during the previous round... */
249 				if ( !friendly ) {
250 					goto done;
251 				}
252 				break;
253 
254 			case LDAP_BUSY:
255 			case LDAP_UNAVAILABLE:
256 				if ( do_retry > 0 ) {
257 					do_retry--;
258 					goto retry;
259 				}
260 				/* fall thru */
261 
262 			default:
263 				goto done;
264 			}
265 		}
266 
267 #if 0
268 		/* wait a second for the add to really complete */
269 		/* This masks some race conditions though. */
270 		sleep( 1 );
271 #endif
272 
273 		/* now delete the entry again */
274 		rc = ldap_delete_ext_s( ld, record->lr_dn.bv_val, NULL, NULL );
275 		if ( rc != LDAP_SUCCESS ) {
276 			tester_ldap_error( ld, "ldap_delete_ext_s", NULL );
277 			switch ( rc ) {
278 			case LDAP_NO_SUCH_OBJECT:
279 				/* NOTE: this likely means
280 				 * the add failed
281 				 * during the previous round... */
282 				if ( !friendly ) {
283 					goto done;
284 				}
285 				break;
286 
287 			case LDAP_BUSY:
288 			case LDAP_UNAVAILABLE:
289 				if ( do_retry > 0 ) {
290 					do_retry--;
291 					goto retry;
292 				}
293 				/* fall thru */
294 
295 			default:
296 				goto done;
297 			}
298 		}
299 	}
300 
301 done:;
302 	fprintf( stderr, "  PID=%ld - Add/Delete done (%d).\n", (long) pid, rc );
303 
304 	ldap_unbind_ext( ld, NULL, NULL );
305 }
306 
307 
308