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