1/* $NetBSD: abandon.c,v 1.3 2021/08/14 16:14:58 christos Exp $ */ 2 3/* abandon.c - decode and handle an ldap abandon operation */ 4/* $OpenLDAP$ */ 5/* This work is part of OpenLDAP Software <http://www.openldap.org/>. 6 * 7 * Copyright 1998-2021 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 <sys/cdefs.h> 30__RCSID("$NetBSD: abandon.c,v 1.3 2021/08/14 16:14:58 christos Exp $"); 31 32#include "portable.h" 33 34#include <stdio.h> 35#include <ac/socket.h> 36 37#include "slap.h" 38 39int 40do_abandon( Operation *op, SlapReply *rs ) 41{ 42 ber_int_t id; 43 Operation *o; 44 const char *msg; 45 46 Debug( LDAP_DEBUG_TRACE, "%s do_abandon\n", 47 op->o_log_prefix ); 48 49 /* 50 * Parse the abandon request. It looks like this: 51 * 52 * AbandonRequest := MessageID 53 */ 54 55 if ( ber_scanf( op->o_ber, "i", &id ) == LBER_ERROR ) { 56 Debug( LDAP_DEBUG_ANY, "%s do_abandon: ber_scanf failed\n", 57 op->o_log_prefix ); 58 send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "decoding error" ); 59 return SLAPD_DISCONNECT; 60 } 61 62 Debug( LDAP_DEBUG_STATS, "%s ABANDON msg=%ld\n", 63 op->o_log_prefix, (long) id ); 64 65 if( get_ctrls( op, rs, 0 ) != LDAP_SUCCESS ) { 66 Debug( LDAP_DEBUG_ANY, "%s do_abandon: get_ctrls failed\n", 67 op->o_log_prefix ); 68 return rs->sr_err; 69 } 70 71 Debug( LDAP_DEBUG_ARGS, "%s do_abandon: id=%ld\n", 72 op->o_log_prefix, (long) id ); 73 74 if( id <= 0 ) { 75 Debug( LDAP_DEBUG_ANY, "%s do_abandon: bad msgid %ld\n", 76 op->o_log_prefix, (long) id ); 77 return LDAP_SUCCESS; 78 } 79 80 ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex ); 81 82 /* Find the operation being abandoned. */ 83 LDAP_STAILQ_FOREACH( o, &op->o_conn->c_ops, o_next ) { 84 if ( o->o_msgid == id ) { 85 break; 86 } 87 } 88 89 if ( o == NULL ) { 90 msg = "not found"; 91 /* The operation is not active. Just discard it if found. */ 92 LDAP_STAILQ_FOREACH( o, &op->o_conn->c_pending_ops, o_next ) { 93 if ( o->o_msgid == id ) { 94 msg = "discarded"; 95 /* FIXME: This traverses c_pending_ops yet again. */ 96 LDAP_STAILQ_REMOVE( &op->o_conn->c_pending_ops, 97 o, Operation, o_next ); 98 LDAP_STAILQ_NEXT(o, o_next) = NULL; 99 op->o_conn->c_n_ops_pending--; 100 slap_op_free( o, NULL ); 101 break; 102 } 103 } 104 105 } else if ( o->o_tag == LDAP_REQ_BIND 106 || o->o_tag == LDAP_REQ_UNBIND 107 || o->o_tag == LDAP_REQ_ABANDON ) { 108 msg = "cannot be abandoned"; 109 110#if 0 /* Would break o_abandon used as "suppress response" flag, ITS#6138 */ 111 } else if ( o->o_abandon ) { 112 msg = "already being abandoned"; 113#endif 114 115 } else { 116 msg = "found"; 117 /* Set the o_abandon flag in the to-be-abandoned operation. 118 * The backend can periodically check this flag and abort the 119 * operation at a convenient time. However it should "send" 120 * the response anyway, with result code SLAPD_ABANDON. 121 * The functions in result.c will intercept the message. 122 */ 123 o->o_abandon = 1; 124 op->orn_msgid = id; 125 op->o_bd = frontendDB; 126 rs->sr_err = frontendDB->be_abandon( op, rs ); 127 } 128 129 ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex ); 130 131 Debug( LDAP_DEBUG_TRACE, "%s do_abandon: op=%ld %s\n", 132 op->o_log_prefix, (long) id, msg ); 133 return rs->sr_err; 134} 135 136int 137fe_op_abandon( Operation *op, SlapReply *rs ) 138{ 139 LDAP_STAILQ_FOREACH( op->o_bd, &backendDB, be_next ) { 140 if ( op->o_bd->be_abandon ) { 141 (void)op->o_bd->be_abandon( op, rs ); 142 } 143 } 144 145 return LDAP_SUCCESS; 146} 147