summaryrefslogtreecommitdiff
path: root/src/libcharon/plugins/duplicheck
diff options
context:
space:
mode:
Diffstat (limited to 'src/libcharon/plugins/duplicheck')
-rw-r--r--src/libcharon/plugins/duplicheck/Makefile.in38
-rw-r--r--src/libcharon/plugins/duplicheck/duplicheck_listener.c186
2 files changed, 155 insertions, 69 deletions
diff --git a/src/libcharon/plugins/duplicheck/Makefile.in b/src/libcharon/plugins/duplicheck/Makefile.in
index 0577b25ac..d1b5dfbe6 100644
--- a/src/libcharon/plugins/duplicheck/Makefile.in
+++ b/src/libcharon/plugins/duplicheck/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11.3 from Makefile.am.
+# Makefile.in generated by automake 1.11.6 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
@@ -17,6 +17,23 @@
VPATH = @srcdir@
+am__make_dryrun = \
+ { \
+ am__dry=no; \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \
+ | grep '^AM OK$$' >/dev/null || am__dry=yes;; \
+ *) \
+ for am__flg in $$MAKEFLAGS; do \
+ case $$am__flg in \
+ *=*|--*) ;; \
+ *n*) am__dry=yes; break;; \
+ esac; \
+ done;; \
+ esac; \
+ test $$am__dry = yes; \
+ }
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
@@ -115,6 +132,11 @@ LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
SOURCES = $(libstrongswan_duplicheck_la_SOURCES) $(duplicheck_SOURCES)
DIST_SOURCES = $(libstrongswan_duplicheck_la_SOURCES) \
$(duplicheck_SOURCES)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
ETAGS = etags
CTAGS = ctags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
@@ -131,6 +153,8 @@ BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
+CHECK_CFLAGS = @CHECK_CFLAGS@
+CHECK_LIBS = @CHECK_LIBS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CYGPATH_W = @CYGPATH_W@
@@ -147,6 +171,7 @@ EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
GPERF = @GPERF@
+GPRBUILD = @GPRBUILD@
GREP = @GREP@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
@@ -215,8 +240,6 @@ am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
attest_plugins = @attest_plugins@
-axis2c_CFLAGS = @axis2c_CFLAGS@
-axis2c_LIBS = @axis2c_LIBS@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
@@ -272,7 +295,6 @@ nm_ca_dir = @nm_ca_dir@
nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
-p_plugins = @p_plugins@
pcsclite_CFLAGS = @pcsclite_CFLAGS@
pcsclite_LIBS = @pcsclite_LIBS@
pdfdir = @pdfdir@
@@ -365,7 +387,6 @@ clean-noinstLTLIBRARIES:
done
install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
@$(NORMAL_INSTALL)
- test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
@list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
list2=; for p in $$list; do \
if test -f $$p; then \
@@ -373,6 +394,8 @@ install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
else :; fi; \
done; \
test -z "$$list2" || { \
+ echo " $(MKDIR_P) '$(DESTDIR)$(plugindir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(plugindir)" || exit 1; \
echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \
$(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \
}
@@ -398,8 +421,11 @@ libstrongswan-duplicheck.la: $(libstrongswan_duplicheck_la_OBJECTS) $(libstrongs
$(libstrongswan_duplicheck_la_LINK) $(am_libstrongswan_duplicheck_la_rpath) $(libstrongswan_duplicheck_la_OBJECTS) $(libstrongswan_duplicheck_la_LIBADD) $(LIBS)
install-ipsecPROGRAMS: $(ipsec_PROGRAMS)
@$(NORMAL_INSTALL)
- test -z "$(ipsecdir)" || $(MKDIR_P) "$(DESTDIR)$(ipsecdir)"
@list='$(ipsec_PROGRAMS)'; test -n "$(ipsecdir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(ipsecdir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(ipsecdir)" || exit 1; \
+ fi; \
for p in $$list; do echo "$$p $$p"; done | \
sed 's/$(EXEEXT)$$//' | \
while read p p1; do if test -f $$p || test -f $$p1; \
diff --git a/src/libcharon/plugins/duplicheck/duplicheck_listener.c b/src/libcharon/plugins/duplicheck/duplicheck_listener.c
index 1b0df1e8b..30a723d36 100644
--- a/src/libcharon/plugins/duplicheck/duplicheck_listener.c
+++ b/src/libcharon/plugins/duplicheck/duplicheck_listener.c
@@ -60,8 +60,8 @@ struct private_duplicheck_listener_t {
typedef struct {
/** peer identity */
identification_t *id;
- /** IKE_SA identifier */
- ike_sa_id_t *sa;
+ /** list of IKE_SA identifiers, ike_sa_id_t */
+ linked_list_t *sas;
} entry_t;
/**
@@ -70,7 +70,7 @@ typedef struct {
static void entry_destroy(entry_t *this)
{
this->id->destroy(this->id);
- this->sa->destroy(this->sa);
+ this->sas->destroy_offset(this->sas, offsetof(ike_sa_id_t, destroy));
free(this);
}
@@ -90,27 +90,101 @@ static bool equals(identification_t *a, identification_t *b)
return a->equals(a, b);
}
-METHOD(listener_t, ike_rekey, bool,
- private_duplicheck_listener_t *this, ike_sa_t *old, ike_sa_t *new)
+/**
+ * Put an IKE_SA identifier to hashtable
+ */
+static void put(hashtable_t *table, identification_t *id, ike_sa_id_t *sa)
{
- identification_t *id;
- ike_sa_id_t *sa;
entry_t *entry;
- sa = new->get_id(new);
- id = new->get_other_id(new);
+ entry = table->get(table, id);
+ if (!entry)
+ {
+ INIT(entry,
+ .id = id->clone(id),
+ .sas = linked_list_create(),
+ );
+ table->put(table, entry->id, entry);
+ }
+ entry->sas->insert_last(entry->sas, sa->clone(sa));
+}
- INIT(entry,
- .id = id->clone(id),
- .sa = sa->clone(sa),
- );
- this->mutex->lock(this->mutex);
- entry = this->active->put(this->active, entry->id, entry);
- this->mutex->unlock(this->mutex);
+/**
+ * Purge an entry from table if it has no IKE_SA identifiers
+ */
+static void remove_if_empty(hashtable_t *table, entry_t *entry)
+{
+ if (entry->sas->get_count(entry->sas) == 0)
+ {
+ entry = table->remove(table, entry->id);
+ if (entry)
+ {
+ entry_destroy(entry);
+ }
+ }
+}
+
+/**
+ * Remove the first entry found in the table for the given id
+ */
+static ike_sa_id_t *remove_first(hashtable_t *table, identification_t *id)
+{
+ ike_sa_id_t *sa = NULL;
+ entry_t *entry;
+
+ entry = table->get(table, id);
+ if (entry)
+ {
+ entry->sas->remove_first(entry->sas, (void**)&sa);
+ remove_if_empty(table, entry);
+ }
+ return sa;
+}
+
+/**
+ * Remove a specific IKE_SA ID for the given identity
+ */
+static bool remove_specific(hashtable_t *table, identification_t *id,
+ ike_sa_id_t *sa)
+{
+ enumerator_t *enumerator;
+ bool found = FALSE;
+ entry_t *entry;
+ ike_sa_id_t *current;
+
+ entry = table->get(table, id);
if (entry)
{
- entry_destroy(entry);
+ enumerator = entry->sas->create_enumerator(entry->sas);
+ while (enumerator->enumerate(enumerator, &current))
+ {
+ if (sa->equals(sa, current))
+ {
+ entry->sas->remove_at(entry->sas, enumerator);
+ current->destroy(current);
+ found = TRUE;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ if (found)
+ {
+ remove_if_empty(table, entry);
+ }
}
+ return found;
+}
+
+METHOD(listener_t, ike_rekey, bool,
+ private_duplicheck_listener_t *this, ike_sa_t *old, ike_sa_t *new)
+{
+ this->mutex->lock(this->mutex);
+
+ remove_specific(this->active, old->get_other_id(old), old->get_id(old));
+ put(this->active, new->get_other_id(new), new->get_id(new));
+
+ this->mutex->unlock(this->mutex);
+
return TRUE;
}
@@ -119,58 +193,41 @@ METHOD(listener_t, ike_updown, bool,
{
identification_t *id;
ike_sa_id_t *sa;
- entry_t *entry;
- job_t *job;
- sa = ike_sa->get_id(ike_sa);
id = ike_sa->get_other_id(ike_sa);
+ this->mutex->lock(this->mutex);
if (up)
{
- INIT(entry,
- .id = id->clone(id),
- .sa = sa->clone(sa),
- );
- this->mutex->lock(this->mutex);
- entry = this->active->put(this->active, entry->id, entry);
- this->mutex->unlock(this->mutex);
- if (entry)
+ /* another IKE_SA for this identity active? */
+ sa = remove_first(this->active, id);
+ if (sa)
{
DBG1(DBG_CFG, "detected duplicate IKE_SA for '%Y', "
"triggering delete for old IKE_SA", id);
- job = (job_t*)delete_ike_sa_job_create(entry->sa, TRUE);
- this->mutex->lock(this->mutex);
- entry = this->checking->put(this->checking, entry->id, entry);
- this->mutex->unlock(this->mutex);
- lib->processor->queue_job(lib->processor, job);
- if (entry)
- {
- entry_destroy(entry);
- }
+ put(this->checking, id, sa);
+ lib->processor->queue_job(lib->processor,
+ (job_t*)delete_ike_sa_job_create(sa, TRUE));
+ sa->destroy(sa);
}
+ /* register IKE_SA as the new active */
+ sa = ike_sa->get_id(ike_sa);
+ put(this->active, id, sa);
}
else
{
- this->mutex->lock(this->mutex);
- entry = this->checking->remove(this->checking, id);
- this->mutex->unlock(this->mutex);
- if (entry)
+ sa = ike_sa->get_id(ike_sa);
+ /* check if closing an IKE_SA currently in checking state */
+ if (remove_specific(this->checking, id, sa))
{
DBG1(DBG_CFG, "delete for duplicate IKE_SA '%Y' timed out, "
"keeping new IKE_SA", id);
- entry_destroy(entry);
- }
- else
- {
- this->mutex->lock(this->mutex);
- entry = this->active->remove(this->active, id);
- this->mutex->unlock(this->mutex);
- if (entry)
- {
- entry_destroy(entry);
- }
}
+ /* check normal close of IKE_SA */
+ remove_specific(this->active, id, sa);
}
+ this->mutex->unlock(this->mutex);
+
return TRUE;
}
@@ -181,29 +238,32 @@ METHOD(listener_t, message_hook, bool,
if (incoming && plain && !message->get_request(message))
{
identification_t *id;
- entry_t *entry;
+ ike_sa_id_t *sa;
id = ike_sa->get_other_id(ike_sa);
+ sa = ike_sa->get_id(ike_sa);
+
this->mutex->lock(this->mutex);
- entry = this->checking->remove(this->checking, id);
- this->mutex->unlock(this->mutex);
- if (entry)
+ if (remove_specific(this->checking, id, sa))
{
DBG1(DBG_CFG, "got a response on a duplicate IKE_SA for '%Y', "
"deleting new IKE_SA", id);
charon->bus->alert(charon->bus, ALERT_UNIQUE_KEEP);
- entry_destroy(entry);
- this->mutex->lock(this->mutex);
- entry = this->active->remove(this->active, id);
- this->mutex->unlock(this->mutex);
- if (entry)
+ sa = remove_first(this->active, id);
+ if (sa)
{
lib->processor->queue_job(lib->processor,
- (job_t*)delete_ike_sa_job_create(entry->sa, TRUE));
- entry_destroy(entry);
+ (job_t*)delete_ike_sa_job_create(sa, TRUE));
+ sa->destroy(sa);
}
+ this->mutex->unlock(this->mutex);
+
this->notify->send(this->notify, id);
}
+ else
+ {
+ this->mutex->unlock(this->mutex);
+ }
}
return TRUE;
}