]> git.sur5r.net Git - openldap/blob - libraries/libldap/abandon.c
ITS#2484, set sasl_maxbuf to SASL_MAX_BUFF_SIZE if it was negotiated
[openldap] / libraries / libldap / abandon.c
1 /* $OpenLDAP$ */
2 /*
3  * Copyright 1998-2003 The OpenLDAP Foundation, All Rights Reserved.
4  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
5  */
6 /*  Portions
7  *  Copyright (c) 1990 Regents of the University of Michigan.
8  *  All rights reserved.
9  *
10  *  abandon.c
11  */
12 /*
13  * Portions Copyright (C) The Internet Society (1997)
14  * ASN.1 fragments are from RFC 2251; see RFC for full legal notices.
15  */
16
17 /*
18  * An abandon request looks like this:
19  *      AbandonRequest ::= MessageID
20  */
21
22 #include "portable.h"
23
24 #include <stdio.h>
25
26 #include <ac/stdlib.h>
27
28 #include <ac/socket.h>
29 #include <ac/string.h>
30 #include <ac/time.h>
31
32 #include "ldap-int.h"
33
34 static int do_abandon LDAP_P((
35         LDAP *ld,
36         ber_int_t origid,
37         ber_int_t msgid,
38         LDAPControl **sctrls,
39         LDAPControl **cctrls));
40
41 /*
42  * ldap_abandon_ext - perform an ldap extended abandon operation.
43  *
44  * Parameters:
45  *      ld                      LDAP descriptor
46  *      msgid           The message id of the operation to abandon
47  *      scntrls         Server Controls
48  *      ccntrls         Client Controls
49  *
50  * ldap_abandon_ext returns a LDAP error code.
51  *              (LDAP_SUCCESS if everything went ok)
52  *
53  * Example:
54  *      ldap_abandon_ext( ld, msgid, scntrls, ccntrls );
55  */
56 int
57 ldap_abandon_ext(
58         LDAP *ld,
59         int msgid,
60         LDAPControl **sctrls,
61         LDAPControl **cctrls )
62 {
63         int rc;
64 #ifdef NEW_LOGGING
65         LDAP_LOG ( OPERATION, ARGS, "ldap_abandon_ext %d\n", msgid, 0, 0 );
66 #else
67         Debug( LDAP_DEBUG_TRACE, "ldap_abandon_ext %d\n", msgid, 0, 0 );
68 #endif
69
70         /* check client controls */
71 #ifdef LDAP_R_COMPILE
72         ldap_pvt_thread_mutex_lock( &ld->ld_req_mutex );
73 #endif
74         rc = ldap_int_client_controls( ld, cctrls );
75         if( rc == LDAP_SUCCESS )
76                 rc = do_abandon( ld, msgid, msgid, sctrls, cctrls );
77
78 #ifdef LDAP_R_COMPILE
79         ldap_pvt_thread_mutex_unlock( &ld->ld_req_mutex );
80 #endif
81         return rc;
82 }
83
84
85 /*
86  * ldap_abandon - perform an ldap abandon operation. Parameters:
87  *
88  *      ld              LDAP descriptor
89  *      msgid           The message id of the operation to abandon
90  *
91  * ldap_abandon returns 0 if everything went ok, -1 otherwise.
92  *
93  * Example:
94  *      ldap_abandon( ld, msgid );
95  */
96 int
97 ldap_abandon( LDAP *ld, int msgid )
98 {
99 #ifdef NEW_LOGGING
100         LDAP_LOG ( OPERATION, ARGS, "ldap_abandon %d\n", msgid, 0, 0 );
101 #else
102         Debug( LDAP_DEBUG_TRACE, "ldap_abandon %d\n", msgid, 0, 0 );
103 #endif
104         return ldap_abandon_ext( ld, msgid, NULL, NULL ) == LDAP_SUCCESS
105                 ? 0 : -1;
106 }
107
108
109 static int
110 do_abandon(
111         LDAP *ld,
112         ber_int_t origid,
113         ber_int_t msgid,
114         LDAPControl **sctrls,
115         LDAPControl **cctrls)
116 {
117         BerElement      *ber;
118         int             i, err, sendabandon;
119         ber_int_t *old_abandon;
120         Sockbuf         *sb;
121         LDAPRequest     *lr;
122
123 #ifdef NEW_LOGGING
124         LDAP_LOG ( OPERATION, ARGS, "do_abandon %d, msgid %d\n", origid, msgid, 0 );
125 #else
126         Debug( LDAP_DEBUG_TRACE, "do_abandon origid %d, msgid %d\n",
127                 origid, msgid, 0 );
128 #endif
129
130         sendabandon = 1;
131
132         /* find the request that we are abandoning */
133         for ( lr = ld->ld_requests; lr != NULL; lr = lr->lr_next ) {
134                 if ( lr->lr_msgid == msgid ) {  /* this message */
135                         break;
136                 }
137                 if ( lr->lr_origid == msgid ) {/* child:  abandon it */
138                         (void) do_abandon( ld,
139                                 msgid, lr->lr_msgid, sctrls, cctrls );
140                 }
141         }
142
143         if ( lr != NULL ) {
144                 if ( origid == msgid && lr->lr_parent != NULL ) {
145                         /* don't let caller abandon child requests! */
146                         ld->ld_errno = LDAP_PARAM_ERROR;
147                         return( LDAP_PARAM_ERROR );
148                 }
149                 if ( lr->lr_status != LDAP_REQST_INPROGRESS ) {
150                         /* no need to send abandon message */
151                         sendabandon = 0;
152                 }
153         }
154
155 /* ldap_msgdelete locks the res_mutex. Give up the req_mutex
156  * while we're in there.
157  */
158 #ifdef LDAP_R_COMPILE
159         ldap_pvt_thread_mutex_unlock( &ld->ld_req_mutex );
160 #endif
161         err = ldap_msgdelete( ld, msgid );
162 #ifdef LDAP_R_COMPILE
163         ldap_pvt_thread_mutex_lock( &ld->ld_req_mutex );
164 #endif
165         if ( err == 0 ) {
166                 ld->ld_errno = LDAP_SUCCESS;
167                 return LDAP_SUCCESS;
168         }
169
170         err = 0;
171         if ( sendabandon ) {
172                 if( ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, NULL ) == -1 ) {
173                         /* not connected */
174                         err = -1;
175                         ld->ld_errno = LDAP_SERVER_DOWN;
176
177                 } else if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) {
178                         /* BER element alocation failed */
179                         err = -1;
180                         ld->ld_errno = LDAP_NO_MEMORY;
181
182                 } else {
183                         LDAP_NEXT_MSGID(ld, i);
184 #ifdef LDAP_CONNECTIONLESS
185                         if ( LDAP_IS_UDP(ld) ) {
186                             err = ber_write( ber, ld->ld_options.ldo_peer,
187                                 sizeof(struct sockaddr), 0);
188                         }
189                         if ( LDAP_IS_UDP(ld) && ld->ld_options.ldo_version ==
190                                 LDAP_VERSION2) {
191                             char *dn = ld->ld_options.ldo_cldapdn;
192                             if (!dn) dn = "";
193                             err = ber_printf( ber, "{isti",  /* '}' */
194                                 i, dn,
195                                 LDAP_REQ_ABANDON, msgid );
196                         } else
197 #endif
198                         {
199                             /* create a message to send */
200                             err = ber_printf( ber, "{iti",  /* '}' */
201                                 i,
202                                 LDAP_REQ_ABANDON, msgid );
203                         }
204
205                         if( err == -1 ) {
206                                 /* encoding error */
207                                 ld->ld_errno = LDAP_ENCODING_ERROR;
208
209                         } else {
210                                 /* Put Server Controls */
211                                 if ( ldap_int_put_controls( ld, sctrls, ber )
212                                         != LDAP_SUCCESS )
213                                 {
214                                         err = -1;
215
216                                 } else {
217                                         /* close '{' */
218                                         err = ber_printf( ber, /*{*/ "N}" );
219
220                                         if( err == -1 ) {
221                                                 /* encoding error */
222                                                 ld->ld_errno = LDAP_ENCODING_ERROR;
223                                         }
224                                 }
225                         }
226
227                         if ( err == -1 ) {
228                                 ber_free( ber, 1 );
229
230                         } else {
231                                 /* send the message */
232                                 if ( lr != NULL ) {
233                                         sb = lr->lr_conn->lconn_sb;
234                                 } else {
235                                         sb = ld->ld_sb;
236                                 }
237
238                                 if ( ber_flush( sb, ber, 1 ) != 0 ) {
239                                         ld->ld_errno = LDAP_SERVER_DOWN;
240                                         err = -1;
241                                 } else {
242                                         err = 0;
243                                 }
244                         }
245                 }
246         }
247
248         if ( lr != NULL ) {
249                 if ( sendabandon || lr->lr_status == LDAP_REQST_WRITING ) {
250                         ldap_free_connection( ld, lr->lr_conn, 0, 1 );
251                 }
252                 if ( origid == msgid ) {
253                         ldap_free_request( ld, lr );
254                 }
255         }
256
257         i = 0;
258         if ( ld->ld_abandoned != NULL ) {
259                 for ( ; ld->ld_abandoned[i] != -1; i++ )
260                         ;       /* NULL */
261         }
262
263         old_abandon = ld->ld_abandoned;
264
265         ld->ld_abandoned = (ber_int_t *) LDAP_REALLOC( (char *)
266                 ld->ld_abandoned, (i + 2) * sizeof(ber_int_t) );
267                 
268         if ( ld->ld_abandoned == NULL ) {
269                 ld->ld_abandoned = old_abandon;
270                 ld->ld_errno = LDAP_NO_MEMORY;
271                 return( ld->ld_errno );
272         }
273
274         ld->ld_abandoned[i] = msgid;
275         ld->ld_abandoned[i + 1] = -1;
276
277         if ( err != -1 ) {
278                 ld->ld_errno = LDAP_SUCCESS;
279         }
280
281         return( ld->ld_errno );
282 }