1*549b59edSchristos /* $NetBSD: abandon.c,v 1.3 2021/08/14 16:14:58 christos Exp $ */
24e6df137Slukem
32de962bdSlukem /* abandon.c - decode and handle an ldap abandon operation */
4d11b170bStron /* $OpenLDAP$ */
52de962bdSlukem /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
62de962bdSlukem *
7*549b59edSchristos * Copyright 1998-2021 The OpenLDAP Foundation.
82de962bdSlukem * All rights reserved.
92de962bdSlukem *
102de962bdSlukem * Redistribution and use in source and binary forms, with or without
112de962bdSlukem * modification, are permitted only as authorized by the OpenLDAP
122de962bdSlukem * Public License.
132de962bdSlukem *
142de962bdSlukem * A copy of this license is available in the file LICENSE in the
152de962bdSlukem * top-level directory of the distribution or, alternatively, at
162de962bdSlukem * <http://www.OpenLDAP.org/license.html>.
172de962bdSlukem */
182de962bdSlukem /* Portions Copyright (c) 1995 Regents of the University of Michigan.
192de962bdSlukem * All rights reserved.
202de962bdSlukem *
212de962bdSlukem * Redistribution and use in source and binary forms are permitted
222de962bdSlukem * provided that this notice is preserved and that due credit is given
232de962bdSlukem * to the University of Michigan at Ann Arbor. The name of the University
242de962bdSlukem * may not be used to endorse or promote products derived from this
252de962bdSlukem * software without specific prior written permission. This software
262de962bdSlukem * is provided ``as is'' without express or implied warranty.
272de962bdSlukem */
282de962bdSlukem
29376af7d7Schristos #include <sys/cdefs.h>
30*549b59edSchristos __RCSID("$NetBSD: abandon.c,v 1.3 2021/08/14 16:14:58 christos Exp $");
31376af7d7Schristos
322de962bdSlukem #include "portable.h"
332de962bdSlukem
342de962bdSlukem #include <stdio.h>
352de962bdSlukem #include <ac/socket.h>
362de962bdSlukem
372de962bdSlukem #include "slap.h"
382de962bdSlukem
392de962bdSlukem int
do_abandon(Operation * op,SlapReply * rs)402de962bdSlukem do_abandon( Operation *op, SlapReply *rs )
412de962bdSlukem {
422de962bdSlukem ber_int_t id;
432de962bdSlukem Operation *o;
444e6df137Slukem const char *msg;
452de962bdSlukem
462de962bdSlukem Debug( LDAP_DEBUG_TRACE, "%s do_abandon\n",
47*549b59edSchristos op->o_log_prefix );
482de962bdSlukem
492de962bdSlukem /*
502de962bdSlukem * Parse the abandon request. It looks like this:
512de962bdSlukem *
522de962bdSlukem * AbandonRequest := MessageID
532de962bdSlukem */
542de962bdSlukem
552de962bdSlukem if ( ber_scanf( op->o_ber, "i", &id ) == LBER_ERROR ) {
562de962bdSlukem Debug( LDAP_DEBUG_ANY, "%s do_abandon: ber_scanf failed\n",
57*549b59edSchristos op->o_log_prefix );
582de962bdSlukem send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "decoding error" );
592de962bdSlukem return SLAPD_DISCONNECT;
602de962bdSlukem }
612de962bdSlukem
62*549b59edSchristos Debug( LDAP_DEBUG_STATS, "%s ABANDON msg=%ld\n",
63*549b59edSchristos op->o_log_prefix, (long) id );
642de962bdSlukem
652de962bdSlukem if( get_ctrls( op, rs, 0 ) != LDAP_SUCCESS ) {
662de962bdSlukem Debug( LDAP_DEBUG_ANY, "%s do_abandon: get_ctrls failed\n",
67*549b59edSchristos op->o_log_prefix );
682de962bdSlukem return rs->sr_err;
692de962bdSlukem }
702de962bdSlukem
712de962bdSlukem Debug( LDAP_DEBUG_ARGS, "%s do_abandon: id=%ld\n",
72*549b59edSchristos op->o_log_prefix, (long) id );
732de962bdSlukem
742de962bdSlukem if( id <= 0 ) {
752de962bdSlukem Debug( LDAP_DEBUG_ANY, "%s do_abandon: bad msgid %ld\n",
76*549b59edSchristos op->o_log_prefix, (long) id );
772de962bdSlukem return LDAP_SUCCESS;
782de962bdSlukem }
792de962bdSlukem
802de962bdSlukem ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex );
812de962bdSlukem
824e6df137Slukem /* Find the operation being abandoned. */
832de962bdSlukem LDAP_STAILQ_FOREACH( o, &op->o_conn->c_ops, o_next ) {
842de962bdSlukem if ( o->o_msgid == id ) {
852de962bdSlukem break;
862de962bdSlukem }
872de962bdSlukem }
882de962bdSlukem
894e6df137Slukem if ( o == NULL ) {
904e6df137Slukem msg = "not found";
914e6df137Slukem /* The operation is not active. Just discard it if found. */
922de962bdSlukem LDAP_STAILQ_FOREACH( o, &op->o_conn->c_pending_ops, o_next ) {
932de962bdSlukem if ( o->o_msgid == id ) {
944e6df137Slukem msg = "discarded";
954e6df137Slukem /* FIXME: This traverses c_pending_ops yet again. */
962de962bdSlukem LDAP_STAILQ_REMOVE( &op->o_conn->c_pending_ops,
972de962bdSlukem o, Operation, o_next );
982de962bdSlukem LDAP_STAILQ_NEXT(o, o_next) = NULL;
992de962bdSlukem op->o_conn->c_n_ops_pending--;
1002de962bdSlukem slap_op_free( o, NULL );
1012de962bdSlukem break;
1022de962bdSlukem }
1032de962bdSlukem }
1044e6df137Slukem
1054e6df137Slukem } else if ( o->o_tag == LDAP_REQ_BIND
1064e6df137Slukem || o->o_tag == LDAP_REQ_UNBIND
1074e6df137Slukem || o->o_tag == LDAP_REQ_ABANDON ) {
1084e6df137Slukem msg = "cannot be abandoned";
1094e6df137Slukem
1104e6df137Slukem #if 0 /* Would break o_abandon used as "suppress response" flag, ITS#6138 */
1114e6df137Slukem } else if ( o->o_abandon ) {
1124e6df137Slukem msg = "already being abandoned";
1134e6df137Slukem #endif
1144e6df137Slukem
1154e6df137Slukem } else {
1164e6df137Slukem msg = "found";
1174e6df137Slukem /* Set the o_abandon flag in the to-be-abandoned operation.
1184e6df137Slukem * The backend can periodically check this flag and abort the
1194e6df137Slukem * operation at a convenient time. However it should "send"
1204e6df137Slukem * the response anyway, with result code SLAPD_ABANDON.
1214e6df137Slukem * The functions in result.c will intercept the message.
1224e6df137Slukem */
1234e6df137Slukem o->o_abandon = 1;
1244e6df137Slukem op->orn_msgid = id;
1254e6df137Slukem op->o_bd = frontendDB;
1264e6df137Slukem rs->sr_err = frontendDB->be_abandon( op, rs );
1272de962bdSlukem }
1282de962bdSlukem
1292de962bdSlukem ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex );
1302de962bdSlukem
1314e6df137Slukem Debug( LDAP_DEBUG_TRACE, "%s do_abandon: op=%ld %s\n",
1324e6df137Slukem op->o_log_prefix, (long) id, msg );
1332de962bdSlukem return rs->sr_err;
1342de962bdSlukem }
1352de962bdSlukem
1362de962bdSlukem int
fe_op_abandon(Operation * op,SlapReply * rs)1372de962bdSlukem fe_op_abandon( Operation *op, SlapReply *rs )
1382de962bdSlukem {
1392de962bdSlukem LDAP_STAILQ_FOREACH( op->o_bd, &backendDB, be_next ) {
1402de962bdSlukem if ( op->o_bd->be_abandon ) {
1412de962bdSlukem (void)op->o_bd->be_abandon( op, rs );
1422de962bdSlukem }
1432de962bdSlukem }
1442de962bdSlukem
1452de962bdSlukem return LDAP_SUCCESS;
1462de962bdSlukem }
147