1/* abandon.c - decode and handle an ldap abandon operation */ 2/* $OpenLDAP$ */ 3/* This work is part of OpenLDAP Software <http://www.openldap.org/>. 4 * 5 * Copyright 1998-2011 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/* Portions Copyright (c) 1995 Regents of the University of Michigan. 17 * All rights reserved. 18 * 19 * Redistribution and use in source and binary forms are permitted 20 * provided that this notice is preserved and that due credit is given 21 * to the University of Michigan at Ann Arbor. The name of the University 22 * may not be used to endorse or promote products derived from this 23 * software without specific prior written permission. This software 24 * is provided ``as is'' without express or implied warranty. 25 */ 26 27#include "portable.h" 28 29#include <stdio.h> 30#include <ac/socket.h> 31 32#include "slap.h" 33 34int 35do_abandon( Operation *op, SlapReply *rs ) 36{ 37 ber_int_t id; 38 Operation *o; 39 const char *msg; 40 41 Debug( LDAP_DEBUG_TRACE, "%s do_abandon\n", 42 op->o_log_prefix, 0, 0 ); 43 44 /* 45 * Parse the abandon request. It looks like this: 46 * 47 * AbandonRequest := MessageID 48 */ 49 50 if ( ber_scanf( op->o_ber, "i", &id ) == LBER_ERROR ) { 51 Debug( LDAP_DEBUG_ANY, "%s do_abandon: ber_scanf failed\n", 52 op->o_log_prefix, 0, 0 ); 53 send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "decoding error" ); 54 return SLAPD_DISCONNECT; 55 } 56 57 Statslog( LDAP_DEBUG_STATS, "%s ABANDON msg=%ld\n", 58 op->o_log_prefix, (long) id, 0, 0, 0 ); 59 60 if( get_ctrls( op, rs, 0 ) != LDAP_SUCCESS ) { 61 Debug( LDAP_DEBUG_ANY, "%s do_abandon: get_ctrls failed\n", 62 op->o_log_prefix, 0, 0 ); 63 return rs->sr_err; 64 } 65 66 Debug( LDAP_DEBUG_ARGS, "%s do_abandon: id=%ld\n", 67 op->o_log_prefix, (long) id, 0 ); 68 69 if( id <= 0 ) { 70 Debug( LDAP_DEBUG_ANY, "%s do_abandon: bad msgid %ld\n", 71 op->o_log_prefix, (long) id, 0 ); 72 return LDAP_SUCCESS; 73 } 74 75 ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex ); 76 77 /* Find the operation being abandoned. */ 78 LDAP_STAILQ_FOREACH( o, &op->o_conn->c_ops, o_next ) { 79 if ( o->o_msgid == id ) { 80 break; 81 } 82 } 83 84 if ( o == NULL ) { 85 msg = "not found"; 86 /* The operation is not active. Just discard it if found. */ 87 LDAP_STAILQ_FOREACH( o, &op->o_conn->c_pending_ops, o_next ) { 88 if ( o->o_msgid == id ) { 89 msg = "discarded"; 90 /* FIXME: This traverses c_pending_ops yet again. */ 91 LDAP_STAILQ_REMOVE( &op->o_conn->c_pending_ops, 92 o, Operation, o_next ); 93 LDAP_STAILQ_NEXT(o, o_next) = NULL; 94 op->o_conn->c_n_ops_pending--; 95 slap_op_free( o, NULL ); 96 break; 97 } 98 } 99 100 } else if ( o->o_tag == LDAP_REQ_BIND 101 || o->o_tag == LDAP_REQ_UNBIND 102 || o->o_tag == LDAP_REQ_ABANDON ) { 103 msg = "cannot be abandoned"; 104 105#if 0 /* Would break o_abandon used as "suppress response" flag, ITS#6138 */ 106 } else if ( o->o_abandon ) { 107 msg = "already being abandoned"; 108#endif 109 110 } else { 111 msg = "found"; 112 /* Set the o_abandon flag in the to-be-abandoned operation. 113 * The backend can periodically check this flag and abort the 114 * operation at a convenient time. However it should "send" 115 * the response anyway, with result code SLAPD_ABANDON. 116 * The functions in result.c will intercept the message. 117 */ 118 o->o_abandon = 1; 119 op->orn_msgid = id; 120 op->o_bd = frontendDB; 121 rs->sr_err = frontendDB->be_abandon( op, rs ); 122 } 123 124 ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex ); 125 126 Debug( LDAP_DEBUG_TRACE, "%s do_abandon: op=%ld %s\n", 127 op->o_log_prefix, (long) id, msg ); 128 return rs->sr_err; 129} 130 131int 132fe_op_abandon( Operation *op, SlapReply *rs ) 133{ 134 LDAP_STAILQ_FOREACH( op->o_bd, &backendDB, be_next ) { 135 if ( op->o_bd->be_abandon ) { 136 (void)op->o_bd->be_abandon( op, rs ); 137 } 138 } 139 140 return LDAP_SUCCESS; 141} 142