]> git.sur5r.net Git - openldap/blobdiff - libraries/libldap/abandon.c
Renamed ppcontrol.c to ppolicy.c
[openldap] / libraries / libldap / abandon.c
index 377beb7eb302f515616562376877bd938b3539ff..24880ab4f9c566e6067a84db1f5a836f944636da 100644 (file)
@@ -1,43 +1,95 @@
-/*
- *  Copyright (c) 1990 Regents of the University of Michigan.
- *  All rights reserved.
+/* abandon.c */
+/* $OpenLDAP$ */
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * Copyright 1998-2004 The OpenLDAP Foundation.
+ * All rights reserved.
  *
- *  abandon.c
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted only as authorized by the OpenLDAP
+ * Public License.
+ *
+ * A copy of this license is available in the file LICENSE in the
+ * top-level directory of the distribution or, alternatively, at
+ * <http://www.OpenLDAP.org/license.html>.
+ */
+/* Portions  Copyright (c) 1990 Regents of the University of Michigan.
+ * All rights reserved.
+ */
+/* Portions Copyright (C) The Internet Society (1997).
+ * ASN.1 fragments are from RFC 2251; see RFC for full legal notices.
  */
 
-#ifndef lint 
-static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University of Michigan.\nAll rights reserved.\n";
-#endif
+/*
+ * An abandon request looks like this:
+ *     AbandonRequest ::= MessageID
+ */
+
+#include "portable.h"
 
 #include <stdio.h>
-#include <string.h>
 
-#if !defined( MACOS ) && !defined( DOS )
-#include <sys/types.h>
-#include <sys/socket.h>
+#include <ac/stdlib.h>
+
+#include <ac/socket.h>
+#include <ac/string.h>
+#include <ac/time.h>
+
+#include "ldap-int.h"
+
+static int do_abandon LDAP_P((
+       LDAP *ld,
+       ber_int_t origid,
+       ber_int_t msgid,
+       LDAPControl **sctrls,
+       LDAPControl **cctrls));
+
+/*
+ * ldap_abandon_ext - perform an ldap extended abandon operation.
+ *
+ * Parameters:
+ *     ld                      LDAP descriptor
+ *     msgid           The message id of the operation to abandon
+ *     scntrls         Server Controls
+ *     ccntrls         Client Controls
+ *
+ * ldap_abandon_ext returns a LDAP error code.
+ *             (LDAP_SUCCESS if everything went ok)
+ *
+ * Example:
+ *     ldap_abandon_ext( ld, msgid, scntrls, ccntrls );
+ */
+int
+ldap_abandon_ext(
+       LDAP *ld,
+       int msgid,
+       LDAPControl **sctrls,
+       LDAPControl **cctrls )
+{
+       int rc;
+#ifdef NEW_LOGGING
+       LDAP_LOG ( OPERATION, ARGS, "ldap_abandon_ext %d\n", msgid, 0, 0 );
+#else
+       Debug( LDAP_DEBUG_TRACE, "ldap_abandon_ext %d\n", msgid, 0, 0 );
 #endif
 
-#if defined( DOS ) || defined( _WIN32 )
-#include <malloc.h>
-#include "msdos.h"
-#endif /* DOS */
+       /* check client controls */
+#ifdef LDAP_R_COMPILE
+       ldap_pvt_thread_mutex_lock( &ld->ld_req_mutex );
+#endif
+       rc = ldap_int_client_controls( ld, cctrls );
+       if( rc == LDAP_SUCCESS )
+               rc = do_abandon( ld, msgid, msgid, sctrls, cctrls );
 
-#ifdef MACOS
-#include <stdlib.h>
-#include "macos.h"
-#endif /* MACOS */
+#ifdef LDAP_R_COMPILE
+       ldap_pvt_thread_mutex_unlock( &ld->ld_req_mutex );
+#endif
+       return rc;
+}
 
-#include "lber.h"
-#include "ldap.h"
-#include "ldap-int.h"
 
-#ifdef NEEDPROTOS
-static int do_abandon( LDAP *ld, int origid, int msgid );
-#else /* NEEDPROTOS */
-static int do_abandon();
-#endif /* NEEDPROTOS */
 /*
- * ldap_abandon - perform an ldap (and X.500) abandon operation. Parameters:
+ * ldap_abandon - perform an ldap abandon operation. Parameters:
  *
  *     ld              LDAP descriptor
  *     msgid           The message id of the operation to abandon
@@ -50,39 +102,47 @@ static int do_abandon();
 int
 ldap_abandon( LDAP *ld, int msgid )
 {
+#ifdef NEW_LOGGING
+       LDAP_LOG ( OPERATION, ARGS, "ldap_abandon %d\n", msgid, 0, 0 );
+#else
        Debug( LDAP_DEBUG_TRACE, "ldap_abandon %d\n", msgid, 0, 0 );
-       return( do_abandon( ld, msgid, msgid ));
+#endif
+       return ldap_abandon_ext( ld, msgid, NULL, NULL ) == LDAP_SUCCESS
+               ? 0 : -1;
 }
 
 
 static int
-do_abandon( LDAP *ld, int origid, int msgid )
+do_abandon(
+       LDAP *ld,
+       ber_int_t origid,
+       ber_int_t msgid,
+       LDAPControl **sctrls,
+       LDAPControl **cctrls)
 {
        BerElement      *ber;
        int             i, err, sendabandon;
+       ber_int_t *old_abandon;
        Sockbuf         *sb;
-#ifdef LDAP_REFERRALS
        LDAPRequest     *lr;
-#endif /* LDAP_REFERRALS */
-
-       /*
-        * An abandon request looks like this:
-        *      AbandonRequest ::= MessageID
-        */
 
+#ifdef NEW_LOGGING
+       LDAP_LOG ( OPERATION, ARGS, "do_abandon %d, msgid %d\n", origid, msgid, 0 );
+#else
        Debug( LDAP_DEBUG_TRACE, "do_abandon origid %d, msgid %d\n",
                origid, msgid, 0 );
+#endif
 
        sendabandon = 1;
 
-#ifdef LDAP_REFERRALS
        /* find the request that we are abandoning */
        for ( lr = ld->ld_requests; lr != NULL; lr = lr->lr_next ) {
                if ( lr->lr_msgid == msgid ) {  /* this message */
                        break;
                }
-               if ( lr->lr_origid == msgid ) { /* child:  abandon it */
-                       do_abandon( ld, msgid, lr->lr_msgid );
+               if ( lr->lr_origid == msgid ) {/* child:  abandon it */
+                       (void) do_abandon( ld,
+                               msgid, lr->lr_msgid, sctrls, cctrls );
                }
        }
 
@@ -90,54 +150,102 @@ do_abandon( LDAP *ld, int origid, int msgid )
                if ( origid == msgid && lr->lr_parent != NULL ) {
                        /* don't let caller abandon child requests! */
                        ld->ld_errno = LDAP_PARAM_ERROR;
-                       return( -1 );
+                       return( LDAP_PARAM_ERROR );
                }
                if ( lr->lr_status != LDAP_REQST_INPROGRESS ) {
                        /* no need to send abandon message */
                        sendabandon = 0;
                }
        }
-#endif /* LDAP_REFERRALS */
 
-       if ( ldap_msgdelete( ld, msgid ) == 0 ) {
+/* ldap_msgdelete locks the res_mutex. Give up the req_mutex
+ * while we're in there.
+ */
+#ifdef LDAP_R_COMPILE
+       ldap_pvt_thread_mutex_unlock( &ld->ld_req_mutex );
+#endif
+       err = ldap_msgdelete( ld, msgid );
+#ifdef LDAP_R_COMPILE
+       ldap_pvt_thread_mutex_lock( &ld->ld_req_mutex );
+#endif
+       if ( err == 0 ) {
                ld->ld_errno = LDAP_SUCCESS;
-               return( 0 );
+               return LDAP_SUCCESS;
        }
 
        err = 0;
        if ( sendabandon ) {
-               /* create a message to send */
-               if ( (ber = ldap_alloc_ber_with_options( ld )) == NULLBER ) {
+               if( ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, NULL ) == -1 ) {
+                       /* not connected */
+                       err = -1;
+                       ld->ld_errno = LDAP_SERVER_DOWN;
+
+               } else if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) {
+                       /* BER element alocation failed */
                        err = -1;
                        ld->ld_errno = LDAP_NO_MEMORY;
+
                } else {
-#ifdef CLDAP
-                       if ( ld->ld_sb.sb_naddr > 0 ) {
-                               err = ber_printf( ber, "{isti}",
-                                   ++ld->ld_msgid, ld->ld_cldapdn,
-                                   LDAP_REQ_ABANDON, msgid );
+       /*
+        * We already have the mutex in LDAP_R_COMPILE, so
+        * don't try to get it again.
+        *              LDAP_NEXT_MSGID(ld, i);
+        */
+                       i = ++(ld)->ld_msgid;
+#ifdef LDAP_CONNECTIONLESS
+                       if ( LDAP_IS_UDP(ld) ) {
+                           err = ber_write( ber, ld->ld_options.ldo_peer,
+                               sizeof(struct sockaddr), 0);
+                       }
+                       if ( LDAP_IS_UDP(ld) && ld->ld_options.ldo_version ==
+                               LDAP_VERSION2) {
+                           char *dn = ld->ld_options.ldo_cldapdn;
+                           if (!dn) dn = "";
+                           err = ber_printf( ber, "{isti",  /* '}' */
+                               i, dn,
+                               LDAP_REQ_ABANDON, msgid );
+                       } else
+#endif
+                       {
+                           /* create a message to send */
+                           err = ber_printf( ber, "{iti",  /* '}' */
+                               i,
+                               LDAP_REQ_ABANDON, msgid );
+                       }
+
+                       if( err == -1 ) {
+                               /* encoding error */
+                               ld->ld_errno = LDAP_ENCODING_ERROR;
+
                        } else {
-#endif /* CLDAP */
-                               err = ber_printf( ber, "{iti}", ++ld->ld_msgid,
-                                   LDAP_REQ_ABANDON, msgid );
-#ifdef CLDAP
+                               /* Put Server Controls */
+                               if ( ldap_int_put_controls( ld, sctrls, ber )
+                                       != LDAP_SUCCESS )
+                               {
+                                       err = -1;
+
+                               } else {
+                                       /* close '{' */
+                                       err = ber_printf( ber, /*{*/ "N}" );
+
+                                       if( err == -1 ) {
+                                               /* encoding error */
+                                               ld->ld_errno = LDAP_ENCODING_ERROR;
+                                       }
+                               }
                        }
-#endif /* CLDAP */
 
                        if ( err == -1 ) {
-                               ld->ld_errno = LDAP_ENCODING_ERROR;
                                ber_free( ber, 1 );
+
                        } else {
                                /* send the message */
-#ifdef LDAP_REFERRALS
                                if ( lr != NULL ) {
                                        sb = lr->lr_conn->lconn_sb;
                                } else {
-                                       sb = &ld->ld_sb;
+                                       sb = ld->ld_sb;
                                }
-#else /* LDAP_REFERRALS */
-                               sb = &ld->ld_sb;
-#endif /* LDAP_REFERRALS */
+
                                if ( ber_flush( sb, ber, 1 ) != 0 ) {
                                        ld->ld_errno = LDAP_SERVER_DOWN;
                                        err = -1;
@@ -148,39 +256,38 @@ do_abandon( LDAP *ld, int origid, int msgid )
                }
        }
 
-#ifdef LDAP_REFERRALS
        if ( lr != NULL ) {
-               if ( sendabandon ) {
+               if ( sendabandon || lr->lr_status == LDAP_REQST_WRITING ) {
                        ldap_free_connection( ld, lr->lr_conn, 0, 1 );
                }
                if ( origid == msgid ) {
                        ldap_free_request( ld, lr );
                }
        }
-#endif /* LDAP_REFERRALS */
 
+       i = 0;
+       if ( ld->ld_abandoned != NULL ) {
+               for ( ; ld->ld_abandoned[i] != -1; i++ )
+                       ;       /* NULL */
+       }
+
+       old_abandon = ld->ld_abandoned;
 
+       ld->ld_abandoned = (ber_int_t *) LDAP_REALLOC( (char *)
+               ld->ld_abandoned, (i + 2) * sizeof(ber_int_t) );
+               
        if ( ld->ld_abandoned == NULL ) {
-               if ( (ld->ld_abandoned = (int *) malloc( 2 * sizeof(int) ))
-                   == NULL ) {
-                       ld->ld_errno = LDAP_NO_MEMORY;
-                       return( -1 );
-               }
-               i = 0;
-       } else {
-               for ( i = 0; ld->ld_abandoned[i] != -1; i++ )
-                       ;       /* NULL */
-               if ( (ld->ld_abandoned = (int *) realloc( (char *)
-                   ld->ld_abandoned, (i + 2) * sizeof(int) )) == NULL ) {
-                       ld->ld_errno = LDAP_NO_MEMORY;
-                       return( -1 );
-               }
+               ld->ld_abandoned = old_abandon;
+               ld->ld_errno = LDAP_NO_MEMORY;
+               return( ld->ld_errno );
        }
+
        ld->ld_abandoned[i] = msgid;
        ld->ld_abandoned[i + 1] = -1;
 
        if ( err != -1 ) {
                ld->ld_errno = LDAP_SUCCESS;
        }
-       return( err );
+
+       return( ld->ld_errno );
 }