xref: /netbsd-src/external/bsd/openldap/dist/servers/slapd/abandon.c (revision 549b59ed3ccf0d36d3097190a0db27b770f3a839)
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