1 /* $NetBSD: operation.c,v 1.3 2021/08/14 16:14:58 christos Exp $ */ 2 3 /* operation.c - routines to deal with pending ldap operations */ 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: operation.c,v 1.3 2021/08/14 16:14:58 christos Exp $"); 31 32 #include "portable.h" 33 34 #include <stdio.h> 35 36 #include <ac/string.h> 37 #include <ac/socket.h> 38 39 #include "slap.h" 40 41 #ifdef LDAP_SLAPI 42 #include "slapi/slapi.h" 43 #endif 44 45 static ldap_pvt_thread_mutex_t slap_op_mutex; 46 static time_t last_time; 47 static int last_incr; 48 49 void slap_op_init(void) 50 { 51 struct timeval tv; 52 ldap_pvt_thread_mutex_init( &slap_op_mutex ); 53 gettimeofday( &tv, NULL ); 54 last_time = tv.tv_sec; 55 last_incr = tv.tv_usec; 56 } 57 58 void slap_op_destroy(void) 59 { 60 ldap_pvt_thread_mutex_destroy( &slap_op_mutex ); 61 } 62 63 static void 64 slap_op_q_destroy( void *key, void *data ) 65 { 66 Operation *op, *op2; 67 for ( op = data; op; op = op2 ) { 68 op2 = LDAP_STAILQ_NEXT( op, o_next ); 69 ber_memfree_x( op, NULL ); 70 } 71 } 72 73 void 74 slap_op_groups_free( Operation *op ) 75 { 76 GroupAssertion *g, *n; 77 for ( g = op->o_groups; g; g = n ) { 78 n = g->ga_next; 79 slap_sl_free( g, op->o_tmpmemctx ); 80 } 81 op->o_groups = NULL; 82 } 83 84 void 85 slap_op_free( Operation *op, void *ctx ) 86 { 87 OperationBuffer *opbuf; 88 89 assert( LDAP_STAILQ_NEXT(op, o_next) == NULL ); 90 91 /* paranoia */ 92 op->o_abandon = 1; 93 94 if ( op->o_ber != NULL ) { 95 ber_free( op->o_ber, 1 ); 96 } 97 if ( !BER_BVISNULL( &op->o_dn ) ) { 98 ch_free( op->o_dn.bv_val ); 99 } 100 if ( !BER_BVISNULL( &op->o_ndn ) ) { 101 ch_free( op->o_ndn.bv_val ); 102 } 103 if ( !BER_BVISNULL( &op->o_authmech ) ) { 104 ch_free( op->o_authmech.bv_val ); 105 } 106 if ( op->o_ctrls != NULL ) { 107 slap_free_ctrls( op, op->o_ctrls ); 108 } 109 110 #ifdef LDAP_CONNECTIONLESS 111 if ( op->o_res_ber != NULL ) { 112 ber_free( op->o_res_ber, 1 ); 113 } 114 #endif 115 116 if ( op->o_groups ) { 117 slap_op_groups_free( op ); 118 } 119 120 #if defined( LDAP_SLAPI ) 121 if ( slapi_plugins_used ) { 122 slapi_int_free_object_extensions( SLAPI_X_EXT_OPERATION, op ); 123 } 124 #endif /* defined( LDAP_SLAPI ) */ 125 126 if ( !BER_BVISNULL( &op->o_csn ) ) { 127 op->o_tmpfree( op->o_csn.bv_val, op->o_tmpmemctx ); 128 } 129 130 if ( op->o_pagedresults_state != NULL ) { 131 op->o_tmpfree( op->o_pagedresults_state, op->o_tmpmemctx ); 132 } 133 134 /* Selectively zero out the struct. Ignore fields that will 135 * get explicitly initialized later anyway. Keep o_abandon intact. 136 */ 137 opbuf = (OperationBuffer *) op; 138 op->o_bd = NULL; 139 BER_BVZERO( &op->o_req_dn ); 140 BER_BVZERO( &op->o_req_ndn ); 141 memset( op->o_hdr, 0, sizeof( *op->o_hdr )); 142 memset( &op->o_request, 0, sizeof( op->o_request )); 143 memset( &op->o_do_not_cache, 0, sizeof( Operation ) - offsetof( Operation, o_do_not_cache )); 144 memset( opbuf->ob_controls, 0, sizeof( opbuf->ob_controls )); 145 op->o_controls = opbuf->ob_controls; 146 147 if ( ctx ) { 148 Operation *op2 = NULL; 149 ldap_pvt_thread_pool_setkey( ctx, (void *)slap_op_free, 150 op, slap_op_q_destroy, (void **)&op2, NULL ); 151 LDAP_STAILQ_NEXT( op, o_next ) = op2; 152 if ( op2 ) { 153 op->o_tincr = op2->o_tincr + 1; 154 /* No more than 10 ops on per-thread free list */ 155 if ( op->o_tincr > 10 ) { 156 ldap_pvt_thread_pool_setkey( ctx, (void *)slap_op_free, 157 op2, slap_op_q_destroy, NULL, NULL ); 158 ber_memfree_x( op, NULL ); 159 } 160 } else { 161 op->o_tincr = 1; 162 } 163 } else { 164 ber_memfree_x( op, NULL ); 165 } 166 } 167 168 void 169 slap_op_time(time_t *t, int *nop) 170 { 171 struct timeval tv; 172 ldap_pvt_thread_mutex_lock( &slap_op_mutex ); 173 gettimeofday( &tv, NULL ); 174 *t = tv.tv_sec; 175 if ( *t == last_time ) { 176 *nop = ++last_incr; 177 } else { 178 last_time = *t; 179 last_incr = 0; 180 *nop = 0; 181 } 182 ldap_pvt_thread_mutex_unlock( &slap_op_mutex ); 183 nop[1] = tv.tv_usec; 184 } 185 186 Operation * 187 slap_op_alloc( 188 BerElement *ber, 189 ber_int_t msgid, 190 ber_tag_t tag, 191 ber_int_t id, 192 void *ctx ) 193 { 194 Operation *op = NULL; 195 196 if ( ctx ) { 197 void *otmp = NULL; 198 ldap_pvt_thread_pool_getkey( ctx, (void *)slap_op_free, &otmp, NULL ); 199 if ( otmp ) { 200 op = otmp; 201 otmp = LDAP_STAILQ_NEXT( op, o_next ); 202 ldap_pvt_thread_pool_setkey( ctx, (void *)slap_op_free, 203 otmp, slap_op_q_destroy, NULL, NULL ); 204 op->o_abandon = 0; 205 op->o_cancel = 0; 206 } 207 } 208 if (!op) { 209 op = (Operation *) ch_calloc( 1, sizeof(OperationBuffer) ); 210 op->o_hdr = &((OperationBuffer *) op)->ob_hdr; 211 op->o_controls = ((OperationBuffer *) op)->ob_controls; 212 } 213 214 op->o_ber = ber; 215 op->o_msgid = msgid; 216 op->o_tag = tag; 217 218 slap_op_time( &op->o_time, &op->o_tincr ); 219 op->o_opid = id; 220 221 #if defined( LDAP_SLAPI ) 222 if ( slapi_plugins_used ) { 223 slapi_int_create_object_extensions( SLAPI_X_EXT_OPERATION, op ); 224 } 225 #endif /* defined( LDAP_SLAPI ) */ 226 227 return( op ); 228 } 229 230 slap_op_t 231 slap_req2op( ber_tag_t tag ) 232 { 233 switch ( tag ) { 234 case LDAP_REQ_BIND: 235 return SLAP_OP_BIND; 236 case LDAP_REQ_UNBIND: 237 return SLAP_OP_UNBIND; 238 case LDAP_REQ_ADD: 239 return SLAP_OP_ADD; 240 case LDAP_REQ_DELETE: 241 return SLAP_OP_DELETE; 242 case LDAP_REQ_MODRDN: 243 return SLAP_OP_MODRDN; 244 case LDAP_REQ_MODIFY: 245 return SLAP_OP_MODIFY; 246 case LDAP_REQ_COMPARE: 247 return SLAP_OP_COMPARE; 248 case LDAP_REQ_SEARCH: 249 return SLAP_OP_SEARCH; 250 case LDAP_REQ_ABANDON: 251 return SLAP_OP_ABANDON; 252 case LDAP_REQ_EXTENDED: 253 return SLAP_OP_EXTENDED; 254 } 255 256 return SLAP_OP_LAST; 257 } 258