You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
kamailio/modules/tls/tls_locking.c

181 lines
4.3 KiB

/*
* $Id$
*
* Copyright (C) 2007 iptelorg GmbH
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
* tls locking and atomic ops related init functions
*
* History:
* --------
* 2007-01-22 created by andrei
*/
/*!
* \file
* \brief SIP-router TLS support :: Locking
* \ingroup tls
* Module: \ref tls
*/
#include <stdlib.h> /* abort() */
#include <openssl/crypto.h>
#include "../../dprint.h"
#include "../../locking.h"
static int n_static_locks=0;
static gen_lock_set_t* static_locks=0;
/* "dynamic" locks */
struct CRYPTO_dynlock_value{
gen_lock_t lock;
};
static struct CRYPTO_dynlock_value* dyn_create_f(const char* file, int line)
{
struct CRYPTO_dynlock_value* l;
l=shm_malloc(sizeof(struct CRYPTO_dynlock_value));
if (l==0){
LOG(L_CRIT, "ERROR: tls: dyn_create_f locking callback out of shm."
" memory (called from %s:%d)\n", file, line);
goto error;
}
if (lock_init(&l->lock)==0){
LOG(L_CRIT, "ERROR: tls: dyn_create_f locking callback: lock "
"initialization failed (called from %s:%d)\n", file, line);
shm_free(l);
goto error;
}
return l;
error:
return 0;
}
static void dyn_lock_f(int mode, struct CRYPTO_dynlock_value* l,
const char* file, int line)
{
if (l==0){
LOG(L_CRIT, "BUG: tls: dyn_lock_f locking callback: null lock"
" (called from %s:%d)\n", file, line);
/* try to continue */
return;
}
if (mode & CRYPTO_LOCK){
lock_get(&l->lock);
}else{
lock_release(&l->lock);
}
}
static void dyn_destroy_f(struct CRYPTO_dynlock_value *l,
const char* file, int line)
{
if (l==0){
LOG(L_CRIT, "BUG: tls: dyn_destroy_f locking callback: null lock"
" (called from %s:%d)\n", file, line);
return;
}
lock_destroy(&l->lock);
shm_free(l);
}
/* normal locking callback */
static void locking_f(int mode, int n, const char* file, int line)
{
if (n<0 || n>=n_static_locks){
LOG(L_CRIT, "BUG: tls: locking_f (callback): invalid lock number: "
" %d (range 0 - %d), called from %s:%d\n",
n, n_static_locks, file, line);
abort(); /* quick crash :-) */
}
if (mode & CRYPTO_LOCK){
lock_set_get(static_locks, n);
}else{
lock_set_release(static_locks, n);
}
}
void tls_destroy_locks()
{
if (static_locks){
lock_set_destroy(static_locks);
lock_set_dealloc(static_locks);
static_locks=0;
n_static_locks=0;
}
}
/* returns -1 on error, 0 on success */
int tls_init_locks()
{
/* init "static" tls locks */
n_static_locks=CRYPTO_num_locks();
if (n_static_locks<0){
LOG(L_CRIT, "BUG: tls: tls_init_locking: bad CRYPTO_num_locks %d\n",
n_static_locks);
n_static_locks=0;
}
if (n_static_locks){
static_locks=lock_set_alloc(n_static_locks);
if (static_locks==0){
LOG(L_CRIT, "ERROR: tls_init_locking: could not allocate lockset"
" with %d locks\n", n_static_locks);
goto error;
}
if (lock_set_init(static_locks)==0){
LOG(L_CRIT, "ERROR: tls_init_locking: lock_set_init failed "
"(%d locks)\n", n_static_locks);
lock_set_dealloc(static_locks);
static_locks=0;
n_static_locks=0;
goto error;
}
CRYPTO_set_locking_callback(locking_f);
}
/* set "dynamic" locks callbacks */
CRYPTO_set_dynlock_create_callback(dyn_create_f);
CRYPTO_set_dynlock_lock_callback(dyn_lock_f);
CRYPTO_set_dynlock_destroy_callback(dyn_destroy_f);
/* thread id callback: not needed because ser doesn't use thread and
* openssl already uses getpid() (by default)
* CRYPTO_set_id_callback(id_f);
*/
/* atomic add -- since for now we don't have atomic_add
* (only atomic_inc), fallback to the default use-locks mode
* CRYPTO_set_add_lock_callback(atomic_add_f);
*/
return 0;
error:
tls_destroy_locks();
return -1;
}