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