1/* $OpenLDAP$ */ 2/* This work is part of OpenLDAP Software <http://www.openldap.org/>. 3 * 4 * Copyright 2000-2011 The OpenLDAP Foundation. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted only as authorized by the OpenLDAP 9 * Public License. 10 * 11 * A copy of this license is available in the file LICENSE in the 12 * top-level directory of the distribution or, alternatively, at 13 * <http://www.OpenLDAP.org/license.html>. 14 */ 15/* ACKNOWLEDGEMENT: 16 * This work was initially developed by Pierangelo Masarati for 17 * inclusion in OpenLDAP Software. 18 */ 19 20#include <portable.h> 21 22#include "rewrite-int.h" 23 24/* 25 * Compares two cookies 26 */ 27static int 28rewrite_cookie_cmp( 29 const void *c1, 30 const void *c2 31) 32{ 33 const struct rewrite_session *s1, *s2; 34 35 s1 = ( const struct rewrite_session * )c1; 36 s2 = ( const struct rewrite_session * )c2; 37 38 assert( s1 != NULL ); 39 assert( s2 != NULL ); 40 assert( s1->ls_cookie != NULL ); 41 assert( s2->ls_cookie != NULL ); 42 43 return ( ( s1->ls_cookie < s2->ls_cookie ) ? -1 : 44 ( ( s1->ls_cookie > s2->ls_cookie ) ? 1 : 0 ) ); 45} 46 47/* 48 * Duplicate cookies? 49 */ 50static int 51rewrite_cookie_dup( 52 void *c1, 53 void *c2 54) 55{ 56 struct rewrite_session *s1, *s2; 57 58 s1 = ( struct rewrite_session * )c1; 59 s2 = ( struct rewrite_session * )c2; 60 61 assert( s1 != NULL ); 62 assert( s2 != NULL ); 63 assert( s1->ls_cookie != NULL ); 64 assert( s2->ls_cookie != NULL ); 65 66 assert( s1->ls_cookie != s2->ls_cookie ); 67 68 return ( ( s1->ls_cookie == s2->ls_cookie ) ? -1 : 0 ); 69} 70 71/* 72 * Inits a session 73 */ 74struct rewrite_session * 75rewrite_session_init( 76 struct rewrite_info *info, 77 const void *cookie 78) 79{ 80 struct rewrite_session *session, tmp; 81 int rc; 82 83 assert( info != NULL ); 84 assert( cookie != NULL ); 85 86#ifdef USE_REWRITE_LDAP_PVT_THREADS 87 ldap_pvt_thread_rdwr_wlock( &info->li_cookies_mutex ); 88#endif /* USE_REWRITE_LDAP_PVT_THREADS */ 89 90 tmp.ls_cookie = ( void * )cookie; 91 session = ( struct rewrite_session * )avl_find( info->li_cookies, 92 ( caddr_t )&tmp, rewrite_cookie_cmp ); 93 if ( session ) { 94 session->ls_count++; 95#ifdef USE_REWRITE_LDAP_PVT_THREADS 96 ldap_pvt_thread_rdwr_wunlock( &info->li_cookies_mutex ); 97#endif /* USE_REWRITE_LDAP_PVT_THREADS */ 98 return session; 99 } 100 101 session = calloc( sizeof( struct rewrite_session ), 1 ); 102 if ( session == NULL ) { 103 return NULL; 104 } 105 session->ls_cookie = ( void * )cookie; 106 session->ls_count = 1; 107 108#ifdef USE_REWRITE_LDAP_PVT_THREADS 109 if ( ldap_pvt_thread_mutex_init( &session->ls_mutex ) ) { 110 free( session ); 111 return NULL; 112 } 113 if ( ldap_pvt_thread_rdwr_init( &session->ls_vars_mutex ) ) { 114 ldap_pvt_thread_mutex_destroy( &session->ls_mutex ); 115 free( session ); 116 return NULL; 117 } 118#endif /* USE_REWRITE_LDAP_PVT_THREADS */ 119 120 rc = avl_insert( &info->li_cookies, ( caddr_t )session, 121 rewrite_cookie_cmp, rewrite_cookie_dup ); 122 info->li_num_cookies++; 123 124#ifdef USE_REWRITE_LDAP_PVT_THREADS 125 ldap_pvt_thread_rdwr_wunlock( &info->li_cookies_mutex ); 126#endif /* USE_REWRITE_LDAP_PVT_THREADS */ 127 128 if ( rc != 0 ) { 129#ifdef USE_REWRITE_LDAP_PVT_THREADS 130 ldap_pvt_thread_rdwr_destroy( &session->ls_vars_mutex ); 131 ldap_pvt_thread_mutex_destroy( &session->ls_mutex ); 132#endif /* USE_REWRITE_LDAP_PVT_THREADS */ 133 134 free( session ); 135 return NULL; 136 } 137 138 return session; 139} 140 141/* 142 * Fetches a session 143 */ 144struct rewrite_session * 145rewrite_session_find( 146 struct rewrite_info *info, 147 const void *cookie 148) 149{ 150 struct rewrite_session *session, tmp; 151 152 assert( info != NULL ); 153 assert( cookie != NULL ); 154 155 tmp.ls_cookie = ( void * )cookie; 156#ifdef USE_REWRITE_LDAP_PVT_THREADS 157 ldap_pvt_thread_rdwr_rlock( &info->li_cookies_mutex ); 158#endif /* USE_REWRITE_LDAP_PVT_THREADS */ 159 session = ( struct rewrite_session * )avl_find( info->li_cookies, 160 ( caddr_t )&tmp, rewrite_cookie_cmp ); 161#ifdef USE_REWRITE_LDAP_PVT_THREADS 162 if ( session ) { 163 ldap_pvt_thread_mutex_lock( &session->ls_mutex ); 164 } 165 ldap_pvt_thread_rdwr_runlock( &info->li_cookies_mutex ); 166#endif /* USE_REWRITE_LDAP_PVT_THREADS */ 167 168 return session; 169} 170 171/* 172 * Returns a session 173 */ 174void 175rewrite_session_return( 176 struct rewrite_info *info, 177 struct rewrite_session *session 178) 179{ 180 assert( session != NULL ); 181 ldap_pvt_thread_mutex_unlock( &session->ls_mutex ); 182} 183 184/* 185 * Defines and inits a var with session scope 186 */ 187int 188rewrite_session_var_set_f( 189 struct rewrite_info *info, 190 const void *cookie, 191 const char *name, 192 const char *value, 193 int flags 194) 195{ 196 struct rewrite_session *session; 197 struct rewrite_var *var; 198 199 assert( info != NULL ); 200 assert( cookie != NULL ); 201 assert( name != NULL ); 202 assert( value != NULL ); 203 204 session = rewrite_session_find( info, cookie ); 205 if ( session == NULL ) { 206 session = rewrite_session_init( info, cookie ); 207 if ( session == NULL ) { 208 return REWRITE_ERR; 209 } 210 211#ifdef USE_REWRITE_LDAP_PVT_THREADS 212 ldap_pvt_thread_mutex_lock( &session->ls_mutex ); 213#endif /* USE_REWRITE_LDAP_PVT_THREADS */ 214 } 215 216#ifdef USE_REWRITE_LDAP_PVT_THREADS 217 ldap_pvt_thread_rdwr_wlock( &session->ls_vars_mutex ); 218#endif /* USE_REWRITE_LDAP_PVT_THREADS */ 219 220 var = rewrite_var_find( session->ls_vars, name ); 221 if ( var != NULL ) { 222 assert( var->lv_value.bv_val != NULL ); 223 224 (void)rewrite_var_replace( var, value, flags ); 225 226 } else { 227 var = rewrite_var_insert_f( &session->ls_vars, name, value, flags ); 228 if ( var == NULL ) { 229#ifdef USE_REWRITE_LDAP_PVT_THREADS 230 ldap_pvt_thread_rdwr_wunlock( &session->ls_vars_mutex ); 231#endif /* USE_REWRITE_LDAP_PVT_THREADS */ 232 rewrite_session_return( info, session ); 233 return REWRITE_ERR; 234 } 235 } 236 237#ifdef USE_REWRITE_LDAP_PVT_THREADS 238 ldap_pvt_thread_rdwr_wunlock( &session->ls_vars_mutex ); 239#endif /* USE_REWRITE_LDAP_PVT_THREADS */ 240 241 rewrite_session_return( info, session ); 242 243 return REWRITE_SUCCESS; 244} 245 246/* 247 * Gets a var with session scope 248 */ 249int 250rewrite_session_var_get( 251 struct rewrite_info *info, 252 const void *cookie, 253 const char *name, 254 struct berval *value 255) 256{ 257 struct rewrite_session *session; 258 struct rewrite_var *var; 259 int rc = REWRITE_SUCCESS; 260 261 assert( info != NULL ); 262 assert( cookie != NULL ); 263 assert( name != NULL ); 264 assert( value != NULL ); 265 266 value->bv_val = NULL; 267 value->bv_len = 0; 268 269 if ( cookie == NULL ) { 270 return REWRITE_ERR; 271 } 272 273 session = rewrite_session_find( info, cookie ); 274 if ( session == NULL ) { 275 return REWRITE_ERR; 276 } 277 278#ifdef USE_REWRITE_LDAP_PVT_THREADS 279 ldap_pvt_thread_rdwr_rlock( &session->ls_vars_mutex ); 280#endif /* USE_REWRITE_LDAP_PVT_THREADS */ 281 282 var = rewrite_var_find( session->ls_vars, name ); 283 if ( var != NULL ) { 284 value->bv_val = strdup( var->lv_value.bv_val ); 285 value->bv_len = var->lv_value.bv_len; 286 } 287 288 if ( var == NULL || value->bv_val == NULL ) { 289 rc = REWRITE_ERR; 290 } 291 292#ifdef USE_REWRITE_LDAP_PVT_THREADS 293 ldap_pvt_thread_rdwr_runlock( &session->ls_vars_mutex ); 294#endif /* USE_REWRITE_LDAP_PVT_THREADS */ 295 296 rewrite_session_return( info, session ); 297 298 return rc; 299} 300 301static void 302rewrite_session_clean( void *v_session ) 303{ 304 struct rewrite_session *session = (struct rewrite_session *)v_session; 305 306#ifdef USE_REWRITE_LDAP_PVT_THREADS 307 ldap_pvt_thread_rdwr_wlock( &session->ls_vars_mutex ); 308#endif /* USE_REWRITE_LDAP_PVT_THREADS */ 309 310 rewrite_var_delete( session->ls_vars ); 311 312#ifdef USE_REWRITE_LDAP_PVT_THREADS 313 ldap_pvt_thread_rdwr_wunlock( &session->ls_vars_mutex ); 314 ldap_pvt_thread_rdwr_destroy( &session->ls_vars_mutex ); 315 ldap_pvt_thread_mutex_unlock( &session->ls_mutex ); 316 ldap_pvt_thread_mutex_destroy( &session->ls_mutex ); 317#endif /* USE_REWRITE_LDAP_PVT_THREADS */ 318} 319 320static void 321rewrite_session_free( void *v_session ) 322{ 323 struct rewrite_session *session = (struct rewrite_session *)v_session; 324 325 ldap_pvt_thread_mutex_lock( &session->ls_mutex ); 326 rewrite_session_clean( v_session ); 327 free( v_session ); 328} 329 330/* 331 * Deletes a session 332 */ 333int 334rewrite_session_delete( 335 struct rewrite_info *info, 336 const void *cookie 337) 338{ 339 struct rewrite_session *session, tmp = { 0 }; 340 341 assert( info != NULL ); 342 assert( cookie != NULL ); 343 344 session = rewrite_session_find( info, cookie ); 345 346 if ( session == NULL ) { 347 return REWRITE_SUCCESS; 348 } 349 350 if ( --session->ls_count > 0 ) { 351 rewrite_session_return( info, session ); 352 return REWRITE_SUCCESS; 353 } 354 355 rewrite_session_clean( session ); 356 357#ifdef USE_REWRITE_LDAP_PVT_THREADS 358 ldap_pvt_thread_rdwr_wlock( &info->li_cookies_mutex ); 359#endif /* USE_REWRITE_LDAP_PVT_THREADS */ 360 361 assert( info->li_num_cookies > 0 ); 362 info->li_num_cookies--; 363 364 /* 365 * There is nothing to delete in the return value 366 */ 367 tmp.ls_cookie = ( void * )cookie; 368 avl_delete( &info->li_cookies, ( caddr_t )&tmp, rewrite_cookie_cmp ); 369 370 free( session ); 371 372#ifdef USE_REWRITE_LDAP_PVT_THREADS 373 ldap_pvt_thread_rdwr_wunlock( &info->li_cookies_mutex ); 374#endif /* USE_REWRITE_LDAP_PVT_THREADS */ 375 376 return REWRITE_SUCCESS; 377} 378 379/* 380 * Destroys the cookie tree 381 */ 382int 383rewrite_session_destroy( 384 struct rewrite_info *info 385) 386{ 387 int count; 388 389 assert( info != NULL ); 390 391#ifdef USE_REWRITE_LDAP_PVT_THREADS 392 ldap_pvt_thread_rdwr_wlock( &info->li_cookies_mutex ); 393#endif /* USE_REWRITE_LDAP_PVT_THREADS */ 394 395 /* 396 * Should call per-session destruction routine ... 397 */ 398 399 count = avl_free( info->li_cookies, rewrite_session_free ); 400 info->li_cookies = NULL; 401 402#if 0 403 fprintf( stderr, "count = %d; num_cookies = %d\n", 404 count, info->li_num_cookies ); 405#endif 406 407 assert( count == info->li_num_cookies ); 408 info->li_num_cookies = 0; 409 410#ifdef USE_REWRITE_LDAP_PVT_THREADS 411 ldap_pvt_thread_rdwr_wunlock( &info->li_cookies_mutex ); 412#endif /* USE_REWRITE_LDAP_PVT_THREADS */ 413 414 return REWRITE_SUCCESS; 415} 416 417