1 /* $NetBSD: operation.c,v 1.1.1.3 2010/12/12 15:22:34 adam Exp $ */ 2 3 /* operation.c - routines to deal with pending ldap operations */ 4 /* OpenLDAP: pkg/ldap/servers/slapd/operation.c,v 1.75.2.11 2010/04/13 20:23:17 kurt Exp */ 5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 6 * 7 * Copyright 1998-2010 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 if ( op->o_ber != NULL ) { 85 ber_free( op->o_ber, 1 ); 86 } 87 if ( !BER_BVISNULL( &op->o_dn ) ) { 88 ch_free( op->o_dn.bv_val ); 89 } 90 if ( !BER_BVISNULL( &op->o_ndn ) ) { 91 ch_free( op->o_ndn.bv_val ); 92 } 93 if ( !BER_BVISNULL( &op->o_authmech ) ) { 94 ch_free( op->o_authmech.bv_val ); 95 } 96 if ( op->o_ctrls != NULL ) { 97 slap_free_ctrls( op, op->o_ctrls ); 98 } 99 100 #ifdef LDAP_CONNECTIONLESS 101 if ( op->o_res_ber != NULL ) { 102 ber_free( op->o_res_ber, 1 ); 103 } 104 #endif 105 106 if ( op->o_groups ) { 107 slap_op_groups_free( op ); 108 } 109 110 #if defined( LDAP_SLAPI ) 111 if ( slapi_plugins_used ) { 112 slapi_int_free_object_extensions( SLAPI_X_EXT_OPERATION, op ); 113 } 114 #endif /* defined( LDAP_SLAPI ) */ 115 116 if ( !BER_BVISNULL( &op->o_csn ) ) { 117 op->o_tmpfree( op->o_csn.bv_val, op->o_tmpmemctx ); 118 BER_BVZERO( &op->o_csn ); 119 } 120 121 opbuf = (OperationBuffer *) op; 122 memset( opbuf, 0, sizeof(*opbuf) ); 123 op->o_hdr = &opbuf->ob_hdr; 124 op->o_controls = opbuf->ob_controls; 125 126 if ( ctx ) { 127 void *op2 = NULL; 128 ldap_pvt_thread_pool_setkey( ctx, (void *)slap_op_free, 129 op, slap_op_q_destroy, &op2, NULL ); 130 LDAP_STAILQ_NEXT( op, o_next ) = op2; 131 } else { 132 ber_memfree_x( op, NULL ); 133 } 134 } 135 136 void 137 slap_op_time(time_t *t, int *nop) 138 { 139 ldap_pvt_thread_mutex_lock( &slap_op_mutex ); 140 *t = slap_get_time(); 141 if ( *t == last_time ) { 142 *nop = ++last_incr; 143 } else { 144 last_time = *t; 145 last_incr = 0; 146 *nop = 0; 147 } 148 ldap_pvt_thread_mutex_unlock( &slap_op_mutex ); 149 } 150 151 Operation * 152 slap_op_alloc( 153 BerElement *ber, 154 ber_int_t msgid, 155 ber_tag_t tag, 156 ber_int_t id, 157 void *ctx ) 158 { 159 Operation *op = NULL; 160 161 if ( ctx ) { 162 void *otmp = NULL; 163 ldap_pvt_thread_pool_getkey( ctx, (void *)slap_op_free, &otmp, NULL ); 164 if ( otmp ) { 165 op = otmp; 166 otmp = LDAP_STAILQ_NEXT( op, o_next ); 167 ldap_pvt_thread_pool_setkey( ctx, (void *)slap_op_free, 168 otmp, slap_op_q_destroy, NULL, NULL ); 169 } 170 } 171 if (!op) { 172 op = (Operation *) ch_calloc( 1, sizeof(OperationBuffer) ); 173 op->o_hdr = &((OperationBuffer *) op)->ob_hdr; 174 op->o_controls = ((OperationBuffer *) op)->ob_controls; 175 } 176 177 op->o_ber = ber; 178 op->o_msgid = msgid; 179 op->o_tag = tag; 180 181 slap_op_time( &op->o_time, &op->o_tincr ); 182 op->o_opid = id; 183 op->o_res_ber = NULL; 184 185 #if defined( LDAP_SLAPI ) 186 if ( slapi_plugins_used ) { 187 slapi_int_create_object_extensions( SLAPI_X_EXT_OPERATION, op ); 188 } 189 #endif /* defined( LDAP_SLAPI ) */ 190 191 return( op ); 192 } 193 194 slap_op_t 195 slap_req2op( ber_tag_t tag ) 196 { 197 switch ( tag ) { 198 case LDAP_REQ_BIND: 199 return SLAP_OP_BIND; 200 case LDAP_REQ_UNBIND: 201 return SLAP_OP_UNBIND; 202 case LDAP_REQ_ADD: 203 return SLAP_OP_ADD; 204 case LDAP_REQ_DELETE: 205 return SLAP_OP_DELETE; 206 case LDAP_REQ_MODRDN: 207 return SLAP_OP_MODRDN; 208 case LDAP_REQ_MODIFY: 209 return SLAP_OP_MODIFY; 210 case LDAP_REQ_COMPARE: 211 return SLAP_OP_COMPARE; 212 case LDAP_REQ_SEARCH: 213 return SLAP_OP_SEARCH; 214 case LDAP_REQ_ABANDON: 215 return SLAP_OP_ABANDON; 216 case LDAP_REQ_EXTENDED: 217 return SLAP_OP_EXTENDED; 218 } 219 220 return SLAP_OP_LAST; 221 } 222