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