Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/libs/ldap/libldap/abandon.c
4394 views
1
/* abandon.c */
2
/* $OpenLDAP$ */
3
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4
*
5
* Copyright 1998-2024 The OpenLDAP Foundation.
6
* All rights reserved.
7
*
8
* Redistribution and use in source and binary forms, with or without
9
* modification, are permitted only as authorized by the OpenLDAP
10
* Public License.
11
*
12
* A copy of this license is available in the file LICENSE in the
13
* top-level directory of the distribution or, alternatively, at
14
* <http://www.OpenLDAP.org/license.html>.
15
*/
16
/* Portions Copyright (c) 1990 Regents of the University of Michigan.
17
* All rights reserved.
18
*/
19
20
#include "portable.h"
21
22
#include <stdio.h>
23
24
#include <ac/stdlib.h>
25
26
#include <ac/socket.h>
27
#include <ac/string.h>
28
#include <ac/time.h>
29
30
#include "ldap-int.h"
31
32
/*
33
* An abandon request looks like this:
34
* AbandonRequest ::= [APPLICATION 16] MessageID
35
* and has no response. (Source: RFC 4511)
36
*/
37
#include "lutil.h"
38
39
static int
40
do_abandon(
41
LDAP *ld,
42
ber_int_t origid,
43
LDAPRequest *lr,
44
LDAPControl **sctrls,
45
int sendabandon );
46
47
/*
48
* ldap_abandon_ext - perform an ldap extended abandon operation.
49
*
50
* Parameters:
51
* ld LDAP descriptor
52
* msgid The message id of the operation to abandon
53
* scntrls Server Controls
54
* ccntrls Client Controls
55
*
56
* ldap_abandon_ext returns a LDAP error code.
57
* (LDAP_SUCCESS if everything went ok)
58
*
59
* Example:
60
* ldap_abandon_ext( ld, msgid, scntrls, ccntrls );
61
*/
62
int
63
ldap_abandon_ext(
64
LDAP *ld,
65
int msgid,
66
LDAPControl **sctrls,
67
LDAPControl **cctrls )
68
{
69
int rc;
70
71
Debug1( LDAP_DEBUG_TRACE, "ldap_abandon_ext %d\n", msgid );
72
73
/* check client controls */
74
LDAP_MUTEX_LOCK( &ld->ld_req_mutex );
75
76
rc = ldap_int_client_controls( ld, cctrls );
77
if ( rc == LDAP_SUCCESS ) {
78
rc = do_abandon( ld, msgid, NULL, sctrls, 1 );
79
}
80
81
LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex );
82
83
return rc;
84
}
85
86
87
/*
88
* ldap_abandon - perform an ldap abandon operation. Parameters:
89
*
90
* ld LDAP descriptor
91
* msgid The message id of the operation to abandon
92
*
93
* ldap_abandon returns 0 if everything went ok, -1 otherwise.
94
*
95
* Example:
96
* ldap_abandon( ld, msgid );
97
*/
98
int
99
ldap_abandon( LDAP *ld, int msgid )
100
{
101
Debug1( LDAP_DEBUG_TRACE, "ldap_abandon %d\n", msgid );
102
return ldap_abandon_ext( ld, msgid, NULL, NULL ) == LDAP_SUCCESS
103
? 0 : -1;
104
}
105
106
107
int
108
ldap_pvt_discard(
109
LDAP *ld,
110
ber_int_t msgid )
111
{
112
int rc;
113
114
LDAP_MUTEX_LOCK( &ld->ld_req_mutex );
115
rc = do_abandon( ld, msgid, NULL, NULL, 0 );
116
LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex );
117
return rc;
118
}
119
120
static int
121
do_abandon(
122
LDAP *ld,
123
ber_int_t origid,
124
LDAPRequest *lr,
125
LDAPControl **sctrls,
126
int sendabandon )
127
{
128
BerElement *ber;
129
int i, err;
130
ber_int_t msgid = origid;
131
Sockbuf *sb;
132
LDAPRequest needle = {0};
133
134
needle.lr_msgid = origid;
135
136
if ( lr != NULL ) {
137
msgid = lr->lr_msgid;
138
Debug2( LDAP_DEBUG_TRACE, "do_abandon origid %d, msgid %d\n",
139
origid, msgid );
140
} else if ( (lr = ldap_tavl_find( ld->ld_requests, &needle, ldap_req_cmp )) != NULL ) {
141
Debug2( LDAP_DEBUG_TRACE, "do_abandon origid %d, msgid %d\n",
142
origid, msgid );
143
if ( lr->lr_parent != NULL ) {
144
/* don't let caller abandon child requests! */
145
ld->ld_errno = LDAP_PARAM_ERROR;
146
return( LDAP_PARAM_ERROR );
147
}
148
msgid = lr->lr_msgid;
149
}
150
151
if ( lr != NULL ) {
152
LDAPRequest **childp = &lr->lr_child;
153
154
needle.lr_msgid = lr->lr_msgid;
155
156
if ( lr->lr_status != LDAP_REQST_INPROGRESS ) {
157
/* no need to send abandon message */
158
sendabandon = 0;
159
}
160
161
while ( *childp ) {
162
/* Abandon children */
163
LDAPRequest *child = *childp;
164
165
(void)do_abandon( ld, lr->lr_origid, child, sctrls, sendabandon );
166
if ( *childp == child ) {
167
childp = &child->lr_refnext;
168
}
169
}
170
}
171
172
/* ldap_msgdelete locks the res_mutex. Give up the req_mutex
173
* while we're in there.
174
*/
175
LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex );
176
err = ldap_msgdelete( ld, msgid );
177
LDAP_MUTEX_LOCK( &ld->ld_req_mutex );
178
if ( err == 0 ) {
179
ld->ld_errno = LDAP_SUCCESS;
180
return LDAP_SUCCESS;
181
}
182
183
/* fetch again the request that we are abandoning */
184
if ( lr != NULL ) {
185
lr = ldap_tavl_find( ld->ld_requests, &needle, ldap_req_cmp );
186
}
187
188
err = 0;
189
if ( sendabandon ) {
190
if ( ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, NULL ) == -1 ) {
191
/* not connected */
192
err = -1;
193
ld->ld_errno = LDAP_SERVER_DOWN;
194
195
} else if ( ( ber = ldap_alloc_ber_with_options( ld ) ) == NULL ) {
196
/* BER element allocation failed */
197
err = -1;
198
ld->ld_errno = LDAP_NO_MEMORY;
199
200
} else {
201
/*
202
* We already have the mutex in LDAP_R_COMPILE, so
203
* don't try to get it again.
204
* LDAP_NEXT_MSGID(ld, i);
205
*/
206
207
LDAP_NEXT_MSGID(ld, i);
208
#ifdef LDAP_CONNECTIONLESS
209
if ( LDAP_IS_UDP(ld) ) {
210
struct sockaddr_storage sa = {0};
211
/* dummy, filled with ldo_peer in request.c */
212
err = ber_write( ber, (char *) &sa, sizeof(sa), 0 );
213
}
214
if ( LDAP_IS_UDP(ld) && ld->ld_options.ldo_version ==
215
LDAP_VERSION2 )
216
{
217
char *dn;
218
LDAP_MUTEX_LOCK( &ld->ld_options.ldo_mutex );
219
dn = ld->ld_options.ldo_cldapdn;
220
if (!dn) dn = "";
221
err = ber_printf( ber, "{isti", /* '}' */
222
i, dn,
223
LDAP_REQ_ABANDON, msgid );
224
LDAP_MUTEX_UNLOCK( &ld->ld_options.ldo_mutex );
225
} else
226
#endif
227
{
228
/* create a message to send */
229
err = ber_printf( ber, "{iti", /* '}' */
230
i,
231
LDAP_REQ_ABANDON, msgid );
232
}
233
234
if ( err == -1 ) {
235
/* encoding error */
236
ld->ld_errno = LDAP_ENCODING_ERROR;
237
238
} else {
239
/* Put Server Controls */
240
if ( ldap_int_put_controls( ld, sctrls, ber )
241
!= LDAP_SUCCESS )
242
{
243
err = -1;
244
245
} else {
246
/* close '{' */
247
err = ber_printf( ber, /*{*/ "N}" );
248
249
if ( err == -1 ) {
250
/* encoding error */
251
ld->ld_errno = LDAP_ENCODING_ERROR;
252
}
253
}
254
}
255
256
if ( err == -1 ) {
257
ber_free( ber, 1 );
258
259
} else {
260
/* send the message */
261
if ( lr != NULL ) {
262
assert( lr->lr_conn != NULL );
263
sb = lr->lr_conn->lconn_sb;
264
} else {
265
sb = ld->ld_sb;
266
}
267
268
if ( ber_flush2( sb, ber, LBER_FLUSH_FREE_ALWAYS ) != 0 ) {
269
ld->ld_errno = LDAP_SERVER_DOWN;
270
err = -1;
271
} else {
272
err = 0;
273
}
274
}
275
}
276
}
277
278
if ( lr != NULL ) {
279
LDAPConn *lc;
280
int freeconn = 0;
281
if ( sendabandon || lr->lr_status == LDAP_REQST_WRITING ) {
282
freeconn = 1;
283
lc = lr->lr_conn;
284
}
285
if ( origid == msgid ) {
286
ldap_free_request( ld, lr );
287
288
} else {
289
lr->lr_abandoned = 1;
290
}
291
292
if ( freeconn ) {
293
/* release ld_req_mutex while grabbing ld_conn_mutex to
294
* prevent deadlock.
295
*/
296
LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex );
297
LDAP_MUTEX_LOCK( &ld->ld_conn_mutex );
298
ldap_free_connection( ld, lc, 0, 1 );
299
LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
300
LDAP_MUTEX_LOCK( &ld->ld_req_mutex );
301
}
302
}
303
304
LDAP_MUTEX_LOCK( &ld->ld_abandon_mutex );
305
306
/* use bisection */
307
i = 0;
308
if ( ld->ld_nabandoned == 0 ||
309
ldap_int_bisect_find( ld->ld_abandoned, ld->ld_nabandoned, msgid, &i ) == 0 )
310
{
311
ldap_int_bisect_insert( &ld->ld_abandoned, &ld->ld_nabandoned, msgid, i );
312
}
313
314
if ( err != -1 ) {
315
ld->ld_errno = LDAP_SUCCESS;
316
}
317
318
LDAP_MUTEX_UNLOCK( &ld->ld_abandon_mutex );
319
return( ld->ld_errno );
320
}
321
322
/*
323
* ldap_int_bisect_find
324
*
325
* args:
326
* v: array of length n (in)
327
* n: length of array v (in)
328
* id: value to look for (in)
329
* idxp: pointer to location of value/insert point
330
*
331
* return:
332
* 0: not found
333
* 1: found
334
* -1: error
335
*/
336
int
337
ldap_int_bisect_find( ber_int_t *v, ber_len_t n, ber_int_t id, int *idxp )
338
{
339
int begin,
340
end,
341
rc = 0;
342
343
assert( id >= 0 );
344
345
begin = 0;
346
end = n - 1;
347
348
if ( n <= 0 || id < v[ begin ] ) {
349
*idxp = 0;
350
351
} else if ( id > v[ end ] ) {
352
*idxp = n;
353
354
} else {
355
int pos;
356
ber_int_t curid;
357
358
do {
359
pos = (begin + end)/2;
360
curid = v[ pos ];
361
362
if ( id < curid ) {
363
end = pos - 1;
364
365
} else if ( id > curid ) {
366
begin = ++pos;
367
368
} else {
369
/* already abandoned? */
370
rc = 1;
371
break;
372
}
373
} while ( end >= begin );
374
375
*idxp = pos;
376
}
377
378
return rc;
379
}
380
381
/*
382
* ldap_int_bisect_insert
383
*
384
* args:
385
* vp: pointer to array of length *np (in/out)
386
* np: pointer to length of array *vp (in/out)
387
* id: value to insert (in)
388
* idx: location of insert point (as computed by ldap_int_bisect_find())
389
*
390
* return:
391
* 0: inserted
392
* -1: error
393
*/
394
int
395
ldap_int_bisect_insert( ber_int_t **vp, ber_len_t *np, int id, int idx )
396
{
397
ber_int_t *v;
398
ber_len_t n;
399
int i;
400
401
assert( vp != NULL );
402
assert( np != NULL );
403
assert( idx >= 0 );
404
assert( (unsigned) idx <= *np );
405
406
n = *np;
407
408
v = ber_memrealloc( *vp, sizeof( ber_int_t ) * ( n + 1 ) );
409
if ( v == NULL ) {
410
return -1;
411
}
412
*vp = v;
413
414
for ( i = n; i > idx; i-- ) {
415
v[ i ] = v[ i - 1 ];
416
}
417
v[ idx ] = id;
418
++(*np);
419
420
return 0;
421
}
422
423
/*
424
* ldap_int_bisect_delete
425
*
426
* args:
427
* vp: pointer to array of length *np (in/out)
428
* np: pointer to length of array *vp (in/out)
429
* id: value to delete (in)
430
* idx: location of value to delete (as computed by ldap_int_bisect_find())
431
*
432
* return:
433
* 0: deleted
434
*/
435
int
436
ldap_int_bisect_delete( ber_int_t **vp, ber_len_t *np, int id, int idx )
437
{
438
ber_int_t *v;
439
ber_len_t i, n;
440
441
assert( vp != NULL );
442
assert( np != NULL );
443
assert( idx >= 0 );
444
assert( (unsigned) idx < *np );
445
446
v = *vp;
447
448
assert( v[ idx ] == id );
449
450
--(*np);
451
n = *np;
452
453
for ( i = idx; i < n; i++ ) {
454
v[ i ] = v[ i + 1 ];
455
}
456
457
return 0;
458
}
459
460