summaryrefslogtreecommitdiff
path: root/src/libstrongswan
diff options
context:
space:
mode:
authorRene Mayrhofer <rene@mayrhofer.eu.org>2008-12-05 16:15:54 +0000
committerRene Mayrhofer <rene@mayrhofer.eu.org>2008-12-05 16:15:54 +0000
commitc7f1b0530b85bc7654e68992f25ed8ced5d0a80d (patch)
tree861798cd7da646014ed6919766b053099646710d /src/libstrongswan
parent8b80ab5a6950ce6515f477624794defd7531642a (diff)
downloadvyos-strongswan-c7f1b0530b85bc7654e68992f25ed8ced5d0a80d.tar.gz
vyos-strongswan-c7f1b0530b85bc7654e68992f25ed8ced5d0a80d.zip
[svn-upgrade] Integrating new upstream version, strongswan (4.2.9)
Diffstat (limited to 'src/libstrongswan')
-rw-r--r--src/libstrongswan/Makefile.am13
-rw-r--r--src/libstrongswan/Makefile.in88
-rw-r--r--src/libstrongswan/crypto/crypters/crypter.h2
-rw-r--r--src/libstrongswan/crypto/crypto_factory.c86
-rw-r--r--src/libstrongswan/crypto/diffie_hellman.h12
-rw-r--r--src/libstrongswan/crypto/prf_plus.c15
-rw-r--r--src/libstrongswan/fetcher/fetcher_manager.c24
-rw-r--r--src/libstrongswan/plugins/agent/agent_private_key.c38
-rw-r--r--src/libstrongswan/plugins/curl/curl_fetcher.c4
-rw-r--r--src/libstrongswan/plugins/gmp/gmp_diffie_hellman.c68
-rw-r--r--src/libstrongswan/plugins/openssl/openssl_diffie_hellman.c115
-rw-r--r--src/libstrongswan/plugins/openssl/openssl_ec_diffie_hellman.c21
-rw-r--r--src/libstrongswan/plugins/openssl/openssl_plugin.c124
-rw-r--r--src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c21
-rw-r--r--src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c10
-rw-r--r--src/libstrongswan/plugins/x509/x509_ac.c2
-rw-r--r--src/libstrongswan/plugins/x509/x509_cert.c3
-rw-r--r--src/libstrongswan/plugins/x509/x509_crl.c4
-rw-r--r--src/libstrongswan/settings.c120
-rw-r--r--src/libstrongswan/settings.h50
-rw-r--r--src/libstrongswan/utils.h7
-rw-r--r--src/libstrongswan/utils/backtrace.c183
-rw-r--r--src/libstrongswan/utils/backtrace.h63
-rw-r--r--src/libstrongswan/utils/host.c139
-rw-r--r--src/libstrongswan/utils/host.h6
-rw-r--r--src/libstrongswan/utils/iterator.h57
-rw-r--r--src/libstrongswan/utils/leak_detective.c155
-rw-r--r--src/libstrongswan/utils/leak_detective.h5
-rw-r--r--src/libstrongswan/utils/linked_list.c113
-rw-r--r--src/libstrongswan/utils/linked_list.h29
-rw-r--r--src/libstrongswan/utils/mutex.c280
-rw-r--r--src/libstrongswan/utils/mutex.h53
32 files changed, 1231 insertions, 679 deletions
diff --git a/src/libstrongswan/Makefile.am b/src/libstrongswan/Makefile.am
index 08409d503..1423db5c3 100644
--- a/src/libstrongswan/Makefile.am
+++ b/src/libstrongswan/Makefile.am
@@ -50,6 +50,7 @@ utils/linked_list.c utils/linked_list.h \
utils/enumerator.c utils/enumerator.h \
utils/optionsfrom.c utils/optionsfrom.h \
utils/mutex.c utils/mutex.h \
+utils/backtrace.c utils/backtrace.h \
plugins/plugin_loader.c plugins/plugin_loader.h plugins/plugin.h
libstrongswan_la_LIBADD = -lpthread -ldl
@@ -63,6 +64,10 @@ if USE_LEAK_DETECTIVE
libstrongswan_la_SOURCES += utils/leak_detective.c utils/leak_detective.h
endif
+if USE_LOCK_PROFILER
+ AM_CFLAGS += -DLOCK_PROFILER
+endif
+
if USE_INTEGRITY_TEST
libstrongswan_la_SOURCES += \
fips/fips_canister_end.c
@@ -72,11 +77,11 @@ EXTRA_DIST = asn1/oid.txt asn1/oid.pl
BUILT_SOURCES = asn1/oid.c asn1/oid.h
MAINTAINERCLEANFILES = asn1/oid.c asn1/oid.h
-asn1/oid.c : asn1/oid.txt asn1/oid.pl
- cd asn1 && $(PERL) oid.pl
+asn1/oid.c : asn1/oid.pl asn1/oid.txt
+ (cd `dirname $<` && $(PERL) `basename $<`)
-asn1/oid.h : asn1/oid.txt asn1/oid.pl
- cd asn1 && $(PERL) oid.pl
+asn1/oid.h : asn1/oid.pl asn1/oid.txt
+ (cd `dirname $<` && $(PERL) `basename $<`)
# build plugins with their own Makefile
diff --git a/src/libstrongswan/Makefile.in b/src/libstrongswan/Makefile.in
index e73411aa6..f1cf4f554 100644
--- a/src/libstrongswan/Makefile.in
+++ b/src/libstrongswan/Makefile.in
@@ -34,26 +34,27 @@ build_triplet = @build@
host_triplet = @host@
@USE_LEAK_DETECTIVE_TRUE@am__append_1 = -DLEAK_DETECTIVE
@USE_LEAK_DETECTIVE_TRUE@am__append_2 = utils/leak_detective.c utils/leak_detective.h
-@USE_AES_TRUE@am__append_3 = plugins/aes
-@USE_DES_TRUE@am__append_4 = plugins/des
-@USE_MD5_TRUE@am__append_5 = plugins/md5
-@USE_SHA1_TRUE@am__append_6 = plugins/sha1
-@USE_SHA2_TRUE@am__append_7 = plugins/sha2
-@USE_FIPS_PRF_TRUE@am__append_8 = plugins/fips_prf
-@USE_GMP_TRUE@am__append_9 = plugins/gmp
-@USE_RANDOM_TRUE@am__append_10 = plugins/random
-@USE_HMAC_TRUE@am__append_11 = plugins/hmac
-@USE_XCBC_TRUE@am__append_12 = plugins/xcbc
-@USE_X509_TRUE@am__append_13 = plugins/x509
-@USE_PUBKEY_TRUE@am__append_14 = plugins/pubkey
-@USE_CURL_TRUE@am__append_15 = plugins/curl
-@USE_LDAP_TRUE@am__append_16 = plugins/ldap
-@USE_MYSQL_TRUE@am__append_17 = plugins/mysql
-@USE_SQLITE_TRUE@am__append_18 = plugins/sqlite
-@USE_PADLOCK_TRUE@am__append_19 = plugins/padlock
-@USE_OPENSSL_TRUE@am__append_20 = plugins/openssl
-@USE_AGENT_TRUE@am__append_21 = plugins/agent
-@USE_INTEGRITY_TEST_TRUE@am__append_22 = fips
+@USE_LOCK_PROFILER_TRUE@am__append_3 = -DLOCK_PROFILER
+@USE_AES_TRUE@am__append_4 = plugins/aes
+@USE_DES_TRUE@am__append_5 = plugins/des
+@USE_MD5_TRUE@am__append_6 = plugins/md5
+@USE_SHA1_TRUE@am__append_7 = plugins/sha1
+@USE_SHA2_TRUE@am__append_8 = plugins/sha2
+@USE_FIPS_PRF_TRUE@am__append_9 = plugins/fips_prf
+@USE_GMP_TRUE@am__append_10 = plugins/gmp
+@USE_RANDOM_TRUE@am__append_11 = plugins/random
+@USE_HMAC_TRUE@am__append_12 = plugins/hmac
+@USE_XCBC_TRUE@am__append_13 = plugins/xcbc
+@USE_X509_TRUE@am__append_14 = plugins/x509
+@USE_PUBKEY_TRUE@am__append_15 = plugins/pubkey
+@USE_CURL_TRUE@am__append_16 = plugins/curl
+@USE_LDAP_TRUE@am__append_17 = plugins/ldap
+@USE_MYSQL_TRUE@am__append_18 = plugins/mysql
+@USE_SQLITE_TRUE@am__append_19 = plugins/sqlite
+@USE_PADLOCK_TRUE@am__append_20 = plugins/padlock
+@USE_OPENSSL_TRUE@am__append_21 = plugins/openssl
+@USE_AGENT_TRUE@am__append_22 = plugins/agent
+@USE_INTEGRITY_TEST_TRUE@am__append_23 = fips
subdir = src/libstrongswan
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
@@ -105,7 +106,8 @@ am__libstrongswan_la_SOURCES_DIST = library.c library.h chunk.c \
utils/iterator.h utils/lexparser.c utils/lexparser.h \
utils/linked_list.c utils/linked_list.h utils/enumerator.c \
utils/enumerator.h utils/optionsfrom.c utils/optionsfrom.h \
- utils/mutex.c utils/mutex.h plugins/plugin_loader.c \
+ utils/mutex.c utils/mutex.h utils/backtrace.c \
+ utils/backtrace.h plugins/plugin_loader.c \
plugins/plugin_loader.h plugins/plugin.h \
utils/leak_detective.c utils/leak_detective.h \
fips/fips_canister_start.c fips/fips.c fips/fips.h \
@@ -126,7 +128,7 @@ am__libstrongswan_la_SOURCES_DIST = library.c library.h chunk.c \
@USE_INTEGRITY_TEST_FALSE@ database_factory.lo utils.lo host.lo \
@USE_INTEGRITY_TEST_FALSE@ identification.lo lexparser.lo \
@USE_INTEGRITY_TEST_FALSE@ linked_list.lo enumerator.lo \
-@USE_INTEGRITY_TEST_FALSE@ optionsfrom.lo mutex.lo \
+@USE_INTEGRITY_TEST_FALSE@ optionsfrom.lo mutex.lo backtrace.lo \
@USE_INTEGRITY_TEST_FALSE@ plugin_loader.lo $(am__objects_1)
@USE_INTEGRITY_TEST_TRUE@am_libstrongswan_la_OBJECTS = \
@USE_INTEGRITY_TEST_TRUE@ fips_canister_start.lo fips.lo \
@@ -144,7 +146,7 @@ am__libstrongswan_la_SOURCES_DIST = library.c library.h chunk.c \
@USE_INTEGRITY_TEST_TRUE@ database_factory.lo utils.lo host.lo \
@USE_INTEGRITY_TEST_TRUE@ identification.lo lexparser.lo \
@USE_INTEGRITY_TEST_TRUE@ linked_list.lo enumerator.lo \
-@USE_INTEGRITY_TEST_TRUE@ optionsfrom.lo mutex.lo \
+@USE_INTEGRITY_TEST_TRUE@ optionsfrom.lo mutex.lo backtrace.lo \
@USE_INTEGRITY_TEST_TRUE@ plugin_loader.lo $(am__objects_1) \
@USE_INTEGRITY_TEST_TRUE@ fips_canister_end.lo
libstrongswan_la_OBJECTS = $(am_libstrongswan_la_OBJECTS)
@@ -375,7 +377,8 @@ lib_LTLIBRARIES = libstrongswan.la
@USE_INTEGRITY_TEST_FALSE@ utils/enumerator.h \
@USE_INTEGRITY_TEST_FALSE@ utils/optionsfrom.c \
@USE_INTEGRITY_TEST_FALSE@ utils/optionsfrom.h utils/mutex.c \
-@USE_INTEGRITY_TEST_FALSE@ utils/mutex.h \
+@USE_INTEGRITY_TEST_FALSE@ utils/mutex.h utils/backtrace.c \
+@USE_INTEGRITY_TEST_FALSE@ utils/backtrace.h \
@USE_INTEGRITY_TEST_FALSE@ plugins/plugin_loader.c \
@USE_INTEGRITY_TEST_FALSE@ plugins/plugin_loader.h \
@USE_INTEGRITY_TEST_FALSE@ plugins/plugin.h $(am__append_2)
@@ -437,27 +440,30 @@ lib_LTLIBRARIES = libstrongswan.la
@USE_INTEGRITY_TEST_TRUE@ utils/enumerator.c utils/enumerator.h \
@USE_INTEGRITY_TEST_TRUE@ utils/optionsfrom.c \
@USE_INTEGRITY_TEST_TRUE@ utils/optionsfrom.h utils/mutex.c \
-@USE_INTEGRITY_TEST_TRUE@ utils/mutex.h plugins/plugin_loader.c \
+@USE_INTEGRITY_TEST_TRUE@ utils/mutex.h utils/backtrace.c \
+@USE_INTEGRITY_TEST_TRUE@ utils/backtrace.h \
+@USE_INTEGRITY_TEST_TRUE@ plugins/plugin_loader.c \
@USE_INTEGRITY_TEST_TRUE@ plugins/plugin_loader.h \
@USE_INTEGRITY_TEST_TRUE@ plugins/plugin.h $(am__append_2) \
@USE_INTEGRITY_TEST_TRUE@ fips/fips_canister_end.c
libstrongswan_la_LIBADD = -lpthread -ldl
INCLUDES = -I$(top_srcdir)/src/libstrongswan
AM_CFLAGS = -DIPSEC_DIR=\"${ipsecdir}\" \
- -DIPSEC_PLUGINDIR=\"${plugindir}\" $(am__append_1)
+ -DIPSEC_PLUGINDIR=\"${plugindir}\" $(am__append_1) \
+ $(am__append_3)
EXTRA_DIST = asn1/oid.txt asn1/oid.pl
BUILT_SOURCES = asn1/oid.c asn1/oid.h
MAINTAINERCLEANFILES = asn1/oid.c asn1/oid.h
# build plugins with their own Makefile
#######################################
-SUBDIRS = . $(am__append_3) $(am__append_4) $(am__append_5) \
- $(am__append_6) $(am__append_7) $(am__append_8) \
- $(am__append_9) $(am__append_10) $(am__append_11) \
- $(am__append_12) $(am__append_13) $(am__append_14) \
- $(am__append_15) $(am__append_16) $(am__append_17) \
- $(am__append_18) $(am__append_19) $(am__append_20) \
- $(am__append_21) $(am__append_22)
+SUBDIRS = . $(am__append_4) $(am__append_5) $(am__append_6) \
+ $(am__append_7) $(am__append_8) $(am__append_9) \
+ $(am__append_10) $(am__append_11) $(am__append_12) \
+ $(am__append_13) $(am__append_14) $(am__append_15) \
+ $(am__append_16) $(am__append_17) $(am__append_18) \
+ $(am__append_19) $(am__append_20) $(am__append_21) \
+ $(am__append_22) $(am__append_23)
all: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) all-recursive
@@ -530,6 +536,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asn1.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asn1_parser.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/backtrace.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/builder.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/certificate.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/chunk.Plo@am__quote@
@@ -810,6 +817,13 @@ mutex.lo: utils/mutex.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mutex.lo `test -f 'utils/mutex.c' || echo '$(srcdir)/'`utils/mutex.c
+backtrace.lo: utils/backtrace.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT backtrace.lo -MD -MP -MF $(DEPDIR)/backtrace.Tpo -c -o backtrace.lo `test -f 'utils/backtrace.c' || echo '$(srcdir)/'`utils/backtrace.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/backtrace.Tpo $(DEPDIR)/backtrace.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='utils/backtrace.c' object='backtrace.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o backtrace.lo `test -f 'utils/backtrace.c' || echo '$(srcdir)/'`utils/backtrace.c
+
plugin_loader.lo: plugins/plugin_loader.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT plugin_loader.lo -MD -MP -MF $(DEPDIR)/plugin_loader.Tpo -c -o plugin_loader.lo `test -f 'plugins/plugin_loader.c' || echo '$(srcdir)/'`plugins/plugin_loader.c
@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/plugin_loader.Tpo $(DEPDIR)/plugin_loader.Plo
@@ -1139,11 +1153,11 @@ uninstall-am: uninstall-libLTLIBRARIES
uninstall-libLTLIBRARIES
-asn1/oid.c : asn1/oid.txt asn1/oid.pl
- cd asn1 && $(PERL) oid.pl
+asn1/oid.c : asn1/oid.pl asn1/oid.txt
+ (cd `dirname $<` && $(PERL) `basename $<`)
-asn1/oid.h : asn1/oid.txt asn1/oid.pl
- cd asn1 && $(PERL) oid.pl
+asn1/oid.h : asn1/oid.pl asn1/oid.txt
+ (cd `dirname $<` && $(PERL) `basename $<`)
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
diff --git a/src/libstrongswan/crypto/crypters/crypter.h b/src/libstrongswan/crypto/crypters/crypter.h
index aade888fa..fb06af97d 100644
--- a/src/libstrongswan/crypto/crypters/crypter.h
+++ b/src/libstrongswan/crypto/crypters/crypter.h
@@ -13,7 +13,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: crypter.h 3971 2008-05-16 13:27:21Z tobias $
+ * $Id: crypter.h 4532 2008-10-30 13:21:21Z martin $
*/
/**
diff --git a/src/libstrongswan/crypto/crypto_factory.c b/src/libstrongswan/crypto/crypto_factory.c
index 9836ed468..dcc881f1d 100644
--- a/src/libstrongswan/crypto/crypto_factory.c
+++ b/src/libstrongswan/crypto/crypto_factory.c
@@ -12,7 +12,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: crypto_factory.c 4307 2008-08-28 09:24:42Z martin $
+ * $Id: crypto_factory.c 4592 2008-11-05 16:21:57Z martin $
*/
#include "crypto_factory.h"
@@ -78,9 +78,9 @@ struct private_crypto_factory_t {
linked_list_t *dhs;
/**
- * mutex to lock access to modules
+ * rwlock to lock access to modules
*/
- mutex_t *mutex;
+ rwlock_t *lock;
};
/**
@@ -93,7 +93,7 @@ static crypter_t* create_crypter(private_crypto_factory_t *this,
entry_t *entry;
crypter_t *crypter = NULL;
- this->mutex->lock(this->mutex);
+ this->lock->read_lock(this->lock);
enumerator = this->crypters->create_enumerator(this->crypters);
while (enumerator->enumerate(enumerator, &entry))
{
@@ -107,7 +107,7 @@ static crypter_t* create_crypter(private_crypto_factory_t *this,
}
}
enumerator->destroy(enumerator);
- this->mutex->unlock(this->mutex);
+ this->lock->unlock(this->lock);
return crypter;
}
@@ -121,7 +121,7 @@ static signer_t* create_signer(private_crypto_factory_t *this,
entry_t *entry;
signer_t *signer = NULL;
- this->mutex->lock(this->mutex);
+ this->lock->read_lock(this->lock);
enumerator = this->signers->create_enumerator(this->signers);
while (enumerator->enumerate(enumerator, &entry))
{
@@ -135,7 +135,7 @@ static signer_t* create_signer(private_crypto_factory_t *this,
}
}
enumerator->destroy(enumerator);
- this->mutex->unlock(this->mutex);
+ this->lock->unlock(this->lock);
return signer;
}
@@ -150,7 +150,7 @@ static hasher_t* create_hasher(private_crypto_factory_t *this,
entry_t *entry;
hasher_t *hasher = NULL;
- this->mutex->lock(this->mutex);
+ this->lock->read_lock(this->lock);
enumerator = this->hashers->create_enumerator(this->hashers);
while (enumerator->enumerate(enumerator, &entry))
{
@@ -164,7 +164,7 @@ static hasher_t* create_hasher(private_crypto_factory_t *this,
}
}
enumerator->destroy(enumerator);
- this->mutex->unlock(this->mutex);
+ this->lock->unlock(this->lock);
return hasher;
}
@@ -178,7 +178,7 @@ static prf_t* create_prf(private_crypto_factory_t *this,
entry_t *entry;
prf_t *prf = NULL;
- this->mutex->lock(this->mutex);
+ this->lock->read_lock(this->lock);
enumerator = this->prfs->create_enumerator(this->prfs);
while (enumerator->enumerate(enumerator, &entry))
{
@@ -192,7 +192,7 @@ static prf_t* create_prf(private_crypto_factory_t *this,
}
}
enumerator->destroy(enumerator);
- this->mutex->unlock(this->mutex);
+ this->lock->unlock(this->lock);
return prf;
}
@@ -206,7 +206,7 @@ static rng_t* create_rng(private_crypto_factory_t *this, rng_quality_t quality)
u_int diff = ~0;
rng_constructor_t constr = NULL;
- this->mutex->lock(this->mutex);
+ this->lock->read_lock(this->lock);
enumerator = this->rngs->create_enumerator(this->rngs);
while (enumerator->enumerate(enumerator, &entry))
{ /* find the best matching quality, but at least as good as requested */
@@ -221,7 +221,7 @@ static rng_t* create_rng(private_crypto_factory_t *this, rng_quality_t quality)
}
}
enumerator->destroy(enumerator);
- this->mutex->unlock(this->mutex);
+ this->lock->unlock(this->lock);
if (constr)
{
return constr(quality);
@@ -239,7 +239,7 @@ static diffie_hellman_t* create_dh(private_crypto_factory_t *this,
entry_t *entry;
diffie_hellman_t *diffie_hellman = NULL;
- this->mutex->lock(this->mutex);
+ this->lock->read_lock(this->lock);
enumerator = this->dhs->create_enumerator(this->dhs);
while (enumerator->enumerate(enumerator, &entry))
{
@@ -253,7 +253,7 @@ static diffie_hellman_t* create_dh(private_crypto_factory_t *this,
}
}
enumerator->destroy(enumerator);
- this->mutex->unlock(this->mutex);
+ this->lock->unlock(this->lock);
return diffie_hellman;
}
@@ -268,9 +268,9 @@ static void add_crypter(private_crypto_factory_t *this,
entry->algo = algo;
entry->create_crypter = create;
- this->mutex->lock(this->mutex);
+ this->lock->write_lock(this->lock);
this->crypters->insert_last(this->crypters, entry);
- this->mutex->unlock(this->mutex);
+ this->lock->unlock(this->lock);
}
/**
@@ -282,7 +282,7 @@ static void remove_crypter(private_crypto_factory_t *this,
entry_t *entry;
enumerator_t *enumerator;
- this->mutex->lock(this->mutex);
+ this->lock->write_lock(this->lock);
enumerator = this->crypters->create_enumerator(this->crypters);
while (enumerator->enumerate(enumerator, &entry))
{
@@ -293,7 +293,7 @@ static void remove_crypter(private_crypto_factory_t *this,
}
}
enumerator->destroy(enumerator);
- this->mutex->unlock(this->mutex);
+ this->lock->unlock(this->lock);
}
/**
@@ -306,9 +306,9 @@ static void add_signer(private_crypto_factory_t *this,
entry->algo = algo;
entry->create_signer = create;
- this->mutex->lock(this->mutex);
+ this->lock->write_lock(this->lock);
this->signers->insert_last(this->signers, entry);
- this->mutex->unlock(this->mutex);
+ this->lock->unlock(this->lock);
}
/**
@@ -320,7 +320,7 @@ static void remove_signer(private_crypto_factory_t *this,
entry_t *entry;
enumerator_t *enumerator;
- this->mutex->lock(this->mutex);
+ this->lock->write_lock(this->lock);
enumerator = this->signers->create_enumerator(this->signers);
while (enumerator->enumerate(enumerator, &entry))
{
@@ -331,7 +331,7 @@ static void remove_signer(private_crypto_factory_t *this,
}
}
enumerator->destroy(enumerator);
- this->mutex->unlock(this->mutex);
+ this->lock->unlock(this->lock);
}
/**
@@ -344,9 +344,9 @@ static void add_hasher(private_crypto_factory_t *this, hash_algorithm_t algo,
entry->algo = algo;
entry->create_hasher = create;
- this->mutex->lock(this->mutex);
+ this->lock->write_lock(this->lock);
this->hashers->insert_last(this->hashers, entry);
- this->mutex->unlock(this->mutex);
+ this->lock->unlock(this->lock);
}
/**
@@ -358,7 +358,7 @@ static void remove_hasher(private_crypto_factory_t *this,
entry_t *entry;
enumerator_t *enumerator;
- this->mutex->lock(this->mutex);
+ this->lock->write_lock(this->lock);
enumerator = this->hashers->create_enumerator(this->hashers);
while (enumerator->enumerate(enumerator, &entry))
{
@@ -369,7 +369,7 @@ static void remove_hasher(private_crypto_factory_t *this,
}
}
enumerator->destroy(enumerator);
- this->mutex->unlock(this->mutex);
+ this->lock->unlock(this->lock);
}
/**
@@ -382,9 +382,9 @@ static void add_prf(private_crypto_factory_t *this,
entry->algo = algo;
entry->create_prf = create;
- this->mutex->lock(this->mutex);
+ this->lock->write_lock(this->lock);
this->prfs->insert_last(this->prfs, entry);
- this->mutex->unlock(this->mutex);
+ this->lock->unlock(this->lock);
}
/**
@@ -395,7 +395,7 @@ static void remove_prf(private_crypto_factory_t *this, prf_constructor_t create)
entry_t *entry;
enumerator_t *enumerator;
- this->mutex->lock(this->mutex);
+ this->lock->write_lock(this->lock);
enumerator = this->prfs->create_enumerator(this->prfs);
while (enumerator->enumerate(enumerator, &entry))
{
@@ -406,7 +406,7 @@ static void remove_prf(private_crypto_factory_t *this, prf_constructor_t create)
}
}
enumerator->destroy(enumerator);
- this->mutex->unlock(this->mutex);
+ this->lock->unlock(this->lock);
}
/**
@@ -419,9 +419,9 @@ static void add_rng(private_crypto_factory_t *this, rng_quality_t quality,
entry->algo = quality;
entry->create_rng = create;
- this->mutex->lock(this->mutex);
+ this->lock->write_lock(this->lock);
this->rngs->insert_last(this->rngs, entry);
- this->mutex->unlock(this->mutex);
+ this->lock->unlock(this->lock);
}
/**
@@ -432,7 +432,7 @@ static void remove_rng(private_crypto_factory_t *this, rng_constructor_t create)
entry_t *entry;
enumerator_t *enumerator;
- this->mutex->lock(this->mutex);
+ this->lock->write_lock(this->lock);
enumerator = this->rngs->create_enumerator(this->rngs);
while (enumerator->enumerate(enumerator, &entry))
{
@@ -443,7 +443,7 @@ static void remove_rng(private_crypto_factory_t *this, rng_constructor_t create)
}
}
enumerator->destroy(enumerator);
- this->mutex->unlock(this->mutex);
+ this->lock->unlock(this->lock);
}
/**
@@ -456,9 +456,9 @@ static void add_dh(private_crypto_factory_t *this, diffie_hellman_group_t group,
entry->algo = group;
entry->create_dh = create;
- this->mutex->lock(this->mutex);
+ this->lock->write_lock(this->lock);
this->dhs->insert_last(this->dhs, entry);
- this->mutex->unlock(this->mutex);
+ this->lock->unlock(this->lock);
}
/**
@@ -469,7 +469,7 @@ static void remove_dh(private_crypto_factory_t *this, dh_constructor_t create)
entry_t *entry;
enumerator_t *enumerator;
- this->mutex->lock(this->mutex);
+ this->lock->write_lock(this->lock);
enumerator = this->dhs->create_enumerator(this->dhs);
while (enumerator->enumerate(enumerator, &entry))
{
@@ -480,7 +480,7 @@ static void remove_dh(private_crypto_factory_t *this, dh_constructor_t create)
}
}
enumerator->destroy(enumerator);
- this->mutex->unlock(this->mutex);
+ this->lock->unlock(this->lock);
}
/**
@@ -511,12 +511,12 @@ static bool unique_check(linked_list_t *list, entry_t **in, entry_t **out)
static enumerator_t *create_enumerator(private_crypto_factory_t *this,
linked_list_t *list, void *filter)
{
- this->mutex->lock(this->mutex);
+ this->lock->read_lock(this->lock);
return enumerator_create_filter(
enumerator_create_filter(
list->create_enumerator(list), (void*)unique_check,
linked_list_create(), (void*)list->destroy),
- filter, this->mutex, (void*)this->mutex->unlock);
+ filter, this->lock, (void*)this->lock->unlock);
}
/**
@@ -615,7 +615,7 @@ static void destroy(private_crypto_factory_t *this)
this->prfs->destroy_function(this->prfs, free);
this->rngs->destroy_function(this->rngs, free);
this->dhs->destroy_function(this->dhs, free);
- this->mutex->destroy(this->mutex);
+ this->lock->destroy(this->lock);
free(this);
}
@@ -657,7 +657,7 @@ crypto_factory_t *crypto_factory_create()
this->prfs = linked_list_create();
this->rngs = linked_list_create();
this->dhs = linked_list_create();
- this->mutex = mutex_create(MUTEX_RECURSIVE);
+ this->lock = rwlock_create(RWLOCK_DEFAULT);
return &this->public;
}
diff --git a/src/libstrongswan/crypto/diffie_hellman.h b/src/libstrongswan/crypto/diffie_hellman.h
index c66ae56c3..ce8ab8e21 100644
--- a/src/libstrongswan/crypto/diffie_hellman.h
+++ b/src/libstrongswan/crypto/diffie_hellman.h
@@ -13,7 +13,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: diffie_hellman.h 4023 2008-05-29 06:55:03Z andreas $
+ * $Id: diffie_hellman.h 4566 2008-11-04 13:12:11Z martin $
*/
/**
@@ -85,16 +85,6 @@ struct diffie_hellman_t {
void (*set_other_public_value) (diffie_hellman_t *this, chunk_t value);
/**
- * Gets the public value of partner.
- *
- * Space for returned chunk is allocated and must be freed by the caller.
- *
- * @param value public value of partner is stored at this location
- * @return SUCCESS, FAILED if other public value not set
- */
- status_t (*get_other_public_value) (diffie_hellman_t *this, chunk_t *value);
-
- /**
* Gets the own public value to transmit.
*
* Space for returned chunk is allocated and must be freed by the caller.
diff --git a/src/libstrongswan/crypto/prf_plus.c b/src/libstrongswan/crypto/prf_plus.c
index de7dbff84..3d37d4ef7 100644
--- a/src/libstrongswan/crypto/prf_plus.c
+++ b/src/libstrongswan/crypto/prf_plus.c
@@ -13,7 +13,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: prf_plus.c 3589 2008-03-13 14:14:44Z martin $
+ * $Id: prf_plus.c 4524 2008-10-29 14:12:54Z martin $
*/
#include <string.h>
@@ -96,9 +96,16 @@ static void get_bytes(private_prf_plus_t *this, size_t length, u_int8_t *buffer)
*/
static void allocate_bytes(private_prf_plus_t *this, size_t length, chunk_t *chunk)
{
- chunk->ptr = malloc(length);
- chunk->len = length;
- this->public.get_bytes(&(this->public), length, chunk->ptr);
+ if (length)
+ {
+ chunk->ptr = malloc(length);
+ chunk->len = length;
+ get_bytes(this, length, chunk->ptr);
+ }
+ else
+ {
+ *chunk = chunk_empty;
+ }
}
/**
diff --git a/src/libstrongswan/fetcher/fetcher_manager.c b/src/libstrongswan/fetcher/fetcher_manager.c
index 517c9dfc9..5d58f224e 100644
--- a/src/libstrongswan/fetcher/fetcher_manager.c
+++ b/src/libstrongswan/fetcher/fetcher_manager.c
@@ -12,16 +12,14 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: fetcher_manager.c 3630 2008-03-20 11:27:55Z martin $
+ * $Id: fetcher_manager.c 4591 2008-11-05 16:12:54Z martin $
*/
-#define _GNU_SOURCE
-
#include "fetcher_manager.h"
#include <debug.h>
-#include <utils/linked_list.h>
#include <utils/mutex.h>
+#include <utils/linked_list.h>
typedef struct private_fetcher_manager_t private_fetcher_manager_t;
@@ -43,7 +41,7 @@ struct private_fetcher_manager_t {
/**
* read write lock to list
*/
- pthread_rwlock_t lock;
+ rwlock_t *lock;
};
typedef struct {
@@ -73,7 +71,7 @@ static status_t fetch(private_fetcher_manager_t *this,
entry_t *entry;
bool capable = FALSE;
- pthread_rwlock_rdlock(&this->lock);
+ this->lock->read_lock(this->lock);
enumerator = this->fetchers->create_enumerator(this->fetchers);
while (enumerator->enumerate(enumerator, &entry))
{
@@ -131,7 +129,7 @@ static status_t fetch(private_fetcher_manager_t *this,
break;
}
enumerator->destroy(enumerator);
- pthread_rwlock_unlock(&this->lock);
+ this->lock->unlock(this->lock);
if (!capable)
{
DBG1("unable to fetch from %s, no capable fetcher found", url);
@@ -150,9 +148,9 @@ static void add_fetcher(private_fetcher_manager_t *this,
entry->url = strdup(url);
entry->create = create;
- pthread_rwlock_wrlock(&this->lock);
+ this->lock->write_lock(this->lock);
this->fetchers->insert_last(this->fetchers, entry);
- pthread_rwlock_unlock(&this->lock);
+ this->lock->unlock(this->lock);
}
/**
@@ -164,7 +162,7 @@ static void remove_fetcher(private_fetcher_manager_t *this,
enumerator_t *enumerator;
entry_t *entry;
- pthread_rwlock_wrlock(&this->lock);
+ this->lock->write_lock(this->lock);
enumerator = this->fetchers->create_enumerator(this->fetchers);
while (enumerator->enumerate(enumerator, &entry))
{
@@ -175,7 +173,7 @@ static void remove_fetcher(private_fetcher_manager_t *this,
}
}
enumerator->destroy(enumerator);
- pthread_rwlock_unlock(&this->lock);
+ this->lock->unlock(this->lock);
}
/**
@@ -184,7 +182,7 @@ static void remove_fetcher(private_fetcher_manager_t *this,
static void destroy(private_fetcher_manager_t *this)
{
this->fetchers->destroy_function(this->fetchers, (void*)entry_destroy);
- pthread_rwlock_destroy(&this->lock);
+ this->lock->destroy(this->lock);
free(this);
}
@@ -201,7 +199,7 @@ fetcher_manager_t *fetcher_manager_create()
this->public.destroy = (void(*)(fetcher_manager_t*))destroy;
this->fetchers = linked_list_create();
- pthread_rwlock_init(&this->lock, NULL);
+ this->lock = rwlock_create(RWLOCK_DEFAULT);
return &this->public;
}
diff --git a/src/libstrongswan/plugins/agent/agent_private_key.c b/src/libstrongswan/plugins/agent/agent_private_key.c
index a3b8eebf3..5e7d0839e 100644
--- a/src/libstrongswan/plugins/agent/agent_private_key.c
+++ b/src/libstrongswan/plugins/agent/agent_private_key.c
@@ -215,9 +215,13 @@ static bool read_key(private_agent_private_key_t *this, public_key_t *pubkey)
chunk_t blob = chunk_from_buf(buf), key, type, tmp;
len = htonl(1);
- write(this->socket, &len, sizeof(len));
buf[0] = SSH_AGENT_ID_REQUEST;
- write(this->socket, &buf, 1);
+ if (write(this->socket, &len, sizeof(len)) != sizeof(len) ||
+ write(this->socket, &buf, 1) != 1)
+ {
+ DBG1("writing to ssh-agent failed");
+ return FALSE;
+ }
blob.len = read(this->socket, blob.ptr, blob.len);
@@ -275,20 +279,36 @@ static bool sign(private_agent_private_key_t *this, signature_scheme_t scheme,
}
len = htonl(1 + sizeof(u_int32_t) * 3 + this->key.len + data.len);
- write(this->socket, &len, sizeof(len));
buf[0] = SSH_AGENT_SIGN_REQUEST;
- write(this->socket, &buf, 1);
+ if (write(this->socket, &len, sizeof(len)) != sizeof(len) ||
+ write(this->socket, &buf, 1) != 1)
+ {
+ DBG1("writing to ssh-agent failed");
+ return FALSE;
+ }
len = htonl(this->key.len);
- write(this->socket, &len, sizeof(len));
- write(this->socket, this->key.ptr, this->key.len);
+ if (write(this->socket, &len, sizeof(len)) != sizeof(len) ||
+ write(this->socket, this->key.ptr, this->key.len) != this->key.len)
+ {
+ DBG1("writing to ssh-agent failed");
+ return FALSE;
+ }
len = htonl(data.len);
- write(this->socket, &len, sizeof(len));
- write(this->socket, data.ptr, data.len);
+ if (write(this->socket, &len, sizeof(len)) != sizeof(len) ||
+ write(this->socket, data.ptr, data.len) != data.len)
+ {
+ DBG1("writing to ssh-agent failed");
+ return FALSE;
+ }
flags = htonl(0);
- write(this->socket, &flags, sizeof(flags));
+ if (write(this->socket, &flags, sizeof(flags)) != sizeof(flags))
+ {
+ DBG1("writing to ssh-agent failed");
+ return FALSE;
+ }
blob.len = read(this->socket, blob.ptr, blob.len);
if (blob.len < sizeof(u_int32_t) + sizeof(u_char) ||
diff --git a/src/libstrongswan/plugins/curl/curl_fetcher.c b/src/libstrongswan/plugins/curl/curl_fetcher.c
index 4754d569e..cd54c76a3 100644
--- a/src/libstrongswan/plugins/curl/curl_fetcher.c
+++ b/src/libstrongswan/plugins/curl/curl_fetcher.c
@@ -13,7 +13,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: curl_fetcher.c 3529 2008-03-05 15:26:24Z martin $
+ * $Id: curl_fetcher.c 4632 2008-11-11 18:37:19Z martin $
*/
#include <curl/curl.h>
@@ -123,7 +123,7 @@ static bool set_option(private_curl_fetcher_t *this, fetcher_option_t option, ..
case FETCH_REQUEST_DATA:
{
chunk_t data = va_arg(args, chunk_t);
- curl_easy_setopt(this->curl, CURLOPT_POSTFIELDS, data.ptr);
+ curl_easy_setopt(this->curl, CURLOPT_POSTFIELDS, (char*)data.ptr);
curl_easy_setopt(this->curl, CURLOPT_POSTFIELDSIZE, data.len);
return TRUE;
}
diff --git a/src/libstrongswan/plugins/gmp/gmp_diffie_hellman.c b/src/libstrongswan/plugins/gmp/gmp_diffie_hellman.c
index 40e83fc4c..294fb722f 100644
--- a/src/libstrongswan/plugins/gmp/gmp_diffie_hellman.c
+++ b/src/libstrongswan/plugins/gmp/gmp_diffie_hellman.c
@@ -15,7 +15,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: gmp_diffie_hellman.c 4346 2008-09-17 09:02:30Z martin $
+ * $Id: gmp_diffie_hellman.c 4566 2008-11-04 13:12:11Z martin $
*/
#include <gmp.h>
@@ -304,23 +304,28 @@ struct modulus_entry_t {
size_t modulus_len;
/*
+ * Optimum length of exponent in bytes.
+ */
+ size_t opt_exponent_len;
+
+ /*
* Generator value.
*/
u_int16_t generator;
};
/**
- * All supported modulus values.
+ * All supported modulus values - optimum exponent size according to RFC 3526.
*/
static modulus_entry_t modulus_entries[] = {
- {MODP_768_BIT, group1_modulus, sizeof(group1_modulus), 2},
- {MODP_1024_BIT, group2_modulus, sizeof(group2_modulus), 2},
- {MODP_1536_BIT, group5_modulus, sizeof(group5_modulus), 2},
- {MODP_2048_BIT, group14_modulus, sizeof(group14_modulus), 2},
- {MODP_3072_BIT, group15_modulus, sizeof(group15_modulus), 2},
- {MODP_4096_BIT, group16_modulus, sizeof(group16_modulus), 2},
- {MODP_6144_BIT, group17_modulus, sizeof(group17_modulus), 2},
- {MODP_8192_BIT, group18_modulus, sizeof(group18_modulus), 2},
+ {MODP_768_BIT, group1_modulus, sizeof(group1_modulus), 32, 2},
+ {MODP_1024_BIT, group2_modulus, sizeof(group2_modulus), 32, 2},
+ {MODP_1536_BIT, group5_modulus, sizeof(group5_modulus), 32, 2},
+ {MODP_2048_BIT, group14_modulus, sizeof(group14_modulus), 48, 2},
+ {MODP_3072_BIT, group15_modulus, sizeof(group15_modulus), 48, 2},
+ {MODP_4096_BIT, group16_modulus, sizeof(group16_modulus), 64, 2},
+ {MODP_6144_BIT, group17_modulus, sizeof(group17_modulus), 64, 2},
+ {MODP_8192_BIT, group18_modulus, sizeof(group18_modulus), 64, 2},
};
typedef struct private_gmp_diffie_hellman_t private_gmp_diffie_hellman_t;
@@ -375,6 +380,11 @@ struct private_gmp_diffie_hellman_t {
size_t p_len;
/**
+ * Optimal exponent length.
+ */
+ size_t opt_exponent_len;
+
+ /**
* True if shared secret is computed and stored in my_public_value.
*/
bool computed;
@@ -430,25 +440,6 @@ static void set_other_public_value(private_gmp_diffie_hellman_t *this, chunk_t v
}
/**
- * Implementation of gmp_diffie_hellman_t.get_other_public_value.
- */
-static status_t get_other_public_value(private_gmp_diffie_hellman_t *this,
- chunk_t *value)
-{
- if (!this->computed)
- {
- return FAILED;
- }
- value->len = this->p_len;
- value->ptr = mpz_export(NULL, NULL, 1, value->len, 1, 0, this->yb);
- if (value->ptr == NULL)
- {
- return FAILED;
- }
- return SUCCESS;
-}
-
-/**
* Implementation of gmp_diffie_hellman_t.get_my_public_value.
*/
static void get_my_public_value(private_gmp_diffie_hellman_t *this,chunk_t *value)
@@ -504,6 +495,7 @@ static status_t set_modulus(private_gmp_diffie_hellman_t *this)
chunk.len = modulus_entries[i].modulus_len;
mpz_import(this->p, chunk.len, 1, 1, 1, 0, chunk.ptr);
this->p_len = chunk.len;
+ this->opt_exponent_len = modulus_entries[i].opt_exponent_len;
mpz_set_ui(this->g, modulus_entries[i].generator);
status = SUCCESS;
break;
@@ -534,11 +526,12 @@ gmp_diffie_hellman_t *gmp_diffie_hellman_create(diffie_hellman_group_t group)
private_gmp_diffie_hellman_t *this = malloc_thing(private_gmp_diffie_hellman_t);
rng_t *rng;
chunk_t random;
+ bool ansi_x9_42;
+ size_t exponent_len;
/* public functions */
this->public.dh.get_shared_secret = (status_t (*)(diffie_hellman_t *, chunk_t *)) get_shared_secret;
this->public.dh.set_other_public_value = (void (*)(diffie_hellman_t *, chunk_t )) set_other_public_value;
- this->public.dh.get_other_public_value = (status_t (*)(diffie_hellman_t *, chunk_t *)) get_other_public_value;
this->public.dh.get_my_public_value = (void (*)(diffie_hellman_t *, chunk_t *)) get_my_public_value;
this->public.dh.get_dh_group = (diffie_hellman_group_t (*)(diffie_hellman_t *)) get_dh_group;
this->public.dh.destroy = (void (*)(diffie_hellman_t *)) destroy;
@@ -567,11 +560,22 @@ gmp_diffie_hellman_t *gmp_diffie_hellman_create(diffie_hellman_group_t group)
destroy(this);
return NULL;
}
- rng->allocate_bytes(rng, this->p_len, &random);
+
+ ansi_x9_42 = lib->settings->get_int(lib->settings,
+ "charon.dh_exponent_ansi_x9_42", TRUE);
+ exponent_len = (ansi_x9_42) ? this->p_len : this->opt_exponent_len;
+ rng->allocate_bytes(rng, exponent_len, &random);
rng->destroy(rng);
+
+ if (ansi_x9_42)
+ {
+ /* achieve bitsof(p)-1 by setting MSB to 0 */
+ *random.ptr &= 0x7F;
+ }
mpz_import(this->xa, random.len, 1, 1, 1, 0, random.ptr);
chunk_free(&random);
-
+ DBG2("size of DH secret exponent: %u bits", mpz_sizeinbase(this->xa, 2));
+
mpz_powm(this->ya, this->g, this->xa, this->p);
return &this->public;
diff --git a/src/libstrongswan/plugins/openssl/openssl_diffie_hellman.c b/src/libstrongswan/plugins/openssl/openssl_diffie_hellman.c
index 95c079b0b..7c83b3dea 100644
--- a/src/libstrongswan/plugins/openssl/openssl_diffie_hellman.c
+++ b/src/libstrongswan/plugins/openssl/openssl_diffie_hellman.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2008 Tobias Brunner
+ * Copyright (C) 2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -12,7 +13,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: openssl_diffie_hellman.c 3896 2008-04-29 15:42:34Z tobias $
+ * $Id: openssl_diffie_hellman.c 4639 2008-11-12 15:09:24Z martin $
*/
#include <openssl/dh.h>
@@ -38,23 +39,28 @@ struct modulus_entry_t {
BIGNUM *(*get_prime)(BIGNUM *bn);
/*
+ * Optimum length of exponent in bits.
+ */
+ long opt_exponent_len;
+
+ /*
* Generator value.
*/
u_int16_t generator;
};
/**
- * All supported modulus values.
+ * All supported modulus values - optimum exponent size according to RFC 3526.
*/
static modulus_entry_t modulus_entries[] = {
- {MODP_768_BIT, get_rfc2409_prime_768, 2},
- {MODP_1024_BIT, get_rfc2409_prime_1024, 2},
- {MODP_1536_BIT, get_rfc3526_prime_1536, 2},
- {MODP_2048_BIT, get_rfc3526_prime_2048, 2},
- {MODP_3072_BIT, get_rfc3526_prime_3072, 2},
- {MODP_4096_BIT, get_rfc3526_prime_4096, 2},
- {MODP_6144_BIT, get_rfc3526_prime_6144, 2},
- {MODP_8192_BIT, get_rfc3526_prime_8192, 2},
+ {MODP_768_BIT, get_rfc2409_prime_768, 256, 2},
+ {MODP_1024_BIT, get_rfc2409_prime_1024, 256, 2},
+ {MODP_1536_BIT, get_rfc3526_prime_1536, 256, 2},
+ {MODP_2048_BIT, get_rfc3526_prime_2048, 384, 2},
+ {MODP_3072_BIT, get_rfc3526_prime_3072, 384, 2},
+ {MODP_4096_BIT, get_rfc3526_prime_4096, 512, 2},
+ {MODP_6144_BIT, get_rfc3526_prime_6144, 512, 2},
+ {MODP_8192_BIT, get_rfc3526_prime_8192, 512, 2},
};
typedef struct private_openssl_diffie_hellman_t private_openssl_diffie_hellman_t;
@@ -87,7 +93,7 @@ struct private_openssl_diffie_hellman_t {
* Shared secret
*/
chunk_t shared_secret;
-
+
/**
* True if shared secret is computed
*/
@@ -95,68 +101,57 @@ struct private_openssl_diffie_hellman_t {
};
/**
- * Convert a BIGNUM to a chunk
- */
-static void bn2chunk(BIGNUM *bn, chunk_t *chunk)
-{
- chunk->len = BN_num_bytes(bn);
- chunk->ptr = malloc(chunk->len);
- BN_bn2bin(bn, chunk->ptr);
-}
-
-/**
- * Implementation of openssl_diffie_hellman_t.set_other_public_value.
+ * Implementation of openssl_diffie_hellman_t.get_my_public_value.
*/
-static void set_other_public_value(private_openssl_diffie_hellman_t *this, chunk_t value)
+static void get_my_public_value(private_openssl_diffie_hellman_t *this,
+ chunk_t *value)
{
- int len;
- BN_bin2bn(value.ptr, value.len, this->pub_key);
-
- len = DH_size(this->dh);
- chunk_free(&this->shared_secret);
- this->shared_secret = chunk_alloc(len);
-
- if (DH_compute_key(this->shared_secret.ptr, this->pub_key, this->dh) < 0) {
- DBG1("DH shared secret computation failed");
- return;
- }
-
- this->computed = TRUE;
+ *value = chunk_alloc(DH_size(this->dh));
+ memset(value->ptr, 0, value->len);
+ BN_bn2bin(this->dh->pub_key,
+ value->ptr + value->len - BN_num_bytes(this->dh->pub_key));
}
/**
- * Implementation of openssl_diffie_hellman_t.get_other_public_value.
+ * Implementation of openssl_diffie_hellman_t.get_shared_secret.
*/
-static status_t get_other_public_value(private_openssl_diffie_hellman_t *this,
- chunk_t *value)
+static status_t get_shared_secret(private_openssl_diffie_hellman_t *this,
+ chunk_t *secret)
{
if (!this->computed)
{
return FAILED;
}
- bn2chunk(this->pub_key, value);
+ /* shared secret should requires a len according the DH group */
+ *secret = chunk_alloc(DH_size(this->dh));
+ memset(secret->ptr, 0, secret->len);
+ memcpy(secret->ptr + secret->len - this->shared_secret.len,
+ this->shared_secret.ptr, this->shared_secret.len);
+
return SUCCESS;
}
-/**
- * Implementation of openssl_diffie_hellman_t.get_my_public_value.
- */
-static void get_my_public_value(private_openssl_diffie_hellman_t *this,chunk_t *value)
-{
- bn2chunk(this->dh->pub_key, value);
-}
/**
- * Implementation of openssl_diffie_hellman_t.get_shared_secret.
+ * Implementation of openssl_diffie_hellman_t.set_other_public_value.
*/
-static status_t get_shared_secret(private_openssl_diffie_hellman_t *this, chunk_t *secret)
+static void set_other_public_value(private_openssl_diffie_hellman_t *this,
+ chunk_t value)
{
- if (!this->computed)
+ int len;
+
+ BN_bin2bn(value.ptr, value.len, this->pub_key);
+ chunk_clear(&this->shared_secret);
+ this->shared_secret.ptr = malloc(DH_size(this->dh));
+ memset(this->shared_secret.ptr, 0xFF, this->shared_secret.len);
+ len = DH_compute_key(this->shared_secret.ptr, this->pub_key, this->dh);
+ if (len < 0)
{
- return FAILED;
+ DBG1("DH shared secret computation failed");
+ return;
}
- *secret = chunk_clone(this->shared_secret);
- return SUCCESS;
+ this->shared_secret.len = len;
+ this->computed = TRUE;
}
/**
@@ -173,6 +168,11 @@ static diffie_hellman_group_t get_dh_group(private_openssl_diffie_hellman_t *thi
static status_t set_modulus(private_openssl_diffie_hellman_t *this)
{
int i;
+ bool ansi_x9_42;
+
+ ansi_x9_42 = lib->settings->get_bool(lib->settings,
+ "charon.dh_exponent_ansi_x9_42", TRUE);
+
for (i = 0; i < (sizeof(modulus_entries) / sizeof(modulus_entry_t)); i++)
{
if (modulus_entries[i].group == this->group)
@@ -180,6 +180,10 @@ static status_t set_modulus(private_openssl_diffie_hellman_t *this)
this->dh->p = modulus_entries[i].get_prime(NULL);
this->dh->g = BN_new();
BN_set_word(this->dh->g, modulus_entries[i].generator);
+ if (!ansi_x9_42)
+ {
+ this->dh->length = modulus_entries[i].opt_exponent_len;
+ }
return SUCCESS;
}
}
@@ -193,7 +197,7 @@ static void destroy(private_openssl_diffie_hellman_t *this)
{
BN_clear_free(this->pub_key);
DH_free(this->dh);
- chunk_free(&this->shared_secret);
+ chunk_clear(&this->shared_secret);
free(this);
}
@@ -206,7 +210,6 @@ openssl_diffie_hellman_t *openssl_diffie_hellman_create(diffie_hellman_group_t g
this->public.dh.get_shared_secret = (status_t (*)(diffie_hellman_t *, chunk_t *)) get_shared_secret;
this->public.dh.set_other_public_value = (void (*)(diffie_hellman_t *, chunk_t )) set_other_public_value;
- this->public.dh.get_other_public_value = (status_t (*)(diffie_hellman_t *, chunk_t *)) get_other_public_value;
this->public.dh.get_my_public_value = (void (*)(diffie_hellman_t *, chunk_t *)) get_my_public_value;
this->public.dh.get_dh_group = (diffie_hellman_group_t (*)(diffie_hellman_t *)) get_dh_group;
this->public.dh.destroy = (void (*)(diffie_hellman_t *)) destroy;
@@ -220,7 +223,6 @@ openssl_diffie_hellman_t *openssl_diffie_hellman_create(diffie_hellman_group_t g
this->group = group;
this->computed = FALSE;
-
this->pub_key = BN_new();
this->shared_secret = chunk_empty;
@@ -237,6 +239,7 @@ openssl_diffie_hellman_t *openssl_diffie_hellman_create(diffie_hellman_group_t g
destroy(this);
return NULL;
}
+ DBG2("size of DH secret exponent: %d bits", BN_num_bits(this->dh->priv_key));
return &this->public;
}
diff --git a/src/libstrongswan/plugins/openssl/openssl_ec_diffie_hellman.c b/src/libstrongswan/plugins/openssl/openssl_ec_diffie_hellman.c
index 9d2bd44cd..9a89ad045 100644
--- a/src/libstrongswan/plugins/openssl/openssl_ec_diffie_hellman.c
+++ b/src/libstrongswan/plugins/openssl/openssl_ec_diffie_hellman.c
@@ -12,7 +12,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: openssl_ec_diffie_hellman.c 4052 2008-06-10 09:19:18Z tobias $
+ * $Id: openssl_ec_diffie_hellman.c 4566 2008-11-04 13:12:11Z martin $
*/
#include <openssl/ec.h>
@@ -217,24 +217,6 @@ static void set_other_public_value(private_openssl_ec_diffie_hellman_t *this, ch
}
/**
- * Implementation of openssl_ec_diffie_hellman_t.get_other_public_value.
- */
-static status_t get_other_public_value(private_openssl_ec_diffie_hellman_t *this,
- chunk_t *value)
-{
- if (!this->computed)
- {
- return FAILED;
- }
-
- if (!ecp2chunk(this->ec_group, this->pub_key, value))
- {
- return FAILED;
- }
- return SUCCESS;
-}
-
-/**
* Implementation of openssl_ec_diffie_hellman_t.get_my_public_value.
*/
static void get_my_public_value(private_openssl_ec_diffie_hellman_t *this,chunk_t *value)
@@ -283,7 +265,6 @@ openssl_ec_diffie_hellman_t *openssl_ec_diffie_hellman_create(diffie_hellman_gro
this->public.dh.get_shared_secret = (status_t (*)(diffie_hellman_t *, chunk_t *)) get_shared_secret;
this->public.dh.set_other_public_value = (void (*)(diffie_hellman_t *, chunk_t )) set_other_public_value;
- this->public.dh.get_other_public_value = (status_t (*)(diffie_hellman_t *, chunk_t *)) get_other_public_value;
this->public.dh.get_my_public_value = (void (*)(diffie_hellman_t *, chunk_t *)) get_my_public_value;
this->public.dh.get_dh_group = (diffie_hellman_group_t (*)(diffie_hellman_t *)) get_dh_group;
this->public.dh.destroy = (void (*)(diffie_hellman_t *)) destroy;
diff --git a/src/libstrongswan/plugins/openssl/openssl_plugin.c b/src/libstrongswan/plugins/openssl/openssl_plugin.c
index 82c54a95e..dcc78aed6 100644
--- a/src/libstrongswan/plugins/openssl/openssl_plugin.c
+++ b/src/libstrongswan/plugins/openssl/openssl_plugin.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2008 Tobias Brunner
+ * Copyright (C) 2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -12,15 +13,18 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: openssl_plugin.c 4309 2008-08-28 11:07:57Z martin $
+ * $Id: openssl_plugin.c 4583 2008-11-05 12:37:37Z martin $
*/
#include <openssl/evp.h>
#include <openssl/engine.h>
+#include <openssl/crypto.h>
+#include <pthread.h>
#include "openssl_plugin.h"
#include <library.h>
+#include <utils/mutex.h>
#include "openssl_crypter.h"
#include "openssl_hasher.h"
#include "openssl_diffie_hellman.h"
@@ -44,6 +48,120 @@ struct private_openssl_plugin_t {
};
/**
+ * Array of static mutexs, with CRYPTO_num_locks() mutex
+ */
+static mutex_t **mutex = NULL;
+
+/**
+ * Locking callback for static locks
+ */
+static void locking_function(int mode, int type, const char *file, int line)
+{
+ if (mutex)
+ {
+ if (mode & CRYPTO_LOCK)
+ {
+ mutex[type]->lock(mutex[type]);
+ }
+ else
+ {
+ mutex[type]->unlock(mutex[type]);
+ }
+ }
+}
+
+/**
+ * Implementation of dynlock
+ */
+struct CRYPTO_dynlock_value {
+ mutex_t *mutex;
+};
+
+/**
+ * Callback to create a dynamic lock
+ */
+static struct CRYPTO_dynlock_value *create_function(const char *file, int line)
+{
+ struct CRYPTO_dynlock_value *lock;
+
+ lock = malloc_thing(struct CRYPTO_dynlock_value);
+ lock->mutex = mutex_create(MUTEX_DEFAULT);
+ return lock;
+}
+
+/**
+ * Callback to (un-)lock a dynamic lock
+ */
+static void lock_function(int mode, struct CRYPTO_dynlock_value *lock,
+ const char *file, int line)
+{
+ if (mode & CRYPTO_LOCK)
+ {
+ lock->mutex->lock(lock->mutex);
+ }
+ else
+ {
+ lock->mutex->unlock(lock->mutex);
+ }
+}
+
+/**
+ * Callback to destroy a dynamic lock
+ */
+static void destroy_function(struct CRYPTO_dynlock_value *lock,
+ const char *file, int line)
+{
+ lock->mutex->destroy(lock->mutex);
+ free(lock);
+}
+
+/**
+ * Thread-ID callback function
+ */
+static unsigned long id_function(void)
+{
+ return pthread_self();
+}
+
+/**
+ * initialize OpenSSL for multi-threaded use
+ */
+static void threading_init()
+{
+ int i, num_locks;
+
+ CRYPTO_set_id_callback(id_function);
+ CRYPTO_set_locking_callback(locking_function);
+
+ CRYPTO_set_dynlock_create_callback(create_function);
+ CRYPTO_set_dynlock_lock_callback(lock_function);
+ CRYPTO_set_dynlock_destroy_callback(destroy_function);
+
+ num_locks = CRYPTO_num_locks();
+ mutex = malloc(sizeof(mutex_t*) * num_locks);
+ for (i = 0; i < num_locks; i++)
+ {
+ mutex[i] = mutex_create(MUTEX_DEFAULT);
+ }
+}
+
+/**
+ * cleanup OpenSSL threading locks
+ */
+static void threading_cleanup()
+{
+ int i, num_locks;
+
+ num_locks = CRYPTO_num_locks();
+ for (i = 0; i < num_locks; i++)
+ {
+ mutex[i]->destroy(mutex[i]);
+ }
+ free(mutex);
+ mutex = NULL;
+}
+
+/**
* Implementation of openssl_plugin_t.destroy
*/
static void destroy(private_openssl_plugin_t *this)
@@ -68,6 +186,8 @@ static void destroy(private_openssl_plugin_t *this)
ENGINE_cleanup();
EVP_cleanup();
+ threading_cleanup();
+
free(this);
}
@@ -80,6 +200,8 @@ plugin_t *plugin_create()
this->public.plugin.destroy = (void(*)(plugin_t*))destroy;
+ threading_init();
+
OpenSSL_add_all_algorithms();
/* activate support for hardware accelerators */
diff --git a/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c b/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c
index 8ad75215a..a815ce622 100644
--- a/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c
+++ b/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c
@@ -12,7 +12,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: openssl_rsa_private_key.c 4317 2008-09-02 11:00:13Z martin $
+ * $Id: openssl_rsa_private_key.c 4564 2008-11-04 13:01:36Z martin $
*/
#include "openssl_rsa_private_key.h"
@@ -74,9 +74,11 @@ openssl_rsa_public_key_t *openssl_rsa_public_key_create_from_n_e(BIGNUM *n, BIGN
* Build an EMPSA PKCS1 signature described in PKCS#1
*/
static bool build_emsa_pkcs1_signature(private_openssl_rsa_private_key_t *this,
- int type, chunk_t data, chunk_t *signature)
+ int type, chunk_t data, chunk_t *out)
{
bool success = FALSE;
+ u_char *sig = NULL;
+ u_int len;
const EVP_MD *hasher = EVP_get_digestbynid(type);
if (!hasher)
{
@@ -105,14 +107,17 @@ static bool build_emsa_pkcs1_signature(private_openssl_rsa_private_key_t *this,
goto error;
}
- *signature = chunk_alloc(RSA_size(this->rsa));
-
- if (!EVP_SignFinal(ctx, signature->ptr, &signature->len, key))
+ sig = malloc(EVP_PKEY_size(key));
+ if (EVP_SignFinal(ctx, sig, &len, key))
{
- goto error;
+ out->ptr = sig;
+ out->len = len;
+ success = TRUE;
+ }
+ else
+ {
+ free(sig);
}
-
- success = TRUE;
error:
if (key)
diff --git a/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c b/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c
index 61b5b9b64..794fa8123 100644
--- a/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c
+++ b/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c
@@ -12,7 +12,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: openssl_rsa_public_key.c 4317 2008-09-02 11:00:13Z martin $
+ * $Id: openssl_rsa_public_key.c 4567 2008-11-04 14:05:42Z martin $
*/
#include "openssl_rsa_public_key.h"
@@ -90,13 +90,11 @@ static bool verify_emsa_pkcs1_signature(private_openssl_rsa_public_key_t *this,
goto error;
}
- /* remove any preceding 0-bytes from signature */
- while (signature.len && *(signature.ptr) == 0x00)
+ /* VerifyFinal expects a signature of exactly RSA size (no leading 0x00) */
+ if (signature.len > RSA_size(this->rsa))
{
- signature.len -= 1;
- signature.ptr++;
+ signature = chunk_skip(signature, signature.len - RSA_size(this->rsa));
}
-
valid = (EVP_VerifyFinal(ctx, signature.ptr, signature.len, key) == 1);
error:
diff --git a/src/libstrongswan/plugins/x509/x509_ac.c b/src/libstrongswan/plugins/x509/x509_ac.c
index caae5e08d..257a903e4 100644
--- a/src/libstrongswan/plugins/x509/x509_ac.c
+++ b/src/libstrongswan/plugins/x509/x509_ac.c
@@ -21,6 +21,8 @@
#include "x509_ac.h"
#include "ietf_attr_list.h"
+#include <time.h>
+
#include <library.h>
#include <debug.h>
#include <asn1/oid.h>
diff --git a/src/libstrongswan/plugins/x509/x509_cert.c b/src/libstrongswan/plugins/x509/x509_cert.c
index c82d14a17..9f76c3486 100644
--- a/src/libstrongswan/plugins/x509/x509_cert.c
+++ b/src/libstrongswan/plugins/x509/x509_cert.c
@@ -17,7 +17,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: x509_cert.c 4317 2008-09-02 11:00:13Z martin $
+ * $Id: x509_cert.c 4576 2008-11-05 08:32:38Z martin $
*/
#define _GNU_SOURCE
@@ -25,6 +25,7 @@
#include "x509_cert.h"
#include <sys/stat.h>
+#include <time.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
diff --git a/src/libstrongswan/plugins/x509/x509_crl.c b/src/libstrongswan/plugins/x509/x509_crl.c
index eb9bfe903..8375d88ef 100644
--- a/src/libstrongswan/plugins/x509/x509_crl.c
+++ b/src/libstrongswan/plugins/x509/x509_crl.c
@@ -12,7 +12,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: x509_crl.c 4317 2008-09-02 11:00:13Z martin $
+ * $Id: x509_crl.c 4576 2008-11-05 08:32:38Z martin $
*/
#include "x509_crl.h"
@@ -20,6 +20,8 @@
typedef struct private_x509_crl_t private_x509_crl_t;
typedef struct revoked_t revoked_t;
+#include <time.h>
+
#include <debug.h>
#include <library.h>
#include <asn1/oid.h>
diff --git a/src/libstrongswan/settings.c b/src/libstrongswan/settings.c
index 6f9e40395..a02823ba0 100644
--- a/src/libstrongswan/settings.c
+++ b/src/libstrongswan/settings.c
@@ -88,9 +88,50 @@ struct kv_t {
char *value;
};
-static char *find(section_t *section, char *key)
+/**
+ * find a section by a given key
+ */
+static section_t *find_section(section_t *section, char *key, va_list args)
+{
+ char name[512], *pos;
+ enumerator_t *enumerator;
+ section_t *current, *found = NULL;
+
+ if (section == NULL)
+ {
+ return NULL;
+ }
+ if (vsnprintf(name, sizeof(name), key, args) >= sizeof(name))
+ {
+ return NULL;
+ }
+
+ pos = strchr(name, '.');
+ if (pos)
+ {
+ *pos = '\0';
+ pos++;
+ }
+ enumerator = section->sections->create_enumerator(section->sections);
+ while (enumerator->enumerate(enumerator, &current))
+ {
+ if (streq(current->name, name))
+ {
+ found = current;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ if (found && pos)
+ {
+ return find_section(found, pos, args);
+ }
+ return found;
+}
+
+static char *find_value(section_t *section, char *key, va_list args)
{
- char *name, *pos, *value = NULL;
+ char name[512], *pos, *value = NULL;
enumerator_t *enumerator;
kv_t *kv;
section_t *current, *found = NULL;
@@ -100,7 +141,10 @@ static char *find(section_t *section, char *key)
return NULL;
}
- name = strdupa(key);
+ if (vsnprintf(name, sizeof(name), key, args) >= sizeof(name))
+ {
+ return NULL;
+ }
pos = strchr(name, '.');
if (pos)
@@ -119,7 +163,7 @@ static char *find(section_t *section, char *key)
enumerator->destroy(enumerator);
if (found)
{
- return find(found, pos);
+ return find_value(found, pos, args);
}
}
else
@@ -141,11 +185,14 @@ static char *find(section_t *section, char *key)
/**
* Implementation of settings_t.get.
*/
-static char* get_str(private_settings_t *this, char *key, char *def)
+static char* get_str(private_settings_t *this, char *key, char *def, ...)
{
char *value;
+ va_list args;
- value = find(this->top, key);
+ va_start(args, def);
+ value = find_value(this->top, key, args);
+ va_end(args);
if (value)
{
return value;
@@ -156,11 +203,14 @@ static char* get_str(private_settings_t *this, char *key, char *def)
/**
* Implementation of settings_t.get_bool.
*/
-static bool get_bool(private_settings_t *this, char *key, bool def)
+static bool get_bool(private_settings_t *this, char *key, bool def, ...)
{
char *value;
+ va_list args;
- value = find(this->top, key);
+ va_start(args, def);
+ value = find_value(this->top, key, args);
+ va_end(args);
if (value)
{
if (strcasecmp(value, "true") == 0 ||
@@ -184,12 +234,15 @@ static bool get_bool(private_settings_t *this, char *key, bool def)
/**
* Implementation of settings_t.get_int.
*/
-static int get_int(private_settings_t *this, char *key, int def)
+static int get_int(private_settings_t *this, char *key, int def, ...)
{
char *value;
int intval;
+ va_list args;
- value = find(this->top, key);
+ va_start(args, def);
+ value = find_value(this->top, key, args);
+ va_end(args);
if (value)
{
errno = 0;
@@ -205,12 +258,15 @@ static int get_int(private_settings_t *this, char *key, int def)
/**
* Implementation of settings_t.get_time.
*/
-static u_int32_t get_time(private_settings_t *this, char *key, u_int32_t def)
+static u_int32_t get_time(private_settings_t *this, char *key, u_int32_t def, ...)
{
char *value, *endptr;
u_int32_t timeval;
+ va_list args;
- value = find(this->top, key);
+ va_start(args, def);
+ value = find_value(this->top, key, args);
+ va_end(args);
if (value)
{
errno = 0;
@@ -239,6 +295,37 @@ static u_int32_t get_time(private_settings_t *this, char *key, u_int32_t def)
}
/**
+ * Enumerate section names, not sections
+ */
+static bool section_filter(void *null, section_t **in, char **out)
+{
+ *out = (*in)->name;
+ return TRUE;
+}
+
+/**
+ * Implementation of settings_t.create_section_enumerator
+ */
+static enumerator_t* create_section_enumerator(private_settings_t *this,
+ char *key, ...)
+{
+ section_t *section;
+ va_list args;
+
+ va_start(args, key);
+ section = find_section(this->top, key, args);
+ va_end(args);
+
+ if (!section)
+ {
+ return enumerator_create_empty();
+ }
+ return enumerator_create_filter(
+ section->sections->create_enumerator(section->sections),
+ (void*)section_filter, NULL, NULL);
+}
+
+/**
* destroy a section
*/
static void section_destroy(section_t *this)
@@ -400,10 +487,11 @@ settings_t *settings_create(char *file)
{
private_settings_t *this = malloc_thing(private_settings_t);
- this->public.get_str = (char*(*)(settings_t*, char *key, char* def))get_str;
- this->public.get_int = (int(*)(settings_t*, char *key, int def))get_int;
- this->public.get_time = (u_int32_t(*)(settings_t*, char *key, u_int32_t def))get_time;
- this->public.get_bool = (bool(*)(settings_t*, char *key, bool def))get_bool;
+ this->public.get_str = (char*(*)(settings_t*, char *key, char* def, ...))get_str;
+ this->public.get_int = (int(*)(settings_t*, char *key, int def, ...))get_int;
+ this->public.get_time = (u_int32_t(*)(settings_t*, char *key, u_int32_t def, ...))get_time;
+ this->public.get_bool = (bool(*)(settings_t*, char *key, bool def, ...))get_bool;
+ this->public.create_section_enumerator = (enumerator_t*(*)(settings_t*,char *section, ...))create_section_enumerator;
this->public.destroy = (void(*)(settings_t*))destroy;
this->top = NULL;
diff --git a/src/libstrongswan/settings.h b/src/libstrongswan/settings.h
index 451c2a583..0f41878c5 100644
--- a/src/libstrongswan/settings.h
+++ b/src/libstrongswan/settings.h
@@ -26,11 +26,12 @@
typedef struct settings_t settings_t;
#include <library.h>
+#include <utils/enumerator.h>
/**
* Generic configuration options read from a config file.
*
- * The sytax is quite simple:
+ * The syntax is quite simple:
*
* settings := (section|keyvalue)*
* section := name { settings }
@@ -38,8 +39,8 @@ typedef struct settings_t settings_t;
*
* E.g.:
* @code
- a = b
- section-one {
+ a = b
+ section-one {
somevalue = asdf
subsection {
othervalue = xxx
@@ -58,43 +59,56 @@ struct settings_t {
/**
* Get a settings value as a string.
*
- * @param key key including sections
+ * @param key key including sections, printf style format
* @param def value returned if key not found
+ * @param ... argument list for key
* @return value pointing to internal string
*/
- char* (*get_str)(settings_t *this, char *key, char *def);
+ char* (*get_str)(settings_t *this, char *key, char *def, ...);
/**
* Get a boolean yes|no, true|false value.
*
- * @param jey key including sections
- * @param def default value returned if key not found
+ * @param key key including sections, printf style format
+ * @param def value returned if key not found
+ * @param ... argument list for key
* @return value of the key
*/
- bool (*get_bool)(settings_t *this, char *key, bool def);
+ bool (*get_bool)(settings_t *this, char *key, bool def, ...);
/**
* Get an integer value.
*
- * @param key key including sections
- * @param def default value to return if key not found
+ * @param key key including sections, printf style format
+ * @param def value returned if key not found
+ * @param ... argument list for key
* @return value of the key
*/
- int (*get_int)(settings_t *this, char *key, int def);
+ int (*get_int)(settings_t *this, char *key, int def, ...);
/**
* Get a time value.
*
- * @param key key including sections
- * @param def default value to return if key not found
+ * @param key key including sections, printf style format
+ * @param def value returned if key not found
+ * @param ... argument list for key
* @return value of the key
*/
- u_int32_t (*get_time)(settings_t *this, char *key, u_int32_t def);
-
+ u_int32_t (*get_time)(settings_t *this, char *key, u_int32_t def, ...);
+
/**
- * Destroy a settings instance.
- */
- void (*destroy)(settings_t *this);
+ * Create an enumerator over subsection names of a section.
+ *
+ * @param section section including parents, printf style format
+ * @param ... argument list for key
+ * @return enumerator over subsection names
+ */
+ enumerator_t* (*create_section_enumerator)(settings_t *this,
+ char *section, ...);
+ /**
+ * Destroy a settings instance.
+ */
+ void (*destroy)(settings_t *this);
};
/**
diff --git a/src/libstrongswan/utils.h b/src/libstrongswan/utils.h
index 4af7df9ad..a5900201a 100644
--- a/src/libstrongswan/utils.h
+++ b/src/libstrongswan/utils.h
@@ -13,7 +13,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: utils.h 4305 2008-08-28 07:47:55Z tobias $
+ * $Id: utils.h 4632 2008-11-11 18:37:19Z martin $
*/
/**
@@ -96,6 +96,11 @@
#define countof(array) (sizeof(array)/sizeof(array[0]))
/**
+ * Ignore result of functions tagged with warn_unused_result attributes
+ */
+#define ignore_result(call) { if(call); }
+
+/**
* Assign a function as a class method
*/
#define ASSIGN(method, function) (method = (typeof(method))function)
diff --git a/src/libstrongswan/utils/backtrace.c b/src/libstrongswan/utils/backtrace.c
new file mode 100644
index 000000000..3caafdc38
--- /dev/null
+++ b/src/libstrongswan/utils/backtrace.c
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2006-2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * $Id$
+ */
+
+#define _GNU_SOURCE
+
+#ifdef HAVE_DLADDR
+# include <dlfcn.h>
+#endif /* HAVE_DLADDR */
+
+#ifdef HAVE_BACKTRACE
+# include <execinfo.h>
+#endif /* HAVE_BACKTRACE */
+
+#include "backtrace.h"
+
+typedef struct private_backtrace_t private_backtrace_t;
+
+/**
+ * Private data of an backtrace_t object.
+ */
+struct private_backtrace_t {
+
+ /**
+ * Public backtrace_t interface.
+ */
+ backtrace_t public;
+
+ /**
+ * Number of stacks frames obtained in stack_frames
+ */
+ int frame_count;
+
+ /**
+ * Recorded stack frames.
+ */
+ void *frames[];
+};
+
+/**
+ * Implementation of backtrace_t.log
+ */
+static void log_(private_backtrace_t *this, FILE *file)
+{
+#ifdef HAVE_BACKTRACE
+ size_t i;
+ char **strings;
+
+ strings = backtrace_symbols(this->frames, this->frame_count);
+
+ fprintf(file, " dumping %d stack frame addresses:\n", this->frame_count);
+ for (i = 0; i < this->frame_count; i++)
+ {
+#ifdef HAVE_DLADDR
+ Dl_info info;
+
+ if (dladdr(this->frames[i], &info))
+ {
+ char cmd[1024];
+ FILE *output;
+ char c;
+ void *ptr = this->frames[i];
+
+ if (strstr(info.dli_fname, ".so"))
+ {
+ ptr = (void*)(this->frames[i] - info.dli_fbase);
+ }
+ snprintf(cmd, sizeof(cmd), "addr2line -e %s %p", info.dli_fname, ptr);
+ if (info.dli_sname)
+ {
+ fprintf(file, " \e[33m%s\e[0m @ %p (\e[31m%s\e[0m+0x%x) [%p]\n",
+ info.dli_fname, info.dli_fbase, info.dli_sname,
+ this->frames[i] - info.dli_saddr, this->frames[i]);
+ }
+ else
+ {
+ fprintf(file, " \e[33m%s\e[0m @ %p [%p]\n", info.dli_fname,
+ info.dli_fbase, this->frames[i]);
+ }
+ fprintf(file, " -> \e[32m");
+ output = popen(cmd, "r");
+ if (output)
+ {
+ while (TRUE)
+ {
+ c = getc(output);
+ if (c == '\n' || c == EOF)
+ {
+ break;
+ }
+ fputc(c, file);
+ }
+ pclose(output);
+ }
+ else
+ {
+#endif /* HAVE_DLADDR */
+ fprintf(file, " %s\n", strings[i]);
+#ifdef HAVE_DLADDR
+ }
+ fprintf(file, "\n\e[0m");
+ }
+ else
+ {
+ fprintf(file, " %s\n", strings[i]);
+ }
+#endif /* HAVE_DLADDR */
+ }
+ free (strings);
+#else /* !HAVE_BACKTRACE */
+ fprintf(file, "C library does not support backtrace().\n");
+#endif /* HAVE_BACKTRACE */
+}
+
+/**
+ * Implementation of backtrace_t.contains_function
+ */
+static bool contains_function(private_backtrace_t *this, char *function)
+{
+#ifdef HAVE_DLADDR
+ int i;
+
+ for (i = 0; i< this->frame_count; i++)
+ {
+ Dl_info info;
+
+ if (dladdr(this->frames[i], &info) && info.dli_sname)
+ {
+ if (streq(info.dli_sname, function))
+ {
+ return TRUE;
+ }
+ }
+ }
+#endif /* HAVE_DLADDR */
+ return FALSE;
+}
+
+/**
+ * Implementation of backtrace_t.destroy.
+ */
+static void destroy(private_backtrace_t *this)
+{
+ free(this);
+}
+
+/**
+ * See header
+ */
+backtrace_t *backtrace_create(int skip)
+{
+ private_backtrace_t *this;
+ void *frames[50];
+ int frame_count = 0;
+
+#ifdef HAVE_BACKTRACE
+ frame_count = backtrace(frames, countof(frames));
+#endif /* HAVE_BACKTRACE */
+ frame_count = max(frame_count - skip, 0);
+ this = malloc(sizeof(private_backtrace_t) + frame_count * sizeof(void*));
+ memcpy(this->frames, frames + skip, frame_count * sizeof(void*));
+ this->frame_count = frame_count;
+
+ this->public.log = (void(*)(backtrace_t*,FILE*))log_;
+ this->public.contains_function = (bool(*)(backtrace_t*, char *function))contains_function;
+ this->public.destroy = (void(*)(backtrace_t*))destroy;
+
+ return &this->public;
+}
+
diff --git a/src/libstrongswan/utils/backtrace.h b/src/libstrongswan/utils/backtrace.h
new file mode 100644
index 000000000..72effd01e
--- /dev/null
+++ b/src/libstrongswan/utils/backtrace.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup backtrace backtrace
+ * @{ @ingroup utils
+ */
+
+#ifndef BACKTRACE_H_
+#define BACKTRACE_H_
+
+#include <stdio.h>
+
+#include <library.h>
+
+typedef struct backtrace_t backtrace_t;
+
+/**
+ * A backtrace registers the frames on the stack during creation.
+ */
+struct backtrace_t {
+
+ /**
+ * Log the backtrace to a FILE stream.
+ */
+ void (*log)(backtrace_t *this, FILE *file);
+
+ /**
+ * Check if the backtrace contains a frame in a specific function.
+ *
+ * @param function name
+ * @return TRUE if function is in the stack
+ */
+ bool (*contains_function)(backtrace_t *this, char *function);
+
+ /**
+ * Destroy a backtrace instance.
+ */
+ void (*destroy)(backtrace_t *this);
+};
+
+/**
+ * Create a backtrace of the current stack.
+ *
+ * @param skip how many of the innerst frames to skip
+ * @return backtrace
+ */
+backtrace_t *backtrace_create(int skip);
+
+#endif /* BACKTRACE_H_ @}*/
+
diff --git a/src/libstrongswan/utils/host.c b/src/libstrongswan/utils/host.c
index eb87f27bc..4702222e8 100644
--- a/src/libstrongswan/utils/host.c
+++ b/src/libstrongswan/utils/host.c
@@ -15,7 +15,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: host.c 4056 2008-06-11 07:44:23Z martin $
+ * $Id: host.c 4639 2008-11-12 15:09:24Z martin $
*/
#define _GNU_SOURCE
@@ -27,6 +27,9 @@
#include <debug.h>
+#define IPV4_LEN 4
+#define IPV6_LEN 16
+
typedef struct private_host_t private_host_t;
/**
@@ -83,17 +86,17 @@ static bool is_anyaddr(private_host_t *this)
{
case AF_INET:
{
- u_int8_t default_route[4];
- memset(default_route, 0, sizeof(default_route));
- return memeq(default_route, &(this->address4.sin_addr.s_addr),
- sizeof(default_route));
+ u_int8_t zeroes[IPV4_LEN];
+
+ memset(zeroes, 0, IPV4_LEN);
+ return memeq(zeroes, &(this->address4.sin_addr.s_addr), IPV4_LEN);
}
case AF_INET6:
{
- u_int8_t default_route[16];
- memset(default_route, 0, sizeof(default_route));
- return memeq(default_route, &(this->address6.sin6_addr.s6_addr),
- sizeof(default_route));
+ u_int8_t zeroes[IPV6_LEN];
+
+ memset(zeroes, 0, IPV6_LEN);
+ return memeq(zeroes, &(this->address6.sin6_addr.s6_addr), IPV6_LEN);
}
default:
{
@@ -196,13 +199,13 @@ static chunk_t get_address(private_host_t *this)
case AF_INET:
{
address.ptr = (char*)&(this->address4.sin_addr.s_addr);
- address.len = 4;
+ address.len = IPV4_LEN;
return address;
}
case AF_INET6:
{
address.ptr = (char*)&(this->address6.sin6_addr.s6_addr);
- address.len = 16;
+ address.len = IPV6_LEN;
return address;
}
default:
@@ -285,33 +288,21 @@ static bool ip_equals(private_host_t *this, private_host_t *other)
{
if (this->address.sa_family != other->address.sa_family)
{
- /* 0.0.0.0 and ::0 are equal */
- if (is_anyaddr(this) && is_anyaddr(other))
- {
- return TRUE;
- }
-
- return FALSE;
+ /* 0.0.0.0 and 0::0 are equal */
+ return (is_anyaddr(this) && is_anyaddr(other));
}
switch (this->address.sa_family)
{
case AF_INET:
{
- if (memeq(&this->address4.sin_addr, &other->address4.sin_addr,
- sizeof(this->address4.sin_addr)))
- {
- return TRUE;
- }
- break;
+ return memeq(&this->address4.sin_addr, &other->address4.sin_addr,
+ sizeof(this->address4.sin_addr));
}
case AF_INET6:
{
- if (memeq(&this->address6.sin6_addr, &other->address6.sin6_addr,
- sizeof(this->address6.sin6_addr)))
- {
- return TRUE;
- }
+ return memeq(&this->address6.sin6_addr, &other->address6.sin6_addr,
+ sizeof(this->address6.sin6_addr));
}
default:
break;
@@ -340,7 +331,7 @@ static host_diff_t get_differences(host_t *this, host_t *other)
}
/**
- * Impelements host_t.equals
+ * Implements host_t.equals
*/
static bool equals(private_host_t *this, private_host_t *other)
{
@@ -353,19 +344,11 @@ static bool equals(private_host_t *this, private_host_t *other)
{
case AF_INET:
{
- if (this->address4.sin_port == other->address4.sin_port)
- {
- return TRUE;
- }
- break;
+ return (this->address4.sin_port == other->address4.sin_port);
}
case AF_INET6:
{
- if (this->address6.sin6_port == other->address6.sin6_port)
- {
- return TRUE;
- }
- break;
+ return (this->address6.sin6_port == other->address6.sin6_port);
}
default:
break;
@@ -409,8 +392,14 @@ static private_host_t *host_create_empty(void)
*/
host_t *host_create_from_string(char *string, u_int16_t port)
{
- private_host_t *this = host_create_empty();
+ private_host_t *this;
+ if (streq(string, "%any"))
+ {
+ return host_create_any(AF_INET);
+ }
+
+ this = host_create_empty();
if (strchr(string, '.'))
{
this->address.sa_family = AF_INET;
@@ -419,7 +408,6 @@ host_t *host_create_from_string(char *string, u_int16_t port)
{
this->address.sa_family = AF_INET6;
}
-
switch (this->address.sa_family)
{
case AF_INET:
@@ -460,9 +448,14 @@ host_t *host_create_from_dns(char *string, int af, u_int16_t port)
struct hostent host, *ptr;
char buf[512];
int err, ret;
-
- if (strchr(string, ':'))
- { /* gethostbyname does not like IPv6 addresses, fallback */
+
+ if (streq(string, "%any"))
+ {
+ return host_create_any(af ? af : AF_INET);
+ }
+ else if (strchr(string, ':'))
+ {
+ /* gethostbyname does not like IPv6 addresses - fallback */
return host_create_from_string(string, port);
}
@@ -511,38 +504,56 @@ host_t *host_create_from_dns(char *string, int af, u_int16_t port)
*/
host_t *host_create_from_chunk(int family, chunk_t address, u_int16_t port)
{
- private_host_t *this = host_create_empty();
+ private_host_t *this;
- this->address.sa_family = family;
switch (family)
{
case AF_INET:
- {
- if (address.len != 4)
+ if (address.len < IPV4_LEN)
{
- break;
+ return NULL;
}
- memcpy(&(this->address4.sin_addr.s_addr), address.ptr,4);
- this->address4.sin_port = htons(port);
- this->socklen = sizeof(struct sockaddr_in);
- return &(this->public);
- }
+ address.len = IPV4_LEN;
+ break;
case AF_INET6:
- {
- if (address.len != 16)
+ if (address.len < IPV6_LEN)
{
- break;
+ return NULL;
+ }
+ address.len = IPV6_LEN;
+ break;
+ case AF_UNSPEC:
+ switch (address.len)
+ {
+ case IPV4_LEN:
+ family = AF_INET;
+ break;
+ case IPV6_LEN:
+ family = AF_INET6;
+ break;
+ default:
+ return NULL;
}
- memcpy(&(this->address6.sin6_addr.s6_addr), address.ptr, 16);
+ break;
+ default:
+ return NULL;
+ }
+ this = host_create_empty();
+ this->address.sa_family = family;
+ switch (family)
+ {
+ case AF_INET:
+ memcpy(&this->address4.sin_addr.s_addr, address.ptr, address.len);
+ this->address4.sin_port = htons(port);
+ this->socklen = sizeof(struct sockaddr_in);
+ break;
+ case AF_INET6:
+ memcpy(&this->address6.sin6_addr.s6_addr, address.ptr, address.len);
this->address6.sin6_port = htons(port);
this->socklen = sizeof(struct sockaddr_in6);
- return &this->public;
- }
- default:
break;
}
- free(this);
- return NULL;
+ return &this->public;
}
/*
diff --git a/src/libstrongswan/utils/host.h b/src/libstrongswan/utils/host.h
index 6a1d824c6..667cc6bcc 100644
--- a/src/libstrongswan/utils/host.h
+++ b/src/libstrongswan/utils/host.h
@@ -170,10 +170,12 @@ host_t *host_create_from_string(char *string, u_int16_t port);
host_t *host_create_from_dns(char *string, int family, u_int16_t port);
/**
- * Constructor to create a host_t object from an address chunk
+ * Constructor to create a host_t object from an address chunk.
+ *
+ * If family is AF_UNSPEC, it is guessed using address.len.
*
* @param family Address family, such as AF_INET or AF_INET6
- * @param address address as chunk_t in networ order
+ * @param address address as chunk_t in network order
* @param port port number
* @return host_t, NULL if family not supported/chunk invalid
*/
diff --git a/src/libstrongswan/utils/iterator.h b/src/libstrongswan/utils/iterator.h
index a1bdad1d6..28ee74cd6 100644
--- a/src/libstrongswan/utils/iterator.h
+++ b/src/libstrongswan/utils/iterator.h
@@ -13,7 +13,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: iterator.h 3589 2008-03-13 14:14:44Z martin $
+ * $Id: iterator.h 4577 2008-11-05 08:37:09Z martin $
*/
/**
@@ -26,43 +26,6 @@
#include <library.h>
-typedef enum hook_result_t hook_result_t;
-
-/**
- * Return value of an iterator hook.
- *
- * Returning HOOK_AGAIN is useful to "inject" additional elements in an
- * iteration, HOOK_NEXT is the normal iterator behavior, and HOOK_SKIP may
- * be used to filter elements out.
- */
-enum hook_result_t {
-
- /**
- * A value was placed in out, hook is called again with the same "in"
- */
- HOOK_AGAIN,
-
- /**
- * A value was placed in out, hook is called again with next "in" (if any)
- */
- HOOK_NEXT,
-
- /**
- * No value in out, call again with next "in" (if any)
- */
- HOOK_SKIP,
-};
-
-/**
- * Iterator hook function prototype.
- *
- * @param param user supplied parameter
- * @param in the value the hook receives from the iterator
- * @param out the value supplied as a result to the iterator
- * @return a hook_result_t
- */
-typedef hook_result_t (iterator_hook_t)(void *param, void *in, void **out);
-
typedef struct iterator_t iterator_t;
@@ -94,24 +57,6 @@ struct iterator_t {
bool (*iterate) (iterator_t *this, void** value);
/**
- * Hook a function into the iterator.
- *
- * Sometimes it is useful to hook in an iterator. The hook function is
- * called before any successful return of iterate(). It takes the
- * iterator value, may manipulate it (or the references object), and returns
- * the value that the iterate() function returns. Depending on the hook
- * return value, the hook is called again, called with next, or skipped.
- * A value of NULL deactivates the iterator hook.
- * If an iterator is hooked, only the iterate() method is valid,
- * all other methods behave undefined.
- *
- * @param hook iterator hook which manipulates the iterated value
- * @param param user supplied parameter to pass back to the hook
- */
- void (*set_iterator_hook) (iterator_t *this, iterator_hook_t *hook,
- void *param);
-
- /**
* Inserts a new item before the given iterator position.
*
* The iterator position is not changed after inserting
diff --git a/src/libstrongswan/utils/leak_detective.c b/src/libstrongswan/utils/leak_detective.c
index bc7f56ebd..73409158d 100644
--- a/src/libstrongswan/utils/leak_detective.c
+++ b/src/libstrongswan/utils/leak_detective.c
@@ -12,13 +12,8 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: leak_detective.c 4311 2008-08-28 16:27:48Z martin $
+ * $Id: leak_detective.c 4609 2008-11-10 16:44:27Z martin $
*/
-
-#ifdef HAVE_DLADDR
-# define _GNU_SOURCE
-# include <dlfcn.h>
-#endif /* HAVE_DLADDR */
#include <stddef.h>
#include <string.h>
@@ -28,21 +23,18 @@
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
-#include <dlfcn.h>
#include <unistd.h>
#include <syslog.h>
#include <pthread.h>
#include <netdb.h>
#include <printf.h>
#include <locale.h>
-#ifdef HAVE_BACKTRACE
-# include <execinfo.h>
-#endif /* HAVE_BACKTRACE */
#include "leak_detective.h"
#include <library.h>
#include <debug.h>
+#include <utils/backtrace.h>
typedef struct private_leak_detective_t private_leak_detective_t;
@@ -106,16 +98,6 @@ struct memory_header_t {
u_int bytes;
/**
- * Stack frames at the time of allocation
- */
- void *stack_frames[STACK_FRAMES_COUNT];
-
- /**
- * Number of stacks frames obtained in stack_frames
- */
- int stack_frame_count;
-
- /**
* Pointer to previous entry in linked list
*/
memory_header_t *previous;
@@ -126,6 +108,11 @@ struct memory_header_t {
memory_header_t *next;
/**
+ * backtrace taken during (re-)allocation
+ */
+ backtrace_t *backtrace;
+
+ /**
* magic bytes to detect bad free or heap underflow, MEMORY_HEADER_MAGIC
*/
u_int32_t magic;
@@ -151,7 +138,7 @@ struct memory_tail_t {
static memory_header_t first_header = {
magic: MEMORY_HEADER_MAGIC,
bytes: 0,
- stack_frame_count: 0,
+ backtrace: NULL,
previous: NULL,
next: NULL
};
@@ -162,88 +149,21 @@ static memory_header_t first_header = {
static bool installed = FALSE;
/**
- * log stack frames queried by backtrace()
- * TODO: Dump symbols of static functions. This could be done with
- * the addr2line utility or the GNU BFD Library...
- */
-static void log_stack_frames(void **stack_frames, int stack_frame_count)
-{
-#ifdef HAVE_BACKTRACE
- size_t i;
- char **strings;
-
- strings = backtrace_symbols(stack_frames, stack_frame_count);
-
- fprintf(stderr, " dumping %d stack frame addresses:\n", stack_frame_count);
- for (i = 0; i < stack_frame_count; i++)
- {
-#ifdef HAVE_DLADDR
- Dl_info info;
-
- if (dladdr(stack_frames[i], &info))
- {
- char cmd[1024];
- FILE *output;
- char c;
- void *ptr = stack_frames[i];
-
- if (strstr(info.dli_fname, ".so"))
- {
- ptr = (void*)(stack_frames[i] - info.dli_fbase);
- }
- snprintf(cmd, sizeof(cmd), "addr2line -e %s %p", info.dli_fname, ptr);
- if (info.dli_sname)
- {
- fprintf(stderr, " \e[33m%s\e[0m @ %p (\e[31m%s\e[0m+0x%x) [%p]\n",
- info.dli_fname, info.dli_fbase, info.dli_sname,
- stack_frames[i] - info.dli_saddr, stack_frames[i]);
- }
- else
- {
- fprintf(stderr, " \e[33m%s\e[0m @ %p [%p]\n", info.dli_fname,
- info.dli_fbase, stack_frames[i]);
- }
- fprintf(stderr, " -> \e[32m");
- output = popen(cmd, "r");
- if (output)
- {
- while (TRUE)
- {
- c = getc(output);
- if (c == '\n' || c == EOF)
- {
- break;
- }
- fputc(c, stderr);
- }
- }
- else
- {
-#endif /* HAVE_DLADDR */
- fprintf(stderr, " %s\n", strings[i]);
-#ifdef HAVE_DLADDR
- }
- fprintf(stderr, "\n\e[0m");
- }
-#endif /* HAVE_DLADDR */
- }
- free (strings);
-#endif /* HAVE_BACKTRACE */
-}
-
-/**
* Leak report white list
*
* List of functions using static allocation buffers or should be suppressed
* otherwise on leak report.
*/
char *whitelist[] = {
+ /* backtraces, including own */
+ "backtrace_create",
/* pthread stuff */
"pthread_create",
"pthread_setspecific",
/* glibc functions */
"mktime",
"__gmtime_r",
+ "localtime_r",
"tzset",
"inet_ntoa",
"strerror",
@@ -284,27 +204,16 @@ char *whitelist[] = {
/**
* check if a stack frame contains functions listed above
*/
-static bool is_whitelisted(void **stack_frames, int stack_frame_count)
+static bool is_whitelisted(backtrace_t *backtrace)
{
- int i, j;
-
-#ifdef HAVE_DLADDR
- for (i=0; i< stack_frame_count; i++)
+ int i;
+ for (i = 0; i < sizeof(whitelist)/sizeof(char*); i++)
{
- Dl_info info;
-
- if (dladdr(stack_frames[i], &info) && info.dli_sname)
- {
- for (j = 0; j < sizeof(whitelist)/sizeof(char*); j++)
- {
- if (streq(info.dli_sname, whitelist[j]))
- {
- return TRUE;
- }
- }
+ if (backtrace->contains_function(backtrace, whitelist[i]))
+ {
+ return TRUE;
}
}
-#endif /* HAVE_DLADDR */
return FALSE;
}
@@ -318,7 +227,7 @@ void report_leaks()
for (hdr = first_header.next; hdr != NULL; hdr = hdr->next)
{
- if (is_whitelisted(hdr->stack_frames, hdr->stack_frame_count))
+ if (is_whitelisted(hdr->backtrace))
{
whitelisted++;
}
@@ -326,7 +235,7 @@ void report_leaks()
{
fprintf(stderr, "Leak (%d bytes at %p):\n", hdr->bytes, hdr + 1);
/* skip the first frame, contains leak detective logic */
- log_stack_frames(hdr->stack_frames + 1, hdr->stack_frame_count - 1);
+ hdr->backtrace->log(hdr->backtrace, stderr);
leaks++;
}
}
@@ -403,7 +312,7 @@ void *malloc_hook(size_t bytes, const void *caller)
hdr->magic = MEMORY_HEADER_MAGIC;
hdr->bytes = bytes;
- hdr->stack_frame_count = backtrace(hdr->stack_frames, STACK_FRAMES_COUNT);
+ hdr->backtrace = backtrace_create(3);
tail->magic = MEMORY_TAIL_MAGIC;
install_hooks();
@@ -426,10 +335,9 @@ void *malloc_hook(size_t bytes, const void *caller)
*/
void free_hook(void *ptr, const void *caller)
{
- void *stack_frames[STACK_FRAMES_COUNT];
- int stack_frame_count;
memory_header_t *hdr;
memory_tail_t *tail;
+ backtrace_t *backtrace;
pthread_t thread_id = pthread_self();
int oldpolicy;
struct sched_param oldparams, params;
@@ -455,8 +363,9 @@ void free_hook(void *ptr, const void *caller)
fprintf(stderr, "freeing invalid memory (%p): "
"header magic 0x%x, tail magic 0x%x:\n",
ptr, hdr->magic, tail->magic);
- stack_frame_count = backtrace(stack_frames, STACK_FRAMES_COUNT);
- log_stack_frames(stack_frames, stack_frame_count);
+ backtrace = backtrace_create(3);
+ backtrace->log(backtrace, stderr);
+ backtrace->destroy(backtrace);
}
else
{
@@ -466,10 +375,11 @@ void free_hook(void *ptr, const void *caller)
hdr->next->previous = hdr->previous;
}
hdr->previous->next = hdr->next;
-
+ hdr->backtrace->destroy(hdr->backtrace);
+
/* clear MAGIC, set mem to something remarkable */
memset(hdr, MEMORY_FREE_PATTERN, hdr->bytes + sizeof(memory_header_t));
-
+
free(hdr);
}
@@ -483,9 +393,8 @@ void free_hook(void *ptr, const void *caller)
void *realloc_hook(void *old, size_t bytes, const void *caller)
{
memory_header_t *hdr;
- void *stack_frames[STACK_FRAMES_COUNT];
- int stack_frame_count;
memory_tail_t *tail;
+ backtrace_t *backtrace;
pthread_t thread_id = pthread_self();
int oldpolicy;
struct sched_param oldparams, params;
@@ -512,8 +421,9 @@ void *realloc_hook(void *old, size_t bytes, const void *caller)
fprintf(stderr, "reallocating invalid memory (%p): "
"header magic 0x%x, tail magic 0x%x:\n",
old, hdr->magic, tail->magic);
- stack_frame_count = backtrace(stack_frames, STACK_FRAMES_COUNT);
- log_stack_frames(stack_frames, stack_frame_count);
+ backtrace = backtrace_create(3);
+ backtrace->log(backtrace, stderr);
+ backtrace->destroy(backtrace);
}
/* clear tail magic, allocate, set tail magic */
memset(&tail->magic, MEMORY_ALLOC_PATTERN, sizeof(tail->magic));
@@ -523,7 +433,8 @@ void *realloc_hook(void *old, size_t bytes, const void *caller)
/* update statistics */
hdr->bytes = bytes;
- hdr->stack_frame_count = backtrace(hdr->stack_frames, STACK_FRAMES_COUNT);
+ hdr->backtrace->destroy(hdr->backtrace);
+ hdr->backtrace = backtrace_create(3);
/* update header of linked list neighbours */
if (hdr->next)
diff --git a/src/libstrongswan/utils/leak_detective.h b/src/libstrongswan/utils/leak_detective.h
index 763814726..3773fb8e5 100644
--- a/src/libstrongswan/utils/leak_detective.h
+++ b/src/libstrongswan/utils/leak_detective.h
@@ -21,11 +21,6 @@
#ifndef LEAK_DETECTIVE_H_
#define LEAK_DETECTIVE_H_
-/**
- * Maximum depth stack frames to register
- */
-#define STACK_FRAMES_COUNT 20
-
typedef struct leak_detective_t leak_detective_t;
/**
diff --git a/src/libstrongswan/utils/linked_list.c b/src/libstrongswan/utils/linked_list.c
index 80c4e6f9f..068d13f99 100644
--- a/src/libstrongswan/utils/linked_list.c
+++ b/src/libstrongswan/utils/linked_list.c
@@ -14,7 +14,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: linked_list.c 3841 2008-04-18 11:48:53Z tobias $
+ * $Id: linked_list.c 4580 2008-11-05 11:55:17Z martin $
*/
#include <stdlib.h>
@@ -119,21 +119,6 @@ struct private_iterator_t {
* Direction of iterator.
*/
bool forward;
-
- /**
- * Mutex to use to synchronize access
- */
- pthread_mutex_t *mutex;
-
- /**
- * iteration hook
- */
- iterator_hook_t *hook;
-
- /**
- * user parameter for iterator hook
- */
- void *hook_param;
};
typedef struct private_enumerator_t private_enumerator_t;
@@ -208,75 +193,23 @@ static int get_list_count(private_iterator_t *this)
}
/**
- * default iterator hook which does nothing
- */
-static hook_result_t iterator_hook(void *param, void *in, void **out)
-{
- *out = in;
- return HOOK_NEXT;
-}
-
-/**
- * Implementation of iterator_t.set_iterator_hook.
+ * Implementation of iterator_t.iterate.
*/
-static void set_iterator_hook(private_iterator_t *this, iterator_hook_t *hook,
- void* param)
+static bool iterate(private_iterator_t *this, void** value)
{
- if (hook == NULL)
+ if (this->forward)
{
- this->hook = iterator_hook;
- this->hook_param = NULL;
+ this->current = this->current ? this->current->next : this->list->first;
}
else
{
- this->hook = hook;
- this->hook_param = param;
+ this->current = this->current ? this->current->previous : this->list->last;
}
-}
-
-/**
- * Implementation of iterator_t.iterate.
- */
-static bool iterate(private_iterator_t *this, void** value)
-{
- while (TRUE)
+ if (this->current == NULL)
{
- if (this->forward)
- {
- this->current = this->current ? this->current->next : this->list->first;
- }
- else
- {
- this->current = this->current ? this->current->previous : this->list->last;
- }
-
- if (this->current == NULL)
- {
- return FALSE;
- }
-
- switch (this->hook(this->hook_param, this->current->value, value))
- {
- case HOOK_AGAIN:
- /* rewind */
- if (this->forward)
- {
- this->current = this->current->previous;
- }
- else
- {
- this->current = this->current->next;
- }
- break;
- case HOOK_NEXT:
- /* normal iteration */
- break;
- case HOOK_SKIP:
- /* advance */
- continue;
- }
- break;
+ return FALSE;
}
+ *value = this->current->value;
return TRUE;
}
@@ -428,10 +361,6 @@ static void insert_after(private_iterator_t *iterator, void *item)
*/
static void iterator_destroy(private_iterator_t *this)
{
- if (this->mutex)
- {
- pthread_mutex_unlock(this->mutex);
- }
free(this);
}
@@ -632,7 +561,8 @@ static status_t find_first(private_linked_list_t *this, linked_list_match_t matc
while (current)
{
- if (match(current->value, d1, d2, d3, d4, d5))
+ if ((match && match(current->value, d1, d2, d3, d4, d5)) ||
+ (!match && item && current->value == *item))
{
if (item != NULL)
{
@@ -655,7 +585,8 @@ static status_t find_last(private_linked_list_t *this, linked_list_match_t match
while (current)
{
- if (match(current->value, d1, d2, d3, d4, d5))
+ if ((match && match(current->value, d1, d2, d3, d4, d5)) ||
+ (!match && item && current->value == *item))
{
if (item != NULL)
{
@@ -793,7 +724,6 @@ static iterator_t *create_iterator(private_linked_list_t *linked_list, bool forw
this->public.get_count = (int (*) (iterator_t*)) get_list_count;
this->public.iterate = (bool (*) (iterator_t*, void **value)) iterate;
- this->public.set_iterator_hook = (void(*)(iterator_t*, iterator_hook_t*, void*))set_iterator_hook;
this->public.insert_before = (void (*) (iterator_t*, void *item)) insert_before;
this->public.insert_after = (void (*) (iterator_t*, void *item)) insert_after;
this->public.replace = (status_t (*) (iterator_t*, void **, void *)) replace;
@@ -804,22 +734,6 @@ static iterator_t *create_iterator(private_linked_list_t *linked_list, bool forw
this->forward = forward;
this->current = NULL;
this->list = linked_list;
- this->mutex = NULL;
- this->hook = iterator_hook;
-
- return &this->public;
-}
-
-/**
- * Implementation of linked_list_t.create_iterator_locked.
- */
-static iterator_t *create_iterator_locked(private_linked_list_t *linked_list,
- pthread_mutex_t *mutex)
-{
- private_iterator_t *this = (private_iterator_t*)create_iterator(linked_list, TRUE);
- this->mutex = mutex;
-
- pthread_mutex_lock(mutex);
return &this->public;
}
@@ -833,7 +747,6 @@ linked_list_t *linked_list_create()
this->public.get_count = (int (*) (linked_list_t *)) get_count;
this->public.create_iterator = (iterator_t * (*) (linked_list_t *,bool))create_iterator;
- this->public.create_iterator_locked = (iterator_t * (*) (linked_list_t *,pthread_mutex_t*))create_iterator_locked;
this->public.create_enumerator = (enumerator_t*(*)(linked_list_t*))create_enumerator;
this->public.get_first = (status_t (*) (linked_list_t *, void **item))get_first;
this->public.get_last = (status_t (*) (linked_list_t *, void **item))get_last;
diff --git a/src/libstrongswan/utils/linked_list.h b/src/libstrongswan/utils/linked_list.h
index 310e91e3c..ba47e7dfb 100644
--- a/src/libstrongswan/utils/linked_list.h
+++ b/src/libstrongswan/utils/linked_list.h
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2007-2008 Tobias Brunner
- * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005-2008 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
*
@@ -14,7 +14,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: linked_list.h 3841 2008-04-18 11:48:53Z tobias $
+ * $Id: linked_list.h 4576 2008-11-05 08:32:38Z martin $
*/
/**
@@ -27,13 +27,10 @@
typedef struct linked_list_t linked_list_t;
-#include <pthread.h>
-
#include <library.h>
#include <utils/iterator.h>
#include <utils/enumerator.h>
-
/**
* Method to match elements in a linked list (used in find_* functions)
*
@@ -81,18 +78,6 @@ struct linked_list_t {
iterator_t *(*create_iterator) (linked_list_t *this, bool forward);
/**
- * Creates a iterator, locking a mutex.
- *
- * The supplied mutex is acquired immediately, and released
- * when the iterator gets destroyed.
- *
- * @param mutex mutex to use for exclusive access
- * @return new iterator_t object
- */
- iterator_t *(*create_iterator_locked) (linked_list_t *this,
- pthread_mutex_t *mutex);
-
- /**
* Create an enumerator over the list.
*
* The enumerator is a "lightweight" iterator. It only has two methods
@@ -130,7 +115,7 @@ struct linked_list_t {
* If a compare function is given, it is called for each item, where
* the first parameter is the current list item and the second parameter
* is the supplied item parameter.
- * If compare is NULL, compare is is done by pointer.
+ * If compare is NULL, compare is done by pointer.
*
* @param item item to remove/pass to comparator
* @param compare compare function, or NULL
@@ -179,10 +164,12 @@ struct linked_list_t {
* If the supplied function returns TRUE this function returns SUCCESS, and
* the current object is returned in the third parameter, otherwise,
* the next item is checked.
+ *
+ * If match is NULL, *item and the current object are compared.
*
* @warning Only use pointers as user supplied data.
*
- * @param match comparison function to call on each object
+ * @param match comparison function to call on each object, or NULL
* @param item the list item, if found
* @param ... user data to supply to match function (limited to 5 arguments)
* @return SUCCESS if found, NOT_FOUND otherwise
@@ -198,9 +185,11 @@ struct linked_list_t {
* the current object is returned in the third parameter, otherwise,
* the next item is checked.
*
+ * If match is NULL, *item and the current object are compared.
+ *
* @warning Only use pointers as user supplied data.
*
- * @param match comparison function to call on each object
+ * @param match comparison function to call on each object, or NULL
* @param item the list item, if found
* @param ... user data to supply to match function (limited to 5 arguments)
* @return SUCCESS if found, NOT_FOUND otherwise
diff --git a/src/libstrongswan/utils/mutex.c b/src/libstrongswan/utils/mutex.c
index 425389b4f..ddb0d2df6 100644
--- a/src/libstrongswan/utils/mutex.c
+++ b/src/libstrongswan/utils/mutex.c
@@ -12,24 +12,92 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: mutex.c 3589 2008-03-13 14:14:44Z martin $
+ * $Id: mutex.c 4591 2008-11-05 16:12:54Z martin $
*/
-#include "mutex.h"
-
-#include <library.h>
-#include <debug.h>
-
+#define _GNU_SOURCE
#include <pthread.h>
#include <sys/time.h>
+#include <stdint.h>
#include <time.h>
#include <errno.h>
+#include "mutex.h"
+
+#include <library.h>
+#include <debug.h>
typedef struct private_mutex_t private_mutex_t;
-typedef struct private_n_mutex_t private_n_mutex_t;
typedef struct private_r_mutex_t private_r_mutex_t;
typedef struct private_condvar_t private_condvar_t;
+typedef struct private_rwlock_t private_rwlock_t;
+
+#ifdef LOCK_PROFILER
+
+/**
+ * Do not report mutexes with an overall waiting time smaller than this (in us)
+ */
+#define PROFILE_TRESHHOLD 1000
+
+#include <utils/backtrace.h>
+
+typedef struct lock_profile_t lock_profile_t;
+
+struct lock_profile_t {
+
+ /**
+ * how long threads have waited for the lock in this mutex so far
+ */
+ struct timeval waited;
+
+ /**
+ * backtrace where mutex has been created
+ */
+ backtrace_t *backtrace;
+};
+
+/**
+ * Print and cleanup mutex profiler
+ */
+static void profiler_cleanup(lock_profile_t *profile)
+{
+ if (profile->waited.tv_sec > 0 ||
+ profile->waited.tv_usec > PROFILE_TRESHHOLD)
+ {
+ fprintf(stderr, "%d.%06ds in lock created at:",
+ profile->waited.tv_sec, profile->waited.tv_usec);
+ profile->backtrace->log(profile->backtrace, stderr);
+ }
+ profile->backtrace->destroy(profile->backtrace);
+}
+
+/**
+ * Initialize mutex profiler
+ */
+static void profiler_init(lock_profile_t *profile)
+{
+ profile->backtrace = backtrace_create(3);
+ timerclear(&profile->waited);
+}
+
+#define profiler_start(profile) { \
+ struct timeval _start, _end, _diff; \
+ gettimeofday(&_start, NULL);
+
+#define profiler_end(profile) \
+ gettimeofday(&_end, NULL); \
+ timersub(&_end, &_start, &_diff); \
+ timeradd(&(profile)->waited, &_diff, &(profile)->waited); }
+
+#else /* !LOCK_PROFILER */
+
+#define lock_profile_t struct {}
+#define profiler_cleanup(...) {}
+#define profiler_init(...) {}
+#define profiler_start(...) {}
+#define profiler_end(...) {}
+
+#endif /* LOCK_PROFILER */
/**
* private data of mutex
@@ -45,6 +113,16 @@ struct private_mutex_t {
* wrapped pthread mutex
*/
pthread_mutex_t mutex;
+
+ /**
+ * is this a recursiv emutex, implementing private_r_mutex_t?
+ */
+ bool recursive;
+
+ /**
+ * profiling info, if enabled
+ */
+ lock_profile_t profile;
};
/**
@@ -53,7 +131,7 @@ struct private_mutex_t {
struct private_r_mutex_t {
/**
- * public functions
+ * Extends private_mutex_t
*/
private_mutex_t generic;
@@ -63,9 +141,9 @@ struct private_r_mutex_t {
pthread_t thread;
/**
- * times we have locked the lock
+ * times we have locked the lock, stored per thread
*/
- int times;
+ pthread_key_t times;
};
/**
@@ -85,14 +163,37 @@ struct private_condvar_t {
};
/**
+ * private data of rwlock
+ */
+struct private_rwlock_t {
+
+ /**
+ * public functions
+ */
+ rwlock_t public;
+
+ /**
+ * wrapped pthread rwlock
+ */
+ pthread_rwlock_t rwlock;
+
+ /**
+ * profiling info, if enabled
+ */
+ lock_profile_t profile;
+};
+
+/**
* Implementation of mutex_t.lock.
*/
static void lock(private_mutex_t *this)
{
+ profiler_start(&this->profile);
if (pthread_mutex_lock(&this->mutex))
{
DBG1("!!!! MUTEX %sLOCK ERROR, your code is buggy !!!", "");
}
+ profiler_end(&this->profile);
}
/**
@@ -115,12 +216,19 @@ static void lock_r(private_r_mutex_t *this)
if (this->thread == self)
{
- this->times++;
- return;
+ uintptr_t times;
+
+ /* times++ */
+ times = (uintptr_t)pthread_getspecific(this->times);
+ pthread_setspecific(this->times, (void*)times + 1);
+ }
+ else
+ {
+ lock(&this->generic);
+ this->thread = self;
+ /* times = 1 */
+ pthread_setspecific(this->times, (void*)1);
}
- lock(&this->generic);
- this->thread = self;
- this->times = 1;
}
/**
@@ -128,7 +236,13 @@ static void lock_r(private_r_mutex_t *this)
*/
static void unlock_r(private_r_mutex_t *this)
{
- if (--this->times == 0)
+ uintptr_t times;
+
+ /* times-- */
+ times = (uintptr_t)pthread_getspecific(this->times);
+ pthread_setspecific(this->times, (void*)--times);
+
+ if (times == 0)
{
this->thread = 0;
unlock(&this->generic);
@@ -140,10 +254,22 @@ static void unlock_r(private_r_mutex_t *this)
*/
static void mutex_destroy(private_mutex_t *this)
{
+ profiler_cleanup(&this->profile);
pthread_mutex_destroy(&this->mutex);
free(this);
}
+/**
+ * Implementation of mutex_t.destroy for recursive mutex'
+ */
+static void mutex_destroy_r(private_r_mutex_t *this)
+{
+ profiler_cleanup(&this->generic.profile);
+ pthread_mutex_destroy(&this->generic.mutex);
+ pthread_key_delete(this->times);
+ free(this);
+}
+
/*
* see header file
*/
@@ -154,15 +280,17 @@ mutex_t *mutex_create(mutex_type_t type)
case MUTEX_RECURSIVE:
{
private_r_mutex_t *this = malloc_thing(private_r_mutex_t);
-
+
this->generic.public.lock = (void(*)(mutex_t*))lock_r;
this->generic.public.unlock = (void(*)(mutex_t*))unlock_r;
- this->generic.public.destroy = (void(*)(mutex_t*))mutex_destroy;
-
+ this->generic.public.destroy = (void(*)(mutex_t*))mutex_destroy_r;
+
pthread_mutex_init(&this->generic.mutex, NULL);
+ pthread_key_create(&this->times, NULL);
+ this->generic.recursive = TRUE;
+ profiler_init(&this->generic.profile);
this->thread = 0;
- this->times = 0;
-
+
return &this->generic.public;
}
case MUTEX_DEFAULT:
@@ -173,9 +301,11 @@ mutex_t *mutex_create(mutex_type_t type)
this->public.lock = (void(*)(mutex_t*))lock;
this->public.unlock = (void(*)(mutex_t*))unlock;
this->public.destroy = (void(*)(mutex_t*))mutex_destroy;
-
+
pthread_mutex_init(&this->mutex, NULL);
-
+ this->recursive = FALSE;
+ profiler_init(&this->profile);
+
return &this->public;
}
}
@@ -186,7 +316,19 @@ mutex_t *mutex_create(mutex_type_t type)
*/
static void wait(private_condvar_t *this, private_mutex_t *mutex)
{
- pthread_cond_wait(&this->condvar, &mutex->mutex);
+ if (mutex->recursive)
+ {
+ private_r_mutex_t* recursive = (private_r_mutex_t*)mutex;
+
+ /* mutex owner gets cleared during condvar wait */
+ recursive->thread = 0;
+ pthread_cond_wait(&this->condvar, &mutex->mutex);
+ recursive->thread = pthread_self();
+ }
+ else
+ {
+ pthread_cond_wait(&this->condvar, &mutex->mutex);
+ }
}
/**
@@ -198,6 +340,7 @@ static bool timed_wait(private_condvar_t *this, private_mutex_t *mutex,
struct timespec ts;
struct timeval tv;
u_int s, ms;
+ bool timed_out;
gettimeofday(&tv, NULL);
@@ -211,8 +354,21 @@ static bool timed_wait(private_condvar_t *this, private_mutex_t *mutex,
ts.tv_nsec -= 1000000000;
ts.tv_sec++;
}
- return (pthread_cond_timedwait(&this->condvar, &mutex->mutex,
- &ts) == ETIMEDOUT);
+ if (mutex->recursive)
+ {
+ private_r_mutex_t* recursive = (private_r_mutex_t*)mutex;
+
+ recursive->thread = 0;
+ timed_out = pthread_cond_timedwait(&this->condvar, &mutex->mutex,
+ &ts) == ETIMEDOUT;
+ recursive->thread = pthread_self();
+ }
+ else
+ {
+ timed_out = pthread_cond_timedwait(&this->condvar, &mutex->mutex,
+ &ts) == ETIMEDOUT;
+ }
+ return timed_out;
}
/**
@@ -265,3 +421,75 @@ condvar_t *condvar_create(condvar_type_t type)
}
}
+/**
+ * Implementation of rwlock_t.read_lock
+ */
+static void read_lock(private_rwlock_t *this)
+{
+ profiler_start(&this->profile);
+ pthread_rwlock_rdlock(&this->rwlock);
+ profiler_end(&this->profile);
+}
+
+/**
+ * Implementation of rwlock_t.write_lock
+ */
+static void write_lock(private_rwlock_t *this)
+{
+ profiler_start(&this->profile);
+ pthread_rwlock_wrlock(&this->rwlock);
+ profiler_end(&this->profile);
+}
+
+/**
+ * Implementation of rwlock_t.try_write_lock
+ */
+static bool try_write_lock(private_rwlock_t *this)
+{
+ return pthread_rwlock_trywrlock(&this->rwlock) == 0;
+}
+
+/**
+ * Implementation of rwlock_t.unlock
+ */
+static void rw_unlock(private_rwlock_t *this)
+{
+ pthread_rwlock_unlock(&this->rwlock);
+}
+
+/**
+ * Implementation of rwlock_t.destroy
+ */
+static void rw_destroy(private_rwlock_t *this)
+{
+ pthread_rwlock_destroy(&this->rwlock);
+ profiler_cleanup(&this->profile);
+ free(this);
+}
+
+/*
+ * see header file
+ */
+rwlock_t *rwlock_create(rwlock_type_t type)
+{
+ switch (type)
+ {
+ case RWLOCK_DEFAULT:
+ default:
+ {
+ private_rwlock_t *this = malloc_thing(private_rwlock_t);
+
+ this->public.read_lock = (void(*)(rwlock_t*))read_lock;
+ this->public.write_lock = (void(*)(rwlock_t*))write_lock;
+ this->public.try_write_lock = (bool(*)(rwlock_t*))try_write_lock;
+ this->public.unlock = (void(*)(rwlock_t*))rw_unlock;
+ this->public.destroy = (void(*)(rwlock_t*))rw_destroy;
+
+ pthread_rwlock_init(&this->rwlock, NULL);
+ profiler_init(&this->profile);
+
+ return &this->public;
+ }
+ }
+}
+
diff --git a/src/libstrongswan/utils/mutex.h b/src/libstrongswan/utils/mutex.h
index cf557c35c..a0a198024 100644
--- a/src/libstrongswan/utils/mutex.h
+++ b/src/libstrongswan/utils/mutex.h
@@ -23,8 +23,10 @@
typedef struct mutex_t mutex_t;
typedef struct condvar_t condvar_t;
+typedef struct rwlock_t rwlock_t;
typedef enum mutex_type_t mutex_type_t;
typedef enum condvar_type_t condvar_type_t;
+typedef enum rwlock_type_t rwlock_type_t;
#include <library.h>
@@ -47,6 +49,14 @@ enum condvar_type_t {
};
/**
+ * Type of read-write lock.
+ */
+enum rwlock_type_t {
+ /** default condvar */
+ RWLOCK_DEFAULT = 0,
+};
+
+/**
* Mutex wrapper implements simple, portable and advanced mutex functions.
*/
struct mutex_t {
@@ -105,6 +115,41 @@ struct condvar_t {
};
/**
+ * Read-Write lock wrapper.
+ */
+struct rwlock_t {
+
+ /**
+ * Acquire the read lock.
+ */
+ void (*read_lock)(rwlock_t *this);
+
+ /**
+ * Acquire the write lock.
+ */
+ void (*write_lock)(rwlock_t *this);
+
+ /**
+ * Try to acquire the write lock.
+ *
+ * Never blocks, but returns FALSE if the lock was already occupied.
+ *
+ * @return TRUE if lock acquired
+ */
+ bool (*try_write_lock)(rwlock_t *this);
+
+ /**
+ * Release any acquired lock.
+ */
+ void (*unlock)(rwlock_t *this);
+
+ /**
+ * Destroy the read-write lock.
+ */
+ void (*destroy)(rwlock_t *this);
+};
+
+/**
* Create a mutex instance.
*
* @param type type of mutex to create
@@ -120,4 +165,12 @@ mutex_t *mutex_create(mutex_type_t type);
*/
condvar_t *condvar_create(condvar_type_t type);
+/**
+ * Create a read-write lock instance.
+ *
+ * @param type type of rwlock to create
+ * @return unlocked rwlock instance
+ */
+rwlock_t *rwlock_create(rwlock_type_t type);
+
#endif /* MUTEX_H_ @}*/