From 0c43007e554d2427ae97d3592e2b4d4a30e96051 Mon Sep 17 00:00:00 2001 From: Jong Hyuk Choi Date: Sat, 25 Jan 2003 00:36:50 +0000 Subject: [PATCH] LDAP cancel operation --- include/ldap.h | 11 +++ libraries/libldap/Makefile.in | 6 +- libraries/libldap/cancel.c | 61 +++++++++++++++++ servers/slapd/Makefile.in | 4 +- servers/slapd/back-bdb/search.c | 9 +++ servers/slapd/backend.c | 7 ++ servers/slapd/cancel.c | 114 ++++++++++++++++++++++++++++++++ servers/slapd/connection.c | 9 +++ servers/slapd/extended.c | 1 + servers/slapd/proto-slap.h | 5 ++ servers/slapd/slap.h | 1 + servers/slapd/tools/Makefile.in | 3 +- 12 files changed, 226 insertions(+), 5 deletions(-) create mode 100644 libraries/libldap/cancel.c create mode 100644 servers/slapd/cancel.c diff --git a/include/ldap.h b/include/ldap.h index 3df4fb536a..0686ca17c9 100644 --- a/include/ldap.h +++ b/include/ldap.h @@ -486,6 +486,17 @@ typedef struct ldapcontrol { #define LDAP_CUP_DEFAULT_SEND_COOKIE_INTERVAL 0x01 #endif /* LDAP_CLIENT_UPDATE */ +/* resultCode for Cancel Response */ +#define LDAP_CANCELLED 0x68 +#define LDAP_NO_SUCH_OPERATION 0x69 +#define LDAP_TOO_LATE 0x6a +#define LDAP_CANNOT_CANCEL 0x6b + +#define LDAP_CANCEL_NONE 0x00 +#define LDAP_CANCEL_REQ 0x01 +#define LDAP_CANCEL_ACK 0x02 +#define LDAP_CANCEL_NOTDONE 0x03 + /* * This structure represents both ldap messages and ldap responses. * These are really the same, except in the case of search responses, diff --git a/libraries/libldap/Makefile.in b/libraries/libldap/Makefile.in index f8962fcb3f..e624abce16 100644 --- a/libraries/libldap/Makefile.in +++ b/libraries/libldap/Makefile.in @@ -16,7 +16,8 @@ SRCS = bind.c open.c result.c error.c compare.c search.c \ getdn.c getentry.c getattr.c getvalues.c addentry.c \ request.c os-ip.c url.c sortctrl.c vlvctrl.c \ init.c options.c print.c string.c util-int.c schema.c \ - charray.c tls.c os-local.c dnssrv.c utf-8.c utf-8-conv.c + charray.c tls.c os-local.c dnssrv.c utf-8.c utf-8-conv.c \ + cancel.c OBJS = bind.lo open.lo result.lo error.lo compare.lo search.lo \ controls.lo messages.lo references.lo extended.lo cyrus.lo \ modify.lo add.lo modrdn.lo delete.lo abandon.lo cache.lo \ @@ -25,7 +26,8 @@ OBJS = bind.lo open.lo result.lo error.lo compare.lo search.lo \ getdn.lo getentry.lo getattr.lo getvalues.lo addentry.lo \ request.lo os-ip.lo url.lo sortctrl.lo vlvctrl.lo \ init.lo options.lo print.lo string.lo util-int.lo schema.lo \ - charray.lo tls.lo os-local.lo dnssrv.lo utf-8.lo utf-8-conv.lo + charray.lo tls.lo os-local.lo dnssrv.lo utf-8.lo utf-8-conv.lo \ + cancel.lo LDAP_INCDIR= ../../include LDAP_LIBDIR= ../../libraries diff --git a/libraries/libldap/cancel.c b/libraries/libldap/cancel.c new file mode 100644 index 0000000000..6b8aeac7f2 --- /dev/null +++ b/libraries/libldap/cancel.c @@ -0,0 +1,61 @@ +/* + * Copyright 1998-2003 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ + +/* + * LDAPv3 Cancel Operation Request + */ + +#include "portable.h" + +#include +#include + +#include +#include +#include + +#include "ldap-int.h" +#include "ldap_log.h" + +int +ldap_cancel( + LDAP *ld, + int cancelid, + LDAPControl **sctrls, + LDAPControl **cctrls, + int *msgidp ) +{ + BerElement *cancelidber = NULL; + struct berval *cancelidvalp = NULL; + int rc; + + cancelidber = ber_alloc_t( LBER_USE_DER ); + ber_printf( cancelidber, "{i}", cancelid ); + ber_flatten( cancelidber, &cancelidvalp ); + rc = ldap_extended_operation( ld, LDAP_EXOP_X_CANCEL, + cancelidvalp, sctrls, cctrls, msgidp ); + ber_free( cancelidber, 1 ); + return rc; +} + +int +ldap_cancel_s( + LDAP *ld, + int cancelid, + LDAPControl **sctrls, + LDAPControl **cctrls ) +{ + BerElement *cancelidber = NULL; + struct berval *cancelidvalp = NULL; + int rc; + + cancelidber = ber_alloc_t( LBER_USE_DER ); + ber_printf( cancelidber, "{i}", cancelid ); + ber_flatten( cancelidber, &cancelidvalp ); + rc = ldap_extended_operation_s( ld, LDAP_EXOP_X_CANCEL, + cancelidvalp, sctrls, cctrls, NULL, NULL ); + ber_free( cancelidber, 1 ); + return rc; +} diff --git a/servers/slapd/Makefile.in b/servers/slapd/Makefile.in index 97e773f031..42d4024637 100644 --- a/servers/slapd/Makefile.in +++ b/servers/slapd/Makefile.in @@ -19,7 +19,7 @@ SRCS = main.c daemon.c connection.c search.c filter.c add.c cr.c \ schemaparse.c ad.c at.c mr.c syntax.c oc.c saslauthz.c \ oidm.c starttls.c index.c sets.c referral.c \ root_dse.c sasl.c module.c suffixalias.c mra.c mods.c \ - limits.c backglue.c operational.c matchedValues.c \ + limits.c backglue.c operational.c matchedValues.c cancel.c \ $(@PLAT@_SRCS) OBJS = main.o daemon.o connection.o search.o filter.o add.o cr.o \ @@ -32,7 +32,7 @@ OBJS = main.o daemon.o connection.o search.o filter.o add.o cr.o \ schemaparse.o ad.o at.o mr.o syntax.o oc.o saslauthz.o \ oidm.o starttls.o index.o sets.o referral.o \ root_dse.o sasl.o module.o suffixalias.o mra.o mods.o \ - limits.o backglue.o operational.o matchedValues.o \ + limits.o backglue.o operational.o matchedValues.o cancel.o \ $(@PLAT@_OBJS) LDAP_INCDIR= ../../include -Islapi diff --git a/servers/slapd/back-bdb/search.c b/servers/slapd/back-bdb/search.c index f85c8b5c09..9916cdb22e 100644 --- a/servers/slapd/back-bdb/search.c +++ b/servers/slapd/back-bdb/search.c @@ -433,6 +433,15 @@ loop_begin: goto done; } + if ( op->o_cancel ) { + assert( op->o_cancel == LDAP_CANCEL_REQ ); + rc = 0; + send_search_result( conn, op, LDAP_CANCELLED, + NULL, NULL, NULL, NULL, 0 ); + op->o_cancel = LDAP_CANCEL_ACK; + goto done; + } + /* check time limit */ if ( tlimit != -1 && slap_get_time() > stoptime ) { send_search_result( conn, op, rc = LDAP_TIMELIMIT_EXCEEDED, diff --git a/servers/slapd/backend.c b/servers/slapd/backend.c index 7d3aea77e3..6ef6f33ff6 100644 --- a/servers/slapd/backend.c +++ b/servers/slapd/backend.c @@ -870,6 +870,13 @@ backend_check_restrictions( } } + { + struct berval bv = BER_BVC( LDAP_EXOP_X_CANCEL ); + if ( bvmatch( opdata, &bv ) ) { + break; + } + } + /* treat everything else as a modify */ opflag = SLAP_RESTRICT_OP_MODIFY; updateop++; diff --git a/servers/slapd/cancel.c b/servers/slapd/cancel.c new file mode 100644 index 0000000000..96bd7300b5 --- /dev/null +++ b/servers/slapd/cancel.c @@ -0,0 +1,114 @@ +/* cancel.c - LDAP cancel extended operation */ +/* + * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ + +#include "portable.h" + +#include + +#include +#include +#include +#include + +#include "slap.h" + +#include +#include + +int cancel_extop( + Connection *conn, + Operation *op, + const char *reqoid, + struct berval *reqdata, + char **rspoid, + struct berval **rspdata, + LDAPControl ***rspctrls, + const char **text, + BerVarray *refs ) +{ + Backend *be; + int rc; + int found = 0; + int opid; + BerElement *ber; + + assert( reqoid != NULL ); + assert( strcmp( LDAP_EXOP_X_CANCEL, reqoid ) == 0 ); + + if ( reqdata == NULL ) { + *text = "no message ID supplied"; + return LDAP_PROTOCOL_ERROR; + } + + ber = ber_init( reqdata ); + if ( ber == NULL ) { + *text = "internal error"; + return LDAP_OTHER; + } + + if ( ber_scanf( ber, "{i}", &opid ) == LBER_ERROR ) { + *text = "message ID parse failed"; + return LDAP_PROTOCOL_ERROR; + } + + (void) ber_free( ber, 1 ); + + if ( opid < 0 ) { + *text = "message ID invalid"; + return LDAP_PROTOCOL_ERROR; + } + + ldap_pvt_thread_mutex_lock( &conn->c_mutex ); + LDAP_STAILQ_FOREACH( op, &conn->c_pending_ops, o_next ) { + if ( op->o_msgid == opid ) { + LDAP_STAILQ_REMOVE( &conn->c_pending_ops, op, slap_op, o_next ); + slap_op_free( op ); + found = 1; + break; + } + } + ldap_pvt_thread_mutex_unlock( &conn->c_mutex ); + + if ( found ) + return LDAP_SUCCESS; + + found = 0; + ldap_pvt_thread_mutex_lock( &conn->c_mutex ); + LDAP_STAILQ_FOREACH( op, &conn->c_ops, o_next ) { + if ( op->o_msgid == opid ) { + found = 1; + break; + } + } + + if ( !found ) { + *text = "message ID not found"; + ldap_pvt_thread_mutex_unlock( &conn->c_mutex ); + return LDAP_NO_SUCH_OPERATION; + } + + if ( op->o_cancel != LDAP_CANCEL_NONE ) { + *text = "message ID already being cancelled"; + ldap_pvt_thread_mutex_unlock( &conn->c_mutex ); + return LDAP_PROTOCOL_ERROR; + } + + op->o_cancel = LDAP_CANCEL_REQ; + ldap_pvt_thread_mutex_unlock( &conn->c_mutex ); + + while ( op->o_cancel == LDAP_CANCEL_REQ ) { + ldap_pvt_thread_yield(); + } + + if ( op->o_cancel == LDAP_CANCEL_ACK ) { + rc = LDAP_SUCCESS; + } else { + rc = op->o_cancel; + op->o_cancel = LDAP_CANCEL_NOTDONE; + } + + return rc; +} diff --git a/servers/slapd/connection.c b/servers/slapd/connection.c index 06abd15472..ba8d419836 100644 --- a/servers/slapd/connection.c +++ b/servers/slapd/connection.c @@ -1024,6 +1024,15 @@ operations_error: #endif /* SLAPD_MONITOR */ ldap_pvt_thread_mutex_unlock( &num_ops_mutex ); + if ( arg->co_op->o_cancel == LDAP_CANCEL_REQ ) + arg->co_op->o_cancel = LDAP_TOO_LATE; + + while ( arg->co_op->o_cancel != LDAP_CANCEL_NONE && + arg->co_op->o_cancel != LDAP_CANCEL_ACK && + arg->co_op->o_cancel != LDAP_CANCEL_NOTDONE ) { + ldap_pvt_thread_yield(); + } + ldap_pvt_thread_mutex_lock( &conn->c_mutex ); conn->c_n_ops_executing--; diff --git a/servers/slapd/extended.c b/servers/slapd/extended.c index b658f215de..d9e70ed4cc 100644 --- a/servers/slapd/extended.c +++ b/servers/slapd/extended.c @@ -64,6 +64,7 @@ static struct { #endif { BVC(LDAP_EXOP_MODIFY_PASSWD), passwd_extop }, { BVC(LDAP_EXOP_X_WHO_AM_I), whoami_extop }, + { BVC(LDAP_EXOP_X_CANCEL), cancel_extop }, { {0,NULL}, NULL } }; diff --git a/servers/slapd/proto-slap.h b/servers/slapd/proto-slap.h index cab27a8eb8..51f1c1eb86 100644 --- a/servers/slapd/proto-slap.h +++ b/servers/slapd/proto-slap.h @@ -474,6 +474,11 @@ LDAP_SLAPD_F (int) extops_kill LDAP_P(( void )); LDAP_SLAPD_F (struct berval *) get_supported_extop LDAP_P((int index)); +/* + * * cancel.c + * */ +LDAP_SLAPD_F ( SLAP_EXTOP_MAIN_FN ) cancel_extop; + /* * filter.c */ diff --git a/servers/slapd/slap.h b/servers/slapd/slap.h index 9ba350adc0..791f91f02f 100644 --- a/servers/slapd/slap.h +++ b/servers/slapd/slap.h @@ -1661,6 +1661,7 @@ typedef struct slap_op { ldap_pvt_thread_t o_tid; /* thread handling this op */ volatile sig_atomic_t o_abandon; /* abandon flag */ + volatile sig_atomic_t o_cancel; /* cancel flag */ char o_do_not_cache; /* don't cache from this op */ diff --git a/servers/slapd/tools/Makefile.in b/servers/slapd/tools/Makefile.in index c47e38afb4..70eaff2304 100644 --- a/servers/slapd/tools/Makefile.in +++ b/servers/slapd/tools/Makefile.in @@ -45,7 +45,8 @@ SLAPD_OBJS = ../config.o ../ch_malloc.o ../cr.o ../backend.o \ ../entry.o ../dn.o ../filter.o ../str2filter.o ../ava.o \ ../init.o ../controls.o ../kerberos.o ../passwd.o \ ../index.o ../extended.o ../starttls.o ../sets.o ../mra.o \ - ../referral.o ../backglue.o ../oidm.o ../mods.o ../operation.o + ../referral.o ../backglue.o ../oidm.o ../mods.o ../operation.o \ + ../cancel.o SLAPOBJS = $(SLAPD_OBJS) slapcommon.o mimic.o -- 2.39.5