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