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