1
2 /*
3 * Portions Copyright 1998 Sun Microsystems, Inc. All rights reserved.
4 * Use is subject to license terms.
5 */
6
7 #pragma ident "%Z%%M% %I% %E% SMI"
8
9 /*
10 * Copyright (c) 1990 Regents of the University of Michigan.
11 * All rights reserved.
12 *
13 * abandon.c
14 */
15
16 #ifndef lint
17 static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University of Michigan.\nAll rights reserved.\n";
18 #endif
19
20 #include <stdio.h>
21 #include <string.h>
22
23 #if !defined( MACOS ) && !defined( DOS )
24 #include <sys/types.h>
25 #include <sys/socket.h>
26 #endif
27
28 #if defined( DOS ) || defined( _WIN32 )
29 #include <malloc.h>
30 #include "msdos.h"
31 #endif /* DOS */
32
33 #ifdef MACOS
34 #include <stdlib.h>
35 #include "macos.h"
36 #endif /* MACOS */
37
38 #include "lber.h"
39 #include "ldap.h"
40 #include "ldap-private.h"
41 #include "ldap-int.h"
42
43 #ifdef NEEDPROTOS
44 static int do_abandon( LDAP *ld, int origid, int msgid, LDAPControl **serverctrls );
45 #else /* NEEDPROTOS */
46 static int do_abandon();
47 #endif /* NEEDPROTOS */
48
ldap_build_abandon_req(LDAP * ld,int msgid,LDAPControl ** serverctrls)49 BerElement * ldap_build_abandon_req( LDAP *ld, int msgid, LDAPControl ** serverctrls)
50 {
51 BerElement *ber;
52 int rc;
53
54 /* create a message to send */
55 if ( (ber = alloc_ber_with_options( ld )) == NULLBER ) {
56 rc = -1;
57 ld->ld_errno = LDAP_NO_MEMORY;
58 return (NULLBER);
59 }
60 #ifdef CLDAP
61 if ( ld->ld_sb.sb_naddr > 0 ) {
62 rc = ber_printf( ber, "{isti",
63 ++ld->ld_msgid, ld->ld_cldapdn,
64 LDAP_REQ_ABANDON, msgid );
65 } else {
66 #endif /* CLDAP */
67 rc = ber_printf( ber, "{iti", ++ld->ld_msgid,
68 LDAP_REQ_ABANDON, msgid );
69 #ifdef CLDAP
70 }
71 #endif /* CLDAP */
72
73 if ( rc == -1 ) {
74 ld->ld_errno = LDAP_ENCODING_ERROR;
75 ber_free( ber, 1 );
76 return (NULLBER);
77 }
78 /* LDAPv3 */
79 /* Code controls if any */
80 if (serverctrls && serverctrls[0]) {
81 if (ldap_controls_code(ber, serverctrls) != LDAP_SUCCESS){
82 ld->ld_errno = LDAP_ENCODING_ERROR;
83 return( NULLBER );
84 }
85 } else if (ld->ld_srvctrls && ld->ld_srvctrls[0]) {
86 /* Otherwise, is there any global server ctrls ? */
87 if (ldap_controls_code(ber, ld->ld_srvctrls) != LDAP_SUCCESS){
88 ld->ld_errno = LDAP_ENCODING_ERROR;
89 return( NULLBER );
90 }
91 }
92
93 if ( ber_printf( ber, "}" ) == -1 ) {
94 ld->ld_errno = LDAP_ENCODING_ERROR;
95 ber_free( ber, 1 );
96 return( NULLBER );
97 }
98 return (ber);
99 }
100
101
102 /*
103 * ldap_abandon - perform an ldap (and X.500) abandon operation. Parameters:
104 *
105 * ld LDAP descriptor
106 * msgid The message id of the operation to abandon
107 *
108 * ldap_abandon returns 0 if everything went ok, -1 otherwise.
109 *
110 * Example:
111 * ldap_abandon( ld, msgid );
112 */
113 int
ldap_abandon(LDAP * ld,int msgid)114 ldap_abandon( LDAP *ld, int msgid )
115 {
116 int rv;
117
118 #ifdef _REENTRANT
119 LOCK_LDAP( ld );
120 #endif
121
122 Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 85, "ldap_abandon %d\n"), msgid, 0, 0 );
123
124 rv = do_abandon( ld, msgid, msgid , NULL);
125 #ifdef _REENTRANT
126 UNLOCK_LDAP( ld );
127 #endif
128 return (rv);
129 }
130
131 /* ldapv3 API extensions */
132
ldap_abandon_ext(LDAP * ld,int msgid,LDAPControl ** serverctrls,LDAPControl ** clientctrls)133 int ldap_abandon_ext(LDAP *ld, int msgid, LDAPControl **serverctrls, LDAPControl **clientctrls)
134 {
135 int rv;
136
137 #ifdef _REENTRANT
138 LOCK_LDAP( ld );
139 #endif
140
141 Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 85, "ldap_abandon %d\n"), msgid, 0, 0 );
142
143 rv = do_abandon( ld, msgid, msgid , NULL);
144 if (rv == -1) {
145 rv = ld->ld_errno;
146 if (rv == LDAP_SUCCESS)
147 rv = LDAP_OTHER;
148 #ifdef _REENTRANT
149 UNLOCK_LDAP( ld );
150 #endif
151 return (rv);
152 }
153 #ifdef _REENTRANT
154 UNLOCK_LDAP( ld );
155 #endif
156 return (LDAP_SUCCESS);
157 }
158
159
160 static int
do_abandon(LDAP * ld,int origid,int msgid,LDAPControl ** serverctrls)161 do_abandon( LDAP *ld, int origid, int msgid , LDAPControl **serverctrls)
162 {
163 BerElement *ber;
164 int i, err, sendabandon;
165 Sockbuf *sb;
166 #ifdef LDAP_REFERRALS
167 LDAPRequest *lr;
168 #endif /* LDAP_REFERRALS */
169
170 /*
171 * An abandon request looks like this:
172 * AbandonRequest ::= MessageID
173 */
174
175 Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 86, "do_abandon origid %1$d, msgid %2$d\n"),
176 origid, msgid, 0 );
177
178 sendabandon = 1;
179
180 #ifdef LDAP_REFERRALS
181 /* find the request that we are abandoning */
182 for ( lr = ld->ld_requests; lr != NULL; lr = lr->lr_next ) {
183 if ( lr->lr_msgid == msgid ) { /* this message */
184 break;
185 }
186 if ( lr->lr_origid == msgid ) { /* child: abandon it */
187 do_abandon( ld, msgid, lr->lr_msgid , serverctrls);
188 }
189 }
190
191 if ( lr != NULL ) {
192 if ( origid == msgid && lr->lr_parent != NULL ) {
193 /* don't let caller abandon child requests! */
194 ld->ld_errno = LDAP_PARAM_ERROR;
195 return( -1 );
196 }
197 if ( lr->lr_status != LDAP_REQST_INPROGRESS ) {
198 /* no need to send abandon message */
199 sendabandon = 0;
200 }
201 }
202 #endif /* LDAP_REFERRALS */
203
204 if ( ldap_msgdelete( ld, msgid ) == 0 ) {
205 ld->ld_errno = LDAP_SUCCESS;
206 return( 0 );
207 }
208
209 err = 0;
210 if ( sendabandon ) {
211 if ((ber = ldap_build_abandon_req(ld, msgid, serverctrls)) == NULLBER){
212 return (-1);
213 }
214
215 #ifdef LDAP_REFERRALS
216 if ( lr != NULL ) {
217 sb = lr->lr_conn->lconn_sb;
218 } else {
219 sb = &ld->ld_sb;
220 }
221 #else /* LDAP_REFERRALS */
222 sb = &ld->ld_sb;
223 #endif /* LDAP_REFERRALS */
224 if ( ber_flush( sb, ber, 1 ) != 0 ) {
225 ld->ld_errno = LDAP_SERVER_DOWN;
226 err = -1;
227 } else {
228 err = 0;
229 }
230 }
231 #ifdef LDAP_REFERRALS
232 if ( lr != NULL ) {
233 if ( sendabandon ) {
234 free_connection( ld, lr->lr_conn, 0, 1 );
235 }
236 if ( origid == msgid ) {
237 free_request( ld, lr );
238 }
239 }
240 #endif /* LDAP_REFERRALS */
241
242
243 if ( ld->ld_abandoned == NULL ) {
244 if ( (ld->ld_abandoned = (int *) malloc( 2 * sizeof(int) ))
245 == NULL ) {
246 ld->ld_errno = LDAP_NO_MEMORY;
247 return( -1 );
248 }
249 i = 0;
250 } else {
251 for ( i = 0; ld->ld_abandoned[i] != -1; i++ )
252 ; /* NULL */
253 if ( (ld->ld_abandoned = (int *) realloc( (char *)
254 ld->ld_abandoned, (i + 2) * sizeof(int) )) == NULL ) {
255 ld->ld_errno = LDAP_NO_MEMORY;
256 return( -1 );
257 }
258 }
259 ld->ld_abandoned[i] = msgid;
260 ld->ld_abandoned[i + 1] = -1;
261
262 if ( err != -1 ) {
263 ld->ld_errno = LDAP_SUCCESS;
264 }
265 return( err );
266 }
267
268