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