1 /* cancel.c - LDAP cancel extended operation */ 2 /* $OpenLDAP: pkg/ldap/servers/slapd/cancel.c,v 1.23.2.4 2008/02/11 23:26:43 kurt Exp $ */ 3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 4 * 5 * Copyright 1998-2008 The OpenLDAP Foundation. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted only as authorized by the OpenLDAP 10 * Public License. 11 * 12 * A copy of this license is available in the file LICENSE in the 13 * top-level directory of the distribution or, alternatively, at 14 * <http://www.OpenLDAP.org/license.html>. 15 */ 16 17 #include "portable.h" 18 19 #include <stdio.h> 20 21 #include <ac/socket.h> 22 #include <ac/string.h> 23 #include <ac/unistd.h> 24 25 #include "slap.h" 26 27 #include <lber_pvt.h> 28 #include <lutil.h> 29 30 const struct berval slap_EXOP_CANCEL = BER_BVC(LDAP_EXOP_CANCEL); 31 32 int cancel_extop( Operation *op, SlapReply *rs ) 33 { 34 Operation *o; 35 int rc; 36 int opid; 37 BerElement *ber; 38 39 assert( ber_bvcmp( &slap_EXOP_CANCEL, &op->ore_reqoid ) == 0 ); 40 41 if ( op->ore_reqdata == NULL ) { 42 rs->sr_text = "no message ID supplied"; 43 return LDAP_PROTOCOL_ERROR; 44 } 45 46 ber = ber_init( op->ore_reqdata ); 47 if ( ber == NULL ) { 48 rs->sr_text = "internal error"; 49 return LDAP_OTHER; 50 } 51 52 if ( ber_scanf( ber, "{i}", &opid ) == LBER_ERROR ) { 53 rs->sr_text = "message ID parse failed"; 54 return LDAP_PROTOCOL_ERROR; 55 } 56 57 (void) ber_free( ber, 1 ); 58 59 Statslog( LDAP_DEBUG_STATS, "%s CANCEL msg=%d\n", 60 op->o_log_prefix, opid, 0, 0, 0 ); 61 62 if ( opid < 0 ) { 63 rs->sr_text = "message ID invalid"; 64 return LDAP_PROTOCOL_ERROR; 65 } 66 67 ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex ); 68 LDAP_STAILQ_FOREACH( o, &op->o_conn->c_pending_ops, o_next ) { 69 if ( o->o_msgid == opid ) { 70 LDAP_STAILQ_REMOVE( &op->o_conn->c_pending_ops, o, Operation, o_next ); 71 LDAP_STAILQ_NEXT(o, o_next) = NULL; 72 op->o_conn->c_n_ops_pending--; 73 slap_op_free( o, NULL ); 74 ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex ); 75 return LDAP_SUCCESS; 76 } 77 } 78 79 LDAP_STAILQ_FOREACH( o, &op->o_conn->c_ops, o_next ) { 80 if ( o->o_msgid == opid ) { 81 o->o_abandon = 1; 82 break; 83 } 84 } 85 86 ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex ); 87 88 if ( o ) { 89 if ( o->o_cancel != SLAP_CANCEL_NONE ) { 90 rs->sr_text = "message ID already being cancelled"; 91 return LDAP_PROTOCOL_ERROR; 92 } 93 94 o->o_cancel = SLAP_CANCEL_REQ; 95 96 LDAP_STAILQ_FOREACH( op->o_bd, &backendDB, be_next ) { 97 if( !op->o_bd->be_cancel ) continue; 98 99 op->oq_cancel.rs_msgid = opid; 100 if ( op->o_bd->be_cancel( op, rs ) == LDAP_SUCCESS ) { 101 return LDAP_SUCCESS; 102 } 103 } 104 105 while ( o->o_cancel == SLAP_CANCEL_REQ ) { 106 ldap_pvt_thread_yield(); 107 } 108 109 if ( o->o_cancel == SLAP_CANCEL_ACK ) { 110 rc = LDAP_SUCCESS; 111 } else { 112 rc = o->o_cancel; 113 } 114 115 o->o_cancel = SLAP_CANCEL_DONE; 116 } else { 117 rs->sr_text = "message ID not found"; 118 rc = LDAP_NO_SUCH_OPERATION; 119 } 120 121 return rc; 122 } 123