1 /* operation.c - routines to deal with pending ldap operations */ 2 /* $OpenLDAP: pkg/ldap/servers/slapd/operation.c,v 1.75.2.8 2008/02/12 20:48:44 quanah Exp $ */ 3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 4 * 5 * Copyright 1998-2008 The OpenLDAP Foundation. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted only as authorized by the OpenLDAP 10 * Public License. 11 * 12 * A copy of this license is available in the file LICENSE in the 13 * top-level directory of the distribution or, alternatively, at 14 * <http://www.OpenLDAP.org/license.html>. 15 */ 16 /* Portions Copyright (c) 1995 Regents of the University of Michigan. 17 * All rights reserved. 18 * 19 * Redistribution and use in source and binary forms are permitted 20 * provided that this notice is preserved and that due credit is given 21 * to the University of Michigan at Ann Arbor. The name of the University 22 * may not be used to endorse or promote products derived from this 23 * software without specific prior written permission. This software 24 * is provided ``as is'' without express or implied warranty. 25 */ 26 27 #include "portable.h" 28 29 #include <stdio.h> 30 31 #include <ac/string.h> 32 #include <ac/socket.h> 33 34 #include "slap.h" 35 36 #ifdef LDAP_SLAPI 37 #include "slapi/slapi.h" 38 #endif 39 40 static ldap_pvt_thread_mutex_t slap_op_mutex; 41 static time_t last_time; 42 static int last_incr; 43 44 void slap_op_init(void) 45 { 46 ldap_pvt_thread_mutex_init( &slap_op_mutex ); 47 } 48 49 void slap_op_destroy(void) 50 { 51 ldap_pvt_thread_mutex_destroy( &slap_op_mutex ); 52 } 53 54 static void 55 slap_op_q_destroy( void *key, void *data ) 56 { 57 Operation *op, *op2; 58 for ( op = data; op; op = op2 ) { 59 op2 = LDAP_STAILQ_NEXT( op, o_next ); 60 ber_memfree_x( op, NULL ); 61 } 62 } 63 64 void 65 slap_op_groups_free( Operation *op ) 66 { 67 GroupAssertion *g, *n; 68 for ( g = op->o_groups; g; g = n ) { 69 n = g->ga_next; 70 slap_sl_free( g, op->o_tmpmemctx ); 71 } 72 op->o_groups = NULL; 73 } 74 75 void 76 slap_op_free( Operation *op, void *ctx ) 77 { 78 OperationBuffer *opbuf; 79 80 assert( LDAP_STAILQ_NEXT(op, o_next) == NULL ); 81 82 if ( op->o_ber != NULL ) { 83 ber_free( op->o_ber, 1 ); 84 } 85 if ( !BER_BVISNULL( &op->o_dn ) ) { 86 ch_free( op->o_dn.bv_val ); 87 } 88 if ( !BER_BVISNULL( &op->o_ndn ) ) { 89 ch_free( op->o_ndn.bv_val ); 90 } 91 if ( !BER_BVISNULL( &op->o_authmech ) ) { 92 ch_free( op->o_authmech.bv_val ); 93 } 94 if ( op->o_ctrls != NULL ) { 95 slap_free_ctrls( op, op->o_ctrls ); 96 } 97 98 #ifdef LDAP_CONNECTIONLESS 99 if ( op->o_res_ber != NULL ) { 100 ber_free( op->o_res_ber, 1 ); 101 } 102 #endif 103 104 if ( op->o_groups ) { 105 slap_op_groups_free( op ); 106 } 107 108 #if defined( LDAP_SLAPI ) 109 if ( slapi_plugins_used ) { 110 slapi_int_free_object_extensions( SLAPI_X_EXT_OPERATION, op ); 111 } 112 #endif /* defined( LDAP_SLAPI ) */ 113 114 opbuf = (OperationBuffer *) op; 115 memset( opbuf, 0, sizeof(*opbuf) ); 116 op->o_hdr = &opbuf->ob_hdr; 117 op->o_controls = opbuf->ob_controls; 118 119 if ( ctx ) { 120 void *op2 = NULL; 121 ldap_pvt_thread_pool_setkey( ctx, (void *)slap_op_free, 122 op, slap_op_q_destroy, &op2, NULL ); 123 LDAP_STAILQ_NEXT( op, o_next ) = op2; 124 } else { 125 ber_memfree_x( op, NULL ); 126 } 127 } 128 129 void 130 slap_op_time(time_t *t, int *nop) 131 { 132 ldap_pvt_thread_mutex_lock( &slap_op_mutex ); 133 *t = slap_get_time(); 134 if ( *t == last_time ) { 135 *nop = ++last_incr; 136 } else { 137 last_time = *t; 138 last_incr = 0; 139 *nop = 0; 140 } 141 ldap_pvt_thread_mutex_unlock( &slap_op_mutex ); 142 } 143 144 Operation * 145 slap_op_alloc( 146 BerElement *ber, 147 ber_int_t msgid, 148 ber_tag_t tag, 149 ber_int_t id, 150 void *ctx ) 151 { 152 Operation *op = NULL; 153 154 if ( ctx ) { 155 void *otmp = NULL; 156 ldap_pvt_thread_pool_getkey( ctx, (void *)slap_op_free, &otmp, NULL ); 157 if ( otmp ) { 158 op = otmp; 159 otmp = LDAP_STAILQ_NEXT( op, o_next ); 160 ldap_pvt_thread_pool_setkey( ctx, (void *)slap_op_free, 161 otmp, slap_op_q_destroy, NULL, NULL ); 162 } 163 } 164 if (!op) { 165 op = (Operation *) ch_calloc( 1, sizeof(OperationBuffer) ); 166 op->o_hdr = &((OperationBuffer *) op)->ob_hdr; 167 op->o_controls = ((OperationBuffer *) op)->ob_controls; 168 } 169 170 op->o_ber = ber; 171 op->o_msgid = msgid; 172 op->o_tag = tag; 173 174 slap_op_time( &op->o_time, &op->o_tincr ); 175 op->o_opid = id; 176 op->o_res_ber = NULL; 177 178 #if defined( LDAP_SLAPI ) 179 if ( slapi_plugins_used ) { 180 slapi_int_create_object_extensions( SLAPI_X_EXT_OPERATION, op ); 181 } 182 #endif /* defined( LDAP_SLAPI ) */ 183 184 return( op ); 185 } 186 187 slap_op_t 188 slap_req2op( ber_tag_t tag ) 189 { 190 switch ( tag ) { 191 case LDAP_REQ_BIND: 192 return SLAP_OP_BIND; 193 case LDAP_REQ_UNBIND: 194 return SLAP_OP_UNBIND; 195 case LDAP_REQ_ADD: 196 return SLAP_OP_ADD; 197 case LDAP_REQ_DELETE: 198 return SLAP_OP_DELETE; 199 case LDAP_REQ_MODRDN: 200 return SLAP_OP_MODRDN; 201 case LDAP_REQ_MODIFY: 202 return SLAP_OP_MODIFY; 203 case LDAP_REQ_COMPARE: 204 return SLAP_OP_COMPARE; 205 case LDAP_REQ_SEARCH: 206 return SLAP_OP_SEARCH; 207 case LDAP_REQ_ABANDON: 208 return SLAP_OP_ABANDON; 209 case LDAP_REQ_EXTENDED: 210 return SLAP_OP_EXTENDED; 211 } 212 213 return SLAP_OP_LAST; 214 } 215